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 *******************************************************************************/
30 #include "threads/thread.h" /* schani */
31 #include "threads/locks.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 ()
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 (CONTEXT(aThread).usedStackTop > CONTEXT(aThread).stackEnd)
477 markreferences((void**)CONTEXT(aThread).stackEnd,
478 (void**)CONTEXT(aThread).usedStackTop);
480 markreferences((void**)CONTEXT(aThread).usedStackTop,
481 (void**)CONTEXT(aThread).stackEnd);
484 markreferences((void**)&threadQhead[0],
485 (void**)&threadQhead[MAX_THREAD_PRIO]);
488 void **top_of_stack = &dummy;
490 /* fprintf(stderr, "marking stack\n"); */
492 if (top_of_stack > bottom_of_stack)
493 markreferences(bottom_of_stack, top_of_stack);
495 markreferences(top_of_stack, bottom_of_stack);
500 /**************** Funktion: searchlivefinalizees *****************************
502 geht die Liste aller Objekte durch, die noch finalisiert werden m"ussen
503 (livefinalizees), und tr"agt alle nicht mehr markierten in die
504 Liste deadfinalizess ein (allerdings werden sie vorher noch als
505 erreicht markiert, damit sie nicht jetzt gleich gel"oscht werden).
507 *****************************************************************************/
509 static void searchlivefinalizees ()
511 finalizernode *fn = livefinalizees;
512 finalizernode *lastlive = NULL;
516 /* alle zu finalisierenden Objekte, die nicht mehr markiert sind: */
517 if (isbitclear (markbits, fn->objstart)) {
518 finalizernode *nextfn = fn->next;
520 mark (heap + fn->objstart);
522 if (lastlive) lastlive -> next = nextfn;
523 else livefinalizees = nextfn;
525 fn -> next = deadfinalizees;
539 /********************** Funktion: finalizedead *******************************
541 ruft die 'finalize'-Methode aller Objekte in der 'deadfinalizees'-
543 Achtung: Es kann hier eventuell zu neuerlichen Speicheranforderungen
544 (mit potentiell notwendigem GC) kommen, deshalb m"ussen manche
545 globalen Variablen in lokale Variblen kopiert werden
546 (Reentrant-F"ahigkeit!!!)
548 ******************************************************************************/
550 static void finalizedead()
552 finalizernode *fn = deadfinalizees;
553 deadfinalizees = NULL;
556 finalizernode *nextfn = fn->next;
558 asm_calljavamethod (fn->finalizer, heap+fn->objstart, NULL,NULL,NULL);
559 FREE (fn, finalizernode);
568 /****************** Funktion: heap_docollect **********************************
570 F"uhrt eine vollst"andige Garbage Collection durch
572 ******************************************************************************/
574 static void heap_docollect ()
576 u4 freestart,freeend;
584 fprintf(stderr, "doing garbage collection\n");
586 /* alle Markierungsbits l"oschen */
587 clearbitfield (markbits, topofheap);
589 /* Alle vom Stack referenzierten Objekte markieren */
590 asm_dumpregistersandcall (markstack);
592 /* fprintf(stderr, "marking references\n"); */
593 /* Alle von globalen Variablen erreichbaren Objekte markieren */
594 p = chain_first (allglobalreferences);
597 p = chain_next (allglobalreferences);
600 /* alle Objekte durchsehen, die eine finalizer-Methode haben */
601 searchlivefinalizees();
603 /* alle Reference-Bits l"oschen, deren Objekte nicht */
604 /* mehr erreichbar sind */
605 maskfieldwithfield (referencebits, markbits, topofheap);
608 /* Freispeicherliste initialisieren */
612 /* Heap schrittweise durchgehen, und alle freien Bl"ocke merken */
617 /* Anfang des n"achsten freien Bereiches suchen */
618 freestart = findnextcombination_set_unset
619 (startbits, markbits, topofheap, freeend);
621 /* Wenn es keinen freien Bereich mehr gibt -> fertig */
622 if (freestart>=topofheap) goto freememfinished;
624 /* Anfang des freien Bereiches markieren */
625 setbit (markbits, freestart);
627 /* Ende des freien Bereiches suchen */
628 freeend = findnextsetbit (markbits, topofheap, freestart+1);
631 if (freeend==topofheap) {
632 topofheap = freestart;
633 heapfreemem += (freeend-freestart);
634 goto freememfinished;
636 fprintf(stderr, "%lx -- %lx\n", heap + freestart, heap + freeend);
639 /* Freien Bereich in Freispeicherliste einh"angen */
640 memlist_addrange (freestart, freeend-freestart);
642 /* Menge des freien Speichers mitnotieren */
643 heapfreemem += (freeend-freestart);
651 /* Die Rollen von markbits und startbits vertauschen */
653 markbits = startbits;
657 /* Threashold-Wert f"ur n"achstes Collect */
658 oldfillgrade = heapfillgrade;
659 heapfillgrade = topofheap - heapfreemem;
660 collectthreashold = heapfillgrade*3; /* eine nette Heuristik */
662 /* Eventuell eine Meldung ausgeben */
663 if (collectverbose) {
664 sprintf (logtext, "Garbage Collection: previous/now = %d / %d ",
665 (int) (oldfillgrade * BLOCKSIZE),
666 (int) (heapfillgrade * BLOCKSIZE) );
672 /* alle gerade unerreichbar gewordenen Objekte mit
673 finalize-Methoden jetzt finalisieren.
674 Achtung: Diese Funktion kann zu neuerlichem GC f"uhren!! */
679 /************************* Function: gc_init **********************************
681 Initializes anything that must be initialized to call the gc on the right
684 ******************************************************************************/
691 /************************** Function: gc_call ********************************
693 Calls the garbage collector. The garbage collector should always be called
694 using this function since it ensures that enough stack space is available.
696 ******************************************************************************/
704 assert(blockInts == 0);
707 if (currentThread == NULL || currentThread == mainThread) {
708 CONTEXT(mainThread).usedStackTop = &dummy;
712 asm_switchstackandcall(CONTEXT(mainThread).usedStackTop, heap_docollect,
713 (void**)&(CONTEXT(currentThread).usedStackTop));
721 /************************* Funktion: heap_init ********************************
723 Initialisiert den Garbage Collector.
725 heapbytesize: Maximale Gr"osse des Heap (in Bytes)
726 heapbytestartsize: Gr"osse des Heaps, bei dem zum ersten mal eine
727 GC durchgef"uhrt werden soll.
728 stackbottom: Ein Zeiger auf die Untergrenze des Stacks, im dem
729 Referenzen auf Objekte stehen k"onnen.
731 ******************************************************************************/
733 void heap_init (u4 heapbytesize, u4 heapbytestartsize, void **stackbottom)
738 heapsize = ALIGN (heapbytesize, getpagesize());
739 heapsize = heapsize/BLOCKSIZE;
740 heap = (void*) mmap ((void*) 0x10000000, (size_t) (heapsize * BLOCKSIZE),
741 PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, (off_t) 0);
742 if (heap != (void *) 0x10000000) {
744 printf("address = %p\n", heap);
745 panic("mmap failed\n");
750 heapsize = ALIGN (heapbytesize, 1024);
751 heapsize = heapsize/BLOCKSIZE;
752 heap = MNEW (heapblock, heapsize);
757 startbits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
758 markbits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
759 referencebits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
760 clearbitfield (startbits, heapsize);
761 clearbitfield (markbits, heapsize);
762 clearbitfield (referencebits, heapsize);
765 collectthreashold = heapbytestartsize/BLOCKSIZE;
766 allglobalreferences = chain_new ();
767 bottom_of_stack = stackbottom;
769 livefinalizees = NULL;
770 deadfinalizees = NULL;
774 /****************** Funktion: heap_close **************************************
776 Gibt allen ben"otigten Speicher frei
778 ******************************************************************************/
782 while (livefinalizees) {
783 finalizernode *n = livefinalizees->next;
784 asm_calljavamethod (livefinalizees->finalizer,
785 heap+livefinalizees->objstart,
787 FREE (livefinalizees, finalizernode);
791 #ifndef TRACECALLARGS
792 MFREE (heap, heapblock, heapsize);
794 MFREE (startbits, bitfieldtype, heapsize/BITFIELDBITS);
795 MFREE (markbits, bitfieldtype, heapsize/BITFIELDBITS);
796 MFREE (referencebits, bitfieldtype, heapsize/BITFIELDBITS);
797 if (allglobalreferences != NULL)
798 chain_free (allglobalreferences);
802 /***************** Funktion: heap_addreference ********************************
804 Teilt dem GC eine Speicherstelle mit, an der eine globale Referenz
805 auf Objekte gespeichert sein kann.
807 ******************************************************************************/
809 void heap_addreference (void **reflocation)
811 intsDisable(); /* schani */
813 chain_addlast (allglobalreferences, reflocation);
815 intsRestore(); /* schani */
820 /***************** Funktion: heap_allocate ************************************
822 Fordert einen Speicher vom Heap an, der eine gew"unschte Gr"osse
823 (in Byte angegeben) haben muss.
824 Wenn kein Speicher mehr vorhanden ist (auch nicht nach einem
825 Garbage Collection-Durchlauf), dann wird NULL zur"uckgegeben.
826 Zus"atzlich wird durch den Parameter 'references' angegeben, ob
827 in das angelegte Objekt Referenzen auf andere Objekte eingetragen
829 (Wichtig wegen Beschleunigung des Mark&Sweep-Durchlauf)
830 Im Zweifelsfalle immer references=true verwenden.
832 ******************************************************************************/
834 void *heap_allocate (u4 bytelength, bool references, methodinfo *finalizer)
836 u4 freestart,freelength;
837 u4 length = ALIGN(bytelength, BLOCKSIZE) / BLOCKSIZE;
839 /* fprintf(stderr, "heap_allocate: 0x%lx (%ld) requested, 0x%lx (%ld) aligned\n", bytelength, bytelength, length * BLOCKSIZE, length * BLOCKSIZE); */
841 /* heap_docollect(); */
843 intsDisable(); /* schani */
845 memlist_getsuitable (&freestart, &freelength, length);
849 if ((topofheap+length > collectthreashold) ||
850 (topofheap+length > heapsize)) {
856 memlist_getsuitable (&freestart, &freelength, length);
857 if (freelength) goto onemoretry;
860 if (topofheap+length > heapsize) {
861 sprintf (logtext, "Heap-Allocation failed for %d bytes",
864 intsRestore(); /* schani */
868 freestart = topofheap;
870 setbit (startbits, topofheap);
874 if (freelength>length) {
875 setbit (startbits, freestart+length);
876 memlist_addrange (freestart+length, freelength-length);
880 if (references) setbit (referencebits, freestart);
882 heapfillgrade += length;
885 finalizernode *n = NEW(finalizernode);
886 n -> next = livefinalizees;
887 n -> objstart = freestart;
888 n -> finalizer = finalizer;
892 intsRestore(); /* schani */
895 sprintf (logtext, "new returns: %lx", (long) (heap + freestart));
899 return (void*) (heap + freestart);