Moved garbage collector from tables.c into mm/ subdirectory.
authorphil <none@none>
Thu, 29 Oct 1998 00:33:54 +0000 (00:33 +0000)
committerphil <none@none>
Thu, 29 Oct 1998 00:33:54 +0000 (00:33 +0000)
Makefile
asmpart.h
global.h
mm/Makefile [new file with mode: 0644]
mm/heap.old.c [new file with mode: 0644]
src/vm/global.h
src/vm/jit/asmpart.h
src/vm/tables.c
tables.c

index 623f70d236315b2d5612cca858770c56ffe7ace4..1d16edf1492e25b6e202bbaca721b8b78e68ee92 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -9,7 +9,7 @@
 # Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
 #          Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
 #
-# Last Change: 1997/10/30
+# Last Change: 1998/09/27
 #
 #
 # ATTENTION: This version of the makefile only works with gmake.
 #
 ################################################################################
 
+VERSION_MAJOR = 0
+VERSION_MINOR = 30
+VERSION_POSTFIX = 
+
+VERSION_STRING=$(VERSION_MAJOR).$(VERSION_MINOR)$(VERSION_POSTFIX)
+
 ##################### generation of the excutable ##############################
 
 # Enabling/disabling thread support
@@ -45,8 +51,9 @@ CC = cc
 CFLAGS = -O3 -ieee $(THREAD_CFLAGS)
 
 OBJ = main.o tables.o loader.o compiler.o newcomp.o builtin.o asmpart.o \
-    toolbox/toolbox.a native.o $(THREAD_OBJ)
-OBJH = headers.o tables.o loader.o builtin.o toolbox/toolbox.a $(THREAD_OBJ)
+       toolbox/toolbox.a native.o $(THREAD_OBJ) mm/mm.o
+OBJH = headers.o tables.o loader.o builtin.o toolbox/toolbox.a $(THREAD_OBJ) \
+        mm/mm.o
 
 cacao: $(OBJ)
        $(CC) $(CFLAGS) -o cacao $(OBJ) -lm
@@ -84,6 +91,9 @@ threads/threads.a: threads/*.c threads/*.h sysdep/threads.h
        cd threads; make threads.a "USE_THREADS=$(USE_THREADS)" "CFLAGS=$(CFLAGS)" "CC=$(CC)" 
 endif
 
+mm/mm.o: mm/*.[ch] mm/Makefile
+       cd mm; make mm.o "USE_THREADS=$(USE_THREADS)" "CFLAGS=$(CFLAGS)" "CC=$(CC)"
+
 asmpart.o: sysdep/asmpart.c
        rm -f asmpart.s
        $(CC) -E sysdep/asmpart.c > asmpart.s
@@ -109,6 +119,21 @@ tar:
        mv cacao.tar.gz cacao.tgz
        ls -l cacao.tgz
 
+dist:
+       rm -rf cacao-$(VERSION_STRING).tar.gz cacao-$(VERSION_STRING);
+       ( mkdir cacao-$(VERSION_STRING); \
+#        tar -cf cacao-$(VERSION_STRING).tar -T FILES; \
+         tar -cvf cacao-$(VERSION_STRING).tar Makefile */Makefile README COPYRIGHT \
+           tst/*.java doc/*.doc html/*.html *.[ch] comp/*.[ch] ncomp/*.[ch] \
+           alpha/*.doc alpha/*.[ch] nat/*.[ch] toolbox/*.[ch] threads/*.[ch]; \
+         cd cacao-$(VERSION_STRING); \
+         tar -xf ../cacao-$(VERSION_STRING).tar; \
+         cd ..; \
+         rm cacao-$(VERSION_STRING).tar; \
+         tar -cvf cacao-$(VERSION_STRING).tar cacao-$(VERSION_STRING); \
+         rm -rf cacao-$(VERSION_STRING); )
+       gzip -9 cacao-$(VERSION_STRING).tar
+       ls -l cacao-$(VERSION_STRING).tar.gz
 
 ########################## supported architectures #############################
 
index 927ccd161ca3f37076a269a18c350a3d8cee0a22..a9d2136250be9a0ed75c5560c3dcc28c5a1bf294 100644 (file)
--- a/asmpart.h
+++ b/asmpart.h
@@ -14,6 +14,8 @@
 
 *******************************************************************************/
 
+#include "global.h"
+
 int has_no_x_instr_set();
        /* determines if the byte support instruction set (21164a and higher)
           is available. */
index e92f7f1164e62e6343d1ac78a25d420017962c36..efcd477d80aa7d061183454c3f4eb0d38f1cdf75 100644 (file)
--- a/global.h
+++ b/global.h
@@ -117,18 +117,18 @@ typedef u1* methodptr;
 /********************** data structures of UNICODE symbol *********************/
 
 struct unicode {
-       unicode   *hashlink; /* externe Verkettung f"ur die unicode-Hashtabelle */
-       u4         key;      /* Hash-Schl"ussel (h"angt nur vom Text ab) */
-       int        length;   /* L"ange des Textes */           
-       u2        *text;     /* Zeiger auf den Text (jeder Buchstabe 16 Bit) */
-       classinfo *class;    /* gegebenenfalls Referenz auf die Klasse dieses 
-                               Namens (oder NULL, wenn es keine solche gibt)  */
-       struct java_objectheader *string;
-                            /* gegebenenfalls Referenz auf einen konstanten
-                               String mit dem entsprechenden Wert */ 
-       };
-
-       /* Alle Unicode-Symbole werden in einer einzigen globalen Tabelle 
+  unicode   *hashlink; /* externe Verkettung f"ur die unicode-Hashtabelle */
+  u4         key;      /* Hash-Schl"ussel (h"angt nur vom Text ab) */
+  int        length;   /* L"ange des Textes */           
+  u2        *text;     /* Zeiger auf den Text (jeder Buchstabe 16 Bit) */
+  classinfo *class;    /* gegebenenfalls Referenz auf die Klasse dieses 
+                         Namens (oder NULL, wenn es keine solche gibt)  */
+  struct java_objectheader *string;
+  /* gegebenenfalls Referenz auf einen konstanten
+     String mit dem entsprechenden Wert */ 
+};
+
+/* Alle Unicode-Symbole werden in einer einzigen globalen Tabelle 
           (Hashtabelle) verwaltet, jedes Symbol wird nur einmal angelegt.
           -> Speicherersparnis, und "Uberpr"ufung auf Gleichheit durch einfachen
           Zeigervergleich */
@@ -138,42 +138,42 @@ struct unicode {
 
 
 typedef struct {
-       classinfo *class;
-       unicode   *name;
-       unicode   *descriptor;
-       } constant_FMIref;
+  classinfo *class;
+  unicode   *name;
+  unicode   *descriptor;
+} constant_FMIref;
 
 
 typedef struct {
-       s4 value;
-       } constant_integer;
+  s4 value;
+} constant_integer;
        
 typedef struct {
-       float value;
-       } constant_float;
+  float value;
+} constant_float;
 
 typedef struct {
-       s8 value;
-       } constant_long;
+  s8 value;
+} constant_long;
        
 typedef struct {
-       double value;
-       } constant_double;
+  double value;
+} constant_double;
 
 
 typedef struct {
-       unicode *name;
-       unicode *descriptor;
-       } constant_nameandtype;
+  unicode *name;
+  unicode *descriptor;
+} constant_nameandtype;
 
 
 typedef struct constant_arraydescriptor {
-       int arraytype;
-       classinfo *objectclass;
-       struct constant_arraydescriptor *elementdescriptor;
-       } constant_arraydescriptor;
+  int arraytype;
+  classinfo *objectclass;
+  struct constant_arraydescriptor *elementdescriptor;
+} constant_arraydescriptor;
 
-       /* Mit einem Arraydescriptor kann ein Array-Typ dargestellt werden.
+/* Mit einem Arraydescriptor kann ein Array-Typ dargestellt werden.
           Bei normalen Arrays (z.B. Array von Bytes,...) gen"ugt dazu,
        dass das Feld arraytype die entsprechende Kennzahl enth"alt
        (z.B. ARRAYTYPE_BYTE).
@@ -229,12 +229,12 @@ typedef struct constant_arraydescriptor {
        */
 
 typedef struct java_objectheader {    /* Der Header f"ur alle Objekte */
-       vftbl *vftbl;                     /* Zeiger auf die Function Table */
+  vftbl *vftbl;                     /* Zeiger auf die Function Table */
 } java_objectheader;
 
 
 
-       /********* Arrays ***********
+/********* Arrays ***********
        
        Alle Arrays in Java sind auch gleichzeitig Objekte (d.h. sie haben auch
        den obligatorischen Object-Header und darin einen Verweis auf eine Klasse)
@@ -255,78 +255,78 @@ typedef struct java_objectheader {    /* Der Header f"ur alle Objekte */
 #define ARRAYTYPE_ARRAY    9
 
 
-       /** Der Header f"ur ein Java-Array **/
+/** Der Header f"ur ein Java-Array **/
 
 typedef struct java_arrayheader {  /* Der Arrayheader f"ur alle Arrays */
-       java_objectheader objheader;       /* Der Object-Header */
-       s4 size;                           /* Gr"osse des Arrays */
-       s4 arraytype;                      /* Typ der Elemente */
+  java_objectheader objheader;       /* Der Object-Header */
+  s4 size;                           /* Gr"osse des Arrays */
+  s4 arraytype;                      /* Typ der Elemente */
 } java_arrayheader;
 
 
 
-       /** Die Unterschiedlichen Strukturen f"ur alle Typen von Arrays **/
+/** Die Unterschiedlichen Strukturen f"ur alle Typen von Arrays **/
 
 typedef struct java_chararray {
-       java_arrayheader header;
-       u2 data[1];
+  java_arrayheader header;
+  u2 data[1];
 } java_chararray;
 
 typedef struct java_floatheader {
-       java_arrayheader header;
-       float data[1];
+  java_arrayheader header;
+  float data[1];
 } java_floatarray;
 
 typedef struct java_doublearray {
-       java_arrayheader header;
-       double data[1];
+  java_arrayheader header;
+  double data[1];
 } java_doublearray;
 
 
-   /* achtung: die beiden Stukturen booleanarray und bytearray m"ussen 
+/* achtung: die beiden Stukturen booleanarray und bytearray m"ussen 
       identisches memory-layout haben, weil mit den selben Funktionen 
       darauf zugegriffen wird */
 
 typedef struct java_booleanarray {
-       java_arrayheader header;
-       u1 data[1];
+  java_arrayheader header;
+  u1 data[1];
 } java_booleanarray;
 
 typedef struct java_bytearray {
-       java_arrayheader header;
-       s1 data[1];
+  java_arrayheader header;
+  s1 data[1];
 } java_bytearray;
 
 typedef struct java_shortarray {
-       java_arrayheader header;
-       s2 data[1];
+  java_arrayheader header;
+  s2 data[1];
 } java_shortarray;
 
 typedef struct java_intarray {
-       java_arrayheader header;
-       s4 data[1];
+  java_arrayheader header;
+  s4 data[1];
 } java_intarray;
 
 typedef struct java_longarray {
-       java_arrayheader header;
-       s8 data[1];
+  java_arrayheader header;
+  s8 data[1];
 } java_longarray;
 
 
-       /* ACHTUNG: die beiden folgenden Strukturen m"ussen unbedingt gleiches
+/* ACHTUNG: die beiden folgenden Strukturen m"ussen unbedingt gleiches
           Memory-Layout haben, weil mit ein und der selben Funktion auf die
           data-Eintr"age beider Typen zugegriffen wird !!!! */
 
 typedef struct java_objectarray {
-       java_arrayheader header;
-       classinfo *elementtype;
-       java_objectheader *data[1];
+  java_arrayheader header;
+  classinfo *elementtype;
+  java_objectheader *data[1];
 } java_objectarray;
 
 typedef struct java_arrayarray {
-       java_arrayheader header;
-       constant_arraydescriptor *elementdescriptor;
-       java_arrayheader *data[1];
+  java_arrayheader header;
+  constant_arraydescriptor *elementdescriptor;
+  java_arrayheader *data[1];
 } java_arrayarray;
 
 
@@ -338,119 +338,120 @@ typedef struct java_arrayarray {
     /*** Struktur: fieldinfo ***/
 
 typedef struct fieldinfo {   /* Struktur f"ur ein Feld einer Klasse */
-       s4       flags;              /* die ACC-Flags */
-       s4       type;               /* Grunddatentyp */
-       unicode *name;               /* Name des Felds */
-       unicode *descriptor;         /* Typedescriptor in JavaVM-Form */
+  s4       flags;              /* die ACC-Flags */
+  s4       type;               /* Grunddatentyp */
+  unicode *name;               /* Name des Felds */
+  unicode *descriptor;         /* Typedescriptor in JavaVM-Form */
        
-       s4       offset;             /* Offset vom Anfang des Objektes */
-                                    /* (bei Instanzvariablen) */
-
-       union {                      /* Speicher f"ur den Wert */
-               s4 i;                    /* (bei Klassenvariablen) */    
-               s8 l;
-               float f;
-               double d;
-               void *a; 
-               } value;
+  s4       offset;             /* Offset vom Anfang des Objektes */
+  /* (bei Instanzvariablen) */
+
+  union {                      /* Speicher f"ur den Wert */
+    s4 i;                    /* (bei Klassenvariablen) */    
+    s8 l;
+    float f;
+    double d;
+    void *a; 
+  } value;
                
-       } fieldinfo;
+} fieldinfo;
 
 
-    /*** Struktur: exceptiontable ***/
+/*** Struktur: exceptiontable ***/
 
 typedef struct exceptiontable {  /* Exceptionhandler-Eintrag in einer Methode */ 
-       s4         startpc;            /* Anfang des G"ultigkeitsbereichs */
-       s4         endpc;              /* Ende des Bereichs (exklusive) */
-       s4         handlerpc;          /* JavaVM-Position des Handlers */
-       classinfo *catchtype;          /* Typ der behandelten Exceptions (oder 
-                                       NULL, wenn alle behandelt werden sollen) */
-       } exceptiontable;
+  s4         startpc;            /* Anfang des G"ultigkeitsbereichs */
+  s4         endpc;              /* Ende des Bereichs (exklusive) */
+  s4         handlerpc;          /* JavaVM-Position des Handlers */
+  classinfo *catchtype;          /* Typ der behandelten Exceptions (oder 
+                                   NULL, wenn alle behandelt werden sollen) */
+} exceptiontable;
 
 
 
