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 *******************************************************************************/
23 #include <sys/types.h>
31 #include "threads/thread.h" /* schani */
32 #include "threads/locks.h"
37 /******************************************************************************
38 ********************* Der garbage-collected Heap ******************************
39 *******************************************************************************
41 verwaltet einen Heap mit automatischer Speicherfreigabe.
43 (eine ausf"uhrliche Dokumentation findet sich in der Datei:
46 ******************************************************************************/
49 bool collectverbose = false; /* soll Meldung beim GC ausgegeben werden? */
52 #define BLOCKSIZE 8 /* Gr"osse eines Speicherblockes */
53 typedef u8 heapblock; /* Datentyp mit der Gr"osse eines Speicherblocks */
55 #if U8_AVAILABLE && SUPPORT_LONG
56 #define bitfieldtype u8
57 #define BITFIELDBITS 64
59 #define bitfieldtype u4
60 #define BITFIELDBITS 32
63 u4 heapsize; /* Gr"osse des Heap in Blocks */
64 u4 topofheap; /* Bisherige Obergrenze Heaps */
65 heapblock *heap; /* Speicher f"ur den Heap selbst */
67 bitfieldtype *startbits; /* Bitfeld f"ur Bereichsstartkennung */
68 bitfieldtype *markbits; /* Bitfeld f"ur Markierung */
69 bitfieldtype *referencebits; /* Bitfeld f"ur Folgereferenzenkennung */
71 u4 heapfillgrade; /* Menge der Daten im Heap */
72 u4 collectthreashold; /* Schwellwert f"ur n"achstes GC */
74 void **bottom_of_stack; /* Zeiger auf Untergrenze des C-Stacks */
75 chain *allglobalreferences; /* Liste f"ur alle globalen Zeiger */
77 typedef struct finalizernode {
78 struct finalizernode *next;
80 methodinfo *finalizer;
83 finalizernode *livefinalizees;
84 finalizernode *deadfinalizees;
87 typedef struct memarea { /* Datenstruktur f"ur einen Freispeicherbereich */
91 typedef struct bigmemarea { /* Datenstruktur f"ur einen */
92 struct bigmemarea *next; /* Freispeicherbereich variabler L"ange */
96 #define DIFFERENTSIZES 128 /* Anzahl der 'kleinen' Freispeicherlisten */
97 memarea *memlist[DIFFERENTSIZES]; /* Die 'kleinen' Freispeicherlisten */
98 bitfieldtype memlistbits[DIFFERENTSIZES/BITFIELDBITS];
99 /* Bitfeld, in dem jeweils ein Bit gesetzt */
100 /* ist, wenn eine Liste noch etwas enth"alt */
102 bigmemarea *bigmemlist; /* Liste der gr"osseren Freispeicherbereiche */
107 /**************** Hilfsfunktion: lowest **************************************
109 liefert als Ergebnis die Nummer des niederwertigsten Bits einer
110 Zahl vom Typ bitfieldtype, das 1 ist.
111 Wenn die ganze Zahl keine 1en enth"alt, dann ist egal, was f"ur einen
112 Wert die Funktion l"iefert.
113 z.B.: lowest(1) = 0, lowest(12) = 2, lowest(1024) = 10
115 *****************************************************************************/
117 static u1 lowesttable[256] = {
118 255, 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 5, 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 6, 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 5, 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 7, 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 5, 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 6, 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,
132 5, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
133 4, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 };
135 static int lowest(bitfieldtype i)
143 if (i111) return lowesttable[i111>>56];
144 else return 8+lowesttable[i11>>56];
148 if (i112) return 16+lowesttable[i112>>56];
149 else return 24+lowesttable[i1>>56];
156 if (i121) return 32+lowesttable[i121>>56];
157 else return 40+lowesttable[i12>>56];
161 if (i122) return 48+lowesttable[i122>>56];
162 else return 56+lowesttable[i>>56];
169 if (i11) return lowesttable[i11>>24];
170 else return 8+lowesttable[i1>>24];
174 if (i12) return 16+lowesttable[i12>>24];
175 else return 24+lowesttable[i>>24];
181 /******** Funktionen zum Setzen und L"oschen von Bits in Bitfeldern ***********/
183 static void setbit(bitfieldtype *bitfield, u4 bitnumber)
185 bitfield[bitnumber/BITFIELDBITS] |=
186 ((bitfieldtype) 1) << (bitnumber%BITFIELDBITS);
189 static void clearbit(bitfieldtype *bitfield, u4 bitnumber)
191 bitfield[bitnumber/BITFIELDBITS] &=
192 ~((bitfieldtype) 1) << (bitnumber%BITFIELDBITS);
195 static bool isbitset(bitfieldtype *bitfield, u4 bitnumber)
197 return ( bitfield[bitnumber/BITFIELDBITS] &
198 ( ((bitfieldtype) 1) << (bitnumber%BITFIELDBITS) ) ) != 0;
201 static bool isbitclear(bitfieldtype *bitfield, u4 bitnumber)
203 return ( bitfield[bitnumber/BITFIELDBITS] &
204 ( ((bitfieldtype) 1) << (bitnumber%BITFIELDBITS) ) ) == 0;
208 /***************** Funktion: clearbitfield ************************************
210 l"oscht ein ganzes Bitfeld
212 ******************************************************************************/
214 static void clearbitfield(bitfieldtype *bitfield, u4 fieldsize)
217 t = ALIGN(fieldsize, BITFIELDBITS) / BITFIELDBITS;
218 for (i=0; i<t; i++) bitfield[i] = 0;
221 /************** Funktion: maskfieldwithfield **********************************
223 Verkn"upft zwei Bitfelder bitweise mit UND, das erste Bitfeld
224 wird mit dem Ergebnis "uberschrieben
226 ******************************************************************************/
228 static void maskfieldwithfield (bitfieldtype* bitfield,
229 bitfieldtype *maskfield, u4 fieldsize)
232 t = ALIGN(fieldsize, BITFIELDBITS) / BITFIELDBITS;
233 for (i=0; i<t; i++) bitfield[i] &= maskfield[i];
237 /************** Funktion: findnextsetbit **************************************
239 Sucht in einem Bitfeld ab einer Stelle das n"achste gesetzte Bit
240 und liefert die Nummer dieses Bits.
241 Wenn kein Bit mehr zwischen 'bitnumber' und 'fieldsize' gesetzt
242 ist, dann wird fieldsize zur"uckgeliefte.
244 ******************************************************************************/
246 static u4 findnextsetbit(bitfieldtype* bitfield, u4 fieldsize, u4 bitnumber)
248 bitfieldtype pattern;
251 if (bitnumber >= fieldsize) return fieldsize;
253 pattern = bitfield[bitnumber/BITFIELDBITS];
254 pattern >>= (bitnumber%BITFIELDBITS);
255 if (pattern) return bitnumber + lowest(pattern);
257 bitnumber = ((bitnumber + BITFIELDBITS) / BITFIELDBITS) * BITFIELDBITS;
262 /************ Funktion: findnextcombination_set_unset *************************
264 funktioniert wie findnextsetbit, allerdings sucht diese Funktion
265 nach einer Stelle, an der gleichzeitig ein Bit im ersten
266 Bitfeld gesetzt ist und im zweiten Bitfeld das entsprechende
267 Bit nicht gesetzt ist.
269 ******************************************************************************/
271 static u4 findnextcombination_set_unset
272 (bitfieldtype *bitfield1, bitfieldtype* bitfield2, u4 fieldsize, u4 bitnumber)
274 bitfieldtype pattern;
277 if (bitnumber >= fieldsize) return fieldsize;
279 pattern = bitfield1[bitnumber/BITFIELDBITS]
280 & (~bitfield2[bitnumber/BITFIELDBITS]);
281 pattern >>= (bitnumber%BITFIELDBITS);
282 if (pattern) return bitnumber + lowest(pattern);
284 bitnumber = ((bitnumber + BITFIELDBITS) / BITFIELDBITS) * BITFIELDBITS;
290 /************** Funktion: memlist_init ****************************************
292 initialisiert die Freispeicherlisten (zum nachfolgenden Eintragen
293 mit memlist_addrange).
295 ******************************************************************************/
297 static void memlist_init ()
300 for (i=0; i<DIFFERENTSIZES; i++) memlist[i] = NULL;
301 clearbitfield (memlistbits, DIFFERENTSIZES);
306 /************** Funktion: memlist_addrange ************************************
308 f"ugt einen Bereich von Heap-Bl"ocken zur Freispeicherliste
309 hinzu (in die freien Heap-Bl"ocke werden dabei verschiedene
310 Verkettungszeiger hineingeschrieben).
312 ******************************************************************************/
314 static void memlist_addrange (u4 freestart, u4 freesize)
316 if (freesize>=DIFFERENTSIZES) {
317 bigmemarea *m = (bigmemarea*) (heap+freestart);
318 m -> next = bigmemlist;
319 m -> size = freesize;
323 if (freesize*BLOCKSIZE>=sizeof(memarea)) {
324 memarea *m = (memarea*) (heap+freestart);
325 m -> next = memlist[freesize];
326 memlist[freesize] = m;
327 setbit (memlistbits, freesize);
333 /************** Funktion: memlist_getsuitable *********************************
335 sucht in der Freispeicherliste einen Speicherbereich, der m"oglichst
336 genau die gew"unschte L"ange hat.
337 Der Bereich wird dabei auf jeden Fall aus der Liste ausgetragen.
338 (Wenn der Bereich zu lang sein sollte, dann kann der Aufrufer den
339 Rest wieder mit 'memlist_addrange' in die Liste einh"angen)
341 Return (in Referenzparametern):
342 *freestart: Anfang des freien Speichers
343 *freelength: L"ange dieses Speicherbereiches
345 Wenn kein passender Speicherblock mehr gefunden werden kann, dann
346 wird in '*freelength' 0 hineingeschrieben.
348 ******************************************************************************/
350 static void memlist_getsuitable (u4 *freestart, u4 *freelength, u4 length)
353 bigmemarea *prevm = NULL;
355 if (length<DIFFERENTSIZES) {
358 if (memlist[length]) {
359 firstfreelength = length;
362 firstfreelength = findnextsetbit
363 (memlistbits, DIFFERENTSIZES, length+3);
364 /* wenn kein passender Block da ist, dann gleich nach */
365 /* einem etwas gr"osseren suchen, damit keine kleinen */
366 /* St"uckchen "ubrigbleiben */
369 if (firstfreelength<DIFFERENTSIZES) {
370 memarea *m = memlist[firstfreelength];
371 memlist[firstfreelength] = m->next;
372 if (!m->next) clearbit (memlistbits, firstfreelength);
373 *freestart = ((heapblock*) m) - heap;
374 *freelength = firstfreelength;
381 if (m->size >= length) {
382 if (prevm) prevm->next = m->next;
383 else bigmemlist = m->next;
385 *freestart = ((heapblock*) m) - heap;
386 *freelength = m->size;
401 /******************* Funktion: mark *******************************************
403 Markiert ein m"oglicherweise g"ultiges Objekt.
404 Sollte sich herausstellen, dass der Zeiger gar nicht auf ein Objekt
405 am Heap zeigt, dann wird eben gar nichts markiert.
407 ******************************************************************************/
409 static void markreferences (void **rstart, void **rend);
411 static void mark (heapblock *obj)
413 u4 blocknum,objectend;
415 if ((long) obj & (BLOCKSIZE-1)) return;
417 if (obj<heap) return;
418 if (obj>=(heap+topofheap) ) return;
421 if ( isbitclear(startbits, blocknum) ) return;
422 if ( isbitset(markbits, blocknum) ) return;
424 /* fprintf(stderr, "mark: marking object at 0x%lx\n", obj); */
425 setbit (markbits, blocknum);
427 if ( isbitclear(referencebits, blocknum) ) return;
429 objectend = findnextsetbit (startbits, topofheap, blocknum+1);
430 markreferences ((void**)obj, (void**) (heap+objectend) );
434 /******************** Funktion: markreferences ********************************
436 Geht einen Speicherbereich durch, und markiert alle Objekte, auf
437 die von diesem Bereich aus irgendeine Referenz existiert.
439 ******************************************************************************/
441 static void markreferences (void **rstart, void **rend)
445 for (ptr=rstart; ptr<rend; ptr++) mark (*ptr);
449 /******************* Funktion: markstack **************************************
451 Marks all objects that are referenced by the (C-)stacks of
454 (The stack-bottom is to be specified in the call to heap_init).
456 ******************************************************************************/
458 static void markstack ()
465 if (currentThread == NULL) {
466 void **top_of_stack = &dummy;
468 if (top_of_stack > bottom_of_stack)
469 markreferences(bottom_of_stack, top_of_stack);
471 markreferences(top_of_stack, bottom_of_stack);
474 for (aThread = liveThreads; aThread != 0;
475 aThread = CONTEXT(aThread).nextlive) {
476 mark((heapblock*)aThread);
477 if (CONTEXT(aThread).usedStackTop > CONTEXT(aThread).stackEnd)
478 markreferences((void**)CONTEXT(aThread).stackEnd,
479 (void**)CONTEXT(aThread).usedStackTop);
481 markreferences((void**)CONTEXT(aThread).usedStackTop,
482 (void**)CONTEXT(aThread).stackEnd);
485 markreferences((void**)&threadQhead[0],
486 (void**)&threadQhead[MAX_THREAD_PRIO]);
489 void **top_of_stack = &dummy;
491 /* fprintf(stderr, "marking stack\n"); */
493 if (top_of_stack > bottom_of_stack)
494 markreferences(bottom_of_stack, top_of_stack);
496 markreferences(top_of_stack, bottom_of_stack);
501 /**************** Funktion: searchlivefinalizees *****************************
503 geht die Liste aller Objekte durch, die noch finalisiert werden m"ussen
504 (livefinalizees), und tr"agt alle nicht mehr markierten in die
505 Liste deadfinalizess ein (allerdings werden sie vorher noch als
506 erreicht markiert, damit sie nicht jetzt gleich gel"oscht werden).
508 *****************************************************************************/
510 static void searchlivefinalizees ()
512 finalizernode *fn = livefinalizees;
513 finalizernode *lastlive = NULL;
517 /* alle zu finalisierenden Objekte, die nicht mehr markiert sind: */
518 if (isbitclear (markbits, fn->objstart)) {
519 finalizernode *nextfn = fn->next;
521 mark (heap + fn->objstart);
523 if (lastlive) lastlive -> next = nextfn;
524 else livefinalizees = nextfn;
526 fn -> next = deadfinalizees;
540 /********************** Funktion: finalizedead *******************************
542 ruft die 'finalize'-Methode aller Objekte in der 'deadfinalizees'-
544 Achtung: Es kann hier eventuell zu neuerlichen Speicheranforderungen
545 (mit potentiell notwendigem GC) kommen, deshalb m"ussen manche
546 globalen Variablen in lokale Variblen kopiert werden
547 (Reentrant-F"ahigkeit!!!)
549 ******************************************************************************/
551 static void finalizedead()
553 finalizernode *fn = deadfinalizees;
554 deadfinalizees = NULL;
557 finalizernode *nextfn = fn->next;
559 asm_calljavamethod (fn->finalizer, heap+fn->objstart, NULL,NULL,NULL);
560 FREE (fn, finalizernode);
569 /****************** Funktion: heap_docollect **********************************
571 F"uhrt eine vollst"andige Garbage Collection durch
573 ******************************************************************************/
575 static void heap_docollect ()
577 u4 freestart,freeend;
585 fprintf(stderr, "doing garbage collection\n");
587 /* alle Markierungsbits l"oschen */
588 clearbitfield (markbits, topofheap);
590 /* Alle vom Stack referenzierten Objekte markieren */
591 asm_dumpregistersandcall (markstack);
593 /* fprintf(stderr, "marking references\n"); */
594 /* Alle von globalen Variablen erreichbaren Objekte markieren */
595 p = chain_first (allglobalreferences);
598 p = chain_next (allglobalreferences);
601 /* alle Objekte durchsehen, die eine finalizer-Methode haben */
602 searchlivefinalizees();
604 /* alle Reference-Bits l"oschen, deren Objekte nicht */
605 /* mehr erreichbar sind */
606 maskfieldwithfield (referencebits, markbits, topofheap);
609 /* Freispeicherliste initialisieren */
613 /* Heap schrittweise durchgehen, und alle freien Bl"ocke merken */
618 /* Anfang des n"achsten freien Bereiches suchen */
619 freestart = findnextcombination_set_unset
620 (startbits, markbits, topofheap, freeend);
622 /* Wenn es keinen freien Bereich mehr gibt -> fertig */
623 if (freestart>=topofheap) goto freememfinished;
625 /* Anfang des freien Bereiches markieren */
626 setbit (markbits, freestart);
628 /* Ende des freien Bereiches suchen */
629 freeend = findnextsetbit (markbits, topofheap, freestart+1);
632 if (freeend==topofheap) {
633 topofheap = freestart;
634 heapfreemem += (freeend-freestart);
635 goto freememfinished;
637 fprintf(stderr, "%lx -- %lx\n", heap + freestart, heap + freeend);
640 /* Freien Bereich in Freispeicherliste einh"angen */
641 memlist_addrange (freestart, freeend-freestart);
643 /* Menge des freien Speichers mitnotieren */
644 heapfreemem += (freeend-freestart);
652 /* Die Rollen von markbits und startbits vertauschen */
654 markbits = startbits;
658 /* Threashold-Wert f"ur n"achstes Collect */
659 oldfillgrade = heapfillgrade;
660 heapfillgrade = topofheap - heapfreemem;
661 collectthreashold = heapfillgrade*3; /* eine nette Heuristik */
663 /* Eventuell eine Meldung ausgeben */
664 if (collectverbose) {
665 sprintf (logtext, "Garbage Collection: previous/now = %d / %d ",
666 (int) (oldfillgrade * BLOCKSIZE),
667 (int) (heapfillgrade * BLOCKSIZE) );
673 /* alle gerade unerreichbar gewordenen Objekte mit
674 finalize-Methoden jetzt finalisieren.
675 Achtung: Diese Funktion kann zu neuerlichem GC f"uhren!! */
680 /************************* Function: gc_init **********************************
682 Initializes anything that must be initialized to call the gc on the right
685 ******************************************************************************/
692 /************************** Function: gc_call ********************************
694 Calls the garbage collector. The garbage collector should always be called
695 using this function since it ensures that enough stack space is available.
697 ******************************************************************************/
705 assert(blockInts == 0);
708 if (currentThread == NULL || currentThread == mainThread) {
709 CONTEXT(mainThread).usedStackTop = &dummy;
713 asm_switchstackandcall(CONTEXT(mainThread).usedStackTop, heap_docollect,
714 (void**)&(CONTEXT(currentThread).usedStackTop),NULL);
722 /************************* Funktion: heap_init ********************************
724 Initialisiert den Garbage Collector.
726 heapbytesize: Maximale Gr"osse des Heap (in Bytes)
727 heapbytestartsize: Gr"osse des Heaps, bei dem zum ersten mal eine
728 GC durchgef"uhrt werden soll.
729 stackbottom: Ein Zeiger auf die Untergrenze des Stacks, im dem
730 Referenzen auf Objekte stehen k"onnen.
732 ******************************************************************************/
734 void heap_init (u4 heapbytesize, u4 heapbytestartsize, void **stackbottom)
739 heapsize = ALIGN (heapbytesize, getpagesize());
740 heapsize = heapsize/BLOCKSIZE;
741 heap = (void*) mmap ((void*) 0x10000000, (size_t) (heapsize * BLOCKSIZE),
742 PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, (off_t) 0);
743 if (heap != (void *) 0x10000000) {
745 printf("address = %p\n", heap);
746 panic("mmap failed\n");
751 heapsize = ALIGN (heapbytesize, 1024);
752 heapsize = heapsize/BLOCKSIZE;
753 heap = MNEW (heapblock, heapsize);
758 startbits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
759 markbits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
760 referencebits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
761 clearbitfield (startbits, heapsize);
762 clearbitfield (markbits, heapsize);
763 clearbitfield (referencebits, heapsize);
766 collectthreashold = heapbytestartsize/BLOCKSIZE;
767 allglobalreferences = chain_new ();
768 bottom_of_stack = stackbottom;
770 livefinalizees = NULL;
771 deadfinalizees = NULL;
775 /****************** Funktion: heap_close **************************************
777 Gibt allen ben"otigten Speicher frei
779 ******************************************************************************/
783 while (livefinalizees) {
784 finalizernode *n = livefinalizees->next;
785 asm_calljavamethod (livefinalizees->finalizer,
786 heap+livefinalizees->objstart,
788 FREE (livefinalizees, finalizernode);
792 #ifndef TRACECALLARGS
793 MFREE (heap, heapblock, heapsize);
795 MFREE (startbits, bitfieldtype, heapsize/BITFIELDBITS);
796 MFREE (markbits, bitfieldtype, heapsize/BITFIELDBITS);
797 MFREE (referencebits, bitfieldtype, heapsize/BITFIELDBITS);
798 if (allglobalreferences != NULL)
799 chain_free (allglobalreferences);
803 /***************** Funktion: heap_addreference ********************************
805 Teilt dem GC eine Speicherstelle mit, an der eine globale Referenz
806 auf Objekte gespeichert sein kann.
808 ******************************************************************************/
810 void heap_addreference (void **reflocation)
812 intsDisable(); /* schani */
814 chain_addlast (allglobalreferences, reflocation);
816 intsRestore(); /* schani */
821 /***************** Funktion: heap_allocate ************************************
823 Fordert einen Speicher vom Heap an, der eine gew"unschte Gr"osse
824 (in Byte angegeben) haben muss.
825 Wenn kein Speicher mehr vorhanden ist (auch nicht nach einem
826 Garbage Collection-Durchlauf), dann wird NULL zur"uckgegeben.
827 Zus"atzlich wird durch den Parameter 'references' angegeben, ob
828 in das angelegte Objekt Referenzen auf andere Objekte eingetragen
830 (Wichtig wegen Beschleunigung des Mark&Sweep-Durchlauf)
831 Im Zweifelsfalle immer references=true verwenden.
833 ******************************************************************************/
835 void *heap_allocate (u4 bytelength, bool references, methodinfo *finalizer)
837 u4 freestart,freelength;
838 u4 length = ALIGN(bytelength, BLOCKSIZE) / BLOCKSIZE;
840 /* fprintf(stderr, "heap_allocate: 0x%lx (%ld) requested, 0x%lx (%ld) aligned\n", bytelength, bytelength, length * BLOCKSIZE, length * BLOCKSIZE); */
842 /* heap_docollect(); */
844 intsDisable(); /* schani */
846 memlist_getsuitable (&freestart, &freelength, length);
850 if ((topofheap+length > collectthreashold) ||
851 (topofheap+length > heapsize)) {
857 memlist_getsuitable (&freestart, &freelength, length);
858 if (freelength) goto onemoretry;
861 if (topofheap+length > heapsize) {
862 sprintf (logtext, "Heap-Allocation failed for %d bytes",
865 intsRestore(); /* schani */
869 freestart = topofheap;
871 setbit (startbits, topofheap);
875 if (freelength>length) {
876 setbit (startbits, freestart+length);
877 memlist_addrange (freestart+length, freelength-length);
881 if (references) setbit (referencebits, freestart);
883 heapfillgrade += length;
886 finalizernode *n = NEW(finalizernode);
887 n -> next = livefinalizees;
888 n -> objstart = freestart;
889 n -> finalizer = finalizer;
893 intsRestore(); /* schani */
896 sprintf (logtext, "new returns: %lx", (long) (heap + freestart));
900 return (void*) (heap + freestart);