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"
32 #include "../sysdep/threads.h"
36 /******************************************************************************
37 ********************* Der garbage-collected Heap ******************************
38 *******************************************************************************
40 verwaltet einen Heap mit automatischer Speicherfreigabe.
42 (eine ausf"uhrliche Dokumentation findet sich in der Datei:
45 ******************************************************************************/
48 bool collectverbose = false; /* soll Meldung beim GC ausgegeben werden? */
51 #define BLOCKSIZE 8 /* Gr"osse eines Speicherblockes */
52 typedef u8 heapblock; /* Datentyp mit der Gr"osse eines Speicherblocks */
54 #if U8_AVAILABLE && SUPPORT_LONG
55 #define bitfieldtype u8
56 #define BITFIELDBITS 64
58 #define bitfieldtype u4
59 #define BITFIELDBITS 32
62 u4 heapsize; /* Gr"osse des Heap in Blocks */
63 u4 topofheap; /* Bisherige Obergrenze Heaps */
64 heapblock *heap; /* Speicher f"ur den Heap selbst */
66 bitfieldtype *startbits; /* Bitfeld f"ur Bereichsstartkennung */
67 bitfieldtype *markbits; /* Bitfeld f"ur Markierung */
68 bitfieldtype *referencebits; /* Bitfeld f"ur Folgereferenzenkennung */
70 u4 heapfillgrade; /* Menge der Daten im Heap */
71 u4 collectthreashold; /* Schwellwert f"ur n"achstes GC */
73 void **bottom_of_stack; /* Zeiger auf Untergrenze des C-Stacks */
74 chain *allglobalreferences; /* Liste f"ur alle globalen Zeiger */
76 typedef struct finalizernode {
77 struct finalizernode *next;
79 methodinfo *finalizer;
82 finalizernode *livefinalizees;
83 finalizernode *deadfinalizees;
86 typedef struct memarea { /* Datenstruktur f"ur einen Freispeicherbereich */
90 typedef struct bigmemarea { /* Datenstruktur f"ur einen */
91 struct bigmemarea *next; /* Freispeicherbereich variabler L"ange */
95 #define DIFFERENTSIZES 128 /* Anzahl der 'kleinen' Freispeicherlisten */
96 memarea *memlist[DIFFERENTSIZES]; /* Die 'kleinen' Freispeicherlisten */
97 bitfieldtype memlistbits[DIFFERENTSIZES/BITFIELDBITS];
98 /* Bitfeld, in dem jeweils ein Bit gesetzt */
99 /* ist, wenn eine Liste noch etwas enth"alt */
101 bigmemarea *bigmemlist; /* Liste der gr"osseren Freispeicherbereiche */
106 /**************** Hilfsfunktion: lowest **************************************
108 liefert als Ergebnis die Nummer des niederwertigsten Bits einer
109 Zahl vom Typ bitfieldtype, das 1 ist.
110 Wenn die ganze Zahl keine 1en enth"alt, dann ist egal, was f"ur einen
111 Wert die Funktion l"iefert.
112 z.B.: lowest(1) = 0, lowest(12) = 2, lowest(1024) = 10
114 *****************************************************************************/
116 static u1 lowesttable[256] = {
117 255, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
118 4, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
119 5, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
120 4, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
121 6, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
122 4, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
123 5, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
124 4, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
125 7, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
126 4, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
127 5, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
128 4, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
129 6, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
130 4, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
131 5, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
132 4, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 };
134 static int lowest(bitfieldtype i)
142 if (i111) return lowesttable[i111>>56];
143 else return 8+lowesttable[i11>>56];
147 if (i112) return 16+lowesttable[i112>>56];
148 else return 24+lowesttable[i1>>56];
155 if (i121) return 32+lowesttable[i121>>56];
156 else return 40+lowesttable[i12>>56];
160 if (i122) return 48+lowesttable[i122>>56];
161 else return 56+lowesttable[i>>56];
168 if (i11) return lowesttable[i11>>24];
169 else return 8+lowesttable[i1>>24];
173 if (i12) return 16+lowesttable[i12>>24];
174 else return 24+lowesttable[i>>24];
180 /******** Funktionen zum Setzen und L"oschen von Bits in Bitfeldern ***********/
182 static void setbit(bitfieldtype *bitfield, u4 bitnumber)
184 bitfield[bitnumber/BITFIELDBITS] |=
185 ((bitfieldtype) 1) << (bitnumber%BITFIELDBITS);
188 static void clearbit(bitfieldtype *bitfield, u4 bitnumber)
190 bitfield[bitnumber/BITFIELDBITS] &=
191 ~((bitfieldtype) 1) << (bitnumber%BITFIELDBITS);
194 static bool isbitset(bitfieldtype *bitfield, u4 bitnumber)
196 return ( bitfield[bitnumber/BITFIELDBITS] &
197 ( ((bitfieldtype) 1) << (bitnumber%BITFIELDBITS) ) ) != 0;
200 static bool isbitclear(bitfieldtype *bitfield, u4 bitnumber)
202 return ( bitfield[bitnumber/BITFIELDBITS] &
203 ( ((bitfieldtype) 1) << (bitnumber%BITFIELDBITS) ) ) == 0;
207 /***************** Funktion: clearbitfield ************************************
209 l"oscht ein ganzes Bitfeld
211 ******************************************************************************/
213 static void clearbitfield(bitfieldtype *bitfield, u4 fieldsize)
216 t = ALIGN(fieldsize, BITFIELDBITS) / BITFIELDBITS;
217 for (i=0; i<t; i++) bitfield[i] = 0;
220 /************** Funktion: maskfieldwithfield **********************************
222 Verkn"upft zwei Bitfelder bitweise mit UND, das erste Bitfeld
223 wird mit dem Ergebnis "uberschrieben
225 ******************************************************************************/
227 static void maskfieldwithfield (bitfieldtype* bitfield,
228 bitfieldtype *maskfield, u4 fieldsize)
231 t = ALIGN(fieldsize, BITFIELDBITS) / BITFIELDBITS;
232 for (i=0; i<t; i++) bitfield[i] &= maskfield[i];
236 /************** Funktion: findnextsetbit **************************************
238 Sucht in einem Bitfeld ab einer Stelle das n"achste gesetzte Bit
239 und liefert die Nummer dieses Bits.
240 Wenn kein Bit mehr zwischen 'bitnumber' und 'fieldsize' gesetzt
241 ist, dann wird fieldsize zur"uckgeliefte.
243 ******************************************************************************/
245 static u4 findnextsetbit(bitfieldtype* bitfield, u4 fieldsize, u4 bitnumber)
247 bitfieldtype pattern;
250 if (bitnumber >= fieldsize) return fieldsize;
252 pattern = bitfield[bitnumber/BITFIELDBITS];
253 pattern >>= (bitnumber%BITFIELDBITS);
254 if (pattern) return bitnumber + lowest(pattern);
256 bitnumber = ((bitnumber + BITFIELDBITS) / BITFIELDBITS) * BITFIELDBITS;
261 /************ Funktion: findnextcombination_set_unset *************************
263 funktioniert wie findnextsetbit, allerdings sucht diese Funktion
264 nach einer Stelle, an der gleichzeitig ein Bit im ersten
265 Bitfeld gesetzt ist und im zweiten Bitfeld das entsprechende
266 Bit nicht gesetzt ist.
268 ******************************************************************************/
270 static u4 findnextcombination_set_unset
271 (bitfieldtype *bitfield1, bitfieldtype* bitfield2, u4 fieldsize, u4 bitnumber)
273 bitfieldtype pattern;
276 if (bitnumber >= fieldsize) return fieldsize;
278 pattern = bitfield1[bitnumber/BITFIELDBITS]
279 & (~bitfield2[bitnumber/BITFIELDBITS]);
280 pattern >>= (bitnumber%BITFIELDBITS);
281 if (pattern) return bitnumber + lowest(pattern);
283 bitnumber = ((bitnumber + BITFIELDBITS) / BITFIELDBITS) * BITFIELDBITS;
289 /************** Funktion: memlist_init ****************************************
291 initialisiert die Freispeicherlisten (zum nachfolgenden Eintragen
292 mit memlist_addrange).
294 ******************************************************************************/
296 static void memlist_init ()
299 for (i=0; i<DIFFERENTSIZES; i++) memlist[i] = NULL;
300 clearbitfield (memlistbits, DIFFERENTSIZES);
305 /************** Funktion: memlist_addrange ************************************
307 f"ugt einen Bereich von Heap-Bl"ocken zur Freispeicherliste
308 hinzu (in die freien Heap-Bl"ocke werden dabei verschiedene
309 Verkettungszeiger hineingeschrieben).
311 ******************************************************************************/
313 static void memlist_addrange (u4 freestart, u4 freesize)
315 if (freesize>=DIFFERENTSIZES) {
316 bigmemarea *m = (bigmemarea*) (heap+freestart);
317 m -> next = bigmemlist;
318 m -> size = freesize;
322 if (freesize*BLOCKSIZE>=sizeof(memarea)) {
323 memarea *m = (memarea*) (heap+freestart);
324 m -> next = memlist[freesize];
325 memlist[freesize] = m;
326 setbit (memlistbits, freesize);
332 /************** Funktion: memlist_getsuitable *********************************
334 sucht in der Freispeicherliste einen Speicherbereich, der m"oglichst
335 genau die gew"unschte L"ange hat.
336 Der Bereich wird dabei auf jeden Fall aus der Liste ausgetragen.
337 (Wenn der Bereich zu lang sein sollte, dann kann der Aufrufer den
338 Rest wieder mit 'memlist_addrange' in die Liste einh"angen)
340 Return (in Referenzparametern):
341 *freestart: Anfang des freien Speichers
342 *freelength: L"ange dieses Speicherbereiches
344 Wenn kein passender Speicherblock mehr gefunden werden kann, dann
345 wird in '*freelength' 0 hineingeschrieben.
347 ******************************************************************************/
349 static void memlist_getsuitable (u4 *freestart, u4 *freelength, u4 length)
352 bigmemarea *prevm = NULL;
354 if (length<DIFFERENTSIZES) {
357 if (memlist[length]) {
358 firstfreelength = length;
361 firstfreelength = findnextsetbit
362 (memlistbits, DIFFERENTSIZES, length+3);
363 /* wenn kein passender Block da ist, dann gleich nach */
364 /* einem etwas gr"osseren suchen, damit keine kleinen */
365 /* St"uckchen "ubrigbleiben */
368 if (firstfreelength<DIFFERENTSIZES) {
369 memarea *m = memlist[firstfreelength];
370 memlist[firstfreelength] = m->next;
371 if (!m->next) clearbit (memlistbits, firstfreelength);
372 *freestart = ((heapblock*) m) - heap;
373 *freelength = firstfreelength;
380 if (m->size >= length) {
381 if (prevm) prevm->next = m->next;
382 else bigmemlist = m->next;
384 *freestart = ((heapblock*) m) - heap;
385 *freelength = m->size;
400 /******************* Funktion: mark *******************************************
402 Markiert ein m"oglicherweise g"ultiges Objekt.
403 Sollte sich herausstellen, dass der Zeiger gar nicht auf ein Objekt
404 am Heap zeigt, dann wird eben gar nichts markiert.
406 ******************************************************************************/
408 static void markreferences (void **rstart, void **rend);
410 static void mark (heapblock *obj)
412 u4 blocknum,objectend;
414 if ((long) obj & (BLOCKSIZE-1)) return;
416 if (obj<heap) return;
417 if (obj>=(heap+topofheap) ) return;
420 if ( isbitclear(startbits, blocknum) ) return;
421 if ( isbitset(markbits, blocknum) ) return;
423 /* fprintf(stderr, "mark: marking object at 0x%lx\n", obj); */
424 setbit (markbits, blocknum);
426 if ( isbitclear(referencebits, blocknum) ) return;
428 objectend = findnextsetbit (startbits, topofheap, blocknum+1);
429 markreferences ((void**)obj, (void**) (heap+objectend) );
433 /******************** Funktion: markreferences ********************************
435 Geht einen Speicherbereich durch, und markiert alle Objekte, auf
436 die von diesem Bereich aus irgendeine Referenz existiert.
438 ******************************************************************************/
440 static void markreferences (void **rstart, void **rend)
444 for (ptr=rstart; ptr<rend; ptr++) mark (*ptr);
448 /******************* Funktion: markstack **************************************
450 Marks all objects that are referenced by the (C-)stacks of
453 (The stack-bottom is to be specified in the call to heap_init).
455 ******************************************************************************/
457 static void markstack () /* schani */
464 if (currentThread == NULL) {
465 void **top_of_stack = &dummy;
467 if (top_of_stack > bottom_of_stack)
468 markreferences(bottom_of_stack, top_of_stack);
470 markreferences(top_of_stack, bottom_of_stack);
473 for (aThread = liveThreads; aThread != 0;
474 aThread = CONTEXT(aThread).nextlive) {
475 mark((heapblock*)aThread);
476 if (aThread == currentThread) {
477 void **top_of_stack = &dummy;
479 if (top_of_stack > (void**)CONTEXT(aThread).stackEnd)
480 markreferences((void**)CONTEXT(aThread).stackEnd, top_of_stack);
482 markreferences(top_of_stack, (void**)CONTEXT(aThread).stackEnd);
485 if (CONTEXT(aThread).usedStackTop > CONTEXT(aThread).stackEnd)
486 markreferences((void**)CONTEXT(aThread).stackEnd,
487 (void**)CONTEXT(aThread).usedStackTop);
489 markreferences((void**)CONTEXT(aThread).usedStackTop,
490 (void**)CONTEXT(aThread).stackEnd);
494 markreferences((void**)&threadQhead[0],
495 (void**)&threadQhead[MAX_THREAD_PRIO]);
498 void **top_of_stack = &dummy;
500 /* fprintf(stderr, "marking stack\n"); */
502 if (top_of_stack > bottom_of_stack)
503 markreferences(bottom_of_stack, top_of_stack);
505 markreferences(top_of_stack, bottom_of_stack);
510 /**************** Funktion: searchlivefinalizees *****************************
512 geht die Liste aller Objekte durch, die noch finalisiert werden m"ussen
513 (livefinalizees), und tr"agt alle nicht mehr markierten in die
514 Liste deadfinalizess ein (allerdings werden sie vorher noch als
515 erreicht markiert, damit sie nicht jetzt gleich gel"oscht werden).
517 *****************************************************************************/
519 static void searchlivefinalizees ()
521 finalizernode *fn = livefinalizees;
522 finalizernode *lastlive = NULL;
526 /* alle zu finalisierenden Objekte, die nicht mehr markiert sind: */
527 if (isbitclear (markbits, fn->objstart)) {
528 finalizernode *nextfn = fn->next;
530 mark (heap + fn->objstart);
532 if (lastlive) lastlive -> next = nextfn;
533 else livefinalizees = nextfn;
535 fn -> next = deadfinalizees;
549 /********************** Funktion: finalizedead *******************************
551 ruft die 'finalize'-Methode aller Objekte in der 'deadfinalizees'-
553 Achtung: Es kann hier eventuell zu neuerlichen Speicheranforderungen
554 (mit potentiell notwendigem GC) kommen, deshalb m"ussen manche
555 globalen Variablen in lokale Variblen kopiert werden
556 (Reentrant-F"ahigkeit!!!)
558 ******************************************************************************/
560 static void finalizedead()
562 finalizernode *fn = deadfinalizees;
563 deadfinalizees = NULL;
566 finalizernode *nextfn = fn->next;
568 asm_calljavamethod (fn->finalizer, heap+fn->objstart, NULL,NULL,NULL);
569 FREE (fn, finalizernode);
578 /****************** Funktion: heap_docollect **********************************
580 F"uhrt eine vollst"andige Garbage Collection durch
582 ******************************************************************************/
584 static void heap_docollect ()
586 u4 freestart,freeend;
594 fprintf(stderr, "doing garbage collection\n");
596 /* alle Markierungsbits l"oschen */
597 clearbitfield (markbits, topofheap);
599 /* Alle vom Stack referenzierten Objekte markieren */
600 asm_dumpregistersandcall (markstack);
602 /* fprintf(stderr, "marking references\n"); */
603 /* Alle von globalen Variablen erreichbaren Objekte markieren */
604 p = chain_first (allglobalreferences);
607 p = chain_next (allglobalreferences);
610 /* alle Objekte durchsehen, die eine finalizer-Methode haben */
611 searchlivefinalizees();
613 /* alle Reference-Bits l"oschen, deren Objekte nicht */
614 /* mehr erreichbar sind */
615 maskfieldwithfield (referencebits, markbits, topofheap);
618 /* Freispeicherliste initialisieren */
622 /* Heap schrittweise durchgehen, und alle freien Bl"ocke merken */
627 /* Anfang des n"achsten freien Bereiches suchen */
628 freestart = findnextcombination_set_unset
629 (startbits, markbits, topofheap, freeend);
631 /* Wenn es keinen freien Bereich mehr gibt -> fertig */
632 if (freestart>=topofheap) goto freememfinished;
634 /* Anfang des freien Bereiches markieren */
635 setbit (markbits, freestart);
637 /* Ende des freien Bereiches suchen */
638 freeend = findnextsetbit (markbits, topofheap, freestart+1);
641 if (freeend==topofheap) {
642 topofheap = freestart;
643 heapfreemem += (freeend-freestart);
644 goto freememfinished;
646 fprintf(stderr, "%lx -- %lx\n", heap + freestart, heap + freeend);
649 /* Freien Bereich in Freispeicherliste einh"angen */
650 memlist_addrange (freestart, freeend-freestart);
652 /* Menge des freien Speichers mitnotieren */
653 heapfreemem += (freeend-freestart);
661 /* Die Rollen von markbits und startbits vertauschen */
663 markbits = startbits;
667 /* Threashold-Wert f"ur n"achstes Collect */
668 oldfillgrade = heapfillgrade;
669 heapfillgrade = topofheap - heapfreemem;
670 collectthreashold = heapfillgrade*3; /* eine nette Heuristik */
672 /* Eventuell eine Meldung ausgeben */
673 if (collectverbose) {
674 sprintf (logtext, "Garbage Collection: previous/now = %d / %d ",
675 (int) (oldfillgrade * BLOCKSIZE),
676 (int) (heapfillgrade * BLOCKSIZE) );
682 /* alle gerade unerreichbar gewordenen Objekte mit
683 finalize-Methoden jetzt finalisieren.
684 Achtung: Diese Funktion kann zu neuerlichem GC f"uhren!! */
689 /************************* Function: gc_init **********************************
691 Initializes anything that must be initialized to call the gc on the right
694 ******************************************************************************/
701 /************************** Function: gc_call ********************************
703 Calls the garbage collector. The garbage collector should always be called
704 using this function since it ensures that enough stack space is available.
706 ******************************************************************************/
712 assert(blockInts == 0);
715 if (currentThread == NULL || currentThread == mainThread)
718 asm_switchstackandcall(CONTEXT(mainThread).usedStackTop, heap_docollect);
726 /************************* Funktion: heap_init ********************************
728 Initialisiert den Garbage Collector.
730 heapbytesize: Maximale Gr"osse des Heap (in Bytes)
731 heapbytestartsize: Gr"osse des Heaps, bei dem zum ersten mal eine
732 GC durchgef"uhrt werden soll.
733 stackbottom: Ein Zeiger auf die Untergrenze des Stacks, im dem
734 Referenzen auf Objekte stehen k"onnen.
736 ******************************************************************************/
738 void heap_init (u4 heapbytesize, u4 heapbytestartsize, void **stackbottom)
743 heapsize = ALIGN (heapbytesize, getpagesize());
744 heapsize = heapsize/BLOCKSIZE;
745 heap = (void*) mmap ((void*) 0x10000000, (size_t) (heapsize * BLOCKSIZE),
746 PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, (off_t) 0);
747 if (heap != (void *) 0x10000000) {
749 printf("address = %p\n", heap);
750 panic("mmap failed\n");
755 heapsize = ALIGN (heapbytesize, 1024);
756 heapsize = heapsize/BLOCKSIZE;
757 heap = MNEW (heapblock, heapsize);
762 startbits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
763 markbits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
764 referencebits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
765 clearbitfield (startbits, heapsize);
766 clearbitfield (markbits, heapsize);
767 clearbitfield (referencebits, heapsize);
770 collectthreashold = heapbytestartsize/BLOCKSIZE;
771 allglobalreferences = chain_new ();
772 bottom_of_stack = stackbottom;
774 livefinalizees = NULL;
775 deadfinalizees = NULL;
779 /****************** Funktion: heap_close **************************************
781 Gibt allen ben"otigten Speicher frei
783 ******************************************************************************/
787 while (livefinalizees) {
788 finalizernode *n = livefinalizees->next;
789 asm_calljavamethod (livefinalizees->finalizer,
790 heap+livefinalizees->objstart,
792 FREE (livefinalizees, finalizernode);
796 #ifndef TRACECALLARGS
797 MFREE (heap, heapblock, heapsize);
799 MFREE (startbits, bitfieldtype, heapsize/BITFIELDBITS);
800 MFREE (markbits, bitfieldtype, heapsize/BITFIELDBITS);
801 MFREE (referencebits, bitfieldtype, heapsize/BITFIELDBITS);
802 chain_free (allglobalreferences);
806 /***************** Funktion: heap_addreference ********************************
808 Teilt dem GC eine Speicherstelle mit, an der eine globale Referenz
809 auf Objekte gespeichert sein kann.
811 ******************************************************************************/
813 void heap_addreference (void **reflocation)
815 intsDisable(); /* schani */
817 chain_addlast (allglobalreferences, reflocation);
819 intsRestore(); /* schani */
824 /***************** Funktion: heap_allocate ************************************
826 Fordert einen Speicher vom Heap an, der eine gew"unschte Gr"osse
827 (in Byte angegeben) haben muss.
828 Wenn kein Speicher mehr vorhanden ist (auch nicht nach einem
829 Garbage Collection-Durchlauf), dann wird NULL zur"uckgegeben.
830 Zus"atzlich wird durch den Parameter 'references' angegeben, ob
831 in das angelegte Objekt Referenzen auf andere Objekte eingetragen
833 (Wichtig wegen Beschleunigung des Mark&Sweep-Durchlauf)
834 Im Zweifelsfalle immer references=true verwenden.
836 ******************************************************************************/
838 void *heap_allocate (u4 bytelength, bool references, methodinfo *finalizer)
840 u4 freestart,freelength;
841 u4 length = ALIGN(bytelength, BLOCKSIZE) / BLOCKSIZE;
843 /* fprintf(stderr, "heap_allocate: 0x%lx (%ld) requested, 0x%lx (%ld) aligned\n", bytelength, bytelength, length * BLOCKSIZE, length * BLOCKSIZE); */
845 /* heap_docollect(); */
847 intsDisable(); /* schani */
849 memlist_getsuitable (&freestart, &freelength, length);
853 if ((topofheap+length > collectthreashold) ||
854 (topofheap+length > heapsize)) {
860 memlist_getsuitable (&freestart, &freelength, length);
861 if (freelength) goto onemoretry;
864 if (topofheap+length > heapsize) {
865 sprintf (logtext, "Heap-Allocation failed for %d bytes",
868 intsRestore(); /* schani */
872 freestart = topofheap;
874 setbit (startbits, topofheap);
878 if (freelength>length) {
879 setbit (startbits, freestart+length);
880 memlist_addrange (freestart+length, freelength-length);
884 if (references) setbit (referencebits, freestart);
886 heapfillgrade += length;
889 finalizernode *n = NEW(finalizernode);
890 n -> next = livefinalizees;
891 n -> objstart = freestart;
892 n -> finalizer = finalizer;
896 intsRestore(); /* schani */
899 sprintf (logtext, "new returns: %lx", (long) (heap + freestart));
903 return (void*) (heap + freestart);