-    /*** Struktur: methodinfo ***/
+/*** Struktur: methodinfo ***/
 
 typedef struct methodinfo {  /* Struktur f"ur eine Methode einer Klasse */
-       s4             flags;            /* die ACC-Flags */
-       unicode   *name;             /* Name der Methode */
-       unicode   *descriptor;       /* der JavaVM-Descriptorstring f"ur Methoden */
-       s4        returntype;        /* only temporary valid, return type */
-       s4        paramcount;        /* only temporary valid, number of parameters */
-       u1        *paramtypes;       /* only temporary valid, parameter types */
-       classinfo *class;            /* Die Klasse, der die Methode geh"ort */
-       u4         vftblindex;       /* Index dieser Methode f"ur die Virtual
-                                       Function Table (wenn es keine statische
-                                       Methode ist) */
-
-       s4       maxstack;                  /* maximale Stacktiefe des JavaVM-Codes */
-       s4   maxlocals;                 /* maximale Anzahl der JavaVM-Variablen */
-       u4   jcodelength;               /* L"ange des JavaVM-Codes */
-       u1  *jcode;                     /* und Zeiger auf den JavaVM-Code */
-
-       s4   exceptiontablelength;      /* L"ange der Exceptintable */
-       exceptiontable *exceptiontable; /* Die Exceptiontable selber */
-
-       u1  *stubroutine;               /* STUB-Routine for compiling or calling 
-                                          natives */   
-       u4   mcodelength;               /* L"ange des generierten Maschinencodes */
-       u1  *mcode;                     /* Zeiger auf den Maschinencode */
-       u1  *entrypoint;                /* Entrypoint to the Maschine-Code */
-
-       
-       } methodinfo;
-
-
-    /*** Struktur: classinfo ***/
+  s4          flags;            /* die ACC-Flags */
+  unicode   *name;             /* Name der Methode */
+  unicode   *descriptor;       /* der JavaVM-Descriptorstring f"ur Methoden */
+  s4        returntype;        /* only temporary valid, return type */
+  s4        paramcount;        /* only temporary valid, number of parameters */
+  u1        *paramtypes;       /* only temporary valid, parameter types */
+  classinfo *class;            /* Die Klasse, der die Methode geh"ort */
+  u4         vftblindex;       /* Index dieser Methode f"ur die Virtual
+                                 Function Table (wenn es keine statische
+                                 Methode ist) */
+
+  s4    maxstack;                  /* maximale Stacktiefe des JavaVM-Codes */
+  s4   maxlocals;                 /* maximale Anzahl der JavaVM-Variablen */
+  u4   jcodelength;               /* L"ange des JavaVM-Codes */
+  u1  *jcode;                     /* und Zeiger auf den JavaVM-Code */
+
+  s4   exceptiontablelength;      /* L"ange der Exceptintable */
+  exceptiontable *exceptiontable; /* Die Exceptiontable selber */
+
+  u1  *stubroutine;               /* STUB-Routine for compiling or calling 
+                                    natives */ 
+  u4   mcodelength;               /* L"ange des generierten Maschinencodes */
+  u1  *mcode;                     /* Zeiger auf den Maschinencode */
+  u1  *entrypoint;                /* Entrypoint to the Maschine-Code */        
+} methodinfo;
+
+
+/*** Struktur: classinfo ***/
 
 struct classinfo {           /* Datenstruktur f"ur eine Klasse */
-       java_objectheader header;     /* Weil auch Klassen als Objekte angesprochen 
-                                        werden */
+  java_objectheader header;     /* Weil auch Klassen als Objekte angesprochen 
+                                  werden */
 
-       s4 flags;                     /* Die ACC-Flags */
-       unicode *name;                /* Name der Klasse */ 
+  s4 flags;                     /* Die ACC-Flags */
+  unicode *name;                /* Name der Klasse */ 
        
-       s4       cpcount;             /* Anzahl der Eintr"age im Constant-Pool */
-       u1      *cptags;              /* Die TAGs f"ur den Constant-Pool */
-       voidptr *cpinfos;             /* Die Zeiger auf die Info-Strukturen */
+  s4       cpcount;             /* Anzahl der Eintr"age im Constant-Pool */
+  u1      *cptags;              /* Die TAGs f"ur den Constant-Pool */
+  voidptr *cpinfos;             /* Die Zeiger auf die Info-Strukturen */
        
-       classinfo *super;             /* Zeiger auf die "ubergeordnete Klasse */
+  classinfo *super;             /* Zeiger auf die "ubergeordnete Klasse */
        
-       s4          interfacescount;  /* Anzahl der Interfaces */
-       classinfo **interfaces;       /* Zeiger auf die Interfaces */
+  s4          interfacescount;  /* Anzahl der Interfaces */
+  classinfo **interfaces;       /* Zeiger auf die Interfaces */
        
-       s4          fieldscount;      /* Anzahl der Felder */
-       fieldinfo  *fields;           /* Die Tabelle der Felder */
+  s4          fieldscount;      /* Anzahl der Felder */
+  fieldinfo  *fields;           /* Die Tabelle der Felder */
        
-       s4          methodscount;     /* Anzahl der Methoden */
-       methodinfo *methods;          /* Die Tabelle der Methoden */
+  s4          methodscount;     /* Anzahl der Methoden */
+  methodinfo *methods;          /* Die Tabelle der Methoden */
        
        
-       listnode    listnode;         /* Verkettungsstruktur (f"ur Listen) */
+  listnode    listnode;         /* Verkettungsstruktur (f"ur Listen) */
 
-       bool        initialized;      /* true, wenn Klasse bereits Initialisiert */ 
-       bool        linked;           /* wird von `class_link` auf true gesetzt */
-       s4                      index;            /* Hierarchietiefe  (bei normalen Klassen)  
-                                        oder fortlaufende Nummer (bei Interfaces)*/ 
-       u4          instancesize;     /* Gr"osse eines Objektes dieser Klasse */
+  bool        initialized;      /* true, wenn Klasse bereits Initialisiert */ 
+  bool        linked;           /* wird von `class_link` auf true gesetzt */
+  s4                   index;            /* Hierarchietiefe  (bei normalen Klassen)  
+                                            oder fortlaufende Nummer (bei Interfaces)*/ 
+  u4          instancesize;     /* Gr"osse eines Objektes dieser Klasse */
 
-       vftbl       *vftbl;
+  vftbl       *vftbl;
 
-       methodinfo *finalizer;        /* Finalizer-Methode f"ur die Klasse */
-       };
+  methodinfo* finalizer;        /* Finalizer-Methode f"ur die Klasse */
+#ifdef JIT_MARKER_SUPPORT
+  methodinfo* marker; 
+#endif
+};
        
 
 struct vftbl {
-       classinfo  *class;            /* Class, the function table belongs to */
+  classinfo  *class;            /* Class, the function table belongs to */
 
-       s4          vftbllength;      /* L"aenge der Virtual Function Table */
+  s4          vftbllength;      /* L"aenge der Virtual Function Table */
 
-       s4          interfacetablelength;   /* L"ange der Interfacetable */   
-       u4         *interfacevftbllength;   /* -> siehe unten */   
-       methodptr **interfacevftbl;
+  s4          interfacetablelength;   /* L"ange der Interfacetable */   
+  u4         *interfacevftbllength;   /* -> siehe unten */   
+  methodptr **interfacevftbl;
        
-       methodptr   table[1];
-       };
+  methodptr   table[1];
+};
 
 /*********** Anmerkungen zur Interfacetable: 
 
@@ -540,3 +541,17 @@ extern int count_vmcode_len;
 extern int count_extable_len;
 
 #endif
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
diff --git a/mm/Makefile b/mm/Makefile
new file mode 100644 (file)
index 0000000..19a3ae6
--- /dev/null
@@ -0,0 +1,75 @@
+# cacao/mm/Makefile
+# $Id: Makefile 26 1998-10-29 00:33:54Z phil $
+
+AR = ar
+COMBINE = $(AR) rcs mm.o
+
+mm.o: actualtarget Makefile
+
+actualtarget: old
+
+clean:
+       rm -rf *.o *~
+
+old: heap.old.o
+       rm -f mm.o; $(COMBINE) heap.old.o
+
+heap.old.o: heap.old.c ../tables.h ../global.h
+
+
+
+
+
+
+
+# Targets below this point are experimental and will usually
+# not work reliably
+
+
+
+
+
+
+
+
+new: heap.allocator.o allocator.o 
+       rm -f mm.o; $(COMBINE) heap.allocator.o allocator.o
+
+newer: heap.bitmap.o allocator.o bitmap.o
+       rm -f mm.o; $(COMBINE) heap.bitmap.o allocator.o bitmap.o
+
+gc: heap.o allocator.o bitmap.o
+       rm -f mm.o; $(COMBINE) heap.o allocator.o bitmap.o
+
+gc2: heap2.o allocator.o bitmap2.o
+       rm -f mm.o; $(COMBINE) heap2.o allocator.o bitmap2.o
+
+heap2.o: heap2.c allocator.h mm.h bitmap2.h
+
+heap.o: heap.c allocator.h bitmap2.h
+
+bitmap2.o: bitmap2.c bitmap2.h allocator.h mm.h
+
+heap.allocator.o: heap.c allocator.h
+
+heap.bitmap.o: heap.bitmap.c bitmap.h allocator.h
+
+bitmap.o: bitmap.c bitmap.h
+
+allocator.o: allocator.h allocator.c 
+
+gc.o:  heap.h gc.c 
+
+
+#
+# These are local overrides for various environment variables in Emacs.
+# Please do not remove this and leave it at the end of the file, where
+# Emacs will automagically detect them.
+# ---------------------------------------------------------------------
+# Local variables:
+# mode: Makefile
+# indent-tabs-mode: t
+# tab-width: 8
+# End:
+#
+
diff --git a/mm/heap.old.c b/mm/heap.old.c
new file mode 100644 (file)
index 0000000..73ec501
--- /dev/null
@@ -0,0 +1,912 @@
+/* -*- mode: c; tab-width: 4; c-basic-offset: 4 -*- */
+/****************************** tables.c ***************************************
+
+       Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
+
+       See file COPYRIGHT for information on usage and disclaimer of warranties
+
+       Enth"alt Supportfunktionen f"ur:
+               - Lesen von JavaClass-Files
+           - unicode-Symbole
+               - den Heap 
+               - zus"atzliche Support-Funktionen
+
+       Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
+       Changes: Mark Probst         EMAIL: cacao@complang.tuwien.ac.at
+                Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
+
+       Last Change: 1998/03/24
+
+*******************************************************************************/
+
+#include <assert.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include "../global.h"
+#include "../tables.h"
+#include "../asmpart.h"
+#include "../callargs.h"
+
+#include "../threads/thread.h"                  /* schani */
+#include "../threads/locks.h"
+
+
+
+/******************************************************************************
+********************* Der garbage-collected Heap ******************************
+*******************************************************************************
+
+       verwaltet einen Heap mit automatischer Speicherfreigabe.
+
+       (eine ausf"uhrliche Dokumentation findet sich in der Datei: 
+       collect.doc)
+       
+******************************************************************************/
+
+
+bool collectverbose = false;  /* soll Meldung beim GC ausgegeben werden? */
+
+
+#define BLOCKSIZE 8         /* Gr"osse eines Speicherblockes */
+typedef u8 heapblock;       /* Datentyp mit der Gr"osse eines Speicherblocks */
+
+#if U8_AVAILABLE && SUPPORT_LONG
+#define        bitfieldtype u8
+#define BITFIELDBITS 64
+#else
+#define bitfieldtype u4
+#define BITFIELDBITS 32
+#endif
+
+u4 heapsize;                /* Gr"osse des Heap in Blocks */
+u4 topofheap;               /* Bisherige Obergrenze Heaps */
+heapblock *heap;            /* Speicher f"ur den Heap selbst */
+
+bitfieldtype *startbits;     /* Bitfeld f"ur Bereichsstartkennung */
+bitfieldtype *markbits;      /* Bitfeld f"ur Markierung */
+bitfieldtype *referencebits; /* Bitfeld f"ur Folgereferenzenkennung */
+
+u4 heapfillgrade;           /* Menge der Daten im Heap */
+u4 collectthreashold;       /* Schwellwert f"ur n"achstes GC */
+
+void **bottom_of_stack;     /* Zeiger auf Untergrenze des C-Stacks */ 
+chain *allglobalreferences; /* Liste f"ur alle globalen Zeiger */
+
+typedef struct finalizernode {
+       struct finalizernode *next;     
+       u4 objstart;
+       methodinfo *finalizer;
+       } finalizernode;
+       
+finalizernode *livefinalizees;
+finalizernode *deadfinalizees;
+
+
+typedef struct memarea {    /* Datenstruktur f"ur einen Freispeicherbereich */
+       struct memarea *next;
+       } memarea;
+
+typedef struct bigmemarea {   /* Datenstruktur f"ur einen */
+       struct bigmemarea *next;  /* Freispeicherbereich variabler L"ange */
+       u4 size;
+       } bigmemarea;
+       
+#define DIFFERENTSIZES 128         /* Anzahl der 'kleinen' Freispeicherlisten */
+memarea *memlist[DIFFERENTSIZES];  /* Die 'kleinen' Freispeicherlisten */
+bitfieldtype memlistbits[DIFFERENTSIZES/BITFIELDBITS]; 
+                                   /* Bitfeld, in dem jeweils ein Bit gesetzt */
+                                   /* ist, wenn eine Liste noch etwas enth"alt */
+
+bigmemarea *bigmemlist;         /* Liste der gr"osseren Freispeicherbereiche */
+
+
+
+
+/**************** Hilfsfunktion: lowest **************************************
+
+liefert als Ergebnis die Nummer des niederwertigsten Bits einer 
+Zahl vom Typ bitfieldtype, das 1 ist.
+Wenn die ganze Zahl keine 1en enth"alt, dann ist egal, was f"ur einen
+Wert die Funktion l"iefert.
+z.B.: lowest(1) = 0,   lowest(12) = 2,   lowest(1024) = 10
+
+*****************************************************************************/
+
+static u1 lowesttable[256] = {
+       255, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       5,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       6,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       5,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       7,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       5,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       6,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       5,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 };
+       
+static int lowest(bitfieldtype i)
+{
+#if BITFIELDBITS==64
+       u8 i1 = i<<32;
+       if (i1) {
+               u8 i11 = i1<<16;
+               if (i11) {
+                       u8 i111 = i11<<8;
+                       if (i111) return lowesttable[i111>>56];
+                       else      return 8+lowesttable[i11>>56];
+                       }
+               else {
+                       u8 i112 = i1<<8;
+                       if (i112) return 16+lowesttable[i112>>56];
+                       else      return 24+lowesttable[i1>>56];
+                       }
+               }
+       else {
+               u8 i12 = i<<16;
+               if (i12) {
+                       u8 i121 = i12<<8;
+                       if (i121) return 32+lowesttable[i121>>56];
+                       else      return 40+lowesttable[i12>>56];
+                       }
+               else {
+                       u8 i122 = i<<8;
+                       if (i122) return 48+lowesttable[i122>>56];
+                       else      return 56+lowesttable[i>>56];
+                       }
+               }
+#else
+       u4 i1 = i<<16;
+       if (i1) {
+               u4 i11 = i1<<8;
+               if (i11) return lowesttable[i11>>24];
+               else     return 8+lowesttable[i1>>24];
+               }
+       else {
+               u4 i12 = i<<8;
+               if (i12) return 16+lowesttable[i12>>24];
+               else     return 24+lowesttable[i>>24];
+               }
+#endif
+}
+
+
+/******** Funktionen zum Setzen und L"oschen von Bits in Bitfeldern ***********/
+
+static void setbit(bitfieldtype *bitfield, u4 bitnumber)
+{
+       bitfield[bitnumber/BITFIELDBITS] |= 
+         ((bitfieldtype) 1) << (bitnumber%BITFIELDBITS);
+}
+
+static void clearbit(bitfieldtype *bitfield, u4 bitnumber)
+{
+       bitfield[bitnumber/BITFIELDBITS] &= 
+          ~((bitfieldtype) 1) << (bitnumber%BITFIELDBITS);
+}
+
+static bool isbitset(bitfieldtype *bitfield, u4 bitnumber)
+{
+       return ( bitfield[bitnumber/BITFIELDBITS] & 
+          ( ((bitfieldtype) 1) << (bitnumber%BITFIELDBITS) ) ) != 0;
+}
+
+static bool isbitclear(bitfieldtype *bitfield, u4 bitnumber)
+{
+       return ( bitfield[bitnumber/BITFIELDBITS] & 
+           ( ((bitfieldtype) 1) << (bitnumber%BITFIELDBITS) ) ) == 0;
+}
+
+
+/***************** Funktion: clearbitfield ************************************
+       
+       l"oscht ein ganzes Bitfeld
+       
+******************************************************************************/
+
+static void clearbitfield(bitfieldtype *bitfield, u4 fieldsize)
+{ 
+       u4 i,t;
+       t = ALIGN(fieldsize, BITFIELDBITS) / BITFIELDBITS;
+       for (i=0; i<t; i++) bitfield[i] = 0;
+}
+
+/************** Funktion: maskfieldwithfield **********************************
+       
+       Verkn"upft zwei Bitfelder bitweise mit UND, das erste Bitfeld
+       wird mit dem Ergebnis "uberschrieben 
+       
+******************************************************************************/
+       
+static void maskfieldwithfield (bitfieldtype* bitfield, 
+                                bitfieldtype *maskfield, u4 fieldsize)
+{
+       u4 i,t;
+       t = ALIGN(fieldsize, BITFIELDBITS) / BITFIELDBITS;
+       for (i=0; i<t; i++) bitfield[i] &= maskfield[i];
+}
+
+
+/************** Funktion: findnextsetbit **************************************
+
+       Sucht in einem Bitfeld ab einer Stelle das n"achste gesetzte Bit
+       und liefert die Nummer dieses Bits.
+       Wenn kein Bit mehr zwischen 'bitnumber' und 'fieldsize' gesetzt
+       ist, dann wird fieldsize zur"uckgeliefte.
+
+******************************************************************************/
+
+static u4 findnextsetbit(bitfieldtype* bitfield, u4 fieldsize, u4 bitnumber)
+{
+       bitfieldtype pattern;
+
+       for (;;) {
+               if (bitnumber >= fieldsize) return fieldsize;
+               
+               pattern = bitfield[bitnumber/BITFIELDBITS];
+               pattern >>= (bitnumber%BITFIELDBITS);
+               if (pattern) return bitnumber + lowest(pattern);
+
+               bitnumber = ((bitnumber + BITFIELDBITS) / BITFIELDBITS) * BITFIELDBITS;
+               }
+}
+
+
+/************ Funktion: findnextcombination_set_unset *************************
+
+       funktioniert wie findnextsetbit, allerdings sucht diese Funktion
+       nach einer Stelle, an der gleichzeitig ein Bit im ersten
+       Bitfeld gesetzt ist und im zweiten Bitfeld das entsprechende
+       Bit nicht gesetzt ist.
+
+******************************************************************************/
+
+static u4 findnextcombination_set_unset 
+       (bitfieldtype *bitfield1, bitfieldtype* bitfield2, u4 fieldsize, u4 bitnumber)
+{
+       bitfieldtype pattern;
+
+       for (;;) {
+               if (bitnumber >= fieldsize) return fieldsize;
+               
+               pattern =     bitfield1[bitnumber/BITFIELDBITS] 
+                         & (~bitfield2[bitnumber/BITFIELDBITS]);
+               pattern >>= (bitnumber%BITFIELDBITS);
+               if (pattern) return bitnumber + lowest(pattern);
+
+               bitnumber = ((bitnumber + BITFIELDBITS) / BITFIELDBITS) * BITFIELDBITS;
+               }
+}
+
+
+
+/************** Funktion: memlist_init ****************************************
+
+       initialisiert die Freispeicherlisten (zum nachfolgenden Eintragen 
+       mit memlist_addrange).
+
+******************************************************************************/
+
+static void memlist_init ()
+{
+       u4 i;
+       for (i=0; i<DIFFERENTSIZES; i++) memlist[i] = NULL;
+       clearbitfield (memlistbits, DIFFERENTSIZES);
+       bigmemlist = NULL;
+}
+
+
+/************** Funktion: memlist_addrange ************************************
+
+       f"ugt einen Bereich von Heap-Bl"ocken zur Freispeicherliste 
+       hinzu (in die freien Heap-Bl"ocke werden dabei verschiedene 
+       Verkettungszeiger hineingeschrieben).
+
+******************************************************************************/
+
+static void memlist_addrange (u4 freestart, u4 freesize)
+{
+       if (freesize>=DIFFERENTSIZES) {
+               bigmemarea *m = (bigmemarea*) (heap+freestart);
+               m -> next = bigmemlist;
+               m -> size = freesize;
+               bigmemlist = m;
+               }
+       else {
+               if (freesize*BLOCKSIZE>=sizeof(memarea)) {
+                       memarea *m = (memarea*) (heap+freestart);
+                       m -> next = memlist[freesize];
+                       memlist[freesize] = m;
+                       setbit (memlistbits, freesize);
+                       }
+               }
+}
+
+
+/************** Funktion: memlist_getsuitable *********************************
+
+       sucht in der Freispeicherliste einen Speicherbereich, der m"oglichst
+       genau die gew"unschte L"ange hat.
+       Der Bereich wird dabei auf jeden Fall aus der Liste ausgetragen.
+       (Wenn der Bereich zu lang sein sollte, dann kann der Aufrufer den
+       Rest wieder mit 'memlist_addrange' in die Liste einh"angen)
+       
+       Return (in Referenzparametern): 
+               *freestart: Anfang des freien Speichers
+               *freelength: L"ange dieses Speicherbereiches
+
+       Wenn kein passender Speicherblock mehr gefunden werden kann, dann 
+       wird in '*freelength' 0 hineingeschrieben.
+       
+******************************************************************************/                
+
+static void memlist_getsuitable (u4 *freestart, u4 *freelength, u4 length)
+{
+       bigmemarea *m;
+       bigmemarea *prevm = NULL;
+       
+       if (length<DIFFERENTSIZES) {
+               u4 firstfreelength;
+
+               if (memlist[length]) {
+                       firstfreelength = length;
+                       }
+               else {
+                       firstfreelength = findnextsetbit 
+                               (memlistbits, DIFFERENTSIZES, length+3); 
+                               /* wenn kein passender Block da ist, dann gleich nach */
+                               /* einem etwas gr"osseren suchen, damit keine kleinen */
+                               /* St"uckchen "ubrigbleiben */
+                       }
+                       
+               if (firstfreelength<DIFFERENTSIZES) {
+                       memarea *m = memlist[firstfreelength];
+                       memlist[firstfreelength] = m->next;             
+                       if (!m->next) clearbit (memlistbits, firstfreelength);
+                       *freestart = ((heapblock*) m) - heap;
+                       *freelength = firstfreelength;
+                       return;
+                       }
+               }
+
+       m = bigmemlist;
+       while (m) {
+               if (m->size >= length) {
+                       if (prevm) prevm->next = m->next;                                       
+                               else   bigmemlist = m->next;
+                       
+                       *freestart = ((heapblock*) m) - heap;
+                       *freelength = m->size;
+                       return ;                        
+                       }
+
+               prevm = m;
+               m = m->next;
+               }
+       
+       *freelength=0;
+}
+
+
+
+
+
+/******************* Funktion: mark *******************************************
+
+       Markiert ein m"oglicherweise g"ultiges Objekt.
+       Sollte sich herausstellen, dass der Zeiger gar nicht auf ein Objekt
+       am Heap zeigt, dann wird eben gar nichts markiert.
+
+******************************************************************************/
+
+static void markreferences (void **rstart, void **rend);
+
+static void mark (heapblock *obj)
+{
+       u4 blocknum,objectend;
+
+       if ((long) obj & (BLOCKSIZE-1)) return;
+       
+       if (obj<heap) return;
+       if (obj>=(heap+topofheap) ) return;
+
+       blocknum = obj-heap;
+       if ( isbitclear(startbits, blocknum) ) return;
+       if ( isbitset(markbits, blocknum) ) return;
+
+       setbit (markbits, blocknum);
+       
+       if ( isbitclear(referencebits, blocknum) ) return;
+
+       objectend = findnextsetbit (startbits, topofheap, blocknum+1);
+       markreferences ((void**)obj, (void**) (heap+objectend) );
+}
+
+
+/******************** Funktion: markreferences ********************************
+
+       Geht einen Speicherbereich durch, und markiert alle Objekte, auf
+       die von diesem Bereich aus irgendeine Referenz existiert.
+
+******************************************************************************/
+
+static void markreferences (void **rstart, void **rend)
+{
+       void **ptr;
+       
+       for (ptr=rstart; ptr<rend; ptr++) mark (*ptr);
+}
+
+
+/******************* Funktion: markstack **************************************
+
+        Marks all objects that are referenced by the (C-)stacks of
+        all live threads.
+
+       (The stack-bottom is to be specified in the call to heap_init).
+
+******************************************************************************/
+
+static void markstack ()                   /* schani */
+{
+       void *dummy;
+       void **top_of_stack = &dummy;
+
+#ifdef USE_THREADS
+       thread *aThread;
+
+       for (aThread = liveThreads; aThread != 0; aThread = CONTEXT(aThread).nextlive) {
+               mark((heapblock*)aThread);
+               if (aThread == currentThread) {
+                       if (top_of_stack > (void**)CONTEXT(aThread).stackEnd)
+                               markreferences ((void**)CONTEXT(aThread).stackEnd, top_of_stack);
+                       else    
+                               markreferences (top_of_stack, (void**)CONTEXT(aThread).stackEnd);
+                       }
+               else {
+                       if (CONTEXT(aThread).usedStackTop > CONTEXT(aThread).stackEnd)
+                               markreferences ((void**)CONTEXT(aThread).stackEnd,
+                                               (void**)CONTEXT(aThread).usedStackTop + 16);
+                       else    
+                               markreferences ((void**)CONTEXT(aThread).usedStackTop - 16,
+                                               (void**)CONTEXT(aThread).stackEnd);
+                       }
+               }
+
+       markreferences((void**)&threadQhead[0], (void**)&threadQhead[MAX_THREAD_PRIO]);
+#else
+       if (top_of_stack > bottom_of_stack)
+               markreferences(bottom_of_stack, top_of_stack);
+       else
+               markreferences(top_of_stack, bottom_of_stack);
+#endif
+}
+
+
+
+/**************** Funktion: searchlivefinalizees *****************************
+
+       geht die Liste aller Objekte durch, die noch finalisiert werden m"ussen
+       (livefinalizees), und tr"agt alle nicht mehr markierten in die
+       Liste deadfinalizess ein (allerdings werden sie vorher noch als
+       erreicht markiert, damit sie nicht jetzt gleich gel"oscht werden).
+       
+*****************************************************************************/ 
+
+static void searchlivefinalizees ()
+{
+       finalizernode *fn = livefinalizees;
+       finalizernode *lastlive = NULL;
+               
+       while (fn) {
+       
+               /* alle zu finalisierenden Objekte, die nicht mehr markiert sind: */
+               if (isbitclear (markbits, fn->objstart)) {
+                       finalizernode *nextfn = fn->next;
+
+                       mark (heap + fn->objstart); 
+
+                       if (lastlive) lastlive -> next = nextfn;
+                                      else livefinalizees = nextfn;
+
+                       fn -> next = deadfinalizees;
+                       deadfinalizees = fn;
+                       
+                       fn = nextfn;
+                       }
+               else {  
+                       lastlive = fn;
+                       fn = fn->next;
+                       }
+               }
+}
+
+
+
+/********************** Funktion: finalizedead *******************************
+
+       ruft die 'finalize'-Methode aller Objekte in der 'deadfinalizees'-
+       Liste auf.
+       Achtung: Es kann hier eventuell zu neuerlichen Speicheranforderungen
+       (mit potentiell notwendigem GC) kommen, deshalb m"ussen manche
+       globalen Variablen in lokale Variblen kopiert werden 
+       (Reentrant-F"ahigkeit!!!)
+        
+******************************************************************************/
+
+static void finalizedead()
+{
+       finalizernode *fn = deadfinalizees;
+       deadfinalizees = NULL;
+       
+       while (fn) {
+               finalizernode *nextfn = fn->next;
+               
+               asm_calljavamethod (fn->finalizer, heap+fn->objstart, NULL,NULL,NULL);
+               FREE (fn, finalizernode);
+               
+               fn = nextfn;
+               }
+
+}
+
+
+
+/****************** Funktion: heap_docollect **********************************
+       
+       F"uhrt eine vollst"andige Garbage Collection durch
+       
+******************************************************************************/
+
+static void heap_docollect ()
+{
+       u4 freestart,freeend;
+       void **p;
+       bitfieldtype *dummy;
+       u4 heapfreemem;
+       u4 oldfillgrade;
+
+
+       if (runverbose) {
+               fprintf(stderr, "doing garbage collection\n");
+               }
+               /* alle Markierungsbits l"oschen */
+       clearbitfield (markbits, topofheap);
+
+               /* Alle vom Stack referenzierten Objekte markieren */
+       asm_dumpregistersandcall (markstack);
+
+               /* Alle von globalen Variablen erreichbaren Objekte markieren */
+       p = chain_first (allglobalreferences);
+       while (p) {
+               mark (*p);
+               p = chain_next (allglobalreferences);   
+               }
+
+               /* alle Objekte durchsehen, die eine finalizer-Methode haben */
+       searchlivefinalizees();
+
+               /* alle Reference-Bits l"oschen, deren Objekte nicht */
+               /* mehr erreichbar sind */
+       maskfieldwithfield (referencebits, markbits, topofheap);
+
+
+               /* Freispeicherliste initialisieren */
+       memlist_init ();
+       
+       
+               /* Heap schrittweise durchgehen, und alle freien Bl"ocke merken */
+
+       heapfreemem = 0;
+       freeend=0;
+       for (;;) {
+                       /* Anfang des n"achsten freien Bereiches suchen */
+               freestart = findnextcombination_set_unset 
+                       (startbits, markbits, topofheap, freeend);
+
+                       /* Wenn es keinen freien Bereich mehr gibt -> fertig */
+               if (freestart>=topofheap) goto freememfinished;
+
+                       /* Anfang des freien Bereiches markieren */
+               setbit (markbits, freestart);
+
+                       /* Ende des freien Bereiches suchen */          
+               freeend = findnextsetbit (markbits, topofheap, freestart+1);
+
+                       /* Freien Bereich in Freispeicherliste einh"angen */
+               memlist_addrange (freestart, freeend-freestart);
+
+                       /* Menge des freien Speichers mitnotieren */
+               heapfreemem += (freeend-freestart);
+               }
+
+       freememfinished:
+
+               /* Die Rollen von markbits und startbits vertauschen */ 
+       dummy = markbits;
+       markbits = startbits;
+       startbits = dummy;
+
+
+               /* Threashold-Wert f"ur n"achstes Collect */
+       oldfillgrade = heapfillgrade;
+       heapfillgrade = topofheap - heapfreemem;
+       collectthreashold = heapfillgrade*3;   /* eine nette Heuristik */
+
+               /* Eventuell eine Meldung ausgeben */
+       if (collectverbose) {
+               sprintf (logtext, "Garbage Collection:  previous/now = %d / %d ",
+                 (int) (oldfillgrade * BLOCKSIZE), 
+                 (int) (heapfillgrade * BLOCKSIZE) );
+               dolog ();
+               }
+
+
+               
+               /* alle gerade unerreichbar gewordenen Objekte mit 
+                  finalize-Methoden jetzt finalisieren.
+                  Achtung: Diese Funktion kann zu neuerlichem GC f"uhren!! */
+       finalizedead ();
+       
+}
+
+/************************* Function: gc_init **********************************
+
+        Initializes the garbage collection thread mechanism.
+
+******************************************************************************/
+
+#ifdef USE_THREADS
+iMux gcStartMutex;
+iMux gcThreadMutex;
+iCv gcConditionStart;
+iCv gcConditionDone;
+
+void
+gc_init (void)
+{
+    gcStartMutex.holder = 0;
+    gcStartMutex.count = 0;
+    gcStartMutex.muxWaiters = 0;
+
+    gcThreadMutex.holder = 0;
+    gcThreadMutex.count = 0;
+    gcThreadMutex.muxWaiters = 0;
+
+    gcConditionStart.cvWaiters = 0;
+    gcConditionStart.mux = 0;
+
+    gcConditionDone.cvWaiters = 0;
+    gcConditionDone.mux = 0;
+}    
+#else
+void
+gc_init (void)
+{
+}
+#endif
+
+/************************* Function: gc_thread ********************************
+
+        In an endless loop waits for a condition to be posted, then
+       garbage collects the heap.
+
+******************************************************************************/
+
+#ifdef USE_THREADS
+void
+gc_thread (void)
+{
+    intsRestore();           /* all threads start with interrupts disabled */
+
+       assert(blockInts == 0);
+
+    lock_mutex(&gcThreadMutex);
+
+    for (;;)
+    {
+               wait_cond(&gcThreadMutex, &gcConditionStart, 0);
+
+               intsDisable();
+               heap_docollect();
+               intsRestore();
+
+               signal_cond(&gcConditionDone);
+    }
+}
+#endif
+
+void
+gc_call (void)
+{
+#ifdef USE_THREADS
+    lock_mutex(&gcThreadMutex);
+
+    signal_cond(&gcConditionStart);
+    wait_cond(&gcThreadMutex, &gcConditionDone, 0);
+
+    unlock_mutex(&gcThreadMutex);
+#else
+    heap_docollect();
+#endif
+}
+
+
+/************************* Funktion: heap_init ********************************
+
+       Initialisiert den Garbage Collector.
+       Parameter: 
+               heapbytesize:      Maximale Gr"osse des Heap (in Bytes)
+               heapbytestartsize: Gr"osse des Heaps, bei dem zum ersten mal eine
+                                  GC durchgef"uhrt werden soll.
+               stackbottom:       Ein Zeiger auf die Untergrenze des Stacks, im dem
+                              Referenzen auf Objekte stehen k"onnen.                  
+                                          
+******************************************************************************/
+
+void heap_init (u4 heapbytesize, u4 heapbytestartsize, void **stackbottom)
+{
+
+#ifdef TRACECALLARGS
+
+       heapsize = ALIGN (heapbytesize, getpagesize());
+       heapsize = heapsize/BLOCKSIZE;
+       heap = (void*) mmap ((void*) 0x10000000, (size_t) (heapsize * BLOCKSIZE),
+              PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, (off_t) 0);
+       if (heap != (void *) 0x10000000) {
+               perror("mmap");
+               printf("address = %p\n", heap);
+               panic("mmap failed\n");
+               }
+
+#else
+
+       heapsize = ALIGN (heapbytesize, 1024);
+       heapsize = heapsize/BLOCKSIZE;
+       heap = MNEW (heapblock, heapsize);
+
+#endif
+
+       topofheap = 0;
+       startbits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
+       markbits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
+       referencebits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
+       clearbitfield (startbits, heapsize);
+       clearbitfield (markbits, heapsize);
+       clearbitfield (referencebits, heapsize);
+
+       heapfillgrade = 0;
+       collectthreashold = heapbytestartsize/BLOCKSIZE;
+       allglobalreferences = chain_new ();
+       bottom_of_stack = stackbottom;
+
+       livefinalizees = NULL;
+       deadfinalizees = NULL;
+}
+
+
+/****************** Funktion: heap_close **************************************
+
+       Gibt allen ben"otigten Speicher frei
+
+******************************************************************************/
+
+void heap_close ()
+{
+#ifndef TRACECALLARGS
+       MFREE (heap, heapblock, heapsize); */
+#endif
+       MFREE (startbits, bitfieldtype, heapsize/BITFIELDBITS);
+       MFREE (markbits, bitfieldtype, heapsize/BITFIELDBITS);
+       MFREE (referencebits, bitfieldtype, heapsize/BITFIELDBITS);
+       chain_free (allglobalreferences);
+
+       while (livefinalizees) {
+               finalizernode *n = livefinalizees->next;
+               FREE (livefinalizees, finalizernode);
+               livefinalizees = n;
+               }
+}
+
+
+/***************** Funktion: heap_addreference ********************************
+
+       Teilt dem GC eine Speicherstelle mit, an der eine globale Referenz
+       auf Objekte gespeichert sein kann.
+
+******************************************************************************/
+
+void heap_addreference (void **reflocation)
+{
+       intsDisable();                     /* schani */
+
+       chain_addlast (allglobalreferences, reflocation);
+
+       intsRestore();                    /* schani */
+}
+
+
+
+/***************** Funktion: heap_allocate ************************************
+
+       Fordert einen Speicher vom Heap an, der eine gew"unschte Gr"osse
+       (in Byte angegeben) haben muss.
+       Wenn kein Speicher mehr vorhanden ist (auch nicht nach einem
+       Garbage Collection-Durchlauf), dann wird NULL zur"uckgegeben.
+       Zus"atzlich wird durch den Parameter 'references' angegeben, ob
+       in das angelegte Objekt Referenzen auf andere Objekte eingetragen
+       werden k"onnten. 
+       (Wichtig wegen Beschleunigung des Mark&Sweep-Durchlauf)
+       Im Zweifelsfalle immer references=true verwenden.
+
+******************************************************************************/
+
+void *heap_allocate (u4 bytelength, bool references, methodinfo *finalizer)
+{
+       u4 freestart,freelength;
+       u4 length = ALIGN(bytelength, BLOCKSIZE) / BLOCKSIZE;
+       
+       intsDisable();                        /* schani */
+
+       memlist_getsuitable (&freestart, &freelength, length);
+
+       if (!freelength) {
+               if ( (topofheap+length > collectthreashold) || (topofheap+length > heapsize) ) {
+                       intsRestore();
+                       gc_call();
+                       intsDisable();
+
+                       memlist_getsuitable (&freestart, &freelength, length);
+                       if (freelength) 
+                               goto have_block; /* phil */
+               }
+               
+               if (topofheap+length > heapsize) {
+                       sprintf (logtext, "Heap-Allocation failed for %d bytes", 
+                                        (int) bytelength);
+                       dolog();
+                       intsRestore();            /* schani */
+                       return NULL;
+               }
+                       
+               freestart = topofheap;
+               freelength = length;
+               setbit (startbits, topofheap);
+               topofheap += length;
+       }
+
+ have_block:
+       if (freelength>length) {
+               setbit (startbits, freestart+length);
+               memlist_addrange (freestart+length, freelength-length);
+       }
+               
+       if (references) 
+               setbit (referencebits, freestart);
+
+       setbit (startbits, freestart);  /* phil */
+
+       heapfillgrade += length;
+
+       if (finalizer) {
+               finalizernode *n = NEW(finalizernode);
+               n -> next = livefinalizees;
+               n -> objstart = freestart;
+               n -> finalizer = finalizer;
+               livefinalizees = n;
+       }
+       
+       intsRestore();                   /* schani */
+
+       if (runverbose) {
+               sprintf (logtext, "new returns: %lx", (long) (heap + freestart));
+               dolog ();
+       }
+
+       return (void*) (heap + freestart);
+}
index e92f7f1164e62e6343d1ac78a25d420017962c36..efcd477d80aa7d061183454c3f4eb0d38f1cdf75 100644 (file)
@@ -117,18 +117,18 @@ typedef u1* methodptr;
 /********************** data structures of UNICODE symbol *********************/
 
 struct unicode {
-       unicode   *hashlink; /* externe Verkettung f"ur die unicode-Hashtabelle */
-       u4         key;      /* Hash-Schl"ussel (h"angt nur vom Text ab) */
-       int        length;   /* L"ange des Textes */           
-       u2        *text;     /* Zeiger auf den Text (jeder Buchstabe 16 Bit) */
-       classinfo *class;    /* gegebenenfalls Referenz auf die Klasse dieses 
-                               Namens (oder NULL, wenn es keine solche gibt)  */
-       struct java_objectheader *string;
-                            /* gegebenenfalls Referenz auf einen konstanten
-                               String mit dem entsprechenden Wert */ 
-       };
-
-       /* Alle Unicode-Symbole werden in einer einzigen globalen Tabelle 
+  unicode   *hashlink; /* externe Verkettung f"ur die unicode-Hashtabelle */
+  u4         key;      /* Hash-Schl"ussel (h"angt nur vom Text ab) */
+  int        length;   /* L"ange des Textes */           
+  u2        *text;     /* Zeiger auf den Text (jeder Buchstabe 16 Bit) */
+  classinfo *class;    /* gegebenenfalls Referenz auf die Klasse dieses 
+                         Namens (oder NULL, wenn es keine solche gibt)  */
+  struct java_objectheader *string;
+  /* gegebenenfalls Referenz auf einen konstanten
+     String mit dem entsprechenden Wert */ 
+};
+
+/* Alle Unicode-Symbole werden in einer einzigen globalen Tabelle 
           (Hashtabelle) verwaltet, jedes Symbol wird nur einmal angelegt.
           -> Speicherersparnis, und "Uberpr"ufung auf Gleichheit durch einfachen
           Zeigervergleich */
