new disassembler options added
[cacao.git] / tables.c
1 /* -*- mode: c; tab-width: 4; c-basic-offset: 4 -*- */
2 /****************************** tables.c ***************************************
3
4         Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
5
6         See file COPYRIGHT for information on usage and disclaimer of warranties
7
8         Enth"alt Supportfunktionen f"ur:
9                 - Lesen von JavaClass-Files
10             - unicode-Symbole
11                 - den Heap 
12                 - zus"atzliche Support-Funktionen
13
14         Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
15         Changes: Mark Probst         EMAIL: cacao@complang.tuwien.ac.at
16                  Andreas  Krall      EMAIL: cacao@complang.tuwien.ac.at
17
18         Last Change: 1998/03/24
19
20 *******************************************************************************/
21
22 #include <assert.h>
23 #include <sys/mman.h>
24 #include <unistd.h>
25 #include "global.h"
26 #include "tables.h"
27 #include "asmpart.h"
28 #include "callargs.h"
29
30 #include "sysdep/threads.h"
31 #include "threads/thread.h"                  /* schani */
32 #include "threads/locks.h"
33
34
35 bool runverbose = false;
36
37 int count_unicode_len = 0;
38
39
40 /******************************************************************************
41 ************************* Der Dateien-Sauger **********************************
42 *******************************************************************************
43
44         dient zum Behandeln von Java-ClassFiles ("offnen, schlie"sen, 
45         einlesen von 8-, 16-, 32-, 64-bit Integers und 32-, 64- bit Floats)
46
47 ******************************************************************************/
48
49 static FILE *classfile = NULL;   /* File-handle der gerade gelesenen Datei */
50 static char *classpath = "";     /* Suchpfad f"ur die ClassFiles */
51
52
53
54 /************************** Funktion: suck_init ******************************
55
56         Wird zu Programmstart einmal aufgerufen und setzt den Suchpfad f"ur
57         Klassenfiles
58
59 ******************************************************************************/
60
61 void suck_init (char *cpath)
62 {
63         classfile = NULL;
64         classpath = cpath;
65 }
66
67
68 /************************** Funktion: suck_start ******************************
69
70         "Offnet die Datei f"ur die Klasse des gegebenen Namens zum Lesen.
71         Dabei werden alle im Suchpfad angegebenen Verzeichnisse durchsucht,
72         bis eine entsprechende Datei  ( <classname>.class) gefunden wird. 
73         
74 ******************************************************************************/
75
76 bool suck_start (unicode *classname)
77 {
78 #define MAXFILENAME 1000           /* Maximale Langes des Dateinamens plus Pfad */
79
80         char filename[MAXFILENAME+10];   /* Platz fuer '.class' */
81         u2 filenamelen;
82         char *pathpos;
83         u2 i,c;
84
85
86         pathpos = classpath;
87
88         while (*pathpos) {
89                 while ( *pathpos == ':' ) pathpos++;
90  
91                 filenamelen=0;
92                 while ( (*pathpos) && (*pathpos!=':') ) {
93                     PANICIF (filenamelen >= MAXFILENAME, "Filename too long") ;
94                         
95                         filename[filenamelen++] = *(pathpos++);
96                         }
97
98                 filename[filenamelen++] = '/';
99    
100                 for (i=0; i < classname -> length; i++) {
101                         PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
102                         
103                         c = classname -> text [i];
104                         if (c=='/') c = '/';     /* Slashes im Namen passen zu UNIX */
105                         else {
106                                 if ( c<=' ' || c>'z') {
107                                         c = '?';
108                                         }
109                                 }
110                         
111                         filename[filenamelen++] = c;    
112                         }
113       
114                 strcpy (filename+filenamelen, ".class");
115
116                 classfile = fopen(filename, "r");
117                 if (classfile) {
118                         return true;
119                         }
120
121                 
122                 }
123                    
124         sprintf (logtext,"Can not open class file '%s'", filename);
125         error();
126         return false;
127 }
128
129
130 /************************** Funktion: suck_stop *******************************
131
132         Schlie"st die offene Datei wieder.
133         
134 ******************************************************************************/
135
136 void suck_stop ()
137 {
138         u4 rest=0;
139         u1 dummy;
140         
141         while ( fread (&dummy, 1,1, classfile) > 0) rest++;
142         if (rest) {
143                 sprintf (logtext,"There are %d access bytes at end of classfile",
144                                  (int) rest);
145                 dolog();
146                 }
147                         
148         fclose (classfile);
149         classfile = NULL;
150 }
151       
152
153
154 /************************** Lesefunktionen ***********************************
155
156         Lesen von der Datei in verschieden grossen Paketen
157         (8,16,32,64-bit Integer oder Float)
158
159 *****************************************************************************/
160
161 void suck_nbytes (u1 *buffer, u4 len)
162 {
163         if ( fread (buffer, 1, len, classfile) != len) panic ("Unexpected EOF");
164 }
165
166
167 void skip_nbytes (u4 len)
168 {
169         u4 i;
170         for (i=0; i<len; i++) suck_u1 ();
171 }
172
173
174 u1 suck_u1 ()
175 {
176         u1 b;
177         if ( fread (&b, 1,1, classfile) != 1) panic ("Unexpected EOF");
178         return b;
179 }
180
181 s1 suck_s1 ()
182 {
183         s1 b;
184         if ( fread (&b, 1,1, classfile) != 1) panic ("Unexpected EOF");
185         return b;
186 }
187
188
189 u2 suck_u2 ()
190 {
191         u1 b[2];
192         if ( fread (b, 1,2, classfile) != 2) panic ("Unexpected EOF");
193         return (b[0]<<8) + b[1];
194 }
195
196 s2 suck_s2 ()
197 {
198         return suck_u2 ();
199 }
200
201
202 u4 suck_u4 ()
203 {
204         u1 b[4];
205         u4 v;
206         if ( fread (b, 1,4, classfile) != 4) panic ("Unexpected EOF");
207         v = ( ((u4)b[0]) <<24) + ( ((u4)b[1])<<16) + ( ((u4)b[2])<<8) + ((u4)b[3]);
208         return v;
209 }
210
211 s4 suck_s4 ()
212 {
213         s4 v = suck_u4 ();
214         return v;
215 }
216
217 u8 suck_u8 ()
218 {
219 #if U8_AVAILABLE
220         u8 lo,hi;
221         hi = suck_u4();
222         lo = suck_u4();
223         return (hi<<32) + lo;
224 #else
225         u8 v;
226         v.high = suck_u4();
227         v.low = suck_u4();
228         return v;
229 #endif
230 }
231
232 s8 suck_s8 ()
233 {
234         return suck_u8 ();
235 }
236         
237
238 float suck_float ()
239 {
240         float f;
241
242 #if !WORDS_BIGENDIAN 
243                 u1 buffer[4];
244                 u2 i;
245                 for (i=0; i<4; i++) buffer[3-i] = suck_u1 ();
246                 memcpy ( (u1*) (&f), buffer, 4);
247 #else 
248                 suck_nbytes ( (u1*) (&f), 4 );
249 #endif
250
251         PANICIF (sizeof(float) != 4, "Incompatible float-format");
252         
253         return f;
254 }
255
256
257 double suck_double ()
258 {
259         double d;
260
261 #if !WORDS_BIGENDIAN 
262                 u1 buffer[8];
263                 u2 i;   
264                 for (i=0; i<8; i++) buffer[7-i] = suck_u1 ();
265                 memcpy ( (u1*) (&d), buffer, 8);
266 #else 
267                 suck_nbytes ( (u1*) (&d), 8 );
268 #endif
269
270         PANICIF (sizeof(double) != 8, "Incompatible double-format" );
271         
272         return d;
273 }
274
275
276
277
278 /******************************************************************************
279 ******************** Der Unicode-Symbol-Verwalter *****************************
280 *******************************************************************************
281
282         legt eine Hashtabelle f"ur unicode-Symbole an und verwaltet
283         das Eintragen neuer Symbole
284         
285 ******************************************************************************/
286
287
288
289 #define UNICODESTART  2187      /* Startgr"osse: moeglichst gross und prim */
290
291 static u4 unicodeentries;       /* Anzahl der Eintr"age in der Tabelle */
292 static u4 unicodehashsize;      /* Gr"osse der Tabelle */
293 static unicode ** unicodehash;  /* Zeiger auf die Tabelle selbst */
294
295
296 /*********************** Funktion: unicode_init ******************************
297
298         Initialisiert die unicode-Symboltabelle (muss zu Systemstart einmal
299         aufgerufen werden)
300         
301 *****************************************************************************/
302
303 void unicode_init ()
304 {
305         u4 i;
306         
307 #ifdef STATISTICS
308         count_unicode_len += sizeof(unicode*) * unicodehashsize;
309 #endif
310
311         unicodeentries = 0;
312         unicodehashsize = UNICODESTART;
313         unicodehash = MNEW (unicode*, unicodehashsize);
314         for (i=0; i<unicodehashsize; i++) unicodehash[i] = NULL;
315 }
316
317
318 /*********************** Funktion: unicode_close *****************************
319
320         Gibt allen Speicher der Symboltabellen frei.
321         Parameter: Ein Zeiger auf eine Funktion, die dazu n"otig ist, 
322                    Stringkonstanten (die mit 'unicode_setstringlink' 
323                    Unicode-Symbole gebunden wurden) wieder freizugeben
324         
325 *****************************************************************************/
326
327 void unicode_close (stringdeleter del)
328 {
329         unicode *u;
330         u4 i;
331         
332         for (i=0; i<unicodehashsize; i++) {
333                 u = unicodehash[i];
334                 while (u) {
335                         unicode *nextu = u->hashlink;
336
337                         if (u->string) del (u->string);
338                         
339                         MFREE (u->text, u2, u->length);
340                         FREE (u, unicode);
341                         u = nextu;
342                         }       
343                 }
344         MFREE (unicodehash, unicode*, unicodehashsize);
345 }
346
347
348 /********************* Funktion: unicode_display ******************************
349         
350         Gibt ein unicode-Symbol auf stdout aus (zu Debugzwecken)
351
352 ******************************************************************************/
353
354 void unicode_display (unicode *u)
355 {
356         u2 i,c;
357         for (i=0; i < u->length; i++) {
358                 c = u->text[i];
359                 if (c>=32 && c<=127) printf ("%c",c);
360                                 else printf ("?");
361                 }
362         fflush (stdout);
363 }
364
365
366 /********************* Funktion: unicode_sprint ******************************
367         
368         Schreibt ein unicode-Symbol in einen C-String
369
370 ******************************************************************************/ 
371
372 void unicode_sprint (char *buffer, unicode *u)
373 {
374         u2 i;
375         for (i=0; i < u->length; i++) buffer[i] = u->text[i];
376         buffer[i] = '\0';
377 }
378
379
380 /********************* Funktion: unicode_fprint ******************************
381         
382         Schreibt ein unicode-Symbol auf eine Datei aus
383
384 ******************************************************************************/ 
385
386 void unicode_fprint (FILE *file, unicode *u)
387 {
388         u2 i;
389         for (i=0; i < u->length; i++) putc (u->text[i], file);
390
391
392
393 /****************** interne Funktion: u_hashkey ******************************/
394
395 static u4 u_hashkey (u2 *text, u2 length)
396 {
397         u4 k = 0;
398         u2 i,sh=0;
399         
400         for (i=0; i<length; i++) {
401                 k ^=  ( ((u4) (text[i])) << sh );
402                 if (sh<16) sh++;
403                      else  sh=0;
404                 }
405                 
406         return k;
407 }
408
409 /*************** interne Funktion: u_reorganizehash **************************/
410
411 static void u_reorganizehash ()
412 {
413         u4 i;
414         unicode *u;
415
416         u4 newhashsize = unicodehashsize*2;
417         unicode **newhash = MNEW (unicode*, newhashsize);
418
419 #ifdef STATISTICS
420         count_unicode_len += sizeof(unicode*) * unicodehashsize;
421 #endif
422
423         for (i=0; i<newhashsize; i++) newhash[i] = NULL;
424
425         for (i=0; i<unicodehashsize; i++) {
426                 u = unicodehash[i];
427                 while (u) {
428                         unicode *nextu = u -> hashlink;
429                         u4 slot = (u->key) % newhashsize;
430                                                 
431                         u->hashlink = newhash[slot];
432                         newhash[slot] = u;
433
434                         u = nextu;
435                         }
436                 }
437         
438         MFREE (unicodehash, unicode*, unicodehashsize);
439         unicodehash = newhash;
440         unicodehashsize = newhashsize;
441 }
442
443
444 /****************** Funktion: unicode_new_u2 **********************************
445
446         Legt ein neues unicode-Symbol an. Der Text des Symbols wird dieser
447         Funktion als u2-Array "ubergeben
448
449 ******************************************************************************/
450
451 unicode *unicode_new_u2 (u2 *text, u2 length)
452 {
453         u4 key = u_hashkey (text, length);
454         u4 slot = key % unicodehashsize;
455         unicode *u = unicodehash[slot];
456         u2 i;
457
458         while (u) {
459                 if (u->key == key) {
460                         if (u->length == length) {
461                                 for (i=0; i<length; i++) {
462                                         if (text[i] != u->text[i]) goto nomatch;
463                                         }       
464                                         return u;
465                                 }
466                         }
467                 nomatch:
468                 u = u->hashlink;
469                 }
470
471 #ifdef STATISTICS
472         count_unicode_len += sizeof(unicode) + 2 * length;
473 #endif
474
475         u = NEW (unicode);
476         u->key = key;
477         u->length = length;
478         u->text = MNEW (u2, length);
479         u->class = NULL;
480         u->string = NULL;
481         u->hashlink = unicodehash[slot];
482         unicodehash[slot] = u;
483         for (i=0; i<length; i++) u->text[i] = text[i];
484
485         unicodeentries++;
486         
487         if ( unicodeentries > (unicodehashsize/2)) u_reorganizehash();
488         
489         return u;
490 }
491
492
493 /********************* Funktion: unicode_new_char *****************************
494
495         Legt ein neues unicode-Symbol an. Der Text des Symbols wird dieser
496         Funktion als C-String ( = char* ) "ubergeben
497
498 ******************************************************************************/
499
500 unicode *unicode_new_char (char *text)
501 {
502 #define MAXNEWCHAR 500
503         u2 buffer[MAXNEWCHAR];
504         u2 length = 0;
505         u1 c;
506         
507         while ( (c = *text) != '\0' ) {
508                 if (length>=MAXNEWCHAR) panic ("Text too long in unicode_new_char");
509                 buffer[length++] = c;
510                 text ++;
511                 }
512         return unicode_new_u2 (buffer, length);
513 }
514
515
516 /********************** Funktion: unicode_setclasslink ************************
517
518         H"angt einen Verweis auf eine Klasse an ein unicode-Symbol an.
519
520 ******************************************************************************/
521
522 void unicode_setclasslink (unicode *u, classinfo *class)
523 {
524         PANICIF (u->class, "Attempt to attach class to already attached symbol");
525         u->class = class;
526 }
527
528 /********************** Funktion: unicode_getclasslink ************************
529
530         Sucht den Verweis von einem unicode-Symbol auf eine Klasse.
531         Wenn keine solche Klasse existiert, dann wird ein Fehler
532         ausgegeben.
533
534 ******************************************************************************/
535
536 classinfo *unicode_getclasslink (unicode *u)
537 {
538         PANICIF (!u->class, "Attempt to get unknown class-reference");
539         return u->class;
540 }
541
542
543
544 /********************* Funktion: unicode_unlinkclass *************************
545
546         Entfernt den Verweis auf eine Klasse wieder von einem Symbol
547         
548 ******************************************************************************/
549
550 void unicode_unlinkclass (unicode *u)
551 {
552         PANICIF (!u->class, "Attempt to unlink not yet linked symbol");
553         u -> class = NULL;
554 }
555
556
557
558 /******************* Funktion> unicode_setstringlink *********************
559
560         H"angt einen Verweis auf einen konstanten String an ein 
561         Unicode-Symbol
562         
563 *************************************************************************/
564
565 void unicode_setstringlink (unicode *u, java_objectheader *str)
566 {
567         PANICIF (u->string, "Attempt to attach string to already attached symbol");
568         u->string = str;
569 }
570
571
572 /********************* Funktion: unicode_unlinkstring *************************
573
574         Entfernt den Verweis auf einen String wieder von einem Symbol
575         
576 ******************************************************************************/
577
578 void unicode_unlinkstring (unicode *u)
579 {
580         PANICIF (!u->class, "Attempt to unlink not yet linked symbol");
581         u -> string = NULL;
582 }
583
584
585
586 /*********************** Funktion: unicode_show ******************************
587
588         gibt eine Aufstellung aller Symbol im unicode-hash auf stdout aus.
589         (nur f"ur Debug-Zwecke)
590         
591 *****************************************************************************/
592
593 void unicode_show ()
594 {
595         unicode *u;
596         u4 i;
597
598         printf ("UNICODE-HASH: %d slots for %d entries\n", 
599                  (int) unicodehashsize, (int) unicodeentries );
600                   
601         for (i=0; i<unicodehashsize; i++) {
602                 u = unicodehash[i];
603                 if (u) {
604                         printf ("SLOT %d: ", (int) i);
605                         while (u) {
606                                 printf ("'");
607                                 unicode_display (u);
608                                 printf ("' ");
609                                 if (u->string) printf ("(string)  ");
610                                 u = u->hashlink;
611                                 }       
612                         printf ("\n");
613                         }
614                 
615                 }
616 }
617
618
619
620 /******************************************************************************
621 *********************** Diverse Support-Funktionen ****************************
622 ******************************************************************************/
623
624
625 /******************** Funktion: desc_to_type **********************************
626
627         Findet zu einem gegebenen Typdescriptor den entsprechenden 
628         Java-Grunddatentyp.
629         
630 ******************************************************************************/
631
632 u2 desc_to_type (unicode *descriptor)
633 {
634         if (descriptor->length < 1) panic ("Type-Descriptor is empty string");
635         
636         switch (descriptor->text[0]) {
637         case 'B': 
638         case 'C':
639         case 'I':
640         case 'S':  
641         case 'Z':  return TYPE_INT;
642         case 'D':  return TYPE_DOUBLE;
643         case 'F':  return TYPE_FLOAT;
644         case 'J':  return TYPE_LONG;
645         case 'L':
646         case '[':  return TYPE_ADDRESS;
647         }
648                         
649         sprintf (logtext, "Invalid Type-Descriptor: "); 
650         unicode_sprint (logtext+strlen(logtext), descriptor);
651         error (); 
652         return 0;
653 }
654
655
656 /********************** Funktion: desc_typesize *******************************
657
658         Berechnet die L"ange (in Byte) eines Datenelements gegebenen Typs,
659         der durch den Typdescriptor gegeben ist.
660         
661 ******************************************************************************/
662
663 u2 desc_typesize (unicode *descriptor)
664 {
665         switch (desc_to_type(descriptor)) {
666         case TYPE_INT:     return 4;
667         case TYPE_LONG:    return 8;
668         case TYPE_FLOAT:   return 4;
669         case TYPE_DOUBLE:  return 8;
670         case TYPE_ADDRESS: return sizeof(voidptr);
671         default:           return 0;
672         }
673 }
674
675
676
677
678
679 /******************************************************************************
680 ********************* Der garbage-collected Heap ******************************
681 *******************************************************************************
682
683         verwaltet einen Heap mit automatischer Speicherfreigabe.
684
685         (eine ausf"uhrliche Dokumentation findet sich in der Datei: 
686         collect.doc)
687         
688 ******************************************************************************/
689
690
691 bool collectverbose = false;  /* soll Meldung beim GC ausgegeben werden? */
692
693
694 #define BLOCKSIZE 8         /* Gr"osse eines Speicherblockes */
695 typedef u8 heapblock;       /* Datentyp mit der Gr"osse eines Speicherblocks */
696
697 #if U8_AVAILABLE && SUPPORT_LONG
698 #define bitfieldtype u8
699 #define BITFIELDBITS 64
700 #else
701 #define bitfieldtype u4
702 #define BITFIELDBITS 32
703 #endif
704
705 u4 heapsize;                /* Gr"osse des Heap in Blocks */
706 u4 topofheap;               /* Bisherige Obergrenze Heaps */
707 heapblock *heap;            /* Speicher f"ur den Heap selbst */
708
709 bitfieldtype *startbits;     /* Bitfeld f"ur Bereichsstartkennung */
710 bitfieldtype *markbits;      /* Bitfeld f"ur Markierung */
711 bitfieldtype *referencebits; /* Bitfeld f"ur Folgereferenzenkennung */
712
713 u4 heapfillgrade;           /* Menge der Daten im Heap */
714 u4 collectthreashold;       /* Schwellwert f"ur n"achstes GC */
715
716 void **bottom_of_stack;     /* Zeiger auf Untergrenze des C-Stacks */ 
717 chain *allglobalreferences; /* Liste f"ur alle globalen Zeiger */
718
719 typedef struct finalizernode {
720         struct finalizernode *next;     
721         u4 objstart;
722         methodinfo *finalizer;
723         } finalizernode;
724         
725 finalizernode *livefinalizees;
726 finalizernode *deadfinalizees;
727
728
729 typedef struct memarea {    /* Datenstruktur f"ur einen Freispeicherbereich */
730         struct memarea *next;
731         } memarea;
732
733 typedef struct bigmemarea {   /* Datenstruktur f"ur einen */
734         struct bigmemarea *next;  /* Freispeicherbereich variabler L"ange */
735         u4 size;
736         } bigmemarea;
737         
738 #define DIFFERENTSIZES 128         /* Anzahl der 'kleinen' Freispeicherlisten */
739 memarea *memlist[DIFFERENTSIZES];  /* Die 'kleinen' Freispeicherlisten */
740 bitfieldtype memlistbits[DIFFERENTSIZES/BITFIELDBITS]; 
741                                    /* Bitfeld, in dem jeweils ein Bit gesetzt */
742                                    /* ist, wenn eine Liste noch etwas enth"alt */
743
744 bigmemarea *bigmemlist;         /* Liste der gr"osseren Freispeicherbereiche */
745
746
747
748
749 /**************** Hilfsfunktion: lowest **************************************
750
751 liefert als Ergebnis die Nummer des niederwertigsten Bits einer 
752 Zahl vom Typ bitfieldtype, das 1 ist.
753 Wenn die ganze Zahl keine 1en enth"alt, dann ist egal, was f"ur einen
754 Wert die Funktion l"iefert.
755 z.B.: lowest(1) = 0,   lowest(12) = 2,   lowest(1024) = 10
756
757 *****************************************************************************/
758
759 static u1 lowesttable[256] = {
760         255, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
761         4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
762         5,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
763         4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
764         6,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
765         4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
766         5,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
767         4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
768         7,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
769         4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
770         5,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
771         4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
772         6,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
773         4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
774         5,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
775         4,   0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 };
776         
777 static int lowest(bitfieldtype i)
778 {
779 #if BITFIELDBITS==64
780         u8 i1 = i<<32;
781         if (i1) {
782                 u8 i11 = i1<<16;
783                 if (i11) {
784                         u8 i111 = i11<<8;
785                         if (i111) return lowesttable[i111>>56];
786                         else      return 8+lowesttable[i11>>56];
787                         }
788                 else {
789                         u8 i112 = i1<<8;
790                         if (i112) return 16+lowesttable[i112>>56];
791                         else      return 24+lowesttable[i1>>56];
792                         }
793                 }
794         else {
795                 u8 i12 = i<<16;
796                 if (i12) {
797                         u8 i121 = i12<<8;
798                         if (i121) return 32+lowesttable[i121>>56];
799                         else      return 40+lowesttable[i12>>56];
800                         }
801                 else {
802                         u8 i122 = i<<8;
803                         if (i122) return 48+lowesttable[i122>>56];
804                         else      return 56+lowesttable[i>>56];
805                         }
806                 }
807 #else
808         u4 i1 = i<<16;
809         if (i1) {
810                 u4 i11 = i1<<8;
811                 if (i11) return lowesttable[i11>>24];
812                 else     return 8+lowesttable[i1>>24];
813                 }
814         else {
815                 u4 i12 = i<<8;
816                 if (i12) return 16+lowesttable[i12>>24];
817                 else     return 24+lowesttable[i>>24];
818                 }
819 #endif
820 }
821
822
823 /******** Funktionen zum Setzen und L"oschen von Bits in Bitfeldern ***********/
824
825 static void setbit(bitfieldtype *bitfield, u4 bitnumber)
826 {
827         bitfield[bitnumber/BITFIELDBITS] |= 
828           ((bitfieldtype) 1) << (bitnumber%BITFIELDBITS);
829 }
830
831 static void clearbit(bitfieldtype *bitfield, u4 bitnumber)
832 {
833         bitfield[bitnumber/BITFIELDBITS] &= 
834            ~((bitfieldtype) 1) << (bitnumber%BITFIELDBITS);
835 }
836
837 static bool isbitset(bitfieldtype *bitfield, u4 bitnumber)
838 {
839         return ( bitfield[bitnumber/BITFIELDBITS] & 
840            ( ((bitfieldtype) 1) << (bitnumber%BITFIELDBITS) ) ) != 0;
841 }
842
843 static bool isbitclear(bitfieldtype *bitfield, u4 bitnumber)
844 {
845         return ( bitfield[bitnumber/BITFIELDBITS] & 
846             ( ((bitfieldtype) 1) << (bitnumber%BITFIELDBITS) ) ) == 0;
847 }
848
849
850 /***************** Funktion: clearbitfield ************************************
851         
852         l"oscht ein ganzes Bitfeld
853         
854 ******************************************************************************/
855
856 static void clearbitfield(bitfieldtype *bitfield, u4 fieldsize)
857
858         u4 i,t;
859         t = ALIGN(fieldsize, BITFIELDBITS) / BITFIELDBITS;
860         for (i=0; i<t; i++) bitfield[i] = 0;
861 }
862
863 /************** Funktion: maskfieldwithfield **********************************
864         
865         Verkn"upft zwei Bitfelder bitweise mit UND, das erste Bitfeld
866         wird mit dem Ergebnis "uberschrieben 
867         
868 ******************************************************************************/
869         
870 static void maskfieldwithfield (bitfieldtype* bitfield, 
871                                 bitfieldtype *maskfield, u4 fieldsize)
872 {
873         u4 i,t;
874         t = ALIGN(fieldsize, BITFIELDBITS) / BITFIELDBITS;
875         for (i=0; i<t; i++) bitfield[i] &= maskfield[i];
876 }
877
878
879 /************** Funktion: findnextsetbit **************************************
880
881         Sucht in einem Bitfeld ab einer Stelle das n"achste gesetzte Bit
882         und liefert die Nummer dieses Bits.
883         Wenn kein Bit mehr zwischen 'bitnumber' und 'fieldsize' gesetzt
884         ist, dann wird fieldsize zur"uckgeliefte.
885
886 ******************************************************************************/
887
888 static u4 findnextsetbit(bitfieldtype* bitfield, u4 fieldsize, u4 bitnumber)
889 {
890         bitfieldtype pattern;
891
892         for (;;) {
893                 if (bitnumber >= fieldsize) return fieldsize;
894                 
895                 pattern = bitfield[bitnumber/BITFIELDBITS];
896                 pattern >>= (bitnumber%BITFIELDBITS);
897                 if (pattern) return bitnumber + lowest(pattern);
898
899                 bitnumber = ((bitnumber + BITFIELDBITS) / BITFIELDBITS) * BITFIELDBITS;
900                 }
901 }
902
903
904 /************ Funktion: findnextcombination_set_unset *************************
905
906         funktioniert wie findnextsetbit, allerdings sucht diese Funktion
907         nach einer Stelle, an der gleichzeitig ein Bit im ersten
908         Bitfeld gesetzt ist und im zweiten Bitfeld das entsprechende
909         Bit nicht gesetzt ist.
910
911 ******************************************************************************/
912
913 static u4 findnextcombination_set_unset 
914         (bitfieldtype *bitfield1, bitfieldtype* bitfield2, u4 fieldsize, u4 bitnumber)
915 {
916         bitfieldtype pattern;
917
918         for (;;) {
919                 if (bitnumber >= fieldsize) return fieldsize;
920                 
921                 pattern =     bitfield1[bitnumber/BITFIELDBITS] 
922                           & (~bitfield2[bitnumber/BITFIELDBITS]);
923                 pattern >>= (bitnumber%BITFIELDBITS);
924                 if (pattern) return bitnumber + lowest(pattern);
925
926                 bitnumber = ((bitnumber + BITFIELDBITS) / BITFIELDBITS) * BITFIELDBITS;
927                 }
928 }
929
930
931
932 /************** Funktion: memlist_init ****************************************
933
934         initialisiert die Freispeicherlisten (zum nachfolgenden Eintragen 
935         mit memlist_addrange).
936
937 ******************************************************************************/
938
939 static void memlist_init ()
940 {
941         u4 i;
942         for (i=0; i<DIFFERENTSIZES; i++) memlist[i] = NULL;
943         clearbitfield (memlistbits, DIFFERENTSIZES);
944         bigmemlist = NULL;
945 }
946
947
948 /************** Funktion: memlist_addrange ************************************
949
950         f"ugt einen Bereich von Heap-Bl"ocken zur Freispeicherliste 
951         hinzu (in die freien Heap-Bl"ocke werden dabei verschiedene 
952         Verkettungszeiger hineingeschrieben).
953
954 ******************************************************************************/
955
956 static void memlist_addrange (u4 freestart, u4 freesize)
957 {
958         if (freesize>=DIFFERENTSIZES) {
959                 bigmemarea *m = (bigmemarea*) (heap+freestart);
960                 m -> next = bigmemlist;
961                 m -> size = freesize;
962                 bigmemlist = m;
963                 }
964         else {
965                 if (freesize*BLOCKSIZE>=sizeof(memarea)) {
966                         memarea *m = (memarea*) (heap+freestart);
967                         m -> next = memlist[freesize];
968                         memlist[freesize] = m;
969                         setbit (memlistbits, freesize);
970                         }
971                 }
972 }
973
974
975 /************** Funktion: memlist_getsuitable *********************************
976
977         sucht in der Freispeicherliste einen Speicherbereich, der m"oglichst
978         genau die gew"unschte L"ange hat.
979         Der Bereich wird dabei auf jeden Fall aus der Liste ausgetragen.
980         (Wenn der Bereich zu lang sein sollte, dann kann der Aufrufer den
981         Rest wieder mit 'memlist_addrange' in die Liste einh"angen)
982         
983         Return (in Referenzparametern): 
984                 *freestart: Anfang des freien Speichers
985                 *freelength: L"ange dieses Speicherbereiches
986
987         Wenn kein passender Speicherblock mehr gefunden werden kann, dann 
988         wird in '*freelength' 0 hineingeschrieben.
989         
990 ******************************************************************************/         
991
992 static void memlist_getsuitable (u4 *freestart, u4 *freelength, u4 length)
993 {
994         bigmemarea *m;
995         bigmemarea *prevm = NULL;
996         
997         if (length<DIFFERENTSIZES) {
998                 u4 firstfreelength;
999
1000                 if (memlist[length]) {
1001                         firstfreelength = length;
1002                         }
1003                 else {
1004                         firstfreelength = findnextsetbit 
1005                                 (memlistbits, DIFFERENTSIZES, length+3); 
1006                                 /* wenn kein passender Block da ist, dann gleich nach */
1007                                 /* einem etwas gr"osseren suchen, damit keine kleinen */
1008                                 /* St"uckchen "ubrigbleiben */
1009                         }
1010                         
1011                 if (firstfreelength<DIFFERENTSIZES) {
1012                         memarea *m = memlist[firstfreelength];
1013                         memlist[firstfreelength] = m->next;             
1014                         if (!m->next) clearbit (memlistbits, firstfreelength);
1015                         *freestart = ((heapblock*) m) - heap;
1016                         *freelength = firstfreelength;
1017                         return;
1018                         }
1019                 }
1020
1021         m = bigmemlist;
1022         while (m) {
1023                 if (m->size >= length) {
1024                         if (prevm) prevm->next = m->next;                                       
1025                                 else   bigmemlist = m->next;
1026                         
1027                         *freestart = ((heapblock*) m) - heap;
1028                         *freelength = m->size;
1029                         return ;                        
1030                         }
1031
1032                 prevm = m;
1033                 m = m->next;
1034                 }
1035         
1036         *freelength=0;
1037 }
1038
1039
1040
1041
1042
1043 /******************* Funktion: mark *******************************************
1044
1045         Markiert ein m"oglicherweise g"ultiges Objekt.
1046         Sollte sich herausstellen, dass der Zeiger gar nicht auf ein Objekt
1047         am Heap zeigt, dann wird eben gar nichts markiert.
1048
1049 ******************************************************************************/
1050
1051 static void markreferences (void **rstart, void **rend);
1052
1053 static void mark (heapblock *obj)
1054 {
1055         u4 blocknum,objectend;
1056
1057         if ((long) obj & (BLOCKSIZE-1)) return;
1058         
1059         if (obj<heap) return;
1060         if (obj>=(heap+topofheap) ) return;
1061
1062         blocknum = obj-heap;
1063         if ( isbitclear(startbits, blocknum) ) return;
1064         if ( isbitset(markbits, blocknum) ) return;
1065
1066         setbit (markbits, blocknum);
1067         
1068         if ( isbitclear(referencebits, blocknum) ) return;
1069
1070         objectend = findnextsetbit (startbits, topofheap, blocknum+1);
1071         markreferences ((void**)obj, (void**) (heap+objectend) );
1072 }
1073
1074
1075 /******************** Funktion: markreferences ********************************
1076
1077         Geht einen Speicherbereich durch, und markiert alle Objekte, auf
1078         die von diesem Bereich aus irgendeine Referenz existiert.
1079
1080 ******************************************************************************/
1081
1082 static void markreferences (void **rstart, void **rend)
1083 {
1084         void **ptr;
1085         
1086         for (ptr=rstart; ptr<rend; ptr++) mark (*ptr);
1087 }
1088
1089
1090 /******************* Funktion: markstack **************************************
1091
1092         Marks all objects that are referenced by the (C-)stacks of
1093         all live threads.
1094
1095         (The stack-bottom is to be specified in the call to heap_init).
1096
1097 ******************************************************************************/
1098
1099 static void markstack ()                   /* schani */
1100 {
1101         void *dummy;
1102
1103 #ifdef USE_THREADS
1104     thread *aThread;
1105
1106     for (aThread = liveThreads; aThread != 0;
1107          aThread = CONTEXT(aThread).nextlive) {
1108                 mark((heapblock*)aThread);
1109                 if (aThread == currentThread) {
1110                     void **top_of_stack = &dummy;
1111                     
1112                     if (top_of_stack > (void**)CONTEXT(aThread).stackEnd)
1113                                 markreferences((void**)CONTEXT(aThread).stackEnd, top_of_stack);
1114                     else        
1115                                 markreferences(top_of_stack, (void**)CONTEXT(aThread).stackEnd);
1116                         }
1117                 else {
1118                     if (CONTEXT(aThread).usedStackTop > CONTEXT(aThread).stackEnd)
1119                                 markreferences((void**)CONTEXT(aThread).stackEnd,
1120                                                (void**)CONTEXT(aThread).usedStackTop);
1121                     else        
1122                                 markreferences((void**)CONTEXT(aThread).usedStackTop,
1123                                                (void**)CONTEXT(aThread).stackEnd);
1124                         }
1125             }
1126
1127     markreferences((void**)&threadQhead[0],
1128                    (void**)&threadQhead[MAX_THREAD_PRIO]);
1129
1130 #else
1131     void **top_of_stack = &dummy;
1132
1133     if (top_of_stack > bottom_of_stack)
1134         markreferences(bottom_of_stack, top_of_stack);
1135     else
1136         markreferences(top_of_stack, bottom_of_stack);
1137 #endif
1138 }
1139
1140
1141
1142 /**************** Funktion: searchlivefinalizees *****************************
1143
1144         geht die Liste aller Objekte durch, die noch finalisiert werden m"ussen
1145         (livefinalizees), und tr"agt alle nicht mehr markierten in die
1146         Liste deadfinalizess ein (allerdings werden sie vorher noch als
1147         erreicht markiert, damit sie nicht jetzt gleich gel"oscht werden).
1148         
1149 *****************************************************************************/ 
1150
1151 static void searchlivefinalizees ()
1152 {
1153         finalizernode *fn = livefinalizees;
1154         finalizernode *lastlive = NULL;
1155                 
1156         while (fn) {
1157         
1158                 /* alle zu finalisierenden Objekte, die nicht mehr markiert sind: */
1159                 if (isbitclear (markbits, fn->objstart)) {
1160                         finalizernode *nextfn = fn->next;
1161
1162                         mark (heap + fn->objstart); 
1163
1164                         if (lastlive) lastlive -> next = nextfn;
1165                                        else livefinalizees = nextfn;
1166
1167                         fn -> next = deadfinalizees;
1168                         deadfinalizees = fn;
1169                         
1170                         fn = nextfn;
1171                         }
1172                 else {  
1173                         lastlive = fn;
1174                         fn = fn->next;
1175                         }
1176                 }
1177 }
1178
1179
1180
1181 /********************** Funktion: finalizedead *******************************
1182
1183         ruft die 'finalize'-Methode aller Objekte in der 'deadfinalizees'-
1184         Liste auf.
1185         Achtung: Es kann hier eventuell zu neuerlichen Speicheranforderungen
1186         (mit potentiell notwendigem GC) kommen, deshalb m"ussen manche
1187         globalen Variablen in lokale Variblen kopiert werden 
1188         (Reentrant-F"ahigkeit!!!)
1189          
1190 ******************************************************************************/
1191
1192 static void finalizedead()
1193 {
1194         finalizernode *fn = deadfinalizees;
1195         deadfinalizees = NULL;
1196         
1197         while (fn) {
1198                 finalizernode *nextfn = fn->next;
1199                 
1200                 asm_calljavamethod (fn->finalizer, heap+fn->objstart, NULL,NULL,NULL);
1201                 FREE (fn, finalizernode);
1202                 
1203                 fn = nextfn;
1204                 }
1205
1206 }
1207
1208
1209
1210 /****************** Funktion: heap_docollect **********************************
1211         
1212         F"uhrt eine vollst"andige Garbage Collection durch
1213         
1214 ******************************************************************************/
1215
1216 static void heap_docollect ()
1217 {
1218         u4 freestart,freeend;
1219         void **p;
1220         bitfieldtype *dummy;
1221         u4 heapfreemem;
1222         u4 oldfillgrade;
1223
1224
1225         if (runverbose) {
1226                 fprintf(stderr, "doing garbage collection\n");
1227                 }
1228                 /* alle Markierungsbits l"oschen */
1229         clearbitfield (markbits, topofheap);
1230
1231                 /* Alle vom Stack referenzierten Objekte markieren */
1232         asm_dumpregistersandcall (markstack);
1233
1234                 /* Alle von globalen Variablen erreichbaren Objekte markieren */
1235         p = chain_first (allglobalreferences);
1236         while (p) {
1237                 mark (*p);
1238                 p = chain_next (allglobalreferences);   
1239                 }
1240
1241                 /* alle Objekte durchsehen, die eine finalizer-Methode haben */
1242         searchlivefinalizees();
1243
1244                 /* alle Reference-Bits l"oschen, deren Objekte nicht */
1245                 /* mehr erreichbar sind */
1246         maskfieldwithfield (referencebits, markbits, topofheap);
1247
1248
1249                 /* Freispeicherliste initialisieren */
1250         memlist_init ();
1251         
1252         
1253                 /* Heap schrittweise durchgehen, und alle freien Bl"ocke merken */
1254
1255         heapfreemem = 0;
1256         freeend=0;
1257         for (;;) {
1258                         /* Anfang des n"achsten freien Bereiches suchen */
1259                 freestart = findnextcombination_set_unset 
1260                         (startbits, markbits, topofheap, freeend);
1261
1262                         /* Wenn es keinen freien Bereich mehr gibt -> fertig */
1263                 if (freestart>=topofheap) goto freememfinished;
1264
1265                         /* Anfang des freien Bereiches markieren */
1266                 setbit (markbits, freestart);
1267
1268                         /* Ende des freien Bereiches suchen */          
1269                 freeend = findnextsetbit (markbits, topofheap, freestart+1);
1270
1271                         /* Freien Bereich in Freispeicherliste einh"angen */
1272                 memlist_addrange (freestart, freeend-freestart);
1273
1274                         /* Menge des freien Speichers mitnotieren */
1275                 heapfreemem += (freeend-freestart);
1276                 }
1277
1278         freememfinished:
1279
1280                 /* Die Rollen von markbits und startbits vertauschen */ 
1281         dummy = markbits;
1282         markbits = startbits;
1283         startbits = dummy;
1284
1285
1286                 /* Threashold-Wert f"ur n"achstes Collect */
1287         oldfillgrade = heapfillgrade;
1288         heapfillgrade = topofheap - heapfreemem;
1289         collectthreashold = heapfillgrade*3;   /* eine nette Heuristik */
1290
1291                 /* Eventuell eine Meldung ausgeben */
1292         if (collectverbose) {
1293                 sprintf (logtext, "Garbage Collection:  previous/now = %d / %d ",
1294                   (int) (oldfillgrade * BLOCKSIZE), 
1295                   (int) (heapfillgrade * BLOCKSIZE) );
1296                 dolog ();
1297                 }
1298
1299
1300                 
1301                 /* alle gerade unerreichbar gewordenen Objekte mit 
1302                    finalize-Methoden jetzt finalisieren.
1303                    Achtung: Diese Funktion kann zu neuerlichem GC f"uhren!! */
1304         finalizedead ();
1305         
1306 }
1307
1308 /************************* Function: gc_init **********************************
1309
1310         Initializes the garbage collection thread mechanism.
1311
1312 ******************************************************************************/
1313
1314 #ifdef USE_THREADS
1315 iMux gcStartMutex;
1316 iMux gcThreadMutex;
1317 iCv gcConditionStart;
1318 iCv gcConditionDone;
1319
1320 void
1321 gc_init (void)
1322 {
1323     gcStartMutex.holder = 0;
1324     gcStartMutex.count = 0;
1325     gcStartMutex.muxWaiters = 0;
1326
1327     gcThreadMutex.holder = 0;
1328     gcThreadMutex.count = 0;
1329     gcThreadMutex.muxWaiters = 0;
1330
1331     gcConditionStart.cvWaiters = 0;
1332     gcConditionStart.mux = 0;
1333
1334     gcConditionDone.cvWaiters = 0;
1335     gcConditionDone.mux = 0;
1336 }    
1337 #else
1338 void
1339 gc_init (void)
1340 {
1341 }
1342 #endif
1343
1344 /************************* Function: gc_thread ********************************
1345
1346         In an endless loop waits for a condition to be posted, then
1347         garbage collects the heap.
1348
1349 ******************************************************************************/
1350
1351 #ifdef USE_THREADS
1352 void
1353 gc_thread (void)
1354 {
1355     intsRestore();           /* all threads start with interrupts disabled */
1356
1357         assert(blockInts == 0);
1358
1359     lock_mutex(&gcThreadMutex);
1360
1361     for (;;)
1362     {
1363                 wait_cond(&gcThreadMutex, &gcConditionStart, 0);
1364
1365                 intsDisable();
1366                 assert(currentThread != mainThread);
1367                 asm_switchstackandcall(CONTEXT(mainThread).usedStackTop, heap_docollect);
1368                 intsRestore();
1369
1370                 signal_cond(&gcConditionDone);
1371     }
1372 }
1373 #endif
1374
1375 void
1376 gc_call (void)
1377 {
1378 #ifdef USE_THREADS
1379     lock_mutex(&gcThreadMutex);
1380
1381     signal_cond(&gcConditionStart);
1382     wait_cond(&gcThreadMutex, &gcConditionDone, 0);
1383
1384     unlock_mutex(&gcThreadMutex);
1385 #else
1386     heap_docollect();
1387 #endif
1388 }
1389
1390
1391 /************************* Funktion: heap_init ********************************
1392
1393         Initialisiert den Garbage Collector.
1394         Parameter: 
1395                 heapbytesize:      Maximale Gr"osse des Heap (in Bytes)
1396                 heapbytestartsize: Gr"osse des Heaps, bei dem zum ersten mal eine
1397                                    GC durchgef"uhrt werden soll.
1398                 stackbottom:       Ein Zeiger auf die Untergrenze des Stacks, im dem
1399                                Referenzen auf Objekte stehen k"onnen.                  
1400                                            
1401 ******************************************************************************/
1402
1403 void heap_init (u4 heapbytesize, u4 heapbytestartsize, void **stackbottom)
1404 {
1405
1406 #ifdef TRACECALLARGS
1407
1408         heapsize = ALIGN (heapbytesize, getpagesize());
1409         heapsize = heapsize/BLOCKSIZE;
1410         heap = (void*) mmap ((void*) 0x10000000, (size_t) (heapsize * BLOCKSIZE),
1411                PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, (off_t) 0);
1412         if (heap != (void *) 0x10000000) {
1413                 perror("mmap");
1414                 printf("address = %p\n", heap);
1415                 panic("mmap failed\n");
1416                 }
1417
1418 #else
1419
1420         heapsize = ALIGN (heapbytesize, 1024);
1421         heapsize = heapsize/BLOCKSIZE;
1422         heap = MNEW (heapblock, heapsize);
1423
1424 #endif
1425
1426         topofheap = 0;
1427         startbits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
1428         markbits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
1429         referencebits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
1430         clearbitfield (startbits, heapsize);
1431         clearbitfield (markbits, heapsize);
1432         clearbitfield (referencebits, heapsize);
1433
1434         heapfillgrade = 0;
1435         collectthreashold = heapbytestartsize/BLOCKSIZE;
1436         allglobalreferences = chain_new ();
1437         bottom_of_stack = stackbottom;
1438
1439         livefinalizees = NULL;
1440         deadfinalizees = NULL;
1441 }
1442
1443
1444 /****************** Funktion: heap_close **************************************
1445
1446         Gibt allen ben"otigten Speicher frei
1447
1448 ******************************************************************************/
1449
1450 void heap_close ()
1451 {
1452 #ifndef TRACECALLARGS
1453         MFREE (heap, heapblock, heapsize); */
1454 #endif
1455         MFREE (startbits, bitfieldtype, heapsize/BITFIELDBITS);
1456         MFREE (markbits, bitfieldtype, heapsize/BITFIELDBITS);
1457         MFREE (referencebits, bitfieldtype, heapsize/BITFIELDBITS);
1458         chain_free (allglobalreferences);
1459
1460         while (livefinalizees) {
1461                 finalizernode *n = livefinalizees->next;
1462                 FREE (livefinalizees, finalizernode);
1463                 livefinalizees = n;
1464                 }
1465 }
1466
1467
1468 /***************** Funktion: heap_addreference ********************************
1469
1470         Teilt dem GC eine Speicherstelle mit, an der eine globale Referenz
1471         auf Objekte gespeichert sein kann.
1472
1473 ******************************************************************************/
1474
1475 void heap_addreference (void **reflocation)
1476 {
1477         intsDisable();                     /* schani */
1478
1479         chain_addlast (allglobalreferences, reflocation);
1480
1481         intsRestore();                    /* schani */
1482 }
1483
1484
1485
1486 /***************** Funktion: heap_allocate ************************************
1487
1488         Fordert einen Speicher vom Heap an, der eine gew"unschte Gr"osse
1489         (in Byte angegeben) haben muss.
1490         Wenn kein Speicher mehr vorhanden ist (auch nicht nach einem
1491         Garbage Collection-Durchlauf), dann wird NULL zur"uckgegeben.
1492         Zus"atzlich wird durch den Parameter 'references' angegeben, ob
1493         in das angelegte Objekt Referenzen auf andere Objekte eingetragen
1494         werden k"onnten. 
1495         (Wichtig wegen Beschleunigung des Mark&Sweep-Durchlauf)
1496         Im Zweifelsfalle immer references=true verwenden.
1497
1498 ******************************************************************************/
1499
1500 void *heap_allocate (u4 bytelength, bool references, methodinfo *finalizer)
1501 {
1502         u4 freestart,freelength;
1503         u4 length = ALIGN(bytelength, BLOCKSIZE) / BLOCKSIZE;
1504         
1505         intsDisable();                        /* schani */
1506
1507         memlist_getsuitable (&freestart, &freelength, length);
1508
1509 onemoretry:
1510         if (!freelength) {
1511                 if (    (topofheap+length > collectthreashold) 
1512                      || (topofheap+length > heapsize) ) {
1513
1514                         intsRestore();
1515                         gc_call();
1516                         intsDisable();
1517                         
1518                         memlist_getsuitable (&freestart, &freelength, length);
1519                         if (freelength) goto onemoretry;
1520                         }
1521                 
1522                 if (topofheap+length > heapsize) {
1523                         sprintf (logtext, "Heap-Allocation failed for %d bytes", 
1524                             (int) bytelength);
1525                         dolog();
1526                         intsRestore();            /* schani */
1527                         return NULL;
1528                         }
1529                         
1530                 freestart = topofheap;
1531                 freelength = length;
1532                 setbit (startbits, topofheap);
1533                 topofheap += length;
1534                 }
1535         else {
1536                 if (freelength>length) {
1537                         setbit (startbits, freestart+length);
1538                         memlist_addrange (freestart+length, freelength-length);
1539                         }
1540                 }
1541                 
1542         if (references) setbit (referencebits, freestart);
1543
1544         heapfillgrade += length;
1545
1546         if (finalizer) {
1547                 finalizernode *n = NEW(finalizernode);
1548                 n -> next = livefinalizees;
1549                 n -> objstart = freestart;
1550                 n -> finalizer = finalizer;
1551                 livefinalizees = n;
1552                 }
1553         
1554         intsRestore();                   /* schani */
1555
1556         if (runverbose) {
1557                 sprintf (logtext, "new returns: %lx", (long) (heap + freestart));
1558                 dolog ();
1559                 }
1560
1561         return (void*) (heap + freestart);
1562 }
1563
1564
1565
1566