diff options
| author | Richard Kistruck | 2010-03-23 01:49:17 +0000 |
|---|---|---|
| committer | Richard Kistruck | 2010-03-23 01:49:17 +0000 |
| commit | 0e6aecdbb86b2c9d30e08c155e4131ef1c663958 (patch) | |
| tree | 801ad57d287ea7d8348baf90d1e1f0a938d580bb /mps/code | |
| parent | e3177d0c02e16581ed17c0d01a43e5a8140807e1 (diff) | |
| download | emacs-0e6aecdbb86b2c9d30e08c155e4131ef1c663958.tar.gz emacs-0e6aecdbb86b2c9d30e08c155e4131ef1c663958.zip | |
mps br/vmem: simple-chunk-return:
arenavm.c -- move chunk-return into new function "VMCompact".
(also, in VMArenaFinish, null out arena->primary in VMArenaFinish, so it is not left dangling).
arena.c, arenavm.c, mpm.h, mpmst.h, mpmtypes.h:
arena->class->compact: ArenaCompact, ArenaTrivCompact, VMCompact
trace.c -- traceReclaim calls ArenaCompact!
Copied from Perforce
Change: 170095
ServerID: perforce.ravenbrook.com
Diffstat (limited to 'mps/code')
| -rw-r--r-- | mps/code/arena.c | 23 | ||||
| -rw-r--r-- | mps/code/arenavm.c | 58 | ||||
| -rw-r--r-- | mps/code/mpm.h | 2 | ||||
| -rw-r--r-- | mps/code/mpmst.h | 1 | ||||
| -rw-r--r-- | mps/code/mpmtypes.h | 1 | ||||
| -rw-r--r-- | mps/code/plan.txt | 6 | ||||
| -rw-r--r-- | mps/code/trace.c | 2 |
7 files changed, 77 insertions, 16 deletions
diff --git a/mps/code/arena.c b/mps/code/arena.c index 21c1759d74a..ac3cec79f09 100644 --- a/mps/code/arena.c +++ b/mps/code/arena.c | |||
| @@ -17,6 +17,11 @@ SRCID(arena, "$Id$"); | |||
| 17 | #define ArenaControlPool(arena) MV2Pool(&(arena)->controlPoolStruct) | 17 | #define ArenaControlPool(arena) MV2Pool(&(arena)->controlPoolStruct) |
| 18 | 18 | ||
| 19 | 19 | ||
| 20 | /* Forward declarations */ | ||
| 21 | |||
| 22 | static void ArenaTrivCompact(Arena arena, Trace trace); | ||
| 23 | |||
| 24 | |||
| 20 | /* ArenaTrivDescribe -- produce trivial description of an arena */ | 25 | /* ArenaTrivDescribe -- produce trivial description of an arena */ |
| 21 | 26 | ||
| 22 | static Res ArenaTrivDescribe(Arena arena, mps_lib_FILE *stream) | 27 | static Res ArenaTrivDescribe(Arena arena, mps_lib_FILE *stream) |
| @@ -63,6 +68,7 @@ DEFINE_CLASS(AbstractArenaClass, class) | |||
| 63 | class->free = NULL; | 68 | class->free = NULL; |
| 64 | class->chunkInit = NULL; | 69 | class->chunkInit = NULL; |
| 65 | class->chunkFinish = NULL; | 70 | class->chunkFinish = NULL; |
| 71 | class->compact = ArenaTrivCompact; | ||
| 66 | class->describe = ArenaTrivDescribe; | 72 | class->describe = ArenaTrivDescribe; |
| 67 | class->sig = ArenaClassSig; | 73 | class->sig = ArenaClassSig; |
| 68 | } | 74 | } |
| @@ -701,6 +707,23 @@ Res ArenaNoExtend(Arena arena, Addr base, Size size) | |||
| 701 | } | 707 | } |
| 702 | 708 | ||
| 703 | 709 | ||
| 710 | /* ArenaCompact -- respond (or not) to trace reclaim */ | ||
| 711 | |||
| 712 | void ArenaCompact(Arena arena, Trace trace) | ||
| 713 | { | ||
| 714 | AVERT(Arena, arena); | ||
| 715 | AVERT(Trace, trace); | ||
| 716 | (*arena->class->compact)(arena, trace); | ||
| 717 | } | ||
| 718 | |||
| 719 | static void ArenaTrivCompact(Arena arena, Trace trace) | ||
| 720 | { | ||
| 721 | UNUSED(arena); | ||
| 722 | UNUSED(trace); | ||
| 723 | return; | ||
| 724 | } | ||
| 725 | |||
| 726 | |||
| 704 | /* Has Addr */ | 727 | /* Has Addr */ |
| 705 | 728 | ||
| 706 | Bool ArenaHasAddr(Arena arena, Addr addr) | 729 | Bool ArenaHasAddr(Arena arena, Addr addr) |
diff --git a/mps/code/arenavm.c b/mps/code/arenavm.c index dd329b58c5a..3fab5f4d547 100644 --- a/mps/code/arenavm.c +++ b/mps/code/arenavm.c | |||
| @@ -91,6 +91,7 @@ typedef struct VMArenaStruct { /* VM arena structure */ | |||
| 91 | static void sparePagesPurge(VMArena vmArena); | 91 | static void sparePagesPurge(VMArena vmArena); |
| 92 | static ArenaClass VMArenaClassGet(void); | 92 | static ArenaClass VMArenaClassGet(void); |
| 93 | static ArenaClass VMNZArenaClassGet(void); | 93 | static ArenaClass VMNZArenaClassGet(void); |
| 94 | static void VMCompact(Arena arena, Trace trace); | ||
| 94 | 95 | ||
| 95 | 96 | ||
| 96 | /* VMChunkCheck -- check the consistency of a VM chunk */ | 97 | /* VMChunkCheck -- check the consistency of a VM chunk */ |
| @@ -540,7 +541,8 @@ static void VMArenaFinish(Arena arena) | |||
| 540 | arenaVM = vmArena->vm; | 541 | arenaVM = vmArena->vm; |
| 541 | 542 | ||
| 542 | sparePagesPurge(vmArena); | 543 | sparePagesPurge(vmArena); |
| 543 | /* destroy all chunks */ | 544 | /* destroy all chunks, including the primary */ |
| 545 | arena->primary = NULL; | ||
| 544 | RING_FOR(node, &arena->chunkRing, next) { | 546 | RING_FOR(node, &arena->chunkRing, next) { |
| 545 | Chunk chunk = RING_ELT(Chunk, chunkRing, node); | 547 | Chunk chunk = RING_ELT(Chunk, chunkRing, node); |
| 546 | vmChunkDestroy(chunk); | 548 | vmChunkDestroy(chunk); |
| @@ -1611,24 +1613,51 @@ static void VMFree(Addr base, Size size, Pool pool) | |||
| 1611 | if (arena->spareCommitted > arena->spareCommitLimit) { | 1613 | if (arena->spareCommitted > arena->spareCommitLimit) { |
| 1612 | sparePagesPurge(vmArena); | 1614 | sparePagesPurge(vmArena); |
| 1613 | } | 1615 | } |
| 1614 | /* @@@@ Chunks are never freed. */ | ||
| 1615 | 1616 | ||
| 1616 | /* ... oh yes they are */ | 1617 | /* Chunks are only freed when ArenaCompact is called. */ |
| 1617 | { | ||
| 1618 | Ring node, next; | ||
| 1619 | sparePagesPurge(vmArena); | ||
| 1620 | /* Destroy any empty chunks (except the primary). */ | ||
| 1621 | RING_FOR(node, &arena->chunkRing, next) { | ||
| 1622 | /*Chunk */chunk = RING_ELT(Chunk, chunkRing, node); | ||
| 1623 | if(chunk != arena->primary | ||
| 1624 | && BTIsResRange(chunk->allocTable, 0, chunk->pages)) | ||
| 1625 | vmChunkDestroy(chunk); | ||
| 1626 | } | ||
| 1627 | } | ||
| 1628 | 1618 | ||
| 1629 | return; | 1619 | return; |
| 1630 | } | 1620 | } |
| 1631 | 1621 | ||
| 1622 | static void VMCompact(Arena arena, Trace trace) | ||
| 1623 | { | ||
| 1624 | VMArena vmArena; | ||
| 1625 | Ring node, next; | ||
| 1626 | DIAG_DECL( Size vmem1; ) | ||
| 1627 | DIAG_DECL( Size vmem2; ) | ||
| 1628 | DIAG_DECL( Size vmemD; ) | ||
| 1629 | DIAG_DECL( Count count; ) | ||
| 1630 | |||
| 1631 | vmArena = Arena2VMArena(arena); | ||
| 1632 | AVERT(VMArena, vmArena); | ||
| 1633 | UNUSED(trace); /* it's there for better diag; not used yet */ | ||
| 1634 | |||
| 1635 | /* Destroy any empty chunks (except the primary). */ | ||
| 1636 | sparePagesPurge(vmArena); | ||
| 1637 | DIAG( | ||
| 1638 | vmem1 = VMArenaReserved(arena); | ||
| 1639 | count = 0; | ||
| 1640 | ); | ||
| 1641 | RING_FOR(node, &arena->chunkRing, next) { | ||
| 1642 | Chunk chunk = RING_ELT(Chunk, chunkRing, node); | ||
| 1643 | if(chunk != arena->primary | ||
| 1644 | && BTIsResRange(chunk->allocTable, 0, chunk->pages)) { | ||
| 1645 | vmChunkDestroy(chunk); | ||
| 1646 | DIAG( count += 1; ); | ||
| 1647 | } | ||
| 1648 | } | ||
| 1649 | DIAG( | ||
| 1650 | vmem2 = VMArenaReserved(arena); | ||
| 1651 | vmemD = vmem1 - vmem2; | ||
| 1652 | |||
| 1653 | if(vmemD != 0) { | ||
| 1654 | DIAG_SINGLEF(( "VMCompact", | ||
| 1655 | "vmem was $W, released $W, now $W", vmem1, vmemD, vmem2, | ||
| 1656 | NULL)); | ||
| 1657 | } | ||
| 1658 | ); | ||
| 1659 | |||
| 1660 | } | ||
| 1632 | 1661 | ||
| 1633 | mps_res_t mps_arena_vm_growth(mps_arena_t mps_arena, | 1662 | mps_res_t mps_arena_vm_growth(mps_arena_t mps_arena, |
| 1634 | size_t mps_desired, size_t mps_minimum) | 1663 | size_t mps_desired, size_t mps_minimum) |
| @@ -1675,6 +1704,7 @@ DEFINE_ARENA_CLASS(VMArenaClass, this) | |||
| 1675 | this->free = VMFree; | 1704 | this->free = VMFree; |
| 1676 | this->chunkInit = VMChunkInit; | 1705 | this->chunkInit = VMChunkInit; |
| 1677 | this->chunkFinish = VMChunkFinish; | 1706 | this->chunkFinish = VMChunkFinish; |
| 1707 | this->compact = VMCompact; | ||
| 1678 | this->describe = VMArenaDescribe; | 1708 | this->describe = VMArenaDescribe; |
| 1679 | } | 1709 | } |
| 1680 | 1710 | ||
diff --git a/mps/code/mpm.h b/mps/code/mpm.h index b4189afadcd..371319aeee6 100644 --- a/mps/code/mpm.h +++ b/mps/code/mpm.h | |||
| @@ -570,6 +570,8 @@ extern Size ArenaAvail(Arena arena); | |||
| 570 | 570 | ||
| 571 | extern Res ArenaExtend(Arena, Addr base, Size size); | 571 | extern Res ArenaExtend(Arena, Addr base, Size size); |
| 572 | 572 | ||
| 573 | extern void ArenaCompact(Arena arena, Trace trace); | ||
| 574 | |||
| 573 | extern Res ArenaFinalize(Arena arena, Ref obj); | 575 | extern Res ArenaFinalize(Arena arena, Ref obj); |
| 574 | extern Res ArenaDefinalize(Arena arena, Ref obj); | 576 | extern Res ArenaDefinalize(Arena arena, Ref obj); |
| 575 | 577 | ||
diff --git a/mps/code/mpmst.h b/mps/code/mpmst.h index 23409087808..c5a4fe0e3f3 100644 --- a/mps/code/mpmst.h +++ b/mps/code/mpmst.h | |||
| @@ -567,6 +567,7 @@ typedef struct ArenaClassStruct { | |||
| 567 | ArenaFreeMethod free; | 567 | ArenaFreeMethod free; |
| 568 | ArenaChunkInitMethod chunkInit; | 568 | ArenaChunkInitMethod chunkInit; |
| 569 | ArenaChunkFinishMethod chunkFinish; | 569 | ArenaChunkFinishMethod chunkFinish; |
| 570 | ArenaCompactMethod compact; | ||
| 570 | ArenaDescribeMethod describe; | 571 | ArenaDescribeMethod describe; |
| 571 | Sig sig; | 572 | Sig sig; |
| 572 | } ArenaClassStruct; | 573 | } ArenaClassStruct; |
diff --git a/mps/code/mpmtypes.h b/mps/code/mpmtypes.h index fd27f8c2a80..056ac0d2ec9 100644 --- a/mps/code/mpmtypes.h +++ b/mps/code/mpmtypes.h | |||
| @@ -118,6 +118,7 @@ typedef Res (*ArenaAllocMethod)(Addr *baseReturn, Tract *baseTractReturn, | |||
| 118 | typedef void (*ArenaFreeMethod)(Addr base, Size size, Pool pool); | 118 | typedef void (*ArenaFreeMethod)(Addr base, Size size, Pool pool); |
| 119 | typedef Res (*ArenaChunkInitMethod)(Chunk chunk, BootBlock boot); | 119 | typedef Res (*ArenaChunkInitMethod)(Chunk chunk, BootBlock boot); |
| 120 | typedef void (*ArenaChunkFinishMethod)(Chunk chunk); | 120 | typedef void (*ArenaChunkFinishMethod)(Chunk chunk); |
| 121 | typedef void (*ArenaCompactMethod)(Arena arena, Trace trace); | ||
| 121 | typedef Res (*ArenaDescribeMethod)(Arena arena, mps_lib_FILE *stream); | 122 | typedef Res (*ArenaDescribeMethod)(Arena arena, mps_lib_FILE *stream); |
| 122 | 123 | ||
| 123 | 124 | ||
diff --git a/mps/code/plan.txt b/mps/code/plan.txt index faeb16a6791..23bf274ecac 100644 --- a/mps/code/plan.txt +++ b/mps/code/plan.txt | |||
| @@ -15,9 +15,11 @@ The primary chunk is used specially: | |||
| 15 | 15 | ||
| 16 | 1. Arenacl requires a chunk to store the ArenaStruct in. (Whereas arenavm gets storage by simply mapping a new page). Therefore destroying the primary chunk would (in general) destroy the arena. | 16 | 1. Arenacl requires a chunk to store the ArenaStruct in. (Whereas arenavm gets storage by simply mapping a new page). Therefore destroying the primary chunk would (in general) destroy the arena. |
| 17 | 17 | ||
| 18 | 2. PageSize is known by chunks, not the arena. When arena needs to know page size, it asks the primary chunk. | 18 | 2. there's a field arena->primary that stores a pointer to the primary chunk. If the primary chunk ever goes away (eg. at ArenaFinish), this pointer must be nulled out so it is not left dangling. |
| 19 | 19 | ||
| 20 | 3. Various *Check functions only bother to check the primary chunk, and ignore other chunks. | 20 | 3. PageSize is known by chunks, not the arena. When arena needs to know page size, it asks the primary chunk. |
| 21 | |||
| 22 | 4. Various *Check functions only bother to check the primary chunk, and ignore other chunks. | ||
| 21 | 23 | ||
| 22 | 24 | ||
| 23 | 25 | ||
diff --git a/mps/code/trace.c b/mps/code/trace.c index b4b17c11b49..5cffa818009 100644 --- a/mps/code/trace.c +++ b/mps/code/trace.c | |||
| @@ -813,6 +813,8 @@ static void traceReclaim(Trace trace) | |||
| 813 | PoolTraceEnd(pool, trace); | 813 | PoolTraceEnd(pool, trace); |
| 814 | } | 814 | } |
| 815 | 815 | ||
| 816 | ArenaCompact(arena, trace); /* let arenavm drop chunks */ | ||
| 817 | |||
| 816 | TracePostMessage(trace); /* trace end */ | 818 | TracePostMessage(trace); /* trace end */ |
| 817 | /* Immediately pre-allocate messages for next time; failure is okay */ | 819 | /* Immediately pre-allocate messages for next time; failure is okay */ |
| 818 | (void)TraceIdMessagesCreate(arena, trace->ti); | 820 | (void)TraceIdMessagesCreate(arena, trace->ti); |