@@ -138,42 +138,42 @@ struct unicode {
 
 
 typedef struct {
-       classinfo *class;
-       unicode   *name;
-       unicode   *descriptor;
-       } constant_FMIref;
+  classinfo *class;
+  unicode   *name;
+  unicode   *descriptor;
+} constant_FMIref;
 
 
 typedef struct {
-       s4 value;
-       } constant_integer;
+  s4 value;
+} constant_integer;
        
 typedef struct {
-       float value;
-       } constant_float;
+  float value;
+} constant_float;
 
 typedef struct {
-       s8 value;
-       } constant_long;
+  s8 value;
+} constant_long;
        
 typedef struct {
-       double value;
-       } constant_double;
+  double value;
+} constant_double;
 
 
 typedef struct {
-       unicode *name;
-       unicode *descriptor;
-       } constant_nameandtype;
+  unicode *name;
+  unicode *descriptor;
+} constant_nameandtype;
 
 
 typedef struct constant_arraydescriptor {
-       int arraytype;
-       classinfo *objectclass;
-       struct constant_arraydescriptor *elementdescriptor;
-       } constant_arraydescriptor;
+  int arraytype;
+  classinfo *objectclass;
+  struct constant_arraydescriptor *elementdescriptor;
+} constant_arraydescriptor;
 
