1 /* -*- mode: c; tab-width: 4; c-basic-offset: 4 -*- */
2 /****************************** tables.c ***************************************
4 Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
6 See file COPYRIGHT for information on usage and disclaimer of warranties
8 Enth"alt Supportfunktionen f"ur:
9 - Lesen von JavaClass-Files
12 - zus"atzliche Support-Funktionen
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
18 Last Change: 1998/03/24
20 *******************************************************************************/
25 #include "../global.h"
26 #include "../tables.h"
27 #include "../asmpart.h"
28 #include "../callargs.h"
30 #include "../threads/thread.h" /* schani */
31 #include "../threads/locks.h"
35 /******************************************************************************
36 ********************* Der garbage-collected Heap ******************************
37 *******************************************************************************
39 verwaltet einen Heap mit automatischer Speicherfreigabe.
41 (eine ausf"uhrliche Dokumentation findet sich in der Datei:
44 ******************************************************************************/
47 bool collectverbose = false; /* soll Meldung beim GC ausgegeben werden? */
50 #define BLOCKSIZE 8 /* Gr"osse eines Speicherblockes */
51 typedef u8 heapblock; /* Datentyp mit der Gr"osse eines Speicherblocks */
53 #if U8_AVAILABLE && SUPPORT_LONG
54 #define bitfieldtype u8
55 #define BITFIELDBITS 64
57 #define bitfieldtype u4
58 #define BITFIELDBITS 32
61 u4 heapsize; /* Gr"osse des Heap in Blocks */
62 u4 topofheap; /* Bisherige Obergrenze Heaps */
63 heapblock *heap; /* Speicher f"ur den Heap selbst */
65 bitfieldtype *startbits; /* Bitfeld f"ur Bereichsstartkennung */
66 bitfieldtype *markbits; /* Bitfeld f"ur Markierung */
67 bitfieldtype *referencebits; /* Bitfeld f"ur Folgereferenzenkennung */
69 u4 heapfillgrade; /* Menge der Daten im Heap */
70 u4 collectthreashold; /* Schwellwert f"ur n"achstes GC */
72 void **bottom_of_stack; /* Zeiger auf Untergrenze des C-Stacks */
73 chain *allglobalreferences; /* Liste f"ur alle globalen Zeiger */
75 typedef struct finalizernode {
76 struct finalizernode *next;
78 methodinfo *finalizer;
81 finalizernode *livefinalizees;
82 finalizernode *deadfinalizees;
85 typedef struct memarea { /* Datenstruktur f"ur einen Freispeicherbereich */
89 typedef struct bigmemarea { /* Datenstruktur f"ur einen */
90 struct bigmemarea *next; /* Freispeicherbereich variabler L"ange */
94 #define DIFFERENTSIZES 128 /* Anzahl der 'kleinen' Freispeicherlisten */
95 memarea *memlist[DIFFERENTSIZES]; /* Die 'kleinen' Freispeicherlisten */
96 bitfieldtype memlistbits[DIFFERENTSIZES/BITFIELDBITS];
97 /* Bitfeld, in dem jeweils ein Bit gesetzt */
98 /* ist, wenn eine Liste noch etwas enth"alt */
100 bigmemarea *bigmemlist; /* Liste der gr"osseren Freispeicherbereiche */
105 /**************** Hilfsfunktion: lowest **************************************
107 liefert als Ergebnis die Nummer des niederwertigsten Bits einer
108 Zahl vom Typ bitfieldtype, das 1 ist.
109 Wenn die ganze Zahl keine 1en enth"alt, dann ist egal, was f"ur einen
110 Wert die Funktion l"iefert.
111 z.B.: lowest(1) = 0, lowest(12) = 2, lowest(1024) = 10
113 *****************************************************************************/
115 static u1 lowesttable[256] = {
116 255, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
117 4, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
118 5, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
119 4, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
120 6, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
121 4, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
122 5, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
123 4, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
124 7, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
125 4, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
126 5, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
127 4, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
128 6, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
129 4, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
130 5, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
131 4, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 };
133 static int lowest(bitfieldtype i)
141 if (i111) return lowesttable[i111>>56];
142 else return 8+lowesttable[i11>>56];
146 if (i112) return 16+lowesttable[i112>>56];
147 else return 24+lowesttable[i1>>56];
154 if (i121) return 32+lowesttable[i121>>56];
155 else return 40+lowesttable[i12>>56];
159 if (i122) return 48+lowesttable[i122>>56];
160 else return 56+lowesttable[i>>56];
167 if (i11) return lowesttable[i11>>24];
168 else return 8+lowesttable[i1>>24];
172 if (i12) return 16+lowesttable[i12>>24];
173 else return 24+lowesttable[i>>24];
179 /******** Funktionen zum Setzen und L"oschen von Bits in Bitfeldern ***********/
181 static void setbit(bitfieldtype *bitfield, u4 bitnumber)
183 bitfield[bitnumber/BITFIELDBITS] |=
184 ((bitfieldtype) 1) << (bitnumber%BITFIELDBITS);
187 static void clearbit(bitfieldtype *bitfield, u4 bitnumber)
189 bitfield[bitnumber/BITFIELDBITS] &=
190 ~((bitfieldtype) 1) << (bitnumber%BITFIELDBITS);
193 static bool isbitset(bitfieldtype *bitfield, u4 bitnumber)
195 return ( bitfield[bitnumber/BITFIELDBITS] &
196 ( ((bitfieldtype) 1) << (bitnumber%BITFIELDBITS) ) ) != 0;
199 static bool isbitclear(bitfieldtype *bitfield, u4 bitnumber)
201 return ( bitfield[bitnumber/BITFIELDBITS] &
202 ( ((bitfieldtype) 1) << (bitnumber%BITFIELDBITS) ) ) == 0;
206 /***************** Funktion: clearbitfield ************************************
208 l"oscht ein ganzes Bitfeld
210 ******************************************************************************/
212 static void clearbitfield(bitfieldtype *bitfield, u4 fieldsize)
215 t = ALIGN(fieldsize, BITFIELDBITS) / BITFIELDBITS;
216 for (i=0; i<t; i++) bitfield[i] = 0;
219 /************** Funktion: maskfieldwithfield **********************************
221 Verkn"upft zwei Bitfelder bitweise mit UND, das erste Bitfeld
222 wird mit dem Ergebnis "uberschrieben
224 ******************************************************************************/
226 static void maskfieldwithfield (bitfieldtype* bitfield,
227 bitfieldtype *maskfield, u4 fieldsize)
230 t = ALIGN(fieldsize, BITFIELDBITS) / BITFIELDBITS;
231 for (i=0; i<t; i++) bitfield[i] &= maskfield[i];
235 /************** Funktion: findnextsetbit **************************************
237 Sucht in einem Bitfeld ab einer Stelle das n"achste gesetzte Bit
238 und liefert die Nummer dieses Bits.
239 Wenn kein Bit mehr zwischen 'bitnumber' und 'fieldsize' gesetzt
240 ist, dann wird fieldsize zur"uckgeliefte.
242 ******************************************************************************/
244 static u4 findnextsetbit(bitfieldtype* bitfield, u4 fieldsize, u4 bitnumber)
246 bitfieldtype pattern;
249 if (bitnumber >= fieldsize) return fieldsize;
251 pattern = bitfield[bitnumber/BITFIELDBITS];
252 pattern >>= (bitnumber%BITFIELDBITS);
253 if (pattern) return bitnumber + lowest(pattern);
255 bitnumber = ((bitnumber + BITFIELDBITS) / BITFIELDBITS) * BITFIELDBITS;
260 /************ Funktion: findnextcombination_set_unset *************************
262 funktioniert wie findnextsetbit, allerdings sucht diese Funktion
263 nach einer Stelle, an der gleichzeitig ein Bit im ersten
264 Bitfeld gesetzt ist und im zweiten Bitfeld das entsprechende
265 Bit nicht gesetzt ist.
267 ******************************************************************************/
269 static u4 findnextcombination_set_unset
270 (bitfieldtype *bitfield1, bitfieldtype* bitfield2, u4 fieldsize, u4 bitnumber)
272 bitfieldtype pattern;
275 if (bitnumber >= fieldsize) return fieldsize;
277 pattern = bitfield1[bitnumber/BITFIELDBITS]
278 & (~bitfield2[bitnumber/BITFIELDBITS]);
279 pattern >>= (bitnumber%BITFIELDBITS);
280 if (pattern) return bitnumber + lowest(pattern);
282 bitnumber = ((bitnumber + BITFIELDBITS) / BITFIELDBITS) * BITFIELDBITS;
288 /************** Funktion: memlist_init ****************************************
290 initialisiert die Freispeicherlisten (zum nachfolgenden Eintragen
291 mit memlist_addrange).
293 ******************************************************************************/
295 static void memlist_init ()
298 for (i=0; i<DIFFERENTSIZES; i++) memlist[i] = NULL;
299 clearbitfield (memlistbits, DIFFERENTSIZES);
304 /************** Funktion: memlist_addrange ************************************
306 f"ugt einen Bereich von Heap-Bl"ocken zur Freispeicherliste
307 hinzu (in die freien Heap-Bl"ocke werden dabei verschiedene
308 Verkettungszeiger hineingeschrieben).
310 ******************************************************************************/
312 static void memlist_addrange (u4 freestart, u4 freesize)
314 if (freesize>=DIFFERENTSIZES) {
315 bigmemarea *m = (bigmemarea*) (heap+freestart);
316 m -> next = bigmemlist;
317 m -> size = freesize;
321 if (freesize*BLOCKSIZE>=sizeof(memarea)) {
322 memarea *m = (memarea*) (heap+freestart);
323 m -> next = memlist[freesize];
324 memlist[freesize] = m;
325 setbit (memlistbits, freesize);
331 /************** Funktion: memlist_getsuitable *********************************
333 sucht in der Freispeicherliste einen Speicherbereich, der m"oglichst
334 genau die gew"unschte L"ange hat.
335 Der Bereich wird dabei auf jeden Fall aus der Liste ausgetragen.
336 (Wenn der Bereich zu lang sein sollte, dann kann der Aufrufer den
337 Rest wieder mit 'memlist_addrange' in die Liste einh"angen)
339 Return (in Referenzparametern):
340 *freestart: Anfang des freien Speichers
341 *freelength: L"ange dieses Speicherbereiches
343 Wenn kein passender Speicherblock mehr gefunden werden kann, dann
344 wird in '*freelength' 0 hineingeschrieben.
346 ******************************************************************************/
348 static void memlist_getsuitable (u4 *freestart, u4 *freelength, u4 length)
351 bigmemarea *prevm = NULL;
353 if (length<DIFFERENTSIZES) {
356 if (memlist[length]) {
357 firstfreelength = length;
360 firstfreelength = findnextsetbit
361 (memlistbits, DIFFERENTSIZES, length+3);
362 /* wenn kein passender Block da ist, dann gleich nach */
363 /* einem etwas gr"osseren suchen, damit keine kleinen */
364 /* St"uckchen "ubrigbleiben */
367 if (firstfreelength<DIFFERENTSIZES) {
368 memarea *m = memlist[firstfreelength];
369 memlist[firstfreelength] = m->next;
370 if (!m->next) clearbit (memlistbits, firstfreelength);
371 *freestart = ((heapblock*) m) - heap;
372 *freelength = firstfreelength;
379 if (m->size >= length) {
380 if (prevm) prevm->next = m->next;
381 else bigmemlist = m->next;
383 *freestart = ((heapblock*) m) - heap;
384 *freelength = m->size;
399 /******************* Funktion: mark *******************************************
401 Markiert ein m"oglicherweise g"ultiges Objekt.
402 Sollte sich herausstellen, dass der Zeiger gar nicht auf ein Objekt
403 am Heap zeigt, dann wird eben gar nichts markiert.
405 ******************************************************************************/
407 static void markreferences (void **rstart, void **rend);
409 static void mark (heapblock *obj)
411 u4 blocknum,objectend;
413 if ((long) obj & (BLOCKSIZE-1)) return;
415 if (obj<heap) return;
416 if (obj>=(heap+topofheap) ) return;
419 if ( isbitclear(startbits, blocknum) ) return;
420 if ( isbitset(markbits, blocknum) ) return;
422 /* fprintf(stderr, "mark: marking object at 0x%lx\n", obj); */
423 setbit (markbits, blocknum);
425 if ( isbitclear(referencebits, blocknum) ) return;
427 objectend = findnextsetbit (startbits, topofheap, blocknum+1);
428 markreferences ((void**)obj, (void**) (heap+objectend) );
432 /******************** Funktion: markreferences ********************************
434 Geht einen Speicherbereich durch, und markiert alle Objekte, auf
435 die von diesem Bereich aus irgendeine Referenz existiert.
437 ******************************************************************************/
439 static void markreferences (void **rstart, void **rend)
443 for (ptr=rstart; ptr<rend; ptr++) mark (*ptr);
447 /******************* Funktion: markstack **************************************
449 Marks all objects that are referenced by the (C-)stacks of
452 (The stack-bottom is to be specified in the call to heap_init).
454 ******************************************************************************/
456 static void markstack () /* schani */
463 if (currentThread == NULL) {
464 void **top_of_stack = &dummy;
466 if (top_of_stack > bottom_of_stack)
467 markreferences(bottom_of_stack, top_of_stack);
469 markreferences(top_of_stack, bottom_of_stack);
472 for (aThread = liveThreads; aThread != 0;
473 aThread = CONTEXT(aThread).nextlive) {
474 mark((heapblock*)aThread);
475 if (aThread == currentThread) {
476 void **top_of_stack = &dummy;
478 if (top_of_stack > (void**)CONTEXT(aThread).stackEnd)
479 markreferences((void**)CONTEXT(aThread).stackEnd, top_of_stack);
481 markreferences(top_of_stack, (void**)CONTEXT(aThread).stackEnd);
484 if (CONTEXT(aThread).usedStackTop > CONTEXT(aThread).stackEnd)
485 markreferences((void**)CONTEXT(aThread).stackEnd,
486 (void**)CONTEXT(aThread).usedStackTop);
488 markreferences((void**)CONTEXT(aThread).usedStackTop,
489 (void**)CONTEXT(aThread).stackEnd);
493 markreferences((void**)&threadQhead[0],
494 (void**)&threadQhead[MAX_THREAD_PRIO]);
497 void **top_of_stack = &dummy;
499 /* fprintf(stderr, "marking stack\n"); */
501 if (top_of_stack > bottom_of_stack)
502 markreferences(bottom_of_stack, top_of_stack);
504 markreferences(top_of_stack, bottom_of_stack);
509 /**************** Funktion: searchlivefinalizees *****************************
511 geht die Liste aller Objekte durch, die noch finalisiert werden m"ussen
512 (livefinalizees), und tr"agt alle nicht mehr markierten in die
513 Liste deadfinalizess ein (allerdings werden sie vorher noch als
514 erreicht markiert, damit sie nicht jetzt gleich gel"oscht werden).
516 *****************************************************************************/
518 static void searchlivefinalizees ()
520 finalizernode *fn = livefinalizees;
521 finalizernode *lastlive = NULL;
525 /* alle zu finalisierenden Objekte, die nicht mehr markiert sind: */
526 if (isbitclear (markbits, fn->objstart)) {
527 finalizernode *nextfn = fn->next;
529 mark (heap + fn->objstart);
531 if (lastlive) lastlive -> next = nextfn;
532 else livefinalizees = nextfn;
534 fn -> next = deadfinalizees;
548 /********************** Funktion: finalizedead *******************************
550 ruft die 'finalize'-Methode aller Objekte in der 'deadfinalizees'-
552 Achtung: Es kann hier eventuell zu neuerlichen Speicheranforderungen
553 (mit potentiell notwendigem GC) kommen, deshalb m"ussen manche
554 globalen Variablen in lokale Variblen kopiert werden
555 (Reentrant-F"ahigkeit!!!)
557 ******************************************************************************/
559 static void finalizedead()
561 finalizernode *fn = deadfinalizees;
562 deadfinalizees = NULL;
565 finalizernode *nextfn = fn->next;
567 asm_calljavamethod (fn->finalizer, heap+fn->objstart, NULL,NULL,NULL);
568 FREE (fn, finalizernode);
577 /****************** Funktion: heap_docollect **********************************
579 F"uhrt eine vollst"andige Garbage Collection durch
581 ******************************************************************************/
583 static void heap_docollect ()
585 u4 freestart,freeend;
593 fprintf(stderr, "doing garbage collection\n");
595 /* alle Markierungsbits l"oschen */
596 clearbitfield (markbits, topofheap);
598 /* Alle vom Stack referenzierten Objekte markieren */
599 asm_dumpregistersandcall (markstack);
601 /* fprintf(stderr, "marking references\n"); */
602 /* Alle von globalen Variablen erreichbaren Objekte markieren */
603 p = chain_first (allglobalreferences);
606 p = chain_next (allglobalreferences);
609 /* alle Objekte durchsehen, die eine finalizer-Methode haben */
610 searchlivefinalizees();
612 /* alle Reference-Bits l"oschen, deren Objekte nicht */
613 /* mehr erreichbar sind */
614 maskfieldwithfield (referencebits, markbits, topofheap);
617 /* Freispeicherliste initialisieren */
621 /* Heap schrittweise durchgehen, und alle freien Bl"ocke merken */
626 /* Anfang des n"achsten freien Bereiches suchen */
627 freestart = findnextcombination_set_unset
628 (startbits, markbits, topofheap, freeend);
630 /* Wenn es keinen freien Bereich mehr gibt -> fertig */
631 if (freestart>=topofheap) goto freememfinished;
633 /* Anfang des freien Bereiches markieren */
634 setbit (markbits, freestart);
636 /* Ende des freien Bereiches suchen */
637 freeend = findnextsetbit (markbits, topofheap, freestart+1);
640 if (freeend==topofheap) {
641 topofheap = freestart;
642 heapfreemem += (freeend-freestart);
643 goto freememfinished;
645 fprintf(stderr, "%lx -- %lx\n", heap + freestart, heap + freeend);
648 /* Freien Bereich in Freispeicherliste einh"angen */
649 memlist_addrange (freestart, freeend-freestart);
651 /* Menge des freien Speichers mitnotieren */
652 heapfreemem += (freeend-freestart);
660 /* Die Rollen von markbits und startbits vertauschen */
662 markbits = startbits;
666 /* Threashold-Wert f"ur n"achstes Collect */
667 oldfillgrade = heapfillgrade;
668 heapfillgrade = topofheap - heapfreemem;
669 collectthreashold = heapfillgrade*3; /* eine nette Heuristik */
671 /* Eventuell eine Meldung ausgeben */
672 if (collectverbose) {
673 sprintf (logtext, "Garbage Collection: previous/now = %d / %d ",
674 (int) (oldfillgrade * BLOCKSIZE),
675 (int) (heapfillgrade * BLOCKSIZE) );
681 /* alle gerade unerreichbar gewordenen Objekte mit
682 finalize-Methoden jetzt finalisieren.
683 Achtung: Diese Funktion kann zu neuerlichem GC f"uhren!! */
688 /************************* Function: gc_init **********************************
690 Initializes anything that must be initialized to call the gc on the right
693 ******************************************************************************/
700 /************************** Function: gc_call ********************************
702 Calls the garbage collector. The garbage collector should always be called
703 using this function since it ensures that enough stack space is available.
705 ******************************************************************************/
711 assert(blockInts == 0);
714 if (currentThread == NULL || currentThread == mainThread)
717 asm_switchstackandcall(CONTEXT(mainThread).usedStackTop, heap_docollect);
725 /************************* Funktion: heap_init ********************************
727 Initialisiert den Garbage Collector.
729 heapbytesize: Maximale Gr"osse des Heap (in Bytes)
730 heapbytestartsize: Gr"osse des Heaps, bei dem zum ersten mal eine
731 GC durchgef"uhrt werden soll.
732 stackbottom: Ein Zeiger auf die Untergrenze des Stacks, im dem
733 Referenzen auf Objekte stehen k"onnen.
735 ******************************************************************************/
737 void heap_init (u4 heapbytesize, u4 heapbytestartsize, void **stackbottom)
742 heapsize = ALIGN (heapbytesize, getpagesize());
743 heapsize = heapsize/BLOCKSIZE;
744 heap = (void*) mmap ((void*) 0x10000000, (size_t) (heapsize * BLOCKSIZE),
745 PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, (off_t) 0);
746 if (heap != (void *) 0x10000000) {
748 printf("address = %p\n", heap);
749 panic("mmap failed\n");
754 heapsize = ALIGN (heapbytesize, 1024);
755 heapsize = heapsize/BLOCKSIZE;
756 heap = MNEW (heapblock, heapsize);
761 startbits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
762 markbits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
763 referencebits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
764 clearbitfield (startbits, heapsize);
765 clearbitfield (markbits, heapsize);
766 clearbitfield (referencebits, heapsize);
769 collectthreashold = heapbytestartsize/BLOCKSIZE;
770 allglobalreferences = chain_new ();
771 bottom_of_stack = stackbottom;
773 livefinalizees = NULL;
774 deadfinalizees = NULL;
778 /****************** Funktion: heap_close **************************************
780 Gibt allen ben"otigten Speicher frei
782 ******************************************************************************/
786 while (livefinalizees) {
787 finalizernode *n = livefinalizees->next;
788 asm_calljavamethod (livefinalizees->finalizer,
789 heap+livefinalizees->objstart,
791 FREE (livefinalizees, finalizernode);
795 #ifndef TRACECALLARGS
796 MFREE (heap, heapblock, heapsize);
798 MFREE (startbits, bitfieldtype, heapsize/BITFIELDBITS);
799 MFREE (markbits, bitfieldtype, heapsize/BITFIELDBITS);
800 MFREE (referencebits, bitfieldtype, heapsize/BITFIELDBITS);
801 chain_free (allglobalreferences);
805 /***************** Funktion: heap_addreference ********************************
807 Teilt dem GC eine Speicherstelle mit, an der eine globale Referenz
808 auf Objekte gespeichert sein kann.
810 ******************************************************************************/
812 void heap_addreference (void **reflocation)
814 intsDisable(); /* schani */
816 chain_addlast (allglobalreferences, reflocation);
818 intsRestore(); /* schani */
823 /***************** Funktion: heap_allocate ************************************
825 Fordert einen Speicher vom Heap an, der eine gew"unschte Gr"osse
826 (in Byte angegeben) haben muss.
827 Wenn kein Speicher mehr vorhanden ist (auch nicht nach einem
828 Garbage Collection-Durchlauf), dann wird NULL zur"uckgegeben.
829 Zus"atzlich wird durch den Parameter 'references' angegeben, ob
830 in das angelegte Objekt Referenzen auf andere Objekte eingetragen
832 (Wichtig wegen Beschleunigung des Mark&Sweep-Durchlauf)
833 Im Zweifelsfalle immer references=true verwenden.
835 ******************************************************************************/
837 void *heap_allocate (u4 bytelength, bool references, methodinfo *finalizer)
839 u4 freestart,freelength;
840 u4 length = ALIGN(bytelength, BLOCKSIZE) / BLOCKSIZE;
842 /* fprintf(stderr, "heap_allocate: 0x%lx (%ld) requested, 0x%lx (%ld) aligned\n", bytelength, bytelength, length * BLOCKSIZE, length * BLOCKSIZE); */
844 /* heap_docollect(); */
846 intsDisable(); /* schani */
848 memlist_getsuitable (&freestart, &freelength, length);
852 if ((topofheap+length > collectthreashold) ||
853 (topofheap+length > heapsize)) {
859 memlist_getsuitable (&freestart, &freelength, length);
860 if (freelength) goto onemoretry;
863 if (topofheap+length > heapsize) {
864 sprintf (logtext, "Heap-Allocation failed for %d bytes",
867 intsRestore(); /* schani */
871 freestart = topofheap;
873 setbit (startbits, topofheap);
877 if (freelength>length) {
878 setbit (startbits, freestart+length);
879 memlist_addrange (freestart+length, freelength-length);
883 if (references) setbit (referencebits, freestart);
885 heapfillgrade += length;
888 finalizernode *n = NEW(finalizernode);
889 n -> next = livefinalizees;
890 n -> objstart = freestart;
891 n -> finalizer = finalizer;
895 intsRestore(); /* schani */
898 sprintf (logtext, "new returns: %lx", (long) (heap + freestart));
902 return (void*) (heap + freestart);