aboutsummaryrefslogtreecommitdiffstats
path: root/mps/code
diff options
context:
space:
mode:
authorGareth Rees2013-05-31 16:29:26 +0100
committerGareth Rees2013-05-31 16:29:26 +0100
commitdb9328da7a3c506983b8027f094dd5234062fea4 (patch)
tree0ff1a55e78e6e5dcac9fef16cbd84458a8f731b7 /mps/code
parent83aff660e27fe56ba6f5c4b898aa00da206c6c9e (diff)
downloademacs-db9328da7a3c506983b8027f094dd5234062fea4.tar.gz
emacs-db9328da7a3c506983b8027f094dd5234062fea4.zip
Use range objects in the cbs interface instead of base, limit pairs. the idea is that freelist and cbs should offer similar interfaces so that the testing code can be shared.
Copied from Perforce Change: 182364 ServerID: perforce.ravenbrook.com
Diffstat (limited to 'mps/code')
-rw-r--r--mps/code/cbs.c173
-rw-r--r--mps/code/cbs.h20
-rw-r--r--mps/code/cbstest.c42
-rw-r--r--mps/code/poolmv2.c70
-rw-r--r--mps/code/poolmvff.c53
-rw-r--r--mps/code/range.c16
-rw-r--r--mps/code/range.h2
7 files changed, 189 insertions, 187 deletions
diff --git a/mps/code/cbs.c b/mps/code/cbs.c
index 45a708f2ba7..8bf9a4300df 100644
--- a/mps/code/cbs.c
+++ b/mps/code/cbs.c
@@ -339,7 +339,7 @@ static void cbsBlockGrew(CBS cbs, CBSBlock block, Size oldSize)
339/* cbsBlockAlloc -- allocate a new block and set its base and limit, 339/* cbsBlockAlloc -- allocate a new block and set its base and limit,
340 but do not insert it into the splay tree yet */ 340 but do not insert it into the splay tree yet */
341 341
342static Res cbsBlockAlloc(CBSBlock *blockReturn, CBS cbs, Addr base, Addr limit) 342static Res cbsBlockAlloc(CBSBlock *blockReturn, CBS cbs, Range range)
343{ 343{
344 Res res; 344 Res res;
345 CBSBlock block; 345 CBSBlock block;
@@ -347,6 +347,7 @@ static Res cbsBlockAlloc(CBSBlock *blockReturn, CBS cbs, Addr base, Addr limit)
347 347
348 AVER(blockReturn != NULL); 348 AVER(blockReturn != NULL);
349 AVERT(CBS, cbs); 349 AVERT(CBS, cbs);
350 AVERT(Range, range);
350 351
351 res = PoolAlloc(&p, cbs->blockPool, sizeof(CBSBlockStruct), 352 res = PoolAlloc(&p, cbs->blockPool, sizeof(CBSBlockStruct),
352 /* withReservoirPermit */ FALSE); 353 /* withReservoirPermit */ FALSE);
@@ -355,8 +356,8 @@ static Res cbsBlockAlloc(CBSBlock *blockReturn, CBS cbs, Addr base, Addr limit)
355 block = (CBSBlock)p; 356 block = (CBSBlock)p;
356 357
357 SplayNodeInit(splayNodeOfCBSBlock(block)); 358 SplayNodeInit(splayNodeOfCBSBlock(block));
358 block->base = base; 359 block->base = RangeBase(range);
359 block->limit = limit; 360 block->limit = RangeLimit(range);
360 block->maxSize = CBSBlockSize(block); 361 block->maxSize = CBSBlockSize(block);
361 362
362 AVERT(CBSBlock, block); 363 AVERT(CBSBlock, block);
@@ -387,21 +388,22 @@ static void cbsBlockInsert(CBS cbs, CBSBlock block)
387 388
388/* cbsInsertIntoTree -- Insert a range into the splay tree */ 389/* cbsInsertIntoTree -- Insert a range into the splay tree */
389 390
390static Res cbsInsertIntoTree(Addr *baseReturn, Addr *limitReturn, 391static Res cbsInsertIntoTree(Range rangeReturn, CBS cbs, Range range)
391 CBS cbs, Addr base, Addr limit)
392{ 392{
393 Res res; 393 Res res;
394 Addr newBase, newLimit; 394 Addr base, limit, newBase, newLimit;
395 SplayNode leftSplay, rightSplay; 395 SplayNode leftSplay, rightSplay;
396 CBSBlock leftCBS, rightCBS; 396 CBSBlock leftCBS, rightCBS;
397 Bool leftMerge, rightMerge; 397 Bool leftMerge, rightMerge;
398 Size oldSize; 398 Size oldSize;
399 399
400 AVER(rangeReturn != NULL);
400 AVERT(CBS, cbs); 401 AVERT(CBS, cbs);
401 AVER(base != (Addr)0); 402 AVERT(Range, range);
402 AVER(base < limit); 403 AVER(RangeIsAligned(range, cbs->alignment));
403 AVER(AddrIsAligned(base, cbs->alignment)); 404
404 AVER(AddrIsAligned(limit, cbs->alignment)); 405 base = RangeBase(range);
406 limit = RangeLimit(range);
405 407
406 METER_ACC(cbs->splaySearch, cbs->splayTreeSize); 408 METER_ACC(cbs->splaySearch, cbs->splayTreeSize);
407 res = SplayTreeNeighbours(&leftSplay, &rightSplay, 409 res = SplayTreeNeighbours(&leftSplay, &rightSplay,
@@ -461,7 +463,7 @@ static Res cbsInsertIntoTree(Addr *baseReturn, Addr *limitReturn,
461 463
462 } else { 464 } else {
463 CBSBlock block; 465 CBSBlock block;
464 res = cbsBlockAlloc(&block, cbs, base, limit); 466 res = cbsBlockAlloc(&block, cbs, range);
465 if (res != ResOK) 467 if (res != ResOK)
466 goto fail; 468 goto fail;
467 cbsBlockInsert(cbs, block); 469 cbsBlockInsert(cbs, block);
@@ -469,8 +471,7 @@ static Res cbsInsertIntoTree(Addr *baseReturn, Addr *limitReturn,
469 471
470 AVER(newBase <= base); 472 AVER(newBase <= base);
471 AVER(newLimit >= limit); 473 AVER(newLimit >= limit);
472 *baseReturn = newBase; 474 RangeInit(rangeReturn, newBase, newLimit);
473 *limitReturn = newLimit;
474 475
475 return ResOK; 476 return ResOK;
476 477
@@ -485,29 +486,18 @@ fail:
485 * See <design/cbs/#functions.cbs.insert>. 486 * See <design/cbs/#functions.cbs.insert>.
486 */ 487 */
487 488
488Res CBSInsert(Addr *baseReturn, Addr *limitReturn, 489Res CBSInsert(Range rangeReturn, CBS cbs, Range range)
489 CBS cbs, Addr base, Addr limit)
490{ 490{
491 Addr newBase, newLimit;
492 Res res; 491 Res res;
493 492
494 AVER(baseReturn != NULL);
495 AVER(limitReturn != NULL);
496 AVERT(CBS, cbs); 493 AVERT(CBS, cbs);
497 CBSEnter(cbs); 494 CBSEnter(cbs);
498 495
499 AVER(base != (Addr)0); 496 AVER(rangeReturn != NULL);
500 AVER(base < limit); 497 AVERT(Range, range);
501 AVER(AddrIsAligned(base, cbs->alignment)); 498 AVER(RangeIsAligned(range, cbs->alignment));
502 AVER(AddrIsAligned(limit, cbs->alignment)); 499
503 500 res = cbsInsertIntoTree(rangeReturn, cbs, range);
504 res = cbsInsertIntoTree(&newBase, &newLimit, cbs, base, limit);
505 if (res == ResOK) {
506 AVER(newBase <= base);
507 AVER(limit <= newLimit);
508 *baseReturn = newBase;
509 *limitReturn = newLimit;
510 }
511 501
512 CBSLeave(cbs); 502 CBSLeave(cbs);
513 return res; 503 return res;
@@ -516,22 +506,21 @@ Res CBSInsert(Addr *baseReturn, Addr *limitReturn,
516 506
517/* cbsDeleteFromTree -- delete blocks from the splay tree */ 507/* cbsDeleteFromTree -- delete blocks from the splay tree */
518 508
519static Res cbsDeleteFromTree(Addr *baseReturn, Addr *limitReturn, 509static Res cbsDeleteFromTree(Range rangeReturn, CBS cbs, Range range)
520 CBS cbs, Addr base, Addr limit)
521{ 510{
522 Res res; 511 Res res;
523 CBSBlock cbsBlock; 512 CBSBlock cbsBlock;
524 SplayNode splayNode; 513 SplayNode splayNode;
525 Addr oldBase, oldLimit; 514 Addr base, limit, oldBase, oldLimit;
526 Size oldSize; 515 Size oldSize;
527 516
528 AVER(baseReturn != NULL); 517 AVER(rangeReturn != NULL);
529 AVER(limitReturn != NULL);
530 AVERT(CBS, cbs); 518 AVERT(CBS, cbs);
531 AVER(base != NULL); 519 AVERT(Range, range);
532 AVER(limit > base); 520 AVER(RangeIsAligned(range, cbs->alignment));
533 AVER(AddrIsAligned(base, cbs->alignment)); 521
534 AVER(AddrIsAligned(limit, cbs->alignment)); 522 base = RangeBase(range);
523 limit = RangeLimit(range);
535 524
536 METER_ACC(cbs->splaySearch, cbs->splayTreeSize); 525 METER_ACC(cbs->splaySearch, cbs->splayTreeSize);
537 res = SplayTreeSearch(&splayNode, splayTreeOfCBS(cbs), (void *)&base); 526 res = SplayTreeSearch(&splayNode, splayTreeOfCBS(cbs), (void *)&base);
@@ -567,10 +556,12 @@ static Res cbsDeleteFromTree(Addr *baseReturn, Addr *limitReturn,
567 } else { 556 } else {
568 /* two remaining fragments. shrink block to represent fragment at 557 /* two remaining fragments. shrink block to represent fragment at
569 left, and create new block for fragment at right. */ 558 left, and create new block for fragment at right. */
559 RangeStruct newRange;
570 CBSBlock newBlock; 560 CBSBlock newBlock;
571 AVER(base > oldBase); 561 AVER(base > oldBase);
572 AVER(limit < oldLimit); 562 AVER(limit < oldLimit);
573 res = cbsBlockAlloc(&newBlock, cbs, limit, oldLimit); 563 RangeInit(&newRange, limit, oldLimit);
564 res = cbsBlockAlloc(&newBlock, cbs, &newRange);
574 if (res != ResOK) { 565 if (res != ResOK) {
575 goto failAlloc; 566 goto failAlloc;
576 } 567 }
@@ -579,8 +570,7 @@ static Res cbsDeleteFromTree(Addr *baseReturn, Addr *limitReturn,
579 cbsBlockInsert(cbs, newBlock); 570 cbsBlockInsert(cbs, newBlock);
580 } 571 }
581 572
582 *baseReturn = oldBase; 573 RangeInit(rangeReturn, oldBase, oldLimit);
583 *limitReturn = oldLimit;
584 return ResOK; 574 return ResOK;
585 575
586failAlloc: 576failAlloc:
@@ -596,20 +586,18 @@ failSplayTreeSearch:
596 * See <design/cbs/#function.cbs.delete>. 586 * See <design/cbs/#function.cbs.delete>.
597 */ 587 */
598 588
599Res CBSDelete(Addr *baseReturn, Addr *limitReturn, 589Res CBSDelete(Range rangeReturn, CBS cbs, Range range)
600 CBS cbs, Addr base, Addr limit)
601{ 590{
602 Res res; 591 Res res;
603 592
604 AVERT(CBS, cbs); 593 AVERT(CBS, cbs);
605 CBSEnter(cbs); 594 CBSEnter(cbs);
606 595
607 AVER(base != NULL); 596 AVER(rangeReturn != NULL);
608 AVER(limit > base); 597 AVERT(Range, range);
609 AVER(AddrIsAligned(base, cbs->alignment)); 598 AVER(RangeIsAligned(range, cbs->alignment));
610 AVER(AddrIsAligned(limit, cbs->alignment));
611 599
612 res = cbsDeleteFromTree(baseReturn, limitReturn, cbs, base, limit); 600 res = cbsDeleteFromTree(rangeReturn, cbs, range);
613 601
614 CBSLeave(cbs); 602 CBSLeave(cbs);
615 return res; 603 return res;
@@ -666,10 +654,11 @@ static void cbsIterateInternal(CBS cbs, CBSIterateMethod iterate,
666 METER_ACC(cbs->splaySearch, cbs->splayTreeSize); 654 METER_ACC(cbs->splaySearch, cbs->splayTreeSize);
667 splayNode = SplayTreeFirst(splayTree, NULL); 655 splayNode = SplayTreeFirst(splayTree, NULL);
668 while(splayNode != NULL) { 656 while(splayNode != NULL) {
657 RangeStruct range;
669 cbsBlock = cbsBlockOfSplayNode(splayNode); 658 cbsBlock = cbsBlockOfSplayNode(splayNode);
670 if (!(*iterate)(cbs, CBSBlockBase(cbsBlock), CBSBlockLimit(cbsBlock), closureP, closureS)) { 659 RangeInit(&range, CBSBlockBase(cbsBlock), CBSBlockLimit(cbsBlock));
660 if (!(*iterate)(cbs, &range, closureP, closureS))
671 break; 661 break;
672 }
673 METER_ACC(cbs->splaySearch, cbs->splayTreeSize); 662 METER_ACC(cbs->splaySearch, cbs->splayTreeSize);
674 splayNode = SplayTreeNext(splayTree, splayNode, keyOfCBSBlock(cbsBlock)); 663 splayNode = SplayTreeNext(splayTree, splayNode, keyOfCBSBlock(cbsBlock));
675 } 664 }
@@ -680,9 +669,10 @@ void CBSIterate(CBS cbs, CBSIterateMethod iterate,
680 void *closureP, Size closureS) 669 void *closureP, Size closureS)
681{ 670{
682 AVERT(CBS, cbs); 671 AVERT(CBS, cbs);
683 AVER(FUNCHECK(iterate));
684 CBSEnter(cbs); 672 CBSEnter(cbs);
685 673
674 AVER(FUNCHECK(iterate));
675
686 cbsIterateInternal(cbs, iterate, closureP, closureS); 676 cbsIterateInternal(cbs, iterate, closureP, closureS);
687 677
688 CBSLeave(cbs); 678 CBSLeave(cbs);
@@ -706,21 +696,26 @@ Bool FindDeleteCheck(FindDelete findDelete)
706 696
707/* cbsFindDeleteRange -- delete appropriate range of block found */ 697/* cbsFindDeleteRange -- delete appropriate range of block found */
708 698
709static void cbsFindDeleteRange(Addr *baseReturn, Addr *limitReturn, 699static void cbsFindDeleteRange(Range rangeReturn, Range oldRangeReturn,
710 Addr *oldBaseReturn, Addr *oldLimitReturn, 700 CBS cbs, Range range, Size size,
711 CBS cbs, Addr base, Addr limit, Size size,
712 FindDelete findDelete) 701 FindDelete findDelete)
713{ 702{
714 Bool callDelete = TRUE; 703 Bool callDelete = TRUE;
704 Addr base, limit;
715 705
716 AVER(baseReturn != NULL); 706 AVER(rangeReturn != NULL);
717 AVER(limitReturn != NULL); 707 AVER(oldRangeReturn != NULL);
718 AVERT(CBS, cbs); 708 AVERT(CBS, cbs);
719 AVER(base < limit); 709 AVERT(Range, range);
710 AVER(RangeIsAligned(range, cbs->alignment));
720 AVER(size > 0); 711 AVER(size > 0);
721 AVER(AddrOffset(base, limit) >= size); 712 AVER(SizeIsAligned(size, cbs->alignment));
713 AVER(RangeSize(range) >= size);
722 AVERT(FindDelete, findDelete); 714 AVERT(FindDelete, findDelete);
723 715
716 base = RangeBase(range);
717 limit = RangeLimit(range);
718
724 switch(findDelete) { 719 switch(findDelete) {
725 720
726 case FindDeleteNONE: 721 case FindDeleteNONE:
@@ -744,25 +739,23 @@ static void cbsFindDeleteRange(Addr *baseReturn, Addr *limitReturn,
744 break; 739 break;
745 } 740 }
746 741
742 RangeInit(rangeReturn, base, limit);
743
747 if (callDelete) { 744 if (callDelete) {
748 Res res; 745 Res res;
749 res = cbsDeleteFromTree(oldBaseReturn, oldLimitReturn, cbs, base, limit); 746 res = cbsDeleteFromTree(oldRangeReturn, cbs, rangeReturn);
750 /* Can't have run out of memory, because all our callers pass in 747 /* Can't have run out of memory, because all our callers pass in
751 blocks that were just found in the splay tree, and we only 748 blocks that were just found in the splay tree, and we only
752 deleted from one end of the block, so cbsDeleteFromTree did not 749 deleted from one end of the block, so cbsDeleteFromTree did not
753 need to allocate a new block. */ 750 need to allocate a new block. */
754 AVER(res == ResOK); 751 AVER(res == ResOK);
755 } 752 }
756
757 *baseReturn = base;
758 *limitReturn = limit;
759} 753}
760 754
761 755
762/* CBSFindFirst -- find the first block of at least the given size */ 756/* CBSFindFirst -- find the first block of at least the given size */
763 757
764Bool CBSFindFirst(Addr *baseReturn, Addr *limitReturn, 758Bool CBSFindFirst(Range rangeReturn, Range oldRangeReturn,
765 Addr *oldBaseReturn, Addr *oldLimitReturn,
766 CBS cbs, Size size, FindDelete findDelete) 759 CBS cbs, Size size, FindDelete findDelete)
767{ 760{
768 Bool found; 761 Bool found;
@@ -771,8 +764,8 @@ Bool CBSFindFirst(Addr *baseReturn, Addr *limitReturn,
771 AVERT(CBS, cbs); 764 AVERT(CBS, cbs);
772 CBSEnter(cbs); 765 CBSEnter(cbs);
773 766
774 AVER(baseReturn != NULL); 767 AVER(rangeReturn != NULL);
775 AVER(limitReturn != NULL); 768 AVER(oldRangeReturn != NULL);
776 AVER(size > 0); 769 AVER(size > 0);
777 AVER(SizeIsAligned(size, cbs->alignment)); 770 AVER(SizeIsAligned(size, cbs->alignment));
778 AVER(cbs->fastFind); 771 AVER(cbs->fastFind);
@@ -783,14 +776,13 @@ Bool CBSFindFirst(Addr *baseReturn, Addr *limitReturn,
783 &cbsTestTree, NULL, size); 776 &cbsTestTree, NULL, size);
784 if (found) { 777 if (found) {
785 CBSBlock block; 778 CBSBlock block;
786 Addr base, limit; 779 RangeStruct range;
787 block = cbsBlockOfSplayNode(node); 780 block = cbsBlockOfSplayNode(node);
788 AVER(CBSBlockSize(block) >= size); 781 AVER(CBSBlockSize(block) >= size);
789 base = CBSBlockBase(block); 782 RangeInit(&range, CBSBlockBase(block), CBSBlockLimit(block));
790 limit = CBSBlockLimit(block); 783 AVER(RangeSize(&range) >= size);
791 AVER(AddrOffset(base, limit) >= size); 784 cbsFindDeleteRange(rangeReturn, oldRangeReturn, cbs, &range,
792 cbsFindDeleteRange(baseReturn, limitReturn, oldBaseReturn, oldLimitReturn, 785 size, findDelete);
793 cbs, base, limit, size, findDelete);
794 } 786 }
795 787
796 CBSLeave(cbs); 788 CBSLeave(cbs);
@@ -800,8 +792,7 @@ Bool CBSFindFirst(Addr *baseReturn, Addr *limitReturn,
800 792
801/* CBSFindLast -- find the last block of at least the given size */ 793/* CBSFindLast -- find the last block of at least the given size */
802 794
803Bool CBSFindLast(Addr *baseReturn, Addr *limitReturn, 795Bool CBSFindLast(Range rangeReturn, Range oldRangeReturn,
804 Addr *oldBaseReturn, Addr *oldLimitReturn,
805 CBS cbs, Size size, FindDelete findDelete) 796 CBS cbs, Size size, FindDelete findDelete)
806{ 797{
807 Bool found; 798 Bool found;
@@ -810,8 +801,8 @@ Bool CBSFindLast(Addr *baseReturn, Addr *limitReturn,
810 AVERT(CBS, cbs); 801 AVERT(CBS, cbs);
811 CBSEnter(cbs); 802 CBSEnter(cbs);
812 803
813 AVER(baseReturn != NULL); 804 AVER(rangeReturn != NULL);
814 AVER(limitReturn != NULL); 805 AVER(oldRangeReturn != NULL);
815 AVER(size > 0); 806 AVER(size > 0);
816 AVER(SizeIsAligned(size, cbs->alignment)); 807 AVER(SizeIsAligned(size, cbs->alignment));
817 AVER(cbs->fastFind); 808 AVER(cbs->fastFind);
@@ -822,14 +813,13 @@ Bool CBSFindLast(Addr *baseReturn, Addr *limitReturn,
822 &cbsTestTree, NULL, size); 813 &cbsTestTree, NULL, size);
823 if (found) { 814 if (found) {
824 CBSBlock block; 815 CBSBlock block;
825 Addr base, limit; 816 RangeStruct range;
826 block = cbsBlockOfSplayNode(node); 817 block = cbsBlockOfSplayNode(node);
827 AVER(CBSBlockSize(block) >= size); 818 AVER(CBSBlockSize(block) >= size);
828 base = CBSBlockBase(block); 819 RangeInit(&range, CBSBlockBase(block), CBSBlockLimit(block));
829 limit = CBSBlockLimit(block); 820 AVER(RangeSize(&range) >= size);
830 AVER(AddrOffset(base, limit) >= size); 821 cbsFindDeleteRange(rangeReturn, oldRangeReturn, cbs, &range,
831 cbsFindDeleteRange(baseReturn, limitReturn, oldBaseReturn, oldLimitReturn, 822 size, findDelete);
832 cbs, base, limit, size, findDelete);
833 } 823 }
834 824
835 CBSLeave(cbs); 825 CBSLeave(cbs);
@@ -839,8 +829,7 @@ Bool CBSFindLast(Addr *baseReturn, Addr *limitReturn,
839 829
840/* CBSFindLargest -- find the largest block in the CBS */ 830/* CBSFindLargest -- find the largest block in the CBS */
841 831
842Bool CBSFindLargest(Addr *baseReturn, Addr *limitReturn, 832Bool CBSFindLargest(Range rangeReturn, Range oldRangeReturn,
843 Addr *oldBaseReturn, Addr *oldLimitReturn,
844 CBS cbs, FindDelete findDelete) 833 CBS cbs, FindDelete findDelete)
845{ 834{
846 Bool found = FALSE; 835 Bool found = FALSE;
@@ -850,16 +839,16 @@ Bool CBSFindLargest(Addr *baseReturn, Addr *limitReturn,
850 AVERT(CBS, cbs); 839 AVERT(CBS, cbs);
851 CBSEnter(cbs); 840 CBSEnter(cbs);
852 841
853 AVER(baseReturn != NULL); 842 AVER(rangeReturn != NULL);
854 AVER(limitReturn != NULL); 843 AVER(oldRangeReturn != NULL);
855 AVER(cbs->fastFind); 844 AVER(cbs->fastFind);
856 AVERT(FindDelete, findDelete); 845 AVERT(FindDelete, findDelete);
857 846
858 notEmpty = SplayRoot(&root, splayTreeOfCBS(cbs)); 847 notEmpty = SplayRoot(&root, splayTreeOfCBS(cbs));
859 if (notEmpty) { 848 if (notEmpty) {
849 RangeStruct range;
860 CBSBlock block; 850 CBSBlock block;
861 SplayNode node = NULL; /* suppress "may be used uninitialized" */ 851 SplayNode node = NULL; /* suppress "may be used uninitialized" */
862 Addr base, limit;
863 Size size; 852 Size size;
864 853
865 size = cbsBlockOfSplayNode(root)->maxSize; 854 size = cbsBlockOfSplayNode(root)->maxSize;
@@ -869,10 +858,10 @@ Bool CBSFindLargest(Addr *baseReturn, Addr *limitReturn,
869 AVER(found); /* maxSize is exact, so we will find it. */ 858 AVER(found); /* maxSize is exact, so we will find it. */
870 block = cbsBlockOfSplayNode(node); 859 block = cbsBlockOfSplayNode(node);
871 AVER(CBSBlockSize(block) >= size); 860 AVER(CBSBlockSize(block) >= size);
872 base = CBSBlockBase(block); 861 RangeInit(&range, CBSBlockBase(block), CBSBlockLimit(block));
873 limit = CBSBlockLimit(block); 862 AVER(RangeSize(&range) >= size);
874 cbsFindDeleteRange(baseReturn, limitReturn, oldBaseReturn, oldLimitReturn, 863 cbsFindDeleteRange(rangeReturn, oldRangeReturn, cbs, &range,
875 cbs, base, limit, size, findDelete); 864 size, findDelete);
876 } 865 }
877 866
878 CBSLeave(cbs); 867 CBSLeave(cbs);
diff --git a/mps/code/cbs.h b/mps/code/cbs.h
index 544df0a0586..5b651c1aaf8 100644
--- a/mps/code/cbs.h
+++ b/mps/code/cbs.h
@@ -11,12 +11,13 @@
11 11
12#include "arg.h" 12#include "arg.h"
13#include "meter.h" 13#include "meter.h"
14#include "splay.h"
15#include "mpmtypes.h" 14#include "mpmtypes.h"
15#include "range.h"
16#include "splay.h"
16 17
17 18
18typedef struct CBSStruct *CBS; 19typedef struct CBSStruct *CBS;
19typedef Bool (*CBSIterateMethod)(CBS cbs, Addr base, Addr limit, 20typedef Bool (*CBSIterateMethod)(CBS cbs, Range range,
20 void *closureP, Size closureS); 21 void *closureP, Size closureS);
21 22
22 23
@@ -40,23 +41,18 @@ extern Res CBSInit(Arena arena, CBS cbs, void *owner,
40 Align alignment, Bool fastFind, ArgList args); 41 Align alignment, Bool fastFind, ArgList args);
41extern void CBSFinish(CBS cbs); 42extern void CBSFinish(CBS cbs);
42 43
43extern Res CBSInsert(Addr *baseReturn, Addr *limitReturn, 44extern Res CBSInsert(Range rangeReturn, CBS cbs, Range range);
44 CBS cbs, Addr base, Addr limit); 45extern Res CBSDelete(Range rangeReturn, CBS cbs, Range range);
45extern Res CBSDelete(Addr *baseReturn, Addr *limitReturn,
46 CBS cbs, Addr base, Addr limit);
47extern void CBSIterate(CBS cbs, CBSIterateMethod iterate, 46extern void CBSIterate(CBS cbs, CBSIterateMethod iterate,
48 void *closureP, Size closureS); 47 void *closureP, Size closureS);
49 48
50extern Res CBSDescribe(CBS cbs, mps_lib_FILE *stream); 49extern Res CBSDescribe(CBS cbs, mps_lib_FILE *stream);
51 50
52extern Bool CBSFindFirst(Addr *baseReturn, Addr *limitReturn, 51extern Bool CBSFindFirst(Range rangeReturn, Range oldRangeReturn,
53 Addr *oldBaseReturn, Addr *oldLimitReturn,
54 CBS cbs, Size size, FindDelete findDelete); 52 CBS cbs, Size size, FindDelete findDelete);
55extern Bool CBSFindLast(Addr *baseReturn, Addr *limitReturn, 53extern Bool CBSFindLast(Range rangeReturn, Range oldRangeReturn,
56 Addr *oldBaseReturn, Addr *oldLimitReturn,
57 CBS cbs, Size size, FindDelete findDelete); 54 CBS cbs, Size size, FindDelete findDelete);
58extern Bool CBSFindLargest(Addr *baseReturn, Addr *limitReturn, 55extern Bool CBSFindLargest(Range rangeReturn, Range oldRangeReturn,
59 Addr *oldBaseReturn, Addr *oldLimitReturn,
60 CBS cbs, FindDelete findDelete); 56 CBS cbs, FindDelete findDelete);
61 57
62 58
diff --git a/mps/code/cbstest.c b/mps/code/cbstest.c
index 3588d488204..4f60880a756 100644
--- a/mps/code/cbstest.c
+++ b/mps/code/cbstest.c
@@ -47,9 +47,9 @@ static Index (indexOfAddr)(Addr block, Addr a)
47} 47}
48 48
49 49
50static Bool checkCBSAction(CBS cbs, Addr base, Addr limit, void *closureP, 50static Bool checkCBSAction(CBS cbs, Range range, void *closureP, Size closureS)
51 Size closureS)
52{ 51{
52 Addr base, limit;
53 CheckCBSClosure closure = (CheckCBSClosure)closureP; 53 CheckCBSClosure closure = (CheckCBSClosure)closureP;
54 54
55 /* Don't need to check cbs every time */ 55 /* Don't need to check cbs every time */
@@ -57,6 +57,9 @@ static Bool checkCBSAction(CBS cbs, Addr base, Addr limit, void *closureP,
57 UNUSED(closureS); 57 UNUSED(closureS);
58 Insist(closure != NULL); 58 Insist(closure != NULL);
59 59
60 base = RangeBase(range);
61 limit = RangeLimit(range);
62
60 if (base > closure->oldLimit) { 63 if (base > closure->oldLimit) {
61 Insist(BTIsSetRange(closure->allocTable, 64 Insist(BTIsSetRange(closure->allocTable,
62 indexOfAddr(closure->base, closure->oldLimit), 65 indexOfAddr(closure->base, closure->oldLimit),
@@ -70,7 +73,6 @@ static Bool checkCBSAction(CBS cbs, Addr base, Addr limit, void *closureP,
70 indexOfAddr(closure->base, base), 73 indexOfAddr(closure->base, base),
71 indexOfAddr(closure->base, limit))); 74 indexOfAddr(closure->base, limit)));
72 75
73
74 closure->oldLimit = limit; 76 closure->oldLimit = limit;
75 77
76 return TRUE; 78 return TRUE;
@@ -201,7 +203,7 @@ static void allocate(CBS cbs, Addr block, BT allocTable,
201 Res res; 203 Res res;
202 Index ib, il; /* Indexed for base and limit */ 204 Index ib, il; /* Indexed for base and limit */
203 Bool isFree; 205 Bool isFree;
204 Addr oldBase, oldLimit; 206 RangeStruct range, oldRange;
205 Addr outerBase, outerLimit; /* interval containing [ib, il) */ 207 Addr outerBase, outerLimit; /* interval containing [ib, il) */
206 208
207 ib = indexOfAddr(block, base); 209 ib = indexOfAddr(block, base);
@@ -234,7 +236,8 @@ static void allocate(CBS cbs, Addr block, BT allocTable,
234 UNUSED(total); 236 UNUSED(total);
235 } 237 }
236 238
237 res = CBSDelete(&oldBase, &oldLimit, cbs, base, limit); 239 RangeInit(&range, base, limit);
240 res = CBSDelete(&oldRange, cbs, &range);
238 241
239 if (!isFree) { 242 if (!isFree) {
240 die_expect((mps_res_t)res, MPS_RES_FAIL, 243 die_expect((mps_res_t)res, MPS_RES_FAIL,
@@ -242,8 +245,8 @@ static void allocate(CBS cbs, Addr block, BT allocTable,
242 } else { /* isFree */ 245 } else { /* isFree */
243 die_expect((mps_res_t)res, MPS_RES_OK, 246 die_expect((mps_res_t)res, MPS_RES_OK,
244 "failed to delete free block"); 247 "failed to delete free block");
245 Insist(oldBase == outerBase); 248 Insist(RangeBase(&oldRange) == outerBase);
246 Insist(oldLimit == outerLimit); 249 Insist(RangeLimit(&oldRange) == outerLimit);
247 NAllocateSucceeded++; 250 NAllocateSucceeded++;
248 BTSetRange(allocTable, ib, il); 251 BTSetRange(allocTable, ib, il);
249 } 252 }
@@ -257,7 +260,7 @@ static void deallocate(CBS cbs, Addr block, BT allocTable,
257 Index ib, il; 260 Index ib, il;
258 Bool isAllocated; 261 Bool isAllocated;
259 Addr outerBase = base, outerLimit = limit; /* interval containing [ib, il) */ 262 Addr outerBase = base, outerLimit = limit; /* interval containing [ib, il) */
260 Addr freeBase, freeLimit; /* interval returned by CBS */ 263 RangeStruct range, freeRange; /* interval returned by CBS */
261 264
262 ib = indexOfAddr(block, base); 265 ib = indexOfAddr(block, base);
263 il = indexOfAddr(block, limit); 266 il = indexOfAddr(block, limit);
@@ -299,7 +302,8 @@ static void deallocate(CBS cbs, Addr block, BT allocTable,
299 UNUSED(total); 302 UNUSED(total);
300 } 303 }
301 304
302 res = CBSInsert(&freeBase, &freeLimit, cbs, base, limit); 305 RangeInit(&range, base, limit);
306 res = CBSInsert(&freeRange, cbs, &range);
303 307
304 if (!isAllocated) { 308 if (!isAllocated) {
305 die_expect((mps_res_t)res, MPS_RES_FAIL, 309 die_expect((mps_res_t)res, MPS_RES_FAIL,
@@ -310,8 +314,8 @@ static void deallocate(CBS cbs, Addr block, BT allocTable,
310 314
311 NDeallocateSucceeded++; 315 NDeallocateSucceeded++;
312 BTResRange(allocTable, ib, il); 316 BTResRange(allocTable, ib, il);
313 Insist(freeBase == outerBase); 317 Insist(RangeBase(&freeRange) == outerBase);
314 Insist(freeLimit == outerLimit); 318 Insist(RangeLimit(&freeRange) == outerLimit);
315 } 319 }
316} 320}
317 321
@@ -321,8 +325,9 @@ static void find(CBS cbs, void *block, BT alloc, Size size, Bool high,
321{ 325{
322 Bool expected, found; 326 Bool expected, found;
323 Index expectedBase, expectedLimit; 327 Index expectedBase, expectedLimit;
324 Addr foundBase, foundLimit, remainderBase, remainderLimit; 328 RangeStruct foundRange, oldRange;
325 Addr oldBase, oldLimit, origBase, origLimit; 329 Addr remainderBase, remainderLimit;
330 Addr origBase, origLimit;
326 Size oldSize, newSize; 331 Size oldSize, newSize;
327 332
328 origBase = origLimit = NULL; 333 origBase = origLimit = NULL;
@@ -362,18 +367,17 @@ static void find(CBS cbs, void *block, BT alloc, Size size, Bool high,
362 } 367 }
363 368
364 found = (high ? CBSFindLast : CBSFindFirst) 369 found = (high ? CBSFindLast : CBSFindFirst)
365 (&foundBase, &foundLimit, &oldBase, &oldLimit, 370 (&foundRange, &oldRange, cbs, size * Alignment, findDelete);
366 cbs, size * Alignment, findDelete);
367 371
368 Insist(found == expected); 372 Insist(found == expected);
369 373
370 if (found) { 374 if (found) {
371 Insist(expectedBase == indexOfAddr(block, foundBase)); 375 Insist(expectedBase == indexOfAddr(block, RangeBase(&foundRange)));
372 Insist(expectedLimit == indexOfAddr(block, foundLimit)); 376 Insist(expectedLimit == indexOfAddr(block, RangeLimit(&foundRange)));
373 377
374 if (findDelete != FindDeleteNONE) { 378 if (findDelete != FindDeleteNONE) {
375 Insist(oldBase == origBase); 379 Insist(RangeBase(&oldRange) == origBase);
376 Insist(oldLimit == origLimit); 380 Insist(RangeLimit(&oldRange) == origLimit);
377 BTSetRange(alloc, expectedBase, expectedLimit); 381 BTSetRange(alloc, expectedBase, expectedLimit);
378 } 382 }
379 } 383 }
diff --git a/mps/code/poolmv2.c b/mps/code/poolmv2.c
index e2642f23c43..bdcfd2a69ae 100644
--- a/mps/code/poolmv2.c
+++ b/mps/code/poolmv2.c
@@ -46,10 +46,10 @@ static Bool MVTReturnRangeSegs(MVT mvt, Range range, Arena arena);
46static Res MVTInsert(MVT mvt, Addr base, Addr limit); 46static Res MVTInsert(MVT mvt, Addr base, Addr limit);
47static Res MVTDelete(MVT mvt, Addr base, Addr limit); 47static Res MVTDelete(MVT mvt, Addr base, Addr limit);
48static void ABQRefillIfNecessary(MVT mvt, Size size); 48static void ABQRefillIfNecessary(MVT mvt, Size size);
49static Bool ABQRefillCallback(CBS cbs, Addr base, Addr limit, 49static Bool ABQRefillCallback(CBS cbs, Range range,
50 void *closureP, Size closureS); 50 void *closureP, Size closureS);
51static Res MVTContingencySearch(Addr *baseReturn, Addr *limitReturn, CBS cbs, Size min); 51static Res MVTContingencySearch(Addr *baseReturn, Addr *limitReturn, CBS cbs, Size min);
52static Bool MVTContingencyCallback(CBS cbs, Addr base, Addr limit, 52static Bool MVTContingencyCallback(CBS cbs, Range range,
53 void *closureP, Size closureS); 53 void *closureP, Size closureS);
54static Bool MVTCheckFit(Addr base, Addr limit, Size min, Arena arena); 54static Bool MVTCheckFit(Addr base, Addr limit, Size min, Arena arena);
55static ABQ MVTABQ(MVT mvt); 55static ABQ MVTABQ(MVT mvt);
@@ -652,24 +652,23 @@ failOverflow:
652static Res MVTInsert(MVT mvt, Addr base, Addr limit) 652static Res MVTInsert(MVT mvt, Addr base, Addr limit)
653{ 653{
654 Res res; 654 Res res;
655 Addr newBase, newLimit; 655 RangeStruct range, newRange;
656 RangeStruct range;
657 656
658 AVERT(MVT, mvt); 657 AVERT(MVT, mvt);
659 AVER(base < limit); 658 AVER(base < limit);
660 659
661 res = CBSInsert(&newBase, &newLimit, MVTCBS(mvt), base, limit); 660 RangeInit(&range, base, limit);
661 res = CBSInsert(&newRange, MVTCBS(mvt), &range);
662 if (res != ResOK) 662 if (res != ResOK)
663 return res; 663 return res;
664 664
665 RangeInit(&range, newBase, newLimit); 665 if (RangeSize(&newRange) >= mvt->reuseSize) {
666 if (RangeSize(&range) >= mvt->reuseSize) {
667 /* The new range is big enough that it might have been coalesced 666 /* The new range is big enough that it might have been coalesced
668 * with ranges on the ABQ, so ensure that they are removed before 667 * with ranges on the ABQ, so ensure that they are removed before
669 * reserving the new range. 668 * reserving the new range.
670 */ 669 */
671 ABQIterate(MVTABQ(mvt), MVTDeleteOverlapping, &range, 0); 670 ABQIterate(MVTABQ(mvt), MVTDeleteOverlapping, &newRange, 0);
672 MVTReserve(mvt, &range); 671 MVTReserve(mvt, &newRange);
673 } 672 }
674 673
675 return ResOK; 674 return ResOK;
@@ -681,32 +680,31 @@ static Res MVTInsert(MVT mvt, Addr base, Addr limit)
681 */ 680 */
682static Res MVTDelete(MVT mvt, Addr base, Addr limit) 681static Res MVTDelete(MVT mvt, Addr base, Addr limit)
683{ 682{
684 Addr oldBase, oldLimit; 683 RangeStruct range, rangeOld, rangeLeft, rangeRight;
685 RangeStruct range, rangeLeft, rangeRight;
686 Res res; 684 Res res;
687 685
688 AVERT(MVT, mvt); 686 AVERT(MVT, mvt);
689 AVER(base < limit); 687 AVER(base < limit);
690 688
691 res = CBSDelete(&oldBase, &oldLimit, MVTCBS(mvt), base, limit); 689 RangeInit(&range, base, limit);
690 res = CBSDelete(&rangeOld, MVTCBS(mvt), &range);
692 if (res != ResOK) 691 if (res != ResOK)
693 return res; 692 return res;
694 693
695 /* If the old address range was larger than the reuse size, then it 694 /* If the old address range was larger than the reuse size, then it
696 * might be on the ABQ, so ensure it is removed. 695 * might be on the ABQ, so ensure it is removed.
697 */ 696 */
698 RangeInit(&range, oldBase, oldLimit); 697 if (RangeSize(&rangeOld) >= mvt->reuseSize)
699 if (RangeSize(&range) >= mvt->reuseSize) 698 ABQIterate(MVTABQ(mvt), MVTDeleteOverlapping, &rangeOld, 0);
700 ABQIterate(MVTABQ(mvt), MVTDeleteOverlapping, &range, 0);
701 699
702 /* There might be fragments at the left or the right of the deleted 700 /* There might be fragments at the left or the right of the deleted
703 * range, and either might be big enough to go back on the ABQ. 701 * range, and either might be big enough to go back on the ABQ.
704 */ 702 */
705 RangeInit(&rangeLeft, oldBase, base); 703 RangeInit(&rangeLeft, RangeBase(&rangeOld), base);
706 if (RangeSize(&rangeLeft) >= mvt->reuseSize) 704 if (RangeSize(&rangeLeft) >= mvt->reuseSize)
707 MVTReserve(mvt, &rangeLeft); 705 MVTReserve(mvt, &rangeLeft);
708 706
709 RangeInit(&rangeRight, limit, oldLimit); 707 RangeInit(&rangeRight, limit, RangeLimit(&rangeOld));
710 if (RangeSize(&rangeRight) >= mvt->reuseSize) 708 if (RangeSize(&rangeRight) >= mvt->reuseSize)
711 MVTReserve(mvt, &rangeRight); 709 MVTReserve(mvt, &rangeRight);
712 710
@@ -1109,29 +1107,25 @@ static void ABQRefillIfNecessary(MVT mvt, Size size)
1109/* ABQRefillCallback -- called from CBSIterate at the behest of 1107/* ABQRefillCallback -- called from CBSIterate at the behest of
1110 * ABQRefillIfNecessary 1108 * ABQRefillIfNecessary
1111 */ 1109 */
1112static Bool ABQRefillCallback(CBS cbs, Addr base, Addr limit, 1110static Bool ABQRefillCallback(CBS cbs, Range range,
1113 void *closureP, Size closureS) 1111 void *closureP, Size closureS)
1114{ 1112{
1115 Res res; 1113 Res res;
1116 MVT mvt; 1114 MVT mvt;
1117 Size size;
1118 RangeStruct range;
1119 1115
1120 AVERT(CBS, cbs); 1116 AVERT(CBS, cbs);
1121 mvt = CBSMVT(cbs); 1117 mvt = CBSMVT(cbs);
1122 AVERT(MVT, mvt); 1118 AVERT(MVT, mvt);
1123 AVERT(ABQ, MVTABQ(mvt)); 1119 AVERT(ABQ, MVTABQ(mvt));
1124 AVER(base < limit); 1120 AVERT(Range, range);
1125 UNUSED(closureP); 1121 UNUSED(closureP);
1126 UNUSED(closureS); 1122 UNUSED(closureS);
1127 1123
1128 size = AddrOffset(base, limit); 1124 if (RangeSize(range) < mvt->reuseSize)
1129 if (size < mvt->reuseSize)
1130 return TRUE; 1125 return TRUE;
1131 1126
1132 METER_ACC(mvt->refillPushes, ABQDepth(MVTABQ(mvt))); 1127 METER_ACC(mvt->refillPushes, ABQDepth(MVTABQ(mvt)));
1133 RangeInit(&range, base, limit); 1128 res = MVTReserve(mvt, range);
1134 res = MVTReserve(mvt, &range);
1135 if (res != ResOK) 1129 if (res != ResOK)
1136 return FALSE; 1130 return FALSE;
1137 1131
@@ -1145,8 +1139,7 @@ typedef struct MVTContigencyStruct *MVTContigency;
1145typedef struct MVTContigencyStruct 1139typedef struct MVTContigencyStruct
1146{ 1140{
1147 Bool found; 1141 Bool found;
1148 Addr base; 1142 RangeStruct range;
1149 Addr limit;
1150 Arena arena; 1143 Arena arena;
1151 Size min; 1144 Size min;
1152 /* meters */ 1145 /* meters */
@@ -1169,13 +1162,13 @@ static Res MVTContingencySearch(Addr *baseReturn, Addr *limitReturn, CBS cbs, Si
1169 1162
1170 CBSIterate(cbs, MVTContingencyCallback, (void *)&cls, 0); 1163 CBSIterate(cbs, MVTContingencyCallback, (void *)&cls, 0);
1171 if (cls.found) { 1164 if (cls.found) {
1172 AVER(AddrOffset(cls.base, cls.limit) >= min); 1165 AVER(RangeSize(&cls.range) >= min);
1173 METER_ACC(CBSMVT(cbs)->contingencySearches, cls.steps); 1166 METER_ACC(CBSMVT(cbs)->contingencySearches, cls.steps);
1174 if (cls.hardSteps) { 1167 if (cls.hardSteps) {
1175 METER_ACC(CBSMVT(cbs)->contingencyHardSearches, cls.hardSteps); 1168 METER_ACC(CBSMVT(cbs)->contingencyHardSearches, cls.hardSteps);
1176 } 1169 }
1177 *baseReturn = cls.base; 1170 *baseReturn = RangeBase(&cls.range);
1178 *limitReturn = cls.limit; 1171 *limitReturn = RangeLimit(&cls.range);
1179 return ResOK; 1172 return ResOK;
1180 } 1173 }
1181 1174
@@ -1186,28 +1179,30 @@ static Res MVTContingencySearch(Addr *baseReturn, Addr *limitReturn, CBS cbs, Si
1186/* MVTContingencyCallback -- called from CBSIterate at the behest of 1179/* MVTContingencyCallback -- called from CBSIterate at the behest of
1187 * MVTContingencySearch 1180 * MVTContingencySearch
1188 */ 1181 */
1189static Bool MVTContingencyCallback(CBS cbs, Addr base, Addr limit, 1182static Bool MVTContingencyCallback(CBS cbs, Range range,
1190 void *closureP, Size closureS) 1183 void *closureP, Size closureS)
1191{ 1184{
1192 MVTContigency cl; 1185 MVTContigency cl;
1193 Size size; 1186 Size size;
1187 Addr base, limit;
1194 1188
1195 AVERT(CBS, cbs); 1189 AVERT(CBS, cbs);
1196 AVER(base < limit); 1190 AVERT(Range, range);
1197 AVER(closureP != NULL); 1191 AVER(closureP != NULL);
1198 UNUSED(closureS); 1192 UNUSED(closureS);
1199 1193
1200 cl = (MVTContigency)closureP; 1194 cl = (MVTContigency)closureP;
1201 size = AddrOffset(base, limit); 1195 base = RangeBase(range);
1202 1196 limit = RangeLimit(range);
1197 size = RangeSize(range);
1198
1203 cl->steps++; 1199 cl->steps++;
1204 if (size < cl->min) 1200 if (size < cl->min)
1205 return TRUE; 1201 return TRUE;
1206 1202
1207 /* verify that min will fit when seg-aligned */ 1203 /* verify that min will fit when seg-aligned */
1208 if (size >= 2 * cl->min) { 1204 if (size >= 2 * cl->min) {
1209 cl->base = base; 1205 RangeInit(&cl->range, base, limit);
1210 cl->limit = limit;
1211 cl->found = TRUE; 1206 cl->found = TRUE;
1212 return FALSE; 1207 return FALSE;
1213 } 1208 }
@@ -1215,8 +1210,7 @@ static Bool MVTContingencyCallback(CBS cbs, Addr base, Addr limit,
1215 /* do it the hard way */ 1210 /* do it the hard way */
1216 cl->hardSteps++; 1211 cl->hardSteps++;
1217 if (MVTCheckFit(base, limit, cl->min, cl->arena)) { 1212 if (MVTCheckFit(base, limit, cl->min, cl->arena)) {
1218 cl->base = base; 1213 RangeInit(&cl->range, base, limit);
1219 cl->limit = limit;
1220 cl->found = TRUE; 1214 cl->found = TRUE;
1221 return FALSE; 1215 return FALSE;
1222 } 1216 }
diff --git a/mps/code/poolmvff.c b/mps/code/poolmvff.c
index e5335377175..89b0160105d 100644
--- a/mps/code/poolmvff.c
+++ b/mps/code/poolmvff.c
@@ -84,22 +84,22 @@ typedef MVFFDebugStruct *MVFFDebug;
84 */ 84 */
85static void MVFFAddToFreeList(Addr *baseIO, Addr *limitIO, MVFF mvff) { 85static void MVFFAddToFreeList(Addr *baseIO, Addr *limitIO, MVFF mvff) {
86 Res res; 86 Res res;
87 Addr base, limit; 87 RangeStruct range, newRange;
88 88
89 AVER(baseIO != NULL); 89 AVER(baseIO != NULL);
90 AVER(limitIO != NULL); 90 AVER(limitIO != NULL);
91 AVERT(MVFF, mvff); 91 AVERT(MVFF, mvff);
92 base = *baseIO; 92 RangeInit(&range, *baseIO, *limitIO);
93 limit = *limitIO;
94 AVER(limit > base);
95 93
96 res = CBSInsert(baseIO, limitIO, CBSOfMVFF(mvff), base, limit); 94 res = CBSInsert(&newRange, CBSOfMVFF(mvff), &range);
97 if (ResIsAllocFailure(res)) 95 if (ResIsAllocFailure(res))
98 /* CBS ran out of memory for splay nodes: lose freed range. */ 96 /* CBS ran out of memory for splay nodes: lose freed range. */
99 return; 97 return;
100 98
101 AVER(res == ResOK); 99 AVER(res == ResOK);
102 mvff->free += AddrOffset(base, limit); 100 mvff->free += RangeSize(&range);
101 *baseIO = RangeBase(&newRange);
102 *limitIO = RangeLimit(&newRange);
103 103
104 return; 104 return;
105} 105}
@@ -140,15 +140,15 @@ static void MVFFFreeSegs(MVFF mvff, Addr base, Addr limit)
140 140
141 while(segLimit <= limit) { /* segment ends in range */ 141 while(segLimit <= limit) { /* segment ends in range */
142 if (segBase >= base) { /* segment starts in range */ 142 if (segBase >= base) { /* segment starts in range */
143 Addr oldBase, oldLimit; 143 RangeStruct range, oldRange;
144 res = CBSDelete(&oldBase, &oldLimit, CBSOfMVFF(mvff), segBase, segLimit); 144 RangeInit(&range, segBase, segLimit);
145 res = CBSDelete(&oldRange, CBSOfMVFF(mvff), &range);
145 if (ResIsAllocFailure(res)) 146 if (ResIsAllocFailure(res))
146 /* CBS ran out of memory for splay nodes: can't delete. */ 147 /* CBS ran out of memory for splay nodes: can't delete. */
147 return; 148 return;
148 149
149 AVER(res == ResOK); 150 AVER(res == ResOK);
150 AVER(oldBase <= segBase); 151 AVER(RangesNest(&oldRange, &range));
151 AVER(segLimit <= oldLimit);
152 mvff->free -= AddrOffset(segBase, segLimit); 152 mvff->free -= AddrOffset(segBase, segLimit);
153 mvff->total -= AddrOffset(segBase, segLimit); 153 mvff->total -= AddrOffset(segBase, segLimit);
154 SegFree(seg); 154 SegFree(seg);
@@ -248,7 +248,7 @@ static Bool MVFFFindFirstFree(Addr *baseReturn, Addr *limitReturn,
248{ 248{
249 Bool foundBlock; 249 Bool foundBlock;
250 FindDelete findDelete; 250 FindDelete findDelete;
251 Addr oldBase, oldLimit; 251 RangeStruct range, oldRange;
252 252
253 AVER(baseReturn != NULL); 253 AVER(baseReturn != NULL);
254 AVER(limitReturn != NULL); 254 AVER(limitReturn != NULL);
@@ -260,11 +260,13 @@ static Bool MVFFFindFirstFree(Addr *baseReturn, Addr *limitReturn,
260 260
261 foundBlock = 261 foundBlock =
262 (mvff->firstFit ? CBSFindFirst : CBSFindLast) 262 (mvff->firstFit ? CBSFindFirst : CBSFindLast)
263 (baseReturn, limitReturn, &oldBase, &oldLimit, 263 (&range, &oldRange, CBSOfMVFF(mvff), size, findDelete);
264 CBSOfMVFF(mvff), size, findDelete);
265 264
266 if (foundBlock) 265 if (foundBlock) {
266 *baseReturn = RangeBase(&range);
267 *limitReturn = RangeLimit(&range);
267 mvff->free -= size; 268 mvff->free -= size;
269 }
268 270
269 return foundBlock; 271 return foundBlock;
270} 272}
@@ -354,7 +356,7 @@ static Res MVFFBufferFill(Addr *baseReturn, Addr *limitReturn,
354{ 356{
355 Res res; 357 Res res;
356 MVFF mvff; 358 MVFF mvff;
357 Addr base, limit, oldBase, oldLimit; 359 RangeStruct range, oldRange;
358 Bool foundBlock; 360 Bool foundBlock;
359 Seg seg = NULL; 361 Seg seg = NULL;
360 362
@@ -369,34 +371,33 @@ static Res MVFFBufferFill(Addr *baseReturn, Addr *limitReturn,
369 AVERT(Bool, withReservoirPermit); 371 AVERT(Bool, withReservoirPermit);
370 372
371 /* Hoping the largest is big enough, delete it and return if small. */ 373 /* Hoping the largest is big enough, delete it and return if small. */
372 foundBlock = CBSFindLargest(&base, &limit, &oldBase, &oldLimit, 374 foundBlock = CBSFindLargest(&range, &oldRange,
373 CBSOfMVFF(mvff), FindDeleteENTIRE); 375 CBSOfMVFF(mvff), FindDeleteENTIRE);
374 if (foundBlock && AddrOffset(base, limit) < size) { 376 if (foundBlock && RangeSize(&range) < size) {
375 Addr newBase, newLimit; 377 RangeStruct newRange;
376 foundBlock = FALSE; 378 foundBlock = FALSE;
377 res = CBSInsert(&newBase, &newLimit, CBSOfMVFF(mvff), base, limit); 379 res = CBSInsert(&newRange, CBSOfMVFF(mvff), &range);
378 if (ResIsAllocFailure(res)) 380 if (ResIsAllocFailure(res))
379 /* CBS ran out of memory for splay nodes: lose block. */ 381 /* CBS ran out of memory for splay nodes: lose block. */
380 return res; 382 return res;
381 383
382 AVER(newBase == base);
383 AVER(newLimit == limit);
384 AVER(res == ResOK); 384 AVER(res == ResOK);
385 AVER(RangesEqual(&newRange, &range));
385 } 386 }
386 if (!foundBlock) { 387 if (!foundBlock) {
387 res = MVFFAddSeg(&seg, mvff, size, withReservoirPermit); 388 res = MVFFAddSeg(&seg, mvff, size, withReservoirPermit);
388 if (res != ResOK) 389 if (res != ResOK)
389 return res; 390 return res;
390 foundBlock = CBSFindLargest(&base, &limit, &oldBase, &oldLimit, 391 foundBlock = CBSFindLargest(&range, &oldRange,
391 CBSOfMVFF(mvff), FindDeleteENTIRE); 392 CBSOfMVFF(mvff), FindDeleteENTIRE);
392 AVER(foundBlock); /* We will find the new segment. */ 393 AVER(foundBlock); /* We will find the new segment. */
393 } 394 }
394 395
395 AVER(AddrOffset(base, limit) >= size); 396 AVER(RangeSize(&range) >= size);
396 mvff->free -= AddrOffset(base, limit); 397 mvff->free -= RangeSize(&range);
397 398
398 *baseReturn = base; 399 *baseReturn = RangeBase(&range);
399 *limitReturn = limit; 400 *limitReturn = RangeLimit(&range);
400 return ResOK; 401 return ResOK;
401} 402}
402 403
diff --git a/mps/code/range.c b/mps/code/range.c
index 60a8b0da367..4cd61d7b04d 100644
--- a/mps/code/range.c
+++ b/mps/code/range.c
@@ -70,6 +70,22 @@ Bool RangesOverlap(Range range1, Range range2)
70 && RangeBase(range2) < RangeLimit(range1); 70 && RangeBase(range2) < RangeLimit(range1);
71} 71}
72 72
73Bool RangesNest(Range outer, Range inner)
74{
75 AVERT(Range, outer);
76 AVERT(Range, inner);
77 return RangeBase(outer) <= RangeBase(inner)
78 && RangeLimit(inner) <= RangeLimit(outer);
79}
80
81Bool RangesEqual(Range range1, Range range2)
82{
83 AVERT(Range, range1);
84 AVERT(Range, range2);
85 return RangeBase(range1) == RangeBase(range2)
86 && RangeLimit(range1) == RangeLimit(range2);
87}
88
73Bool RangeIsAligned(Range range, Align alignment) 89Bool RangeIsAligned(Range range, Align alignment)
74{ 90{
75 AVERT(Range, range); 91 AVERT(Range, range);
diff --git a/mps/code/range.h b/mps/code/range.h
index c6c70ddb1c4..42ab4167715 100644
--- a/mps/code/range.h
+++ b/mps/code/range.h
@@ -33,6 +33,8 @@ extern Res RangeDescribe(Range range, mps_lib_FILE *stream);
33extern Bool RangeCheck(Range range); 33extern Bool RangeCheck(Range range);
34extern Bool RangeIsAligned(Range range, Align align); 34extern Bool RangeIsAligned(Range range, Align align);
35extern Bool RangesOverlap(Range range1, Range range2); 35extern Bool RangesOverlap(Range range1, Range range2);
36extern Bool RangesNest(Range outer, Range inner);
37extern Bool RangesEqual(Range range1, Range range2);
36extern Addr (RangeBase)(Range range); 38extern Addr (RangeBase)(Range range);
37extern Addr (RangeLimit)(Range range); 39extern Addr (RangeLimit)(Range range);
38extern Size (RangeSize)(Range range); 40extern Size (RangeSize)(Range range);