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 setbit (markbits, blocknum);
424 if ( isbitclear(referencebits, blocknum) ) return;
426 objectend = findnextsetbit (startbits, topofheap, blocknum+1);
427 markreferences ((void**)obj, (void**) (heap+objectend) );
431 /******************** Funktion: markreferences ********************************
433 Geht einen Speicherbereich durch, und markiert alle Objekte, auf
434 die von diesem Bereich aus irgendeine Referenz existiert.
436 ******************************************************************************/
438 static void markreferences (void **rstart, void **rend)
442 for (ptr=rstart; ptr<rend; ptr++) mark (*ptr);
446 /******************* Funktion: markstack **************************************
448 Marks all objects that are referenced by the (C-)stacks of
451 (The stack-bottom is to be specified in the call to heap_init).
453 ******************************************************************************/
455 static void markstack () /* schani */
458 void **top_of_stack = &dummy;
463 for (aThread = liveThreads; aThread != 0; aThread = CONTEXT(aThread).nextlive) {
464 mark((heapblock*)aThread);
465 if (aThread == currentThread) {
466 if (top_of_stack > (void**)CONTEXT(aThread).stackEnd)
467 markreferences ((void**)CONTEXT(aThread).stackEnd, top_of_stack);
469 markreferences (top_of_stack, (void**)CONTEXT(aThread).stackEnd);
472 if (CONTEXT(aThread).usedStackTop > CONTEXT(aThread).stackEnd)
473 markreferences ((void**)CONTEXT(aThread).stackEnd,
474 (void**)CONTEXT(aThread).usedStackTop + 16);
476 markreferences ((void**)CONTEXT(aThread).usedStackTop - 16,
477 (void**)CONTEXT(aThread).stackEnd);
481 markreferences((void**)&threadQhead[0], (void**)&threadQhead[MAX_THREAD_PRIO]);
483 if (top_of_stack > bottom_of_stack)
484 markreferences(bottom_of_stack, top_of_stack);
486 markreferences(top_of_stack, bottom_of_stack);
492 /**************** Funktion: searchlivefinalizees *****************************
494 geht die Liste aller Objekte durch, die noch finalisiert werden m"ussen
495 (livefinalizees), und tr"agt alle nicht mehr markierten in die
496 Liste deadfinalizess ein (allerdings werden sie vorher noch als
497 erreicht markiert, damit sie nicht jetzt gleich gel"oscht werden).
499 *****************************************************************************/
501 static void searchlivefinalizees ()
503 finalizernode *fn = livefinalizees;
504 finalizernode *lastlive = NULL;
508 /* alle zu finalisierenden Objekte, die nicht mehr markiert sind: */
509 if (isbitclear (markbits, fn->objstart)) {
510 finalizernode *nextfn = fn->next;
512 mark (heap + fn->objstart);
514 if (lastlive) lastlive -> next = nextfn;
515 else livefinalizees = nextfn;
517 fn -> next = deadfinalizees;
531 /********************** Funktion: finalizedead *******************************
533 ruft die 'finalize'-Methode aller Objekte in der 'deadfinalizees'-
535 Achtung: Es kann hier eventuell zu neuerlichen Speicheranforderungen
536 (mit potentiell notwendigem GC) kommen, deshalb m"ussen manche
537 globalen Variablen in lokale Variblen kopiert werden
538 (Reentrant-F"ahigkeit!!!)
540 ******************************************************************************/
542 static void finalizedead()
544 finalizernode *fn = deadfinalizees;
545 deadfinalizees = NULL;
548 finalizernode *nextfn = fn->next;
550 asm_calljavamethod (fn->finalizer, heap+fn->objstart, NULL,NULL,NULL);
551 FREE (fn, finalizernode);
560 /****************** Funktion: heap_docollect **********************************
562 F"uhrt eine vollst"andige Garbage Collection durch
564 ******************************************************************************/
566 static void heap_docollect ()
568 u4 freestart,freeend;
576 fprintf(stderr, "doing garbage collection\n");
578 /* alle Markierungsbits l"oschen */
579 clearbitfield (markbits, topofheap);
581 /* Alle vom Stack referenzierten Objekte markieren */
582 asm_dumpregistersandcall (markstack);
584 /* Alle von globalen Variablen erreichbaren Objekte markieren */
585 p = chain_first (allglobalreferences);
588 p = chain_next (allglobalreferences);
591 /* alle Objekte durchsehen, die eine finalizer-Methode haben */
592 searchlivefinalizees();
594 /* alle Reference-Bits l"oschen, deren Objekte nicht */
595 /* mehr erreichbar sind */
596 maskfieldwithfield (referencebits, markbits, topofheap);
599 /* Freispeicherliste initialisieren */
603 /* Heap schrittweise durchgehen, und alle freien Bl"ocke merken */
608 /* Anfang des n"achsten freien Bereiches suchen */
609 freestart = findnextcombination_set_unset
610 (startbits, markbits, topofheap, freeend);
612 /* Wenn es keinen freien Bereich mehr gibt -> fertig */
613 if (freestart>=topofheap) goto freememfinished;
615 /* Anfang des freien Bereiches markieren */
616 setbit (markbits, freestart);
618 /* Ende des freien Bereiches suchen */
619 freeend = findnextsetbit (markbits, topofheap, freestart+1);
621 /* Freien Bereich in Freispeicherliste einh"angen */
622 memlist_addrange (freestart, freeend-freestart);
624 /* Menge des freien Speichers mitnotieren */
625 heapfreemem += (freeend-freestart);
630 /* Die Rollen von markbits und startbits vertauschen */
632 markbits = startbits;
636 /* Threashold-Wert f"ur n"achstes Collect */
637 oldfillgrade = heapfillgrade;
638 heapfillgrade = topofheap - heapfreemem;
639 collectthreashold = heapfillgrade*3; /* eine nette Heuristik */
641 /* Eventuell eine Meldung ausgeben */
642 if (collectverbose) {
643 sprintf (logtext, "Garbage Collection: previous/now = %d / %d ",
644 (int) (oldfillgrade * BLOCKSIZE),
645 (int) (heapfillgrade * BLOCKSIZE) );
651 /* alle gerade unerreichbar gewordenen Objekte mit
652 finalize-Methoden jetzt finalisieren.
653 Achtung: Diese Funktion kann zu neuerlichem GC f"uhren!! */
658 /************************* Function: gc_init **********************************
660 Initializes the garbage collection thread mechanism.
662 ******************************************************************************/
667 iCv gcConditionStart;
673 gcStartMutex.holder = 0;
674 gcStartMutex.count = 0;
675 gcStartMutex.muxWaiters = 0;
677 gcThreadMutex.holder = 0;
678 gcThreadMutex.count = 0;
679 gcThreadMutex.muxWaiters = 0;
681 gcConditionStart.cvWaiters = 0;
682 gcConditionStart.mux = 0;
684 gcConditionDone.cvWaiters = 0;
685 gcConditionDone.mux = 0;
694 /************************* Function: gc_thread ********************************
696 In an endless loop waits for a condition to be posted, then
697 garbage collects the heap.
699 ******************************************************************************/
705 intsRestore(); /* all threads start with interrupts disabled */
707 assert(blockInts == 0);
709 lock_mutex(&gcThreadMutex);
713 wait_cond(&gcThreadMutex, &gcConditionStart, 0);
719 signal_cond(&gcConditionDone);
728 lock_mutex(&gcThreadMutex);
730 signal_cond(&gcConditionStart);
731 wait_cond(&gcThreadMutex, &gcConditionDone, 0);
733 unlock_mutex(&gcThreadMutex);
740 /************************* Funktion: heap_init ********************************
742 Initialisiert den Garbage Collector.
744 heapbytesize: Maximale Gr"osse des Heap (in Bytes)
745 heapbytestartsize: Gr"osse des Heaps, bei dem zum ersten mal eine
746 GC durchgef"uhrt werden soll.
747 stackbottom: Ein Zeiger auf die Untergrenze des Stacks, im dem
748 Referenzen auf Objekte stehen k"onnen.
750 ******************************************************************************/
752 void heap_init (u4 heapbytesize, u4 heapbytestartsize, void **stackbottom)
757 heapsize = ALIGN (heapbytesize, getpagesize());
758 heapsize = heapsize/BLOCKSIZE;
759 heap = (void*) mmap ((void*) 0x10000000, (size_t) (heapsize * BLOCKSIZE),
760 PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, (off_t) 0);
761 if (heap != (void *) 0x10000000) {
763 printf("address = %p\n", heap);
764 panic("mmap failed\n");
769 heapsize = ALIGN (heapbytesize, 1024);
770 heapsize = heapsize/BLOCKSIZE;
771 heap = MNEW (heapblock, heapsize);
776 startbits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
777 markbits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
778 referencebits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
779 clearbitfield (startbits, heapsize);
780 clearbitfield (markbits, heapsize);
781 clearbitfield (referencebits, heapsize);
784 collectthreashold = heapbytestartsize/BLOCKSIZE;
785 allglobalreferences = chain_new ();
786 bottom_of_stack = stackbottom;
788 livefinalizees = NULL;
789 deadfinalizees = NULL;
793 /****************** Funktion: heap_close **************************************
795 Gibt allen ben"otigten Speicher frei
797 ******************************************************************************/
801 #ifndef TRACECALLARGS
802 MFREE (heap, heapblock, heapsize); */
804 MFREE (startbits, bitfieldtype, heapsize/BITFIELDBITS);
805 MFREE (markbits, bitfieldtype, heapsize/BITFIELDBITS);
806 MFREE (referencebits, bitfieldtype, heapsize/BITFIELDBITS);
807 chain_free (allglobalreferences);
809 while (livefinalizees) {
810 finalizernode *n = livefinalizees->next;
811 FREE (livefinalizees, finalizernode);
817 /***************** Funktion: heap_addreference ********************************
819 Teilt dem GC eine Speicherstelle mit, an der eine globale Referenz
820 auf Objekte gespeichert sein kann.
822 ******************************************************************************/
824 void heap_addreference (void **reflocation)
826 intsDisable(); /* schani */
828 chain_addlast (allglobalreferences, reflocation);
830 intsRestore(); /* schani */
835 /***************** Funktion: heap_allocate ************************************
837 Fordert einen Speicher vom Heap an, der eine gew"unschte Gr"osse
838 (in Byte angegeben) haben muss.
839 Wenn kein Speicher mehr vorhanden ist (auch nicht nach einem
840 Garbage Collection-Durchlauf), dann wird NULL zur"uckgegeben.
841 Zus"atzlich wird durch den Parameter 'references' angegeben, ob
842 in das angelegte Objekt Referenzen auf andere Objekte eingetragen
844 (Wichtig wegen Beschleunigung des Mark&Sweep-Durchlauf)
845 Im Zweifelsfalle immer references=true verwenden.
847 ******************************************************************************/
849 void *heap_allocate (u4 bytelength, bool references, methodinfo *finalizer)
851 u4 freestart,freelength;
852 u4 length = ALIGN(bytelength, BLOCKSIZE) / BLOCKSIZE;
854 intsDisable(); /* schani */
856 memlist_getsuitable (&freestart, &freelength, length);
859 if ( (topofheap+length > collectthreashold) || (topofheap+length > heapsize) ) {
864 memlist_getsuitable (&freestart, &freelength, length);
866 goto have_block; /* phil */
869 if (topofheap+length > heapsize) {
870 sprintf (logtext, "Heap-Allocation failed for %d bytes",
873 intsRestore(); /* schani */
877 freestart = topofheap;
879 setbit (startbits, topofheap);
884 if (freelength>length) {
885 setbit (startbits, freestart+length);
886 memlist_addrange (freestart+length, freelength-length);
890 setbit (referencebits, freestart);
892 setbit (startbits, freestart); /* phil */
894 heapfillgrade += length;
897 finalizernode *n = NEW(finalizernode);
898 n -> next = livefinalizees;
899 n -> objstart = freestart;
900 n -> finalizer = finalizer;
904 intsRestore(); /* schani */
907 sprintf (logtext, "new returns: %lx", (long) (heap + freestart));
911 return (void*) (heap + freestart);