-       /* Mit einem Arraydescriptor kann ein Array-Typ dargestellt werden.
+/* Mit einem Arraydescriptor kann ein Array-Typ dargestellt werden.
           Bei normalen Arrays (z.B. Array von Bytes,...) gen"ugt dazu,
        dass das Feld arraytype die entsprechende Kennzahl enth"alt
        (z.B. ARRAYTYPE_BYTE).
@@ -229,12 +229,12 @@ typedef struct constant_arraydescriptor {
        */
 
 typedef struct java_objectheader {    /* Der Header f"ur alle Objekte */
-       vftbl *vftbl;                     /* Zeiger auf die Function Table */
+  vftbl *vftbl;                     /* Zeiger auf die Function Table */
 } java_objectheader;
 
 
 
-       /********* Arrays ***********
+/********* Arrays ***********
        
        Alle Arrays in Java sind auch gleichzeitig Objekte (d.h. sie haben auch
        den obligatorischen Object-Header und darin einen Verweis auf eine Klasse)
@@ -255,78 +255,78 @@ typedef struct java_objectheader {    /* Der Header f"ur alle Objekte */
 #define ARRAYTYPE_ARRAY    9
 
 
-       /** Der Header f"ur ein Java-Array **/
+/** Der Header f"ur ein Java-Array **/
 
 typedef struct java_arrayheader {  /* Der Arrayheader f"ur alle Arrays */
-       java_objectheader objheader;       /* Der Object-Header */
-       s4 size;                           /* Gr"osse des Arrays */
-       s4 arraytype;                      /* Typ der Elemente */
+  java_objectheader objheader;       /* Der Object-Header */
+  s4 size;                           /* Gr"osse des Arrays */
+  s4 arraytype;                      /* Typ der Elemente */
 } java_arrayheader;
 
 
 
-       /** Die Unterschiedlichen Strukturen f"ur alle Typen von Arrays **/
+/** Die Unterschiedlichen Strukturen f"ur alle Typen von Arrays **/
 
 typedef struct java_chararray {
-       java_arrayheader header;
-       u2 data[1];
+  java_arrayheader header;
+  u2 data[1];
 } java_chararray;
 
 typedef struct java_floatheader {
-       java_arrayheader header;
-       float data[1];
+  java_arrayheader header;
+  float data[1];
 } java_floatarray;
 
 typedef struct java_doublearray {
-       java_arrayheader header;
-       double data[1];
+  java_arrayheader header;
+  double data[1];
 } java_doublearray;
 
 
-   /* achtung: die beiden Stukturen booleanarray und bytearray m"ussen 
+/* achtung: die beiden Stukturen booleanarray und bytearray m"ussen 
       identisches memory-layout haben, weil mit den selben Funktionen 
       darauf zugegriffen wird */
 
 typedef struct java_booleanarray {
-       java_arrayheader header;
-       u1 data[1];
+  java_arrayheader header;
+  u1 data[1];
 } java_booleanarray;
 
 typedef struct java_bytearray {
-       java_arrayheader header;
-       s1 data[1];
+  java_arrayheader header;
+  s1 data[1];
 } java_bytearray;
 
 typedef struct java_shortarray {
-       java_arrayheader header;
-       s2 data[1];
+  java_arrayheader header;
+  s2 data[1];
 } java_shortarray;
 
 typedef struct java_intarray {
-       java_arrayheader header;
-       s4 data[1];
+  java_arrayheader header;
+  s4 data[1];
 } java_intarray;
 
 typedef struct java_longarray {
-       java_arrayheader header;
-       s8 data[1];
+  java_arrayheader header;
+  s8 data[1];
 } java_longarray;
 
 
-       /* ACHTUNG: die beiden folgenden Strukturen m"ussen unbedingt gleiches
+/* ACHTUNG: die beiden folgenden Strukturen m"ussen unbedingt gleiches
           Memory-Layout haben, weil mit ein und der selben Funktion auf die
           data-Eintr"age beider Typen zugegriffen wird !!!! */
 
 typedef struct java_objectarray {
-       java_arrayheader header;
-       classinfo *elementtype;
-       java_objectheader *data[1];
+  java_arrayheader header;
+  classinfo *elementtype;
+  java_objectheader *data[1];
 } java_objectarray;
 
 typedef struct java_arrayarray {
-       java_arrayheader header;
-       constant_arraydescriptor *elementdescriptor;
-       java_arrayheader *data[1];
+  java_arrayheader header;
+  constant_arraydescriptor *elementdescriptor;
+  java_arrayheader *data[1];
 } java_arrayarray;
 
 
@@ -338,119 +338,120 @@ typedef struct java_arrayarray {
     /*** Struktur: fieldinfo ***/
 
 typedef struct fieldinfo {   /* Struktur f"ur ein Feld einer Klasse */
-       s4       flags;              /* die ACC-Flags */
-       s4       type;               /* Grunddatentyp */
-       unicode *name;               /* Name des Felds */
-       unicode *descriptor;         /* Typedescriptor in JavaVM-Form */
+  s4       flags;              /* die ACC-Flags */
+  s4       type;               /* Grunddatentyp */
+  unicode *name;               /* Name des Felds */
+  unicode *descriptor;         /* Typedescriptor in JavaVM-Form */
        
-       s4       offset;             /* Offset vom Anfang des Objektes */
-                                    /* (bei Instanzvariablen) */
-
-       union {                      /* Speicher f"ur den Wert */
-               s4 i;                    /* (bei Klassenvariablen) */    
-               s8 l;
-               float f;
-               double d;
-               void *a; 
-               } value;
+  s4       offset;             /* Offset vom Anfang des Objektes */
+  /* (bei Instanzvariablen) */
+
+  union {                      /* Speicher f"ur den Wert */
+    s4 i;                    /* (bei Klassenvariablen) */    
+    s8 l;
+    float f;
+    double d;
+    void *a; 
+  } value;
                
-       } fieldinfo;
+} fieldinfo;
 
 
-    /*** Struktur: exceptiontable ***/
+/*** Struktur: exceptiontable ***/
 
 typedef struct exceptiontable {  /* Exceptionhandler-Eintrag in einer Methode */ 
-       s4         startpc;            /* Anfang des G"ultigkeitsbereichs */
-       s4         endpc;              /* Ende des Bereichs (exklusive) */
-       s4         handlerpc;          /* JavaVM-Position des Handlers */
-       classinfo *catchtype;          /* Typ der behandelten Exceptions (oder 
-                                       NULL, wenn alle behandelt werden sollen) */
-       } exceptiontable;
+  s4         startpc;            /* Anfang des G"ultigkeitsbereichs */
+  s4         endpc;              /* Ende des Bereichs (exklusive) */
+  s4         handlerpc;          /* JavaVM-Position des Handlers */
+  classinfo *catchtype;          /* Typ der behandelten Exceptions (oder 
+                                   NULL, wenn alle behandelt werden sollen) */
+} exceptiontable;
 
 
 
-    /*** Struktur: methodinfo ***/
+/*** Struktur: methodinfo ***/
 
 typedef struct methodinfo {  /* Struktur f"ur eine Methode einer Klasse */
-       s4             flags;            /* die ACC-Flags */
-       unicode   *name;             /* Name der Methode */
-       unicode   *descriptor;       /* der JavaVM-Descriptorstring f"ur Methoden */
-       s4        returntype;        /* only temporary valid, return type */
-       s4        paramcount;        /* only temporary valid, number of parameters */
-       u1        *paramtypes;       /* only temporary valid, parameter types */
-       classinfo *class;            /* Die Klasse, der die Methode geh"ort */
-       u4         vftblindex;       /* Index dieser Methode f"ur die Virtual
-                                       Function Table (wenn es keine statische
-                                       Methode ist) */
-
-       s4       maxstack;                  /* maximale Stacktiefe des JavaVM-Codes */
-       s4   maxlocals;                 /* maximale Anzahl der JavaVM-Variablen */
-       u4   jcodelength;               /* L"ange des JavaVM-Codes */
-       u1  *jcode;                     /* und Zeiger auf den JavaVM-Code */
-
-       s4   exceptiontablelength;      /* L"ange der Exceptintable */
-       exceptiontable *exceptiontable; /* Die Exceptiontable selber */
-
-       u1  *stubroutine;               /* STUB-Routine for compiling or calling 
-                                          natives */   
-       u4   mcodelength;               /* L"ange des generierten Maschinencodes */
-       u1  *mcode;                     /* Zeiger auf den Maschinencode */
-       u1  *entrypoint;                /* Entrypoint to the Maschine-Code */
-
-       
-       } methodinfo;
-
-
-    /*** Struktur: classinfo ***/
+  s4          flags;            /* die ACC-Flags */
+  unicode   *name;             /* Name der Methode */
+  unicode   *descriptor;       /* der JavaVM-Descriptorstring f"ur Methoden */
+  s4        returntype;        /* only temporary valid, return type */
+  s4        paramcount;        /* only temporary valid, number of parameters */
+  u1        *paramtypes;       /* only temporary valid, parameter types */
+  classinfo *class;            /* Die Klasse, der die Methode geh"ort */
+  u4         vftblindex;       /* Index dieser Methode f"ur die Virtual
+                                 Function Table (wenn es keine statische
+                                 Methode ist) */
+
+  s4    maxstack;                  /* maximale Stacktiefe des JavaVM-Codes */
+  s4   maxlocals;                 /* maximale Anzahl der JavaVM-Variablen */
+  u4   jcodelength;               /* L"ange des JavaVM-Codes */
+  u1  *jcode;                     /* und Zeiger auf den JavaVM-Code */
+
+  s4   exceptiontablelength;      /* L"ange der Exceptintable */
+  exceptiontable *exceptiontable; /* Die Exceptiontable selber */
+
+  u1  *stubroutine;               /* STUB-Routine for compiling or calling 
+                                    natives */ 
+  u4   mcodelength;               /* L"ange des generierten Maschinencodes */
+  u1  *mcode;                     /* Zeiger auf den Maschinencode */
+  u1  *entrypoint;                /* Entrypoint to the Maschine-Code */        
+} methodinfo;
+
+
+/*** Struktur: classinfo ***/
 
 struct classinfo {           /* Datenstruktur f"ur eine Klasse */
-       java_objectheader header;     /* Weil auch Klassen als Objekte angesprochen 
-                                        werden */
+  java_objectheader header;     /* Weil auch Klassen als Objekte angesprochen 
+                                  werden */
 
-       s4 flags;                     /* Die ACC-Flags */
-       unicode *name;                /* Name der Klasse */ 
+  s4 flags;                     /* Die ACC-Flags */
+  unicode *name;                /* Name der Klasse */ 
        
-       s4       cpcount;             /* Anzahl der Eintr"age im Constant-Pool */
-       u1      *cptags;              /* Die TAGs f"ur den Constant-Pool */
-       voidptr *cpinfos;             /* Die Zeiger auf die Info-Strukturen */
+  s4       cpcount;             /* Anzahl der Eintr"age im Constant-Pool */
+  u1      *cptags;              /* Die TAGs f"ur den Constant-Pool */
+  voidptr *cpinfos;             /* Die Zeiger auf die Info-Strukturen */
        
-       classinfo *super;             /* Zeiger auf die "ubergeordnete Klasse */
+  classinfo *super;             /* Zeiger auf die "ubergeordnete Klasse */
        
-       s4          interfacescount;  /* Anzahl der Interfaces */
-       classinfo **interfaces;       /* Zeiger auf die Interfaces */
+  s4          interfacescount;  /* Anzahl der Interfaces */
+  classinfo **interfaces;       /* Zeiger auf die Interfaces */
        
-       s4          fieldscount;      /* Anzahl der Felder */
-       fieldinfo  *fields;           /* Die Tabelle der Felder */
+  s4          fieldscount;      /* Anzahl der Felder */
+  fieldinfo  *fields;           /* Die Tabelle der Felder */
        
-       s4          methodscount;     /* Anzahl der Methoden */
-       methodinfo *methods;          /* Die Tabelle der Methoden */
+  s4          methodscount;     /* Anzahl der Methoden */
+  methodinfo *methods;          /* Die Tabelle der Methoden */
        
        
-       listnode    listnode;         /* Verkettungsstruktur (f"ur Listen) */
+  listnode    listnode;         /* Verkettungsstruktur (f"ur Listen) */
 
-       bool        initialized;      /* true, wenn Klasse bereits Initialisiert */ 
-       bool        linked;           /* wird von `class_link` auf true gesetzt */
-       s4                      index;            /* Hierarchietiefe  (bei normalen Klassen)  
-                                        oder fortlaufende Nummer (bei Interfaces)*/ 
-       u4          instancesize;     /* Gr"osse eines Objektes dieser Klasse */
+  bool        initialized;      /* true, wenn Klasse bereits Initialisiert */ 
+  bool        linked;           /* wird von `class_link` auf true gesetzt */
+  s4                   index;            /* Hierarchietiefe  (bei normalen Klassen)  
+                                            oder fortlaufende Nummer (bei Interfaces)*/ 
+  u4          instancesize;     /* Gr"osse eines Objektes dieser Klasse */
 
-       vftbl       *vftbl;
+  vftbl       *vftbl;
 
-       methodinfo *finalizer;        /* Finalizer-Methode f"ur die Klasse */
-       };
+  methodinfo* finalizer;        /* Finalizer-Methode f"ur die Klasse */
+#ifdef JIT_MARKER_SUPPORT
+  methodinfo* marker; 
+#endif
+};
        
 
 struct vftbl {
-       classinfo  *class;            /* Class, the function table belongs to */
+  classinfo  *class;            /* Class, the function table belongs to */
 
-       s4          vftbllength;      /* L"aenge der Virtual Function Table */
+  s4          vftbllength;      /* L"aenge der Virtual Function Table */
 
-       s4          interfacetablelength;   /* L"ange der Interfacetable */   
-       u4         *interfacevftbllength;   /* -> siehe unten */   
-       methodptr **interfacevftbl;
+  s4          interfacetablelength;   /* L"ange der Interfacetable */   
+  u4         *interfacevftbllength;   /* -> siehe unten */   
+  methodptr **interfacevftbl;
        
-       methodptr   table[1];
-       };
+  methodptr   table[1];
+};
 
 /*********** Anmerkungen zur Interfacetable: 
 
@@ -540,3 +541,17 @@ extern int count_vmcode_len;
 extern int count_extable_len;
 
 #endif
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
index 927ccd161ca3f37076a269a18c350a3d8cee0a22..a9d2136250be9a0ed75c5560c3dcc28c5a1bf294 100644 (file)
@@ -14,6 +14,8 @@
 
 *******************************************************************************/
 
+#include "global.h"
+
 int has_no_x_instr_set();
        /* determines if the byte support instruction set (21164a and higher)
           is available. */
index 6cd6ee8c1863ed505729658b05bea639b8145aa4..48103bee3b6b5db2d5ac74854066bb4730bbe21f 100644 (file)
@@ -27,7 +27,6 @@
 #include "asmpart.h"
 #include "callargs.h"
 
-#include "sysdep/threads.h"
 #include "threads/thread.h"                  /* schani */
 #include "threads/locks.h"
 
@@ -675,853 +674,3 @@ u2 desc_typesize (unicode *descriptor)
 
 
 
-
-/******************************************************************************
-********************* Der garbage-collected Heap ******************************
-*******************************************************************************
-
-       verwaltet einen Heap mit automatischer Speicherfreigabe.
-
-       (eine ausf"uhrliche Dokumentation findet sich in der Datei: 
-       collect.doc)
-       
-******************************************************************************/
-
-
-bool collectverbose = false;  /* soll Meldung beim GC ausgegeben werden? */
-
-
-#define BLOCKSIZE 8         /* Gr"osse eines Speicherblockes */
-typedef u8 heapblock;       /* Datentyp mit der Gr"osse eines Speicherblocks */
-
-#if U8_AVAILABLE && SUPPORT_LONG
-#define        bitfieldtype u8
-#define BITFIELDBITS 64
-#else
-#define bitfieldtype u4
-#define BITFIELDBITS 32
-#endif
-
-u4 heapsize;                /* Gr"osse des Heap in Blocks */
-u4 topofheap;               /* Bisherige Obergrenze Heaps */
-heapblock *heap;            /* Speicher f"ur den Heap selbst */
-
-bitfieldtype *startbits;     /* Bitfeld f"ur Bereichsstartkennung */
-bitfieldtype *markbits;      /* Bitfeld f"ur Markierung */
-bitfieldtype *referencebits; /* Bitfeld f"ur Folgereferenzenkennung */
-
-u4 heapfillgrade;           /* Menge der Daten im Heap */
-u4 collectthreashold;       /* Schwellwert f"ur n"achstes GC */
-
-void **bottom_of_stack;     /* Zeiger auf Untergrenze des C-Stacks */ 
-chain *allglobalreferences; /* Liste f"ur alle globalen Zeiger */
-
-typedef struct finalizernode {
-       struct finalizernode *next;     
-       u4 objstart;
-       methodinfo *finalizer;
-       } finalizernode;
-       
-finalizernode *livefinalizees;
-finalizernode *deadfinalizees;
-
-
-typedef struct memarea {    /* Datenstruktur f"ur einen Freispeicherbereich */
-       struct memarea *next;
-       } memarea;
-
-typedef struct bigmemarea {   /* Datenstruktur f"ur einen */
-       struct bigmemarea *next;  /* Freispeicherbereich variabler L"ange */
-       u4 size;
-       } bigmemarea;
-       
-#define DIFFERENTSIZES 128         /* Anzahl der 'kleinen' Freispeicherlisten */
-memarea *memlist[DIFFERENTSIZES];  /* Die 'kleinen' Freispeicherlisten */
-bitfieldtype memlistbits[DIFFERENTSIZES/BITFIELDBITS]; 
-                                   /* Bitfeld, in dem jeweils ein Bit gesetzt */
-                                   /* ist, wenn eine Liste noch etwas enth"alt */
-
-bigmemarea *bigmemlist;         /* Liste der gr"osseren Freispeicherbereiche */
-
-
-
-
-/**************** Hilfsfunktion: lowest **************************************
-
-liefert als Ergebnis die Nummer des niederwertigsten Bits einer 
-Zahl vom Typ bitfieldtype, das 1 ist.
-Wenn die ganze Zahl keine 1en enth"alt, dann ist egal, was f"ur einen
-Wert die Funktion l"iefert.
-z.B.: lowest(1) = 0,   lowest(12) = 2,   lowest(1024) = 10
-
-*****************************************************************************/
-
-static u1 lowesttable[256] = {
-       255, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-       5,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-       6,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-       5,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-       7,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-       5,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-       6,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-       5,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 };
-       
-static int lowest(bitfieldtype i)
-{
-#if BITFIELDBITS==64
-       u8 i1 = i<<32;
-       if (i1) {
-               u8 i11 = i1<<16;
-               if (i11) {
-                       u8 i111 = i11<<8;
-                       if (i111) return lowesttable[i111>>56];
-                       else      return 8+lowesttable[i11>>56];
-                       }
-               else {
-                       u8 i112 = i1<<8;
-                       if (i112) return 16+lowesttable[i112>>56];
-                       else      return 24+lowesttable[i1>>56];
-                       }
-               }
-       else {
-               u8 i12 = i<<16;
-               if (i12) {
-                       u8 i121 = i12<<8;
-                       if (i121) return 32+lowesttable[i121>>56];
-                       else      return 40+lowesttable[i12>>56];
-                       }
-               else {
-                       u8 i122 = i<<8;
-                       if (i122) return 48+lowesttable[i122>>56];
-                       else      return 56+lowesttable[i>>56];
-                       }
-               }
-#else
-       u4 i1 = i<<16;
-       if (i1) {
-               u4 i11 = i1<<8;
-               if (i11) return lowesttable[i11>>24];
-               else     return 8+lowesttable[i1>>24];
-               }
-       else {
-               u4 i12 = i<<8;
-               if (i12) return 16+lowesttable[i12>>24];
-               else     return 24+lowesttable[i>>24];
-               }
-#endif
-}
-
-
-/******** Funktionen zum Setzen und L"oschen von Bits in Bitfeldern ***********/
-
-static void setbit(bitfieldtype *bitfield, u4 bitnumber)
-{
-       bitfield[bitnumber/BITFIELDBITS] |= 
-         ((bitfieldtype) 1) << (bitnumber%BITFIELDBITS);
-}
-
-static void clearbit(bitfieldtype *bitfield, u4 bitnumber)
-{
-       bitfield[bitnumber/BITFIELDBITS] &= 
-          ~((bitfieldtype) 1) << (bitnumber%BITFIELDBITS);
-}
-
-static bool isbitset(bitfieldtype *bitfield, u4 bitnumber)
-{
-       return ( bitfield[bitnumber/BITFIELDBITS] & 
-          ( ((bitfieldtype) 1) << (bitnumber%BITFIELDBITS) ) ) != 0;
-}
-
-static bool isbitclear(bitfieldtype *bitfield, u4 bitnumber)
-{
-       return ( bitfield[bitnumber/BITFIELDBITS] & 
-           ( ((bitfieldtype) 1) << (bitnumber%BITFIELDBITS) ) ) == 0;
-}
-
-
-/***************** Funktion: clearbitfield ************************************
-       
-       l"oscht ein ganzes Bitfeld
-       
-******************************************************************************/
-
-static void clearbitfield(bitfieldtype *bitfield, u4 fieldsize)
-{ 
-       u4 i,t;
-       t = ALIGN(fieldsize, BITFIELDBITS) / BITFIELDBITS;
-       for (i=0; i<t; i++) bitfield[i] = 0;
-}
-
-/************** Funktion: maskfieldwithfield **********************************
-       
-       Verkn"upft zwei Bitfelder bitweise mit UND, das erste Bitfeld
-       wird mit dem Ergebnis "uberschrieben 
-       
-******************************************************************************/
-       
-static void maskfieldwithfield (bitfieldtype* bitfield, 
-                                bitfieldtype *maskfield, u4 fieldsize)
-{
-       u4 i,t;
-       t = ALIGN(fieldsize, BITFIELDBITS) / BITFIELDBITS;
-       for (i=0; i<t; i++) bitfield[i] &= maskfield[i];
-}
-
-
-/************** Funktion: findnextsetbit **************************************
-
-       Sucht in einem Bitfeld ab einer Stelle das n"achste gesetzte Bit
-       und liefert die Nummer dieses Bits.
-       Wenn kein Bit mehr zwischen 'bitnumber' und 'fieldsize' gesetzt
-       ist, dann wird fieldsize zur"uckgeliefte.
-
-******************************************************************************/
-
-static u4 findnextsetbit(bitfieldtype* bitfield, u4 fieldsize, u4 bitnumber)
-{
-       bitfieldtype pattern;
-
-       for (;;) {
-               if (bitnumber >= fieldsize) return fieldsize;
-               
-               pattern = bitfield[bitnumber/BITFIELDBITS];
-               pattern >>= (bitnumber%BITFIELDBITS);
-               if (pattern) return bitnumber + lowest(pattern);
-
-               bitnumber = ((bitnumber + BITFIELDBITS) / BITFIELDBITS) * BITFIELDBITS;
-               }
-}
-
-
-/************ Funktion: findnextcombination_set_unset *************************
-
-       funktioniert wie findnextsetbit, allerdings sucht diese Funktion
-       nach einer Stelle, an der gleichzeitig ein Bit im ersten
-       Bitfeld gesetzt ist und im zweiten Bitfeld das entsprechende
-       Bit nicht gesetzt ist.
-
-******************************************************************************/
-
-static u4 findnextcombination_set_unset 
-       (bitfieldtype *bitfield1, bitfieldtype* bitfield2, u4 fieldsize, u4 bitnumber)
-{
-       bitfieldtype pattern;
-
-       for (;;) {
-               if (bitnumber >= fieldsize) return fieldsize;
-               
-               pattern =     bitfield1[bitnumber/BITFIELDBITS] 
-                         & (~bitfield2[bitnumber/BITFIELDBITS]);
-               pattern >>= (bitnumber%BITFIELDBITS);
-               if (pattern) return bitnumber + lowest(pattern);
-
-               bitnumber = ((bitnumber + BITFIELDBITS) / BITFIELDBITS) * BITFIELDBITS;
-               }
-}
-
-
-
-/************** Funktion: memlist_init ****************************************
-
-       initialisiert die Freispeicherlisten (zum nachfolgenden Eintragen 
-       mit memlist_addrange).
-
-******************************************************************************/
-
-static void memlist_init ()
-{
-       u4 i;
-       for (i=0; i<DIFFERENTSIZES; i++) memlist[i] = NULL;
-       clearbitfield (memlistbits, DIFFERENTSIZES);
-       bigmemlist = NULL;
-}
-
-
-/************** Funktion: memlist_addrange ************************************
-
-       f"ugt einen Bereich von Heap-Bl"ocken zur Freispeicherliste 
-       hinzu (in die freien Heap-Bl"ocke werden dabei verschiedene 
-       Verkettungszeiger hineingeschrieben).
-
-******************************************************************************/
-
-static void memlist_addrange (u4 freestart, u4 freesize)
-{
-       if (freesize>=DIFFERENTSIZES) {
-               bigmemarea *m = (bigmemarea*) (heap+freestart);
-               m -> next = bigmemlist;
-               m -> size = freesize;
-               bigmemlist = m;
-               }
-       else {
-               if (freesize*BLOCKSIZE>=sizeof(memarea)) {
-                       memarea *m = (memarea*) (heap+freestart);
-                       m -> next = memlist[freesize];
-                       memlist[freesize] = m;
-                       setbit (memlistbits, freesize);
-                       }
-               }
-}
-
-
-/************** Funktion: memlist_getsuitable *********************************
-
-       sucht in der Freispeicherliste einen Speicherbereich, der m"oglichst
-       genau die gew"unschte L"ange hat.
-       Der Bereich wird dabei auf jeden Fall aus der Liste ausgetragen.
-       (Wenn der Bereich zu lang sein sollte, dann kann der Aufrufer den
-       Rest wieder mit 'memlist_addrange' in die Liste einh"angen)
-       
-       Return (in Referenzparametern): 
-               *freestart: Anfang des freien Speichers
-               *freelength: L"ange dieses Speicherbereiches
-
-       Wenn kein passender Speicherblock mehr gefunden werden kann, dann 
-       wird in '*freelength' 0 hineingeschrieben.
-       
-******************************************************************************/                
-
-static void memlist_getsuitable (u4 *freestart, u4 *freelength, u4 length)
-{
-       bigmemarea *m;
-       bigmemarea *prevm = NULL;
-       
-       if (length<DIFFERENTSIZES) {
-               u4 firstfreelength;
-
-               if (memlist[length]) {
-                       firstfreelength = length;
-                       }
-               else {
-                       firstfreelength = findnextsetbit 
-                               (memlistbits, DIFFERENTSIZES, length+3); 
-                               /* wenn kein passender Block da ist, dann gleich nach */
-                               /* einem etwas gr"osseren suchen, damit keine kleinen */
-                               /* St"uckchen "ubrigbleiben */
-                       }
-                       
-               if (firstfreelength<DIFFERENTSIZES) {
-                       memarea *m = memlist[firstfreelength];
-                       memlist[firstfreelength] = m->next;             
-                       if (!m->next) clearbit (memlistbits, firstfreelength);
-                       *freestart = ((heapblock*) m) - heap;
-                       *freelength = firstfreelength;
-                       return;
-                       }
-               }
-
-       m = bigmemlist;
-       while (m) {
-               if (m->size >= length) {
-                       if (prevm) prevm->next = m->next;                                       
-                               else   bigmemlist = m->next;
-                       
-                       *freestart = ((heapblock*) m) - heap;
-                       *freelength = m->size;
-                       return ;                        
-                       }
-
-               prevm = m;
-               m = m->next;
-               }
-       
-       *freelength=0;
-}
-
-
-
-
-
-/******************* Funktion: mark *******************************************
-
-       Markiert ein m"oglicherweise g"ultiges Objekt.
-       Sollte sich herausstellen, dass der Zeiger gar nicht auf ein Objekt
-       am Heap zeigt, dann wird eben gar nichts markiert.
-
-******************************************************************************/
-
-static void markreferences (void **rstart, void **rend);
-
-static void mark (heapblock *obj)
-{
-       u4 blocknum,objectend;
-
-       if ((long) obj & (BLOCKSIZE-1)) return;
-       
-       if (obj<heap) return;
-       if (obj>=(heap+topofheap) ) return;
-
-       blocknum = obj-heap;
-       if ( isbitclear(startbits, blocknum) ) return;
-       if ( isbitset(markbits, blocknum) ) return;
-
-       setbit (markbits, blocknum);
-       
-       if ( isbitclear(referencebits, blocknum) ) return;
-
-       objectend = findnextsetbit (startbits, topofheap, blocknum+1);
-       markreferences ((void**)obj, (void**) (heap+objectend) );
-}
-
-
-/******************** Funktion: markreferences ********************************
-
-       Geht einen Speicherbereich durch, und markiert alle Objekte, auf
-       die von diesem Bereich aus irgendeine Referenz existiert.
-
-******************************************************************************/
-
-static void markreferences (void **rstart, void **rend)
-{
-       void **ptr;
-       
-       for (ptr=rstart; ptr<rend; ptr++) mark (*ptr);
-}
-
-
-/******************* Funktion: markstack **************************************
-
-        Marks all objects that are referenced by the (C-)stacks of
-        all live threads.
-
-       (The stack-bottom is to be specified in the call to heap_init).
-
-******************************************************************************/
-
-static void markstack ()                   /* schani */
-{
-       void *dummy;
-
-#ifdef USE_THREADS
-    thread *aThread;
-
-       if (currentThread == NULL) {
-               void **top_of_stack = &dummy;
-                               
-               if (top_of_stack > bottom_of_stack)
-                       markreferences(bottom_of_stack, top_of_stack);
-               else
-                       markreferences(top_of_stack, bottom_of_stack);
-       }
-       else {
-               for (aThread = liveThreads; aThread != 0;
-                        aThread = CONTEXT(aThread).nextlive) {
-                       mark((heapblock*)aThread);
-                       if (aThread == currentThread) {
-                               void **top_of_stack = &dummy;
-                               
-                               if (top_of_stack > (void**)CONTEXT(aThread).stackEnd)
-                                       markreferences((void**)CONTEXT(aThread).stackEnd, top_of_stack);
-                               else    
-                                       markreferences(top_of_stack, (void**)CONTEXT(aThread).stackEnd);
-                       }
-                       else {
-                               if (CONTEXT(aThread).usedStackTop > CONTEXT(aThread).stackEnd)
-                                       markreferences((void**)CONTEXT(aThread).stackEnd,
-                                                                  (void**)CONTEXT(aThread).usedStackTop);
-                               else    
-                                       markreferences((void**)CONTEXT(aThread).usedStackTop,
-                                                                  (void**)CONTEXT(aThread).stackEnd);
-                       }
-           }
-
-               markreferences((void**)&threadQhead[0],
-                                          (void**)&threadQhead[MAX_THREAD_PRIO]);
-       }
-#else
-    void **top_of_stack = &dummy;
-
-    if (top_of_stack > bottom_of_stack)
-        markreferences(bottom_of_stack, top_of_stack);
-    else
-        markreferences(top_of_stack, bottom_of_stack);
-#endif
-}
-
-
-
-/**************** Funktion: searchlivefinalizees *****************************
-
-       geht die Liste aller Objekte durch, die noch finalisiert werden m"ussen
-       (livefinalizees), und tr"agt alle nicht mehr markierten in die
-       Liste deadfinalizess ein (allerdings werden sie vorher noch als
-       erreicht markiert, damit sie nicht jetzt gleich gel"oscht werden).
-       
-*****************************************************************************/ 
-
-static void searchlivefinalizees ()
-{
-       finalizernode *fn = livefinalizees;
-       finalizernode *lastlive = NULL;
-               
-       while (fn) {
-       
-               /* alle zu finalisierenden Objekte, die nicht mehr markiert sind: */
-               if (isbitclear (markbits, fn->objstart)) {
-                       finalizernode *nextfn = fn->next;
-
-                       mark (heap + fn->objstart); 
-
-                       if (lastlive) lastlive -> next = nextfn;
-                                      else livefinalizees = nextfn;
-
-                       fn -> next = deadfinalizees;
-                       deadfinalizees = fn;
-                       
-                       fn = nextfn;
-                       }
-               else {  
-                       lastlive = fn;
-                       fn = fn->next;
-                       }
-               }
-}
-
-
-
-/********************** Funktion: finalizedead *******************************
-
-       ruft die 'finalize'-Methode aller Objekte in der 'deadfinalizees'-
-       Liste auf.
-       Achtung: Es kann hier eventuell zu neuerlichen Speicheranforderungen
-       (mit potentiell notwendigem GC) kommen, deshalb m"ussen manche
-       globalen Variablen in lokale Variblen kopiert werden 
-       (Reentrant-F"ahigkeit!!!)
-        
-******************************************************************************/
-
-static void finalizedead()
-{
-       finalizernode *fn = deadfinalizees;
-       deadfinalizees = NULL;
-       
-       while (fn) {
-               finalizernode *nextfn = fn->next;
-               
-               asm_calljavamethod (fn->finalizer, heap+fn->objstart, NULL,NULL,NULL);
-               FREE (fn, finalizernode);
-               
-               fn = nextfn;
-               }
-
-}
-
-
-
-/****************** Funktion: heap_docollect **********************************
-       
-       F"uhrt eine vollst"andige Garbage Collection durch
-       
-******************************************************************************/
-
-static void heap_docollect ()
-{
-       u4 freestart,freeend;
-       void **p;
-       bitfieldtype *dummy;
-       u4 heapfreemem;
-       u4 oldfillgrade;
-
-
-       if (runverbose) {
-               fprintf(stderr, "doing garbage collection\n");
-               }
-               /* alle Markierungsbits l"oschen */
-       clearbitfield (markbits, topofheap);
-
-               /* Alle vom Stack referenzierten Objekte markieren */
-       asm_dumpregistersandcall (markstack);
-
-               /* Alle von globalen Variablen erreichbaren Objekte markieren */
-       p = chain_first (allglobalreferences);
-       while (p) {
-               mark (*p);
-               p = chain_next (allglobalreferences);   
-               }
-
-               /* alle Objekte durchsehen, die eine finalizer-Methode haben */
-       searchlivefinalizees();
-
-               /* alle Reference-Bits l"oschen, deren Objekte nicht */
-               /* mehr erreichbar sind */
-       maskfieldwithfield (referencebits, markbits, topofheap);
-
-
-               /* Freispeicherliste initialisieren */
-       memlist_init ();
-       
-       
-               /* Heap schrittweise durchgehen, und alle freien Bl"ocke merken */
-
-       heapfreemem = 0;
-       freeend=0;
-       for (;;) {
-                       /* Anfang des n"achsten freien Bereiches suchen */
-               freestart = findnextcombination_set_unset 
-                       (startbits, markbits, topofheap, freeend);
-
-                       /* Wenn es keinen freien Bereich mehr gibt -> fertig */
-               if (freestart>=topofheap) goto freememfinished;
-
-                       /* Anfang des freien Bereiches markieren */
-               setbit (markbits, freestart);
-
-                       /* Ende des freien Bereiches suchen */          
-               freeend = findnextsetbit (markbits, topofheap, freestart+1);
-
-                       /* Freien Bereich in Freispeicherliste einh"angen */
-               memlist_addrange (freestart, freeend-freestart);
-
-                       /* Menge des freien Speichers mitnotieren */
-               heapfreemem += (freeend-freestart);
-               }
-
-       freememfinished:
-
-               /* Die Rollen von markbits und startbits vertauschen */ 
-       dummy = markbits;
-       markbits = startbits;
-       startbits = dummy;
-
-
-               /* Threashold-Wert f"ur n"achstes Collect */
-       oldfillgrade = heapfillgrade;
-       heapfillgrade = topofheap - heapfreemem;
-       collectthreashold = heapfillgrade*3;   /* eine nette Heuristik */
-
-               /* Eventuell eine Meldung ausgeben */
-       if (collectverbose) {
-               sprintf (logtext, "Garbage Collection:  previous/now = %d / %d ",
-                 (int) (oldfillgrade * BLOCKSIZE), 
-                 (int) (heapfillgrade * BLOCKSIZE) );
-               dolog ();
-               }
-
-
-               
-               /* alle gerade unerreichbar gewordenen Objekte mit 
-                  finalize-Methoden jetzt finalisieren.
-                  Achtung: Diese Funktion kann zu neuerlichem GC f"uhren!! */
-       finalizedead ();
-       
-}
-
-/************************* Function: gc_init **********************************
-
-  Initializes anything that must be initialized to call the gc on the right
-  stack.
-
-******************************************************************************/
-
-void
-gc_init (void)
-{
-}
-
-/************************** Function: gc_call ********************************
-
-  Calls the garbage collector. The garbage collector should always be called
-  using this function since it ensures that enough stack space is available.
-
-******************************************************************************/
-
-void
-gc_call (void)
-{
-#ifdef USE_THREADS
-       assert(blockInts == 0);
-#endif
-
-       intsDisable();
-       if (currentThread == NULL || currentThread == mainThread)
-               heap_docollect();
-       else
-               asm_switchstackandcall(CONTEXT(mainThread).usedStackTop, heap_docollect);
-       intsRestore();
-}
-
-
-/************************* Funktion: heap_init ********************************
-
-       Initialisiert den Garbage Collector.
-       Parameter: 
-               heapbytesize:      Maximale Gr"osse des Heap (in Bytes)
-               heapbytestartsize: Gr"osse des Heaps, bei dem zum ersten mal eine
-                                  GC durchgef"uhrt werden soll.
-               stackbottom:       Ein Zeiger auf die Untergrenze des Stacks, im dem
-                              Referenzen auf Objekte stehen k"onnen.                  
-                                          
-******************************************************************************/
-
-void heap_init (u4 heapbytesize, u4 heapbytestartsize, void **stackbottom)
-{
-
-#ifdef TRACECALLARGS
-
-       heapsize = ALIGN (heapbytesize, getpagesize());
-       heapsize = heapsize/BLOCKSIZE;
-       heap = (void*) mmap ((void*) 0x10000000, (size_t) (heapsize * BLOCKSIZE),
-              PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, (off_t) 0);
-       if (heap != (void *) 0x10000000) {
-               perror("mmap");
-               printf("address = %p\n", heap);
-               panic("mmap failed\n");
-               }
-
-#else
-
-       heapsize = ALIGN (heapbytesize, 1024);
-       heapsize = heapsize/BLOCKSIZE;
-       heap = MNEW (heapblock, heapsize);
-
-#endif
-
-       topofheap = 0;
-       startbits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
-       markbits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
-       referencebits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
-       clearbitfield (startbits, heapsize);
-       clearbitfield (markbits, heapsize);
-       clearbitfield (referencebits, heapsize);
-
-       heapfillgrade = 0;
-       collectthreashold = heapbytestartsize/BLOCKSIZE;
-       allglobalreferences = chain_new ();
-       bottom_of_stack = stackbottom;
-
-       livefinalizees = NULL;
-       deadfinalizees = NULL;
-}
-
-
-/****************** Funktion: heap_close **************************************
-
-       Gibt allen ben"otigten Speicher frei
-
-******************************************************************************/
-
-void heap_close ()
-{
-#ifndef TRACECALLARGS
-       MFREE (heap, heapblock, heapsize); */
-#endif
-       MFREE (startbits, bitfieldtype, heapsize/BITFIELDBITS);
-       MFREE (markbits, bitfieldtype, heapsize/BITFIELDBITS);
-       MFREE (referencebits, bitfieldtype, heapsize/BITFIELDBITS);
-       chain_free (allglobalreferences);
-
-       while (livefinalizees) {
-               finalizernode *n = livefinalizees->next;
-               FREE (livefinalizees, finalizernode);
-               livefinalizees = n;
-               }
-}
-
-
-/***************** Funktion: heap_addreference ********************************
-
-       Teilt dem GC eine Speicherstelle mit, an der eine globale Referenz
-       auf Objekte gespeichert sein kann.
-
-******************************************************************************/
-
-void heap_addreference (void **reflocation)
-{
-       intsDisable();                     /* schani */
-
-       chain_addlast (allglobalreferences, reflocation);
-
-       intsRestore();                    /* schani */
-}
-
-
-
-/***************** Funktion: heap_allocate ************************************
-
-       Fordert einen Speicher vom Heap an, der eine gew"unschte Gr"osse
-       (in Byte angegeben) haben muss.
-       Wenn kein Speicher mehr vorhanden ist (auch nicht nach einem
-       Garbage Collection-Durchlauf), dann wird NULL zur"uckgegeben.
-       Zus"atzlich wird durch den Parameter 'references' angegeben, ob
-       in das angelegte Objekt Referenzen auf andere Objekte eingetragen
-       werden k"onnten. 
-       (Wichtig wegen Beschleunigung des Mark&Sweep-Durchlauf)
-       Im Zweifelsfalle immer references=true verwenden.
-
-******************************************************************************/
-
-void *heap_allocate (u4 bytelength, bool references, methodinfo *finalizer)
-{
-       u4 freestart,freelength;
-       u4 length = ALIGN(bytelength, BLOCKSIZE) / BLOCKSIZE;
-       
-       intsDisable();                        /* schani */
-
-       memlist_getsuitable (&freestart, &freelength, length);
-
-onemoretry:
-       if (!freelength) {
-               if (    (topofheap+length > collectthreashold) 
-                    || (topofheap+length > heapsize) ) {
-
-                       intsRestore();
-                       gc_call();
-                       intsDisable();
-                       
-                       memlist_getsuitable (&freestart, &freelength, length);
-                       if (freelength) goto onemoretry;
-                       }
-               
-               if (topofheap+length > heapsize) {
-                       sprintf (logtext, "Heap-Allocation failed for %d bytes", 
-                           (int) bytelength);
-                       dolog();
-                       intsRestore();            /* schani */
-                       return NULL;
-                       }
-                       
-               freestart = topofheap;
-               freelength = length;
-               setbit (startbits, topofheap);
-               topofheap += length;
-               }
-       else {
-               if (freelength>length) {
-                       setbit (startbits, freestart+length);
-                       memlist_addrange (freestart+length, freelength-length);
-                       }
-               }
-               
-       if (references) setbit (referencebits, freestart);
-
-       heapfillgrade += length;
-
-       if (finalizer) {
-               finalizernode *n = NEW(finalizernode);
-               n -> next = livefinalizees;
-               n -> objstart = freestart;
-               n -> finalizer = finalizer;
-               livefinalizees = n;
-               }
-       
-       intsRestore();                   /* schani */
-
-       if (runverbose) {
-               sprintf (logtext, "new returns: %lx", (long) (heap + freestart));
-               dolog ();
-               }
-
-       return (void*) (heap + freestart);
-}
-
-
-
-
index 6cd6ee8c1863ed505729658b05bea639b8145aa4..48103bee3b6b5db2d5ac74854066bb4730bbe21f 100644 (file)
--- a/tables.c
+++ b/tables.c
@@ -27,7 +27,6 @@
 #include "asmpart.h"
 #include "callargs.h"
 
-#include "sysdep/threads.h"
 #include "threads/thread.h"                  /* schani */
 #include "threads/locks.h"
 
@@ -675,853 +674,3 @@ u2 desc_typesize (unicode *descriptor)
 
 
 
-
-/******************************************************************************
-********************* Der garbage-collected Heap ******************************
-*******************************************************************************
-
-       verwaltet einen Heap mit automatischer Speicherfreigabe.
-
-       (eine ausf"uhrliche Dokumentation findet sich in der Datei: 
-       collect.doc)
-       
-******************************************************************************/
-
-
-bool collectverbose = false;  /* soll Meldung beim GC ausgegeben werden? */
-
-
-#define BLOCKSIZE 8         /* Gr"osse eines Speicherblockes */
-typedef u8 heapblock;       /* Datentyp mit der Gr"osse eines Speicherblocks */
-
-#if U8_AVAILABLE && SUPPORT_LONG
-#define        bitfieldtype u8
-#define BITFIELDBITS 64
-#else
-#define bitfieldtype u4
-#define BITFIELDBITS 32
-#endif
-
-u4 heapsize;                /* Gr"osse des Heap in Blocks */
-u4 topofheap;               /* Bisherige Obergrenze Heaps */
-heapblock *heap;            /* Speicher f"ur den Heap selbst */
-
-bitfieldtype *startbits;     /* Bitfeld f"ur Bereichsstartkennung */
-bitfieldtype *markbits;      /* Bitfeld f"ur Markierung */
-bitfieldtype *referencebits; /* Bitfeld f"ur Folgereferenzenkennung */
-
-u4 heapfillgrade;           /* Menge der Daten im Heap */
-u4 collectthreashold;       /* Schwellwert f"ur n"achstes GC */
-
-void **bottom_of_stack;     /* Zeiger auf Untergrenze des C-Stacks */ 
-chain *allglobalreferences; /* Liste f"ur alle globalen Zeiger */
-
-typedef struct finalizernode {
-       struct finalizernode *next;     
-       u4 objstart;
-       methodinfo *finalizer;
-       } finalizernode;
-       
-finalizernode *livefinalizees;
-finalizernode *deadfinalizees;
-
-
-typedef struct memarea {    /* Datenstruktur f"ur einen Freispeicherbereich */
-       struct memarea *next;
-       } memarea;
-
-typedef struct bigmemarea {   /* Datenstruktur f"ur einen */
-       struct bigmemarea *next;  /* Freispeicherbereich variabler L"ange */
-       u4 size;
-       } bigmemarea;
-       
-#define DIFFERENTSIZES 128         /* Anzahl der 'kleinen' Freispeicherlisten */
-memarea *memlist[DIFFERENTSIZES];  /* Die 'kleinen' Freispeicherlisten */
-bitfieldtype memlistbits[DIFFERENTSIZES/BITFIELDBITS]; 
-                                   /* Bitfeld, in dem jeweils ein Bit gesetzt */
-                                   /* ist, wenn eine Liste noch etwas enth"alt */
-
-bigmemarea *bigmemlist;         /* Liste der gr"osseren Freispeicherbereiche */
-
-
-
-
-/**************** Hilfsfunktion: lowest **************************************
-
-liefert als Ergebnis die Nummer des niederwertigsten Bits einer 
-Zahl vom Typ bitfieldtype, das 1 ist.
-Wenn die ganze Zahl keine 1en enth"alt, dann ist egal, was f"ur einen
-Wert die Funktion l"iefert.
-z.B.: lowest(1) = 0,   lowest(12) = 2,   lowest(1024) = 10
-
-*****************************************************************************/
-
-static u1 lowesttable[256] = {
-       255, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-       5,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-       6,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-       5,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-       7,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-       5,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-       6,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-       5,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-       4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 };
-       
-static int lowest(bitfieldtype i)
-{
-#if BITFIELDBITS==64
-       u8 i1 = i<<32;
-       if (i1) {
-               u8 i11 = i1<<16;
-               if (i11) {
-                       u8 i111 = i11<<8;
-                       if (i111) return lowesttable[i111>>56];
-                       else      return 8+lowesttable[i11>>56];
-                       }
-               else {
-                       u8 i112 = i1<<8;
-                       if (i112) return 16+lowesttable[i112>>56];
-                       else      return 24+lowesttable[i1>>56];
-                       }
-               }
-       else {
-               u8 i12 = i<<16;
-               if (i12) {
-                       u8 i121 = i12<<8;
-                       if (i121) return 32+lowesttable[i121>>56];
-                       else      return 40+lowesttable[i12>>56];
-                       }
-               else {
-                       u8 i122 = i<<8;
-                       if (i122) return 48+lowesttable[i122>>56];
-                       else      return 56+lowesttable[i>>56];
-                       }
-               }
-#else
-       u4 i1 = i<<16;
-       if (i1) {
-               u4 i11 = i1<<8;
-               if (i11) return lowesttable[i11>>24];
-               else     return 8+lowesttable[i1>>24];
-               }
-       else {
-               u4 i12 = i<<8;
-               if (i12) return 16+lowesttable[i12>>24];
-               else     return 24+lowesttable[i>>24];
-               }
-#endif
-}
-
-
-/******** Funktionen zum Setzen und L"oschen von Bits in Bitfeldern ***********/
-
-static void setbit(bitfieldtype *bitfield, u4 bitnumber)
-{
-       bitfield[bitnumber/BITFIELDBITS] |= 
-         ((bitfieldtype) 1) << (bitnumber%BITFIELDBITS);
-}
-
-static void clearbit(bitfieldtype *bitfield, u4 bitnumber)
-{
-       bitfield[bitnumber/BITFIELDBITS] &= 
-          ~((bitfieldtype) 1) << (bitnumber%BITFIELDBITS);
-}
-
-static bool isbitset(bitfieldtype *bitfield, u4 bitnumber)
-{
-       return ( bitfield[bitnumber/BITFIELDBITS] & 
-          ( ((bitfieldtype) 1) << (bitnumber%BITFIELDBITS) ) ) != 0;
-}
-
-static bool isbitclear(bitfieldtype *bitfield, u4 bitnumber)
-{
-       return ( bitfield[bitnumber/BITFIELDBITS] & 
-           ( ((bitfieldtype) 1) << (bitnumber%BITFIELDBITS) ) ) == 0;
-}
-
-
-/***************** Funktion: clearbitfield ************************************
-       
-       l"oscht ein ganzes Bitfeld
-       
-******************************************************************************/
-
-static void clearbitfield(bitfieldtype *bitfield, u4 fieldsize)
-{ 
-       u4 i,t;
-       t = ALIGN(fieldsize, BITFIELDBITS) / BITFIELDBITS;
-       for (i=0; i<t; i++) bitfield[i] = 0;
-}
-
-/************** Funktion: maskfieldwithfield **********************************
-       
-       Verkn"upft zwei Bitfelder bitweise mit UND, das erste Bitfeld
-       wird mit dem Ergebnis "uberschrieben 
-       
-******************************************************************************/
-       
-static void maskfieldwithfield (bitfieldtype* bitfield, 
-                                bitfieldtype *maskfield, u4 fieldsize)
-{
-       u4 i,t;
-       t = ALIGN(fieldsize, BITFIELDBITS) / BITFIELDBITS;
-       for (i=0; i<t; i++) bitfield[i] &= maskfield[i];
-}
-
-
-/************** Funktion: findnextsetbit **************************************
-
-       Sucht in einem Bitfeld ab einer Stelle das n"achste gesetzte Bit
-       und liefert die Nummer dieses Bits.
-       Wenn kein Bit mehr zwischen 'bitnumber' und 'fieldsize' gesetzt
-       ist, dann wird fieldsize zur"uckgeliefte.
-
-******************************************************************************/
-
-static u4 findnextsetbit(bitfieldtype* bitfield, u4 fieldsize, u4 bitnumber)
-{
-       bitfieldtype pattern;
-
-       for (;;) {
-               if (bitnumber >= fieldsize) return fieldsize;
-               
-               pattern = bitfield[bitnumber/BITFIELDBITS];
-               pattern >>= (bitnumber%BITFIELDBITS);
-               if (pattern) return bitnumber + lowest(pattern);
-
-               bitnumber = ((bitnumber + BITFIELDBITS) / BITFIELDBITS) * BITFIELDBITS;
-               }
-}
-
-
-/************ Funktion: findnextcombination_set_unset *************************
-
-       funktioniert wie findnextsetbit, allerdings sucht diese Funktion
-       nach einer Stelle, an der gleichzeitig ein Bit im ersten
-       Bitfeld gesetzt ist und im zweiten Bitfeld das entsprechende
-       Bit nicht gesetzt ist.
-
-******************************************************************************/
-
-static u4 findnextcombination_set_unset 
-       (bitfieldtype *bitfield1, bitfieldtype* bitfield2, u4 fieldsize, u4 bitnumber)
-{
-       bitfieldtype pattern;
-
-       for (;;) {
-               if (bitnumber >= fieldsize) return fieldsize;
-               
-               pattern =     bitfield1[bitnumber/BITFIELDBITS] 
-                         & (~bitfield2[bitnumber/BITFIELDBITS]);
-               pattern >>= (bitnumber%BITFIELDBITS);
-               if (pattern) return bitnumber + lowest(pattern);
-
-               bitnumber = ((bitnumber + BITFIELDBITS) / BITFIELDBITS) * BITFIELDBITS;
-               }
-}
-
-
-
-/************** Funktion: memlist_init ****************************************
-
-       initialisiert die Freispeicherlisten (zum nachfolgenden Eintragen 
-       mit memlist_addrange).
-
-******************************************************************************/
-
-static void memlist_init ()
-{
-       u4 i;
-       for (i=0; i<DIFFERENTSIZES; i++) memlist[i] = NULL;
-       clearbitfield (memlistbits, DIFFERENTSIZES);
-       bigmemlist = NULL;
-}
-
-
-/************** Funktion: memlist_addrange ************************************
-
-       f"ugt einen Bereich von Heap-Bl"ocken zur Freispeicherliste 
-       hinzu (in die freien Heap-Bl"ocke werden dabei verschiedene 
-       Verkettungszeiger hineingeschrieben).
-
-******************************************************************************/
-
-static void memlist_addrange (u4 freestart, u4 freesize)
-{
-       if (freesize>=DIFFERENTSIZES) {
-               bigmemarea *m = (bigmemarea*) (heap+freestart);
-               m -> next = bigmemlist;
-               m -> size = freesize;
-               bigmemlist = m;
-               }
-       else {
-               if (freesize*BLOCKSIZE>=sizeof(memarea)) {
-                       memarea *m = (memarea*) (heap+freestart);
-                       m -> next = memlist[freesize];
-                       memlist[freesize] = m;
-                       setbit (memlistbits, freesize);
-                       }
-               }
-}
-
-
-/************** Funktion: memlist_getsuitable *********************************
-
-       sucht in der Freispeicherliste einen Speicherbereich, der m"oglichst
-       genau die gew"unschte L"ange hat.
-       Der Bereich wird dabei auf jeden Fall aus der Liste ausgetragen.
-       (Wenn der Bereich zu lang sein sollte, dann kann der Aufrufer den
-       Rest wieder mit 'memlist_addrange' in die Liste einh"angen)
-       
-       Return (in Referenzparametern): 
-               *freestart: Anfang des freien Speichers
-               *freelength: L"ange dieses Speicherbereiches
-
-       Wenn kein passender Speicherblock mehr gefunden werden kann, dann 
-       wird in '*freelength' 0 hineingeschrieben.
-       
-******************************************************************************/                
-
-static void memlist_getsuitable (u4 *freestart, u4 *freelength, u4 length)
-{
-       bigmemarea *m;
-       bigmemarea *prevm = NULL;
-       
-       if (length<DIFFERENTSIZES) {
-               u4 firstfreelength;
-
-               if (memlist[length]) {
-                       firstfreelength = length;
-                       }
-               else {
-                       firstfreelength = findnextsetbit 
-                               (memlistbits, DIFFERENTSIZES, length+3); 
-                               /* wenn kein passender Block da ist, dann gleich nach */
-                               /* einem etwas gr"osseren suchen, damit keine kleinen */
-                               /* St"uckchen "ubrigbleiben */
-                       }
-                       
-               if (firstfreelength<DIFFERENTSIZES) {
-                       memarea *m = memlist[firstfreelength];
-                       memlist[firstfreelength] = m->next;             
-                       if (!m->next) clearbit (memlistbits, firstfreelength);
-                       *freestart = ((heapblock*) m) - heap;
-                       *freelength = firstfreelength;
-                       return;
-                       }
-               }
-
-       m = bigmemlist;
-       while (m) {
-               if (m->size >= length) {
-                       if (prevm) prevm->next = m->next;                                       
-                               else   bigmemlist = m->next;
-                       
-                       *freestart = ((heapblock*) m) - heap;
-                       *freelength = m->size;
-                       return ;                        
-                       }
-
-               prevm = m;
-               m = m->next;
-               }
-       
-       *freelength=0;
-}
-
-
-
-
-
-/******************* Funktion: mark *******************************************
-
-       Markiert ein m"oglicherweise g"ultiges Objekt.
-       Sollte sich herausstellen, dass der Zeiger gar nicht auf ein Objekt
-       am Heap zeigt, dann wird eben gar nichts markiert.
-
-******************************************************************************/
-
-static void markreferences (void **rstart, void **rend);
-
-static void mark (heapblock *obj)
-{
-       u4 blocknum,objectend;
-
-       if ((long) obj & (BLOCKSIZE-1)) return;
-       
-       if (obj<heap) return;
-       if (obj>=(heap+topofheap) ) return;
-
-       blocknum = obj-heap;
-       if ( isbitclear(startbits, blocknum) ) return;
-       if ( isbitset(markbits, blocknum) ) return;
-
-       setbit (markbits, blocknum);
-       
-       if ( isbitclear(referencebits, blocknum) ) return;
-
-       objectend = findnextsetbit (startbits, topofheap, blocknum+1);
-       markreferences ((void**)obj, (void**) (heap+objectend) );
-}
-
-
-/******************** Funktion: markreferences ********************************
-
-       Geht einen Speicherbereich durch, und markiert alle Objekte, auf
-       die von diesem Bereich aus irgendeine Referenz existiert.
-
-******************************************************************************/
-
-static void markreferences (void **rstart, void **rend)
-{
-       void **ptr;
-       
-       for (ptr=rstart; ptr<rend; ptr++) mark (*ptr);
-}
-
-
-/******************* Funktion: markstack **************************************
-
-        Marks all objects that are referenced by the (C-)stacks of
-        all live threads.
-
-       (The stack-bottom is to be specified in the call to heap_init).
-
-******************************************************************************/
-
-static void markstack ()                   /* schani */
-{
-       void *dummy;
-
-#ifdef USE_THREADS
-    thread *aThread;
-
-       if (currentThread == NULL) {
-               void **top_of_stack = &dummy;
-                               
-               if (top_of_stack > bottom_of_stack)
-                       markreferences(bottom_of_stack, top_of_stack);
-               else
-                       markreferences(top_of_stack, bottom_of_stack);
-       }
-       else {
-               for (aThread = liveThreads; aThread != 0;
-                        aThread = CONTEXT(aThread).nextlive) {
-                       mark((heapblock*)aThread);
-                       if (aThread == currentThread) {
-                               void **top_of_stack = &dummy;
-                               
-                               if (top_of_stack > (void**)CONTEXT(aThread).stackEnd)
-                                       markreferences((void**)CONTEXT(aThread).stackEnd, top_of_stack);
-                               else    
-                                       markreferences(top_of_stack, (void**)CONTEXT(aThread).stackEnd);
-                       }
-                       else {
-                               if (CONTEXT(aThread).usedStackTop > CONTEXT(aThread).stackEnd)
-                                       markreferences((void**)CONTEXT(aThread).stackEnd,
-                                                                  (void**)CONTEXT(aThread).usedStackTop);
-                               else    
-                                       markreferences((void**)CONTEXT(aThread).usedStackTop,
-                                                                  (void**)CONTEXT(aThread).stackEnd);
-                       }
-           }
-
-               markreferences((void**)&threadQhead[0],
-                                          (void**)&threadQhead[MAX_THREAD_PRIO]);
-       }
-#else
-    void **top_of_stack = &dummy;
-
-    if (top_of_stack > bottom_of_stack)
-        markreferences(bottom_of_stack, top_of_stack);
-    else
-        markreferences(top_of_stack, bottom_of_stack);
-#endif
-}
-
-
-
-/**************** Funktion: searchlivefinalizees *****************************
-
-       geht die Liste aller Objekte durch, die noch finalisiert werden m"ussen
-       (livefinalizees), und tr"agt alle nicht mehr markierten in die
-       Liste deadfinalizess ein (allerdings werden sie vorher noch als
-       erreicht markiert, damit sie nicht jetzt gleich gel"oscht werden).
-       
-*****************************************************************************/ 
-
-static void searchlivefinalizees ()
-{
-       finalizernode *fn = livefinalizees;
-       finalizernode *lastlive = NULL;
-               
-       while (fn) {
-       
-               /* alle zu finalisierenden Objekte, die nicht mehr markiert sind: */
-               if (isbitclear (markbits, fn->objstart)) {
-                       finalizernode *nextfn = fn->next;
-
-                       mark (heap + fn->objstart); 
-
-                       if (lastlive) lastlive -> next = nextfn;
-                                      else livefinalizees = nextfn;
-
-                       fn -> next = deadfinalizees;
-                       deadfinalizees = fn;
-                       
-                       fn = nextfn;
-                       }
-               else {  
-                       lastlive = fn;
-                       fn = fn->next;
-                       }
-               }
-}
-
-
-
-/********************** Funktion: finalizedead *******************************
-
-       ruft die 'finalize'-Methode aller Objekte in der 'deadfinalizees'-
-       Liste auf.
-       Achtung: Es kann hier eventuell zu neuerlichen Speicheranforderungen
-       (mit potentiell notwendigem GC) kommen, deshalb m"ussen manche
-       globalen Variablen in lokale Variblen kopiert werden 
-       (Reentrant-F"ahigkeit!!!)
-        
-******************************************************************************/
-
-static void finalizedead()
-{
-       finalizernode *fn = deadfinalizees;
-       deadfinalizees = NULL;
-       
-       while (fn) {
-               finalizernode *nextfn = fn->next;
-               
-               asm_calljavamethod (fn->finalizer, heap+fn->objstart, NULL,NULL,NULL);
-               FREE (fn, finalizernode);
-               
-               fn = nextfn;
-               }
-
-}
-
-
-
-/****************** Funktion: heap_docollect **********************************
-       
-       F"uhrt eine vollst"andige Garbage Collection durch
-       
-******************************************************************************/
-
-static void heap_docollect ()
-{
-       u4 freestart,freeend;
-       void **p;
-       bitfieldtype *dummy;
-       u4 heapfreemem;
-       u4 oldfillgrade;
-
-
-       if (runverbose) {
-               fprintf(stderr, "doing garbage collection\n");
-               }
-               /* alle Markierungsbits l"oschen */
-       clearbitfield (markbits, topofheap);
-
-               /* Alle vom Stack referenzierten Objekte markieren */
-       asm_dumpregistersandcall (markstack);
-
-               /* Alle von globalen Variablen erreichbaren Objekte markieren */
-       p = chain_first (allglobalreferences);
-       while (p) {
-               mark (*p);
-               p = chain_next (allglobalreferences);   
-               }
-
-               /* alle Objekte durchsehen, die eine finalizer-Methode haben */
-       searchlivefinalizees();
-
-               /* alle Reference-Bits l"oschen, deren Objekte nicht */
-               /* mehr erreichbar sind */
-       maskfieldwithfield (referencebits, markbits, topofheap);
-
-
-               /* Freispeicherliste initialisieren */
-       memlist_init ();
-       
-       
-               /* Heap schrittweise durchgehen, und alle freien Bl"ocke merken */
-
-       heapfreemem = 0;
-       freeend=0;
-       for (;;) {
-                       /* Anfang des n"achsten freien Bereiches suchen */
-               freestart = findnextcombination_set_unset 
-                       (startbits, markbits, topofheap, freeend);
-
-                       /* Wenn es keinen freien Bereich mehr gibt -> fertig */
-               if (freestart>=topofheap) goto freememfinished;
-
-                       /* Anfang des freien Bereiches markieren */
-               setbit (markbits, freestart);
-
-                       /* Ende des freien Bereiches suchen */          
-               freeend = findnextsetbit (markbits, topofheap, freestart+1);
-
-                       /* Freien Bereich in Freispeicherliste einh"angen */
-               memlist_addrange (freestart, freeend-freestart);
-
-                       /* Menge des freien Speichers mitnotieren */
-               heapfreemem += (freeend-freestart);
-               }
-
-       freememfinished:
-
-               /* Die Rollen von markbits und startbits vertauschen */ 
-       dummy = markbits;
-       markbits = startbits;
-       startbits = dummy;
-
-
-               /* Threashold-Wert f"ur n"achstes Collect */
-       oldfillgrade = heapfillgrade;
-       heapfillgrade = topofheap - heapfreemem;
-       collectthreashold = heapfillgrade*3;   /* eine nette Heuristik */
-
-               /* Eventuell eine Meldung ausgeben */
-       if (collectverbose) {
-               sprintf (logtext, "Garbage Collection:  previous/now = %d / %d ",
-                 (int) (oldfillgrade * BLOCKSIZE), 
-                 (int) (heapfillgrade * BLOCKSIZE) );
-               dolog ();
-               }
-
-
-               
-               /* alle gerade unerreichbar gewordenen Objekte mit 
-                  finalize-Methoden jetzt finalisieren.
-                  Achtung: Diese Funktion kann zu neuerlichem GC f"uhren!! */
-       finalizedead ();
-       
-}
-
-/************************* Function: gc_init **********************************
-
-  Initializes anything that must be initialized to call the gc on the right
-  stack.
-
-******************************************************************************/
-
-void
-gc_init (void)
-{
-}
-
-/************************** Function: gc_call ********************************
-
-  Calls the garbage collector. The garbage collector should always be called
-  using this function since it ensures that enough stack space is available.
-
-******************************************************************************/
-
-void
-gc_call (void)
-{
-#ifdef USE_THREADS
-       assert(blockInts == 0);
-#endif
-
-       intsDisable();
-       if (currentThread == NULL || currentThread == mainThread)
-               heap_docollect();
-       else
-               asm_switchstackandcall(CONTEXT(mainThread).usedStackTop, heap_docollect);
-       intsRestore();
-}
-
-
-/************************* Funktion: heap_init ********************************
-
-       Initialisiert den Garbage Collector.
-       Parameter: 
-               heapbytesize:      Maximale Gr"osse des Heap (in Bytes)
-               heapbytestartsize: Gr"osse des Heaps, bei dem zum ersten mal eine
-                                  GC durchgef"uhrt werden soll.
-               stackbottom:       Ein Zeiger auf die Untergrenze des Stacks, im dem
-                              Referenzen auf Objekte stehen k"onnen.                  
-                                          
-******************************************************************************/
-
-void heap_init (u4 heapbytesize, u4 heapbytestartsize, void **stackbottom)
-{
-
-#ifdef TRACECALLARGS
-
-       heapsize = ALIGN (heapbytesize, getpagesize());
-       heapsize = heapsize/BLOCKSIZE;
-       heap = (void*) mmap ((void*) 0x10000000, (size_t) (heapsize * BLOCKSIZE),
-              PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, (off_t) 0);
-       if (heap != (void *) 0x10000000) {
-               perror("mmap");
-               printf("address = %p\n", heap);
-               panic("mmap failed\n");
-               }
-
-#else
-
-       heapsize = ALIGN (heapbytesize, 1024);
-       heapsize = heapsize/BLOCKSIZE;
-       heap = MNEW (heapblock, heapsize);
-
-#endif
-
-       topofheap = 0;
-       startbits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
-       markbits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
-       referencebits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
-       clearbitfield (startbits, heapsize);
-       clearbitfield (markbits, heapsize);
-       clearbitfield (referencebits, heapsize);
-
-       heapfillgrade = 0;
-       collectthreashold = heapbytestartsize/BLOCKSIZE;
-       allglobalreferences = chain_new ();
-       bottom_of_stack = stackbottom;
-
-       livefinalizees = NULL;
-       deadfinalizees = NULL;
-}
-
-
-/****************** Funktion: heap_close **************************************
-
-       Gibt allen ben"otigten Speicher frei
-
-******************************************************************************/
-
-void heap_close ()
-{
-#ifndef TRACECALLARGS
-       MFREE (heap, heapblock, heapsize); */
-#endif
-       MFREE (startbits, bitfieldtype, heapsize/BITFIELDBITS);
-       MFREE (markbits, bitfieldtype, heapsize/BITFIELDBITS);
-       MFREE (referencebits, bitfieldtype, heapsize/BITFIELDBITS);
-       chain_free (allglobalreferences);
-
-       while (livefinalizees) {
-               finalizernode *n = livefinalizees->next;
-               FREE (livefinalizees, finalizernode);
-               livefinalizees = n;
-               }
-}
-
-
-/***************** Funktion: heap_addreference ********************************
-
-       Teilt dem GC eine Speicherstelle mit, an der eine globale Referenz
-       auf Objekte gespeichert sein kann.
-
-******************************************************************************/
-
-void heap_addreference (void **reflocation)
-{
-       intsDisable();                     /* schani */
-
-       chain_addlast (allglobalreferences, reflocation);
-
-       intsRestore();                    /* schani */
-}
-
-
-
-/***************** Funktion: heap_allocate ************************************
-
-       Fordert einen Speicher vom Heap an, der eine gew"unschte Gr"osse
-       (in Byte angegeben) haben muss.
-       Wenn kein Speicher mehr vorhanden ist (auch nicht nach einem
-       Garbage Collection-Durchlauf), dann wird NULL zur"uckgegeben.
-       Zus"atzlich wird durch den Parameter 'references' angegeben, ob
-       in das angelegte Objekt Referenzen auf andere Objekte eingetragen
-       werden k"onnten. 
-       (Wichtig wegen Beschleunigung des Mark&Sweep-Durchlauf)
-       Im Zweifelsfalle immer references=true verwenden.
-
-******************************************************************************/
-
-void *heap_allocate (u4 bytelength, bool references, methodinfo *finalizer)
-{
-       u4 freestart,freelength;
-       u4 length = ALIGN(bytelength, BLOCKSIZE) / BLOCKSIZE;
-       
-       intsDisable();                        /* schani */
-
-       memlist_getsuitable (&freestart, &freelength, length);
-
-onemoretry:
-       if (!freelength) {
-               if (    (topofheap+length > collectthreashold) 
-                    || (topofheap+length > heapsize) ) {
-
-                       intsRestore();
-                       gc_call();
-                       intsDisable();
-                       
-                       memlist_getsuitable (&freestart, &freelength, length);
-                       if (freelength) goto onemoretry;
-                       }
-               
-               if (topofheap+length > heapsize) {
-                       sprintf (logtext, "Heap-Allocation failed for %d bytes", 
-                           (int) bytelength);
-                       dolog();
-                       intsRestore();            /* schani */
-                       return NULL;
-                       }
-                       
-               freestart = topofheap;
-               freelength = length;
-               setbit (startbits, topofheap);
-               topofheap += length;
-               }
-       else {
-               if (freelength>length) {
-                       setbit (startbits, freestart+length);
-                       memlist_addrange (freestart+length, freelength-length);
-                       }
-               }
-               
-       if (references) setbit (referencebits, freestart);
-
-       heapfillgrade += length;
-
-       if (finalizer) {
-               finalizernode *n = NEW(finalizernode);
-               n -> next = livefinalizees;
-               n -> objstart = freestart;
-               n -> finalizer = finalizer;
-               livefinalizees = n;
-               }
-       
-       intsRestore();                   /* schani */
-
-       if (runverbose) {
-               sprintf (logtext, "new returns: %lx", (long) (heap + freestart));
-               dolog ();
-               }
-
-       return (void*) (heap + freestart);
-}
-
-
-
-