11import { AL_BITS , AL_MASK , DEBUG , BLOCK , BLOCK_OVERHEAD , BLOCK_MAXSIZE } from "rt/common" ;
2- import { onfree , onalloc } from "./rtrace" ;
2+ import { onfree , onalloc , onrealloc } from "./rtrace" ;
33import { REFCOUNT_MASK } from "./pure" ;
44
55/////////////////////// The TLSF (Two-Level Segregate Fit) memory allocator ///////////////////////
@@ -486,7 +486,7 @@ export function maybeInitialize(): Root {
486486var collectLock : bool = false ;
487487
488488/** Allocates a block of the specified size. */
489- export function allocateBlock ( root : Root , size : usize ) : Block {
489+ export function allocateBlock ( root : Root , size : usize , id : u32 ) : Block {
490490 if ( DEBUG ) assert ( ! collectLock ) ; // must not allocate while collecting
491491 var payloadSize = prepareSize ( size ) ;
492492 var block = searchBlock ( root , payloadSize ) ;
@@ -509,7 +509,7 @@ export function allocateBlock(root: Root, size: usize): Block {
509509 }
510510 if ( DEBUG ) assert ( ( block . mmInfo & ~ TAGS_MASK ) >= payloadSize ) ; // must fit
511511 block . gcInfo = 0 ; // RC=0
512- // block.rtId = 0; // set by the caller (__alloc)
512+ block . rtId = id ;
513513 block . rtSize = size ;
514514 removeBlock ( root , < Block > block ) ;
515515 prepareBlock ( root , < Block > block , payloadSize ) ;
@@ -521,12 +521,6 @@ export function allocateBlock(root: Root, size: usize): Block {
521521export function reallocateBlock ( root : Root , block : Block , size : usize ) : Block {
522522 var payloadSize = prepareSize ( size ) ;
523523 var blockInfo = block . mmInfo ;
524- if ( DEBUG ) {
525- assert (
526- ! ( blockInfo & FREE ) && // must be used
527- ! ( block . gcInfo & ~ REFCOUNT_MASK ) // not buffered or != BLACK
528- ) ;
529- }
530524
531525 // possibly split and update runtime size if it still fits
532526 if ( payloadSize <= ( blockInfo & ~ TAGS_MASK ) ) {
@@ -552,44 +546,53 @@ export function reallocateBlock(root: Root, block: Block, size: usize): Block {
552546 }
553547
554548 // otherwise move the block
555- var newBlock = allocateBlock ( root , size ) ;
556- newBlock . rtId = block . rtId ;
549+ var newBlock = allocateBlock ( root , size , block . rtId ) ; // may invalidate cached blockInfo
550+ newBlock . gcInfo = block . gcInfo ; // keep RC
557551 memory . copy ( changetype < usize > ( newBlock ) + BLOCK_OVERHEAD , changetype < usize > ( block ) + BLOCK_OVERHEAD , size ) ;
558552 if ( changetype < usize > ( block ) >= __heap_base ) {
559- block . mmInfo = blockInfo | FREE ;
560- insertBlock ( root , block ) ;
561- if ( isDefined ( ASC_RTRACE ) ) onfree ( block ) ;
553+ if ( isDefined ( ASC_RTRACE ) ) onrealloc ( block , newBlock ) ;
554+ freeBlock ( root , block ) ;
562555 }
563556 return newBlock ;
564557}
565558
566559/** Frees a block. */
567560export function freeBlock ( root : Root , block : Block ) : void {
568561 var blockInfo = block . mmInfo ;
569- assert ( ! ( blockInfo & FREE ) ) ; // must be used (user might call through to this)
570562 block . mmInfo = blockInfo | FREE ;
571563 insertBlock ( root , block ) ;
572564 if ( isDefined ( ASC_RTRACE ) ) onfree ( block ) ;
573565}
574566
567+ /** Checks that a used block is valid to be freed or reallocated. */
568+ function checkUsedBlock ( ref : usize ) : Block {
569+ var block = changetype < Block > ( ref - BLOCK_OVERHEAD ) ;
570+ assert (
571+ ref != 0 && ! ( ref & AL_MASK ) && // must exist and be aligned
572+ ! ( block . mmInfo & FREE ) && // must be used
573+ ! ( block . gcInfo & ~ REFCOUNT_MASK ) // not buffered or != BLACK
574+ ) ;
575+ return block ;
576+ }
577+
575578// @ts -ignore: decorator
576579@global @unsafe
577580export function __alloc ( size : usize , id : u32 ) : usize {
578- var block = allocateBlock ( maybeInitialize ( ) , size ) ;
579- block . rtId = id ;
580- return changetype < usize > ( block ) + BLOCK_OVERHEAD ;
581+ return changetype < usize > (
582+ allocateBlock ( maybeInitialize ( ) , size , id )
583+ ) + BLOCK_OVERHEAD ;
581584}
582585
583586// @ts -ignore: decorator
584587@global @unsafe
585588export function __realloc ( ref : usize , size : usize ) : usize {
586- assert ( ref != 0 && ! ( ref & AL_MASK ) ) ; // must exist and be aligned
587- return changetype < usize > ( reallocateBlock ( maybeInitialize ( ) , changetype < Block > ( ref - BLOCK_OVERHEAD ) , size ) ) + BLOCK_OVERHEAD ;
589+ return changetype < usize > (
590+ reallocateBlock ( maybeInitialize ( ) , checkUsedBlock ( ref ) , size )
591+ ) + BLOCK_OVERHEAD ;
588592}
589593
590594// @ts -ignore: decorator
591595@global @unsafe
592596export function __free ( ref : usize ) : void {
593- assert ( ref != 0 && ! ( ref & AL_MASK ) ) ; // must exist and be aligned
594- freeBlock ( maybeInitialize ( ) , changetype < Block > ( ref - BLOCK_OVERHEAD ) ) ;
597+ freeBlock ( maybeInitialize ( ) , checkUsedBlock ( ref ) ) ;
595598}
0 commit comments