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 */
462 if (currentThread == NULL) {
463 void **top_of_stack = &dummy;
465 if (top_of_stack > bottom_of_stack)
466 markreferences(bottom_of_stack, top_of_stack);
468 markreferences(top_of_stack, bottom_of_stack);
471 for (aThread = liveThreads; aThread != 0;
472 aThread = CONTEXT(aThread).nextlive) {
473 mark((heapblock*)aThread);
474 if (aThread == currentThread) {
475 void **top_of_stack = &dummy;
477 if (top_of_stack > (void**)CONTEXT(aThread).stackEnd)
478 markreferences((void**)CONTEXT(aThread).stackEnd, top_of_stack);
480 markreferences(top_of_stack, (void**)CONTEXT(aThread).stackEnd);
483 if (CONTEXT(aThread).usedStackTop > CONTEXT(aThread).stackEnd)
484 markreferences((void**)CONTEXT(aThread).stackEnd,
485 (void**)CONTEXT(aThread).usedStackTop);
487 markreferences((void**)CONTEXT(aThread).usedStackTop,
488 (void**)CONTEXT(aThread).stackEnd);
492 markreferences((void**)&threadQhead[0],
493 (void**)&threadQhead[MAX_THREAD_PRIO]);
496 void **top_of_stack = &dummy;
498 if (top_of_stack > bottom_of_stack)
499 markreferences(bottom_of_stack, top_of_stack);
501 markreferences(top_of_stack, bottom_of_stack);
506 /**************** Funktion: searchlivefinalizees *****************************
508 geht die Liste aller Objekte durch, die noch finalisiert werden m"ussen
509 (livefinalizees), und tr"agt alle nicht mehr markierten in die
510 Liste deadfinalizess ein (allerdings werden sie vorher noch als
511 erreicht markiert, damit sie nicht jetzt gleich gel"oscht werden).
513 *****************************************************************************/
515 static void searchlivefinalizees ()
517 finalizernode *fn = livefinalizees;
518 finalizernode *lastlive = NULL;
522 /* alle zu finalisierenden Objekte, die nicht mehr markiert sind: */
523 if (isbitclear (markbits, fn->objstart)) {
524 finalizernode *nextfn = fn->next;
526 mark (heap + fn->objstart);
528 if (lastlive) lastlive -> next = nextfn;
529 else livefinalizees = nextfn;
531 fn -> next = deadfinalizees;
545 /********************** Funktion: finalizedead *******************************
547 ruft die 'finalize'-Methode aller Objekte in der 'deadfinalizees'-
549 Achtung: Es kann hier eventuell zu neuerlichen Speicheranforderungen
550 (mit potentiell notwendigem GC) kommen, deshalb m"ussen manche
551 globalen Variablen in lokale Variblen kopiert werden
552 (Reentrant-F"ahigkeit!!!)
554 ******************************************************************************/
556 static void finalizedead()
558 finalizernode *fn = deadfinalizees;
559 deadfinalizees = NULL;
562 finalizernode *nextfn = fn->next;
564 asm_calljavamethod (fn->finalizer, heap+fn->objstart, NULL,NULL,NULL);
565 FREE (fn, finalizernode);
574 /****************** Funktion: heap_docollect **********************************
576 F"uhrt eine vollst"andige Garbage Collection durch
578 ******************************************************************************/
580 static void heap_docollect ()
582 u4 freestart,freeend;
590 fprintf(stderr, "doing garbage collection\n");
592 /* alle Markierungsbits l"oschen */
593 clearbitfield (markbits, topofheap);
595 /* Alle vom Stack referenzierten Objekte markieren */
596 asm_dumpregistersandcall (markstack);
598 /* Alle von globalen Variablen erreichbaren Objekte markieren */
599 p = chain_first (allglobalreferences);
602 p = chain_next (allglobalreferences);
605 /* alle Objekte durchsehen, die eine finalizer-Methode haben */
606 searchlivefinalizees();
608 /* alle Reference-Bits l"oschen, deren Objekte nicht */
609 /* mehr erreichbar sind */
610 maskfieldwithfield (referencebits, markbits, topofheap);
613 /* Freispeicherliste initialisieren */
617 /* Heap schrittweise durchgehen, und alle freien Bl"ocke merken */
622 /* Anfang des n"achsten freien Bereiches suchen */
623 freestart = findnextcombination_set_unset
624 (startbits, markbits, topofheap, freeend);
626 /* Wenn es keinen freien Bereich mehr gibt -> fertig */
627 if (freestart>=topofheap) goto freememfinished;
629 /* Anfang des freien Bereiches markieren */
630 setbit (markbits, freestart);
632 /* Ende des freien Bereiches suchen */
633 freeend = findnextsetbit (markbits, topofheap, freestart+1);
635 /* Freien Bereich in Freispeicherliste einh"angen */
636 memlist_addrange (freestart, freeend-freestart);
638 /* Menge des freien Speichers mitnotieren */
639 heapfreemem += (freeend-freestart);
644 /* Die Rollen von markbits und startbits vertauschen */
646 markbits = startbits;
650 /* Threashold-Wert f"ur n"achstes Collect */
651 oldfillgrade = heapfillgrade;
652 heapfillgrade = topofheap - heapfreemem;
653 collectthreashold = heapfillgrade*3; /* eine nette Heuristik */
655 /* Eventuell eine Meldung ausgeben */
656 if (collectverbose) {
657 sprintf (logtext, "Garbage Collection: previous/now = %d / %d ",
658 (int) (oldfillgrade * BLOCKSIZE),
659 (int) (heapfillgrade * BLOCKSIZE) );
665 /* alle gerade unerreichbar gewordenen Objekte mit
666 finalize-Methoden jetzt finalisieren.
667 Achtung: Diese Funktion kann zu neuerlichem GC f"uhren!! */
672 /************************* Function: gc_init **********************************
674 Initializes anything that must be initialized to call the gc on the right
677 ******************************************************************************/
684 /************************** Function: gc_call ********************************
686 Calls the garbage collector. The garbage collector should always be called
687 using this function since it ensures that enough stack space is available.
689 ******************************************************************************/
695 assert(blockInts == 0);
698 if (currentThread == NULL || currentThread == mainThread)
701 asm_switchstackandcall(CONTEXT(mainThread).usedStackTop, heap_docollect);
709 /************************* Funktion: heap_init ********************************
711 Initialisiert den Garbage Collector.
713 heapbytesize: Maximale Gr"osse des Heap (in Bytes)
714 heapbytestartsize: Gr"osse des Heaps, bei dem zum ersten mal eine
715 GC durchgef"uhrt werden soll.
716 stackbottom: Ein Zeiger auf die Untergrenze des Stacks, im dem
717 Referenzen auf Objekte stehen k"onnen.
719 ******************************************************************************/
721 void heap_init (u4 heapbytesize, u4 heapbytestartsize, void **stackbottom)
726 heapsize = ALIGN (heapbytesize, getpagesize());
727 heapsize = heapsize/BLOCKSIZE;
728 heap = (void*) mmap ((void*) 0x10000000, (size_t) (heapsize * BLOCKSIZE),
729 PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, (off_t) 0);
730 if (heap != (void *) 0x10000000) {
732 printf("address = %p\n", heap);
733 panic("mmap failed\n");
738 heapsize = ALIGN (heapbytesize, 1024);
739 heapsize = heapsize/BLOCKSIZE;
740 heap = MNEW (heapblock, heapsize);
745 startbits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
746 markbits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
747 referencebits = MNEW (bitfieldtype, heapsize/BITFIELDBITS);
748 clearbitfield (startbits, heapsize);
749 clearbitfield (markbits, heapsize);
750 clearbitfield (referencebits, heapsize);
753 collectthreashold = heapbytestartsize/BLOCKSIZE;
754 allglobalreferences = chain_new ();
755 bottom_of_stack = stackbottom;
757 livefinalizees = NULL;
758 deadfinalizees = NULL;
762 /****************** Funktion: heap_close **************************************
764 Gibt allen ben"otigten Speicher frei
766 ******************************************************************************/
770 #ifndef TRACECALLARGS
771 MFREE (heap, heapblock, heapsize); */
773 MFREE (startbits, bitfieldtype, heapsize/BITFIELDBITS);
774 MFREE (markbits, bitfieldtype, heapsize/BITFIELDBITS);
775 MFREE (referencebits, bitfieldtype, heapsize/BITFIELDBITS);
776 chain_free (allglobalreferences);
778 while (livefinalizees) {
779 finalizernode *n = livefinalizees->next;
780 asm_calljavamethod (livefinalizees->finalizer,
781 heap+livefinalizees->objstart,
783 FREE (livefinalizees, finalizernode);
789 /***************** Funktion: heap_addreference ********************************
791 Teilt dem GC eine Speicherstelle mit, an der eine globale Referenz
792 auf Objekte gespeichert sein kann.
794 ******************************************************************************/
796 void heap_addreference (void **reflocation)
798 intsDisable(); /* schani */
800 chain_addlast (allglobalreferences, reflocation);
802 intsRestore(); /* schani */
807 /***************** Funktion: heap_allocate ************************************
809 Fordert einen Speicher vom Heap an, der eine gew"unschte Gr"osse
810 (in Byte angegeben) haben muss.
811 Wenn kein Speicher mehr vorhanden ist (auch nicht nach einem
812 Garbage Collection-Durchlauf), dann wird NULL zur"uckgegeben.
813 Zus"atzlich wird durch den Parameter 'references' angegeben, ob
814 in das angelegte Objekt Referenzen auf andere Objekte eingetragen
816 (Wichtig wegen Beschleunigung des Mark&Sweep-Durchlauf)
817 Im Zweifelsfalle immer references=true verwenden.
819 ******************************************************************************/
821 void *heap_allocate (u4 bytelength, bool references, methodinfo *finalizer)
823 u4 freestart,freelength;
824 u4 length = ALIGN(bytelength, BLOCKSIZE) / BLOCKSIZE;
826 intsDisable(); /* schani */
828 memlist_getsuitable (&freestart, &freelength, length);
832 if ((topofheap+length > collectthreashold) ||
833 (topofheap+length > heapsize)) {
839 memlist_getsuitable (&freestart, &freelength, length);
840 if (freelength) goto onemoretry;
843 if (topofheap+length > heapsize) {
844 sprintf (logtext, "Heap-Allocation failed for %d bytes",
847 intsRestore(); /* schani */
851 freestart = topofheap;
853 setbit (startbits, topofheap);
857 if (freelength>length) {
858 setbit (startbits, freestart+length);
859 memlist_addrange (freestart+length, freelength-length);
863 if (references) setbit (referencebits, freestart);
865 heapfillgrade += length;
868 finalizernode *n = NEW(finalizernode);
869 n -> next = livefinalizees;
870 n -> objstart = freestart;
871 n -> finalizer = finalizer;
875 intsRestore(); /* schani */
878 sprintf (logtext, "new returns: %lx", (long) (heap + freestart));
882 return (void*) (heap + freestart);