1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-24 14:30:43 -08:00

Catch-up merge from master sources to branch/2015-08-06/config.

Copied from Perforce
 Change: 188146
 ServerID: perforce.ravenbrook.com
This commit is contained in:
Gareth Rees 2015-08-14 16:35:07 +01:00
commit c2d2eacdb2
8 changed files with 136 additions and 63 deletions

View file

@ -243,10 +243,11 @@ Res ArenaInit(Arena arena, ArenaClass class, Size grainSize, ArgList args)
arena->sig = ArenaSig;
AVERT(Arena, arena);
/* Initialise a pool to hold the arena's CBS blocks. This pool can't be
allowed to extend itself using ArenaAlloc because it is used during
ArenaAlloc, so MFSExtendSelf is set to FALSE. Failures to extend are
handled where the Land is used. */
/* Initialise a pool to hold the CBS blocks for the arena's free
* land. This pool can't be allowed to extend itself using
* ArenaAlloc because it is used to implement ArenaAlloc, so
* MFSExtendSelf is set to FALSE. Failures to extend are handled
* where the free land is used: see arenaFreeLandInsertExtend. */
MPS_ARGS_BEGIN(piArgs) {
MPS_ARGS_ADD(piArgs, MPS_KEY_MFS_UNIT_SIZE, sizeof(CBSZonedBlockStruct));
@ -258,18 +259,6 @@ Res ArenaInit(Arena arena, ArenaClass class, Size grainSize, ArgList args)
if (res != ResOK)
goto failMFSInit;
/* Initialise the freeLand. */
MPS_ARGS_BEGIN(liArgs) {
MPS_ARGS_ADD(liArgs, CBSBlockPool, ArenaCBSBlockPool(arena));
res = LandInit(ArenaFreeLand(arena), CBSZonedLandClassGet(), arena,
ArenaGrainSize(arena), arena, liArgs);
} MPS_ARGS_END(liArgs);
AVER(res == ResOK); /* no allocation, no failure expected */
if (res != ResOK)
goto failLandInit;
/* Note that although freeLand is initialised, it doesn't have any memory
for its blocks, so hasFreeLand remains FALSE until later. */
/* initialize the reservoir, <design/reservoir/> */
res = ReservoirInit(&arena->reservoirStruct, arena);
if (res != ResOK)
@ -279,8 +268,6 @@ Res ArenaInit(Arena arena, ArenaClass class, Size grainSize, ArgList args)
return ResOK;
failReservoirInit:
LandFinish(ArenaFreeLand(arena));
failLandInit:
PoolFinish(ArenaCBSBlockPool(arena));
failMFSInit:
GlobalsFinish(ArenaGlobals(arena));
@ -316,16 +303,33 @@ static Res arenaFreeLandInit(Arena arena)
AVER(!arena->hasFreeLand);
AVER(arena->primary != NULL);
/* With the primary chunk initialised we can add page memory to the freeLand
* that describes the free address space in the primary chunk. */
/* Initialise the free land. */
MPS_ARGS_BEGIN(liArgs) {
MPS_ARGS_ADD(liArgs, CBSBlockPool, ArenaCBSBlockPool(arena));
res = LandInit(ArenaFreeLand(arena), CBSZonedLandClassGet(), arena,
ArenaGrainSize(arena), arena, liArgs);
} MPS_ARGS_END(liArgs);
AVER(res == ResOK); /* no allocation, no failure expected */
if (res != ResOK)
goto failLandInit;
/* With the primary chunk initialised we can add page memory to the
* free land that describes the free address space in the primary
* chunk. */
res = ArenaFreeLandInsert(arena,
PageIndexBase(arena->primary,
arena->primary->allocBase),
arena->primary->limit);
if (res != ResOK)
return res;
goto failFreeLandInsert;
arena->hasFreeLand = TRUE;
return ResOK;
failFreeLandInsert:
LandFinish(ArenaFreeLand(arena));
failLandInit:
return res;
}
Res ArenaCreate(Arena *arenaReturn, ArenaClass class, ArgList args)
@ -441,16 +445,16 @@ static void arenaMFSPageFreeVisitor(Pool pool, Addr base, Size size,
static void arenaFreeLandFinish(Arena arena)
{
/* We must tear down the freeLand before the chunks, because pages
* containing CBS blocks might be allocated in those chunks. */
AVERT(Arena, arena);
AVER(arena->hasFreeLand);
arena->hasFreeLand = FALSE;
LandFinish(ArenaFreeLand(arena));
/* The CBS block pool can't free its own memory via ArenaFree because
* that would use the freeLand. */
* that would use the free land. */
MFSFinishTracts(ArenaCBSBlockPool(arena), arenaMFSPageFreeVisitor,
UNUSED_POINTER, UNUSED_SIZE);
arena->hasFreeLand = FALSE;
LandFinish(ArenaFreeLand(arena));
}
void ArenaDestroy(Arena arena)
@ -464,6 +468,8 @@ void ArenaDestroy(Arena arena)
ControlFinish(arena);
/* We must tear down the free land before the chunks, because pages
* containing CBS blocks might be allocated in those chunks. */
arenaFreeLandFinish(arena);
/* Call class-specific finishing. This will call ArenaFinish. */
@ -854,7 +860,7 @@ static Res arenaExtendCBSBlockPool(Range pageRangeReturn, Arena arena)
return res;
MFSExtend(ArenaCBSBlockPool(arena), pageBase, ArenaGrainSize(arena));
RangeInit(pageRangeReturn, pageBase, AddrAdd(pageBase, ArenaGrainSize(arena)));
RangeInitSize(pageRangeReturn, pageBase, ArenaGrainSize(arena));
return ResOK;
}
@ -874,15 +880,19 @@ static void arenaExcludePage(Arena arena, Range pageRange)
}
/* arenaLandInsert -- add range to arena's land, maybe extending block pool
/* arenaFreeLandInsertExtend -- add range to arena's free land, maybe
* extending block pool
*
* The arena's land can't get memory in the usual way because it is
* used in the basic allocator, so we allocate pages specially.
* The arena's free land can't get memory for its block pool in the
* usual way (via ArenaAlloc), because it is the mechanism behind
* ArenaAlloc! So we extend the block pool via a back door (see
* arenaExtendCBSBlockPool).
*
* Only fails if it can't get a page for the block pool.
*/
static Res arenaLandInsert(Range rangeReturn, Arena arena, Range range)
static Res arenaFreeLandInsertExtend(Range rangeReturn, Arena arena,
Range range)
{
Res res;
@ -908,16 +918,18 @@ static Res arenaLandInsert(Range rangeReturn, Arena arena, Range range)
}
/* ArenaFreeLandInsert -- add range to arena's land, maybe stealing memory
/* arenaFreeLandInsertSteal -- add range to arena's free land, maybe
* stealing memory
*
* See arenaLandInsert. This function may only be applied to mapped
* pages and may steal them to store Land nodes if it's unable to
* allocate space for CBS blocks.
* See arenaFreeLandInsertExtend. This function may only be applied to
* mapped pages and may steal them to store Land nodes if it's unable
* to allocate space for CBS blocks.
*
* IMPORTANT: May update rangeIO.
*/
static void arenaLandInsertSteal(Range rangeReturn, Arena arena, Range rangeIO)
static void arenaFreeLandInsertSteal(Range rangeReturn, Arena arena,
Range rangeIO)
{
Res res;
@ -925,7 +937,7 @@ static void arenaLandInsertSteal(Range rangeReturn, Arena arena, Range rangeIO)
AVERT(Arena, arena);
AVERT(Range, rangeIO);
res = arenaLandInsert(rangeReturn, arena, rangeIO);
res = arenaFreeLandInsertExtend(rangeReturn, arena, rangeIO);
if (res != ResOK) {
Addr pageBase;
@ -954,7 +966,8 @@ static void arenaLandInsertSteal(Range rangeReturn, Arena arena, Range rangeIO)
}
/* ArenaFreeLandInsert -- add range to arena's land, maybe extending block pool
/* ArenaFreeLandInsert -- add range to arena's free land, maybe extending
* block pool
*
* The inserted block of address space may not abut any existing block.
* This restriction ensures that we don't coalesce chunks and allocate
@ -969,7 +982,7 @@ Res ArenaFreeLandInsert(Arena arena, Addr base, Addr limit)
AVERT(Arena, arena);
RangeInit(&range, base, limit);
res = arenaLandInsert(&oldRange, arena, &range);
res = arenaFreeLandInsertExtend(&oldRange, arena, &range);
if (res != ResOK)
return res;
@ -984,7 +997,8 @@ Res ArenaFreeLandInsert(Arena arena, Addr base, Addr limit)
}
/* ArenaFreeLandDelete -- remove range from arena's land, maybe extending block pool
/* ArenaFreeLandDelete -- remove range from arena's free land, maybe
* extending block pool
*
* This is called from ChunkFinish in order to remove address space from
* the arena.
@ -1076,7 +1090,7 @@ static Res arenaAllocFromLand(Tract *tractReturn, ZoneSet zones, Bool high,
failMark:
{
Res insertRes = arenaLandInsert(&oldRange, arena, &range);
Res insertRes = arenaFreeLandInsertExtend(&oldRange, arena, &range);
AVER(insertRes == ResOK); /* We only just deleted it. */
/* If the insert does fail, we lose some address space permanently. */
}
@ -1288,7 +1302,7 @@ void ArenaFree(Addr base, Size size, Pool pool)
RangeInit(&range, base, limit);
arenaLandInsertSteal(&oldRange, arena, &range); /* may update range */
arenaFreeLandInsertSteal(&oldRange, arena, &range); /* may update range */
(*arena->class->free)(RangeBase(&range), RangeSize(&range), pool);

View file

@ -1,7 +1,7 @@
/* freelist.c: FREE LIST ALLOCATOR IMPLEMENTATION
*
* $Id$
* Copyright (c) 2013-2014 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2013-2015 Ravenbrook Limited. See end of file for license.
*
* .sources: <design/freelist/>.
*/
@ -18,11 +18,11 @@ SRCID(freelist, "$Id$");
typedef union FreelistBlockUnion {
struct {
struct FreelistBlockSmall {
FreelistBlock next; /* tagged with low bit 1 */
/* limit is (char *)this + freelistAlignment(fl) */
} small;
struct {
struct FreelistBlockLarge {
FreelistBlock next; /* not tagged (low bit 0) */
Addr limit;
} large;
@ -101,6 +101,9 @@ static Bool FreelistBlockCheck(FreelistBlock block)
CHECKL(freelistBlockNext(block) == freelistEND
|| block < freelistBlockNext(block));
CHECKL(freelistBlockIsSmall(block) || (Addr)block < block->large.limit);
/* Would like to CHECKL(!freelistBlockIsSmall(block) ||
* freelistBlockSize(fl, block) == freelistAlignment(fl)) but we
* don't have 'fl' here. This is checked in freelistBlockSetLimit. */
return TRUE;
}
@ -139,6 +142,7 @@ static void freelistBlockSetLimit(Freelist fl, FreelistBlock block, Addr limit)
} else {
AVER(size >= sizeof(block->small));
block->small.next = freelistTagSet(block->small.next);
AVER(freelistBlockSize(fl, block) == freelistAlignment(fl));
}
AVER(freelistBlockLimit(fl, block) == limit);
}
@ -170,6 +174,9 @@ Bool FreelistCheck(Freelist fl)
CHECKS(Freelist, fl);
land = FreelistLand(fl);
CHECKD(Land, land);
CHECKL(AlignCheck(FreelistMinimumAlignment));
CHECKL(sizeof(struct FreelistBlockSmall) < sizeof(struct FreelistBlockLarge));
CHECKL(sizeof(struct FreelistBlockSmall) <= freelistAlignment(fl));
/* See <design/freelist/#impl.grain.align> */
CHECKL(AlignIsAligned(freelistAlignment(fl), FreelistMinimumAlignment));
CHECKL((fl->list == freelistEND) == (fl->listSize == 0));
@ -236,12 +243,14 @@ static Size freelistSize(Land land)
* Otherwise, if next is freelistEND, make prev the last block in the list.
* Otherwise, make next follow prev in the list.
* Update the count of blocks by 'delta'.
*
* It is tempting to try to simplify this code by putting a
* FreelistBlockUnion into the FreelistStruct and so avoiding the
* special case on prev. But the problem with that idea is that we
* can't guarantee that such a sentinel would respect the isolated
* range invariant, and so it would still have to be special-cases.
* range invariant (it would have to be at a lower address than the
* first block in the free list, which the MPS has no mechanism to
* enforce), and so it would still have to be special-cased.
*/
static void freelistBlockSetPrevNext(Freelist fl, FreelistBlock prev,
@ -781,6 +790,7 @@ static Res freelistDescribe(Land land, mps_lib_FILE *stream, Count depth)
res = WriteF(stream, depth,
"Freelist $P {\n", (WriteFP)fl,
" listSize = $U\n", (WriteFU)fl->listSize,
" size = $U\n", (WriteFU)fl->size,
NULL);
b = LandIterate(land, freelistDescribeVisitor, stream, depth + 2);
@ -815,7 +825,7 @@ DEFINE_LAND_CLASS(FreelistLandClass, class)
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2013-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2013-2015 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -76,14 +76,14 @@ class, a subclass of ``LandClass`` suitable for passing to
``LandClass CBSFastLandClassGet(void)``
_`.function.class`: Returns a subclass of ``CBSLandClass`` that
_`.function.class.fast`: Returns a subclass of ``CBSLandClass`` that
maintains, for each subtree, the size of the largest block in that
subtree. This enables the ``LandFindFirst()``, ``LandFindLast()``, and
``LandFindLargest()`` generic functions.
``LandClass CBSZonedLandClassGet(void)``
_`.function.class`: Returns a subclass of ``CBSFastLandClass`` that
_`.function.class.zoned`: Returns a subclass of ``CBSFastLandClass`` that
maintains, for each subtree, the union of the zone sets of all ranges
in that subtree. This enables the ``LandFindInZones()`` generic
function.

View file

@ -74,8 +74,8 @@ available, only language facilities.
_`.int.free.lib`: We assume that the headers ``<float.h>``,
``<limits.h>``, ``<stdarg.h>`` and ``<stddef.h>`` are available in the
freestanding environment, because they define only language features
and not library calls. We assume that we may not make use of any other
definitions if freestanding parts of the system.
and not library calls. We assume that we may not make use of
definitions in any other headers in freestanding parts of the system.
_`.int.free.term`: We may not terminate the program in a freestanding
environment, and therefore we may not call :c:func:`abort`. We can't
@ -149,7 +149,7 @@ Document History
Copyright and License
---------------------
Copyright © 1996-2014 Ravenbrook Limited. All rights reserved.
Copyright © 1996-2015 Ravenbrook Limited. All rights reserved.
<http://www.ravenbrook.com/>. This is an open source license. Contact
Ravenbrook for commercial licensing options.

View file

@ -86,7 +86,7 @@ indicating whether to continue with the iteration.
``typedef Bool (*LandDeleteVisitor)(Bool *deleteReturn, Land land, Range range, void *closureP, Size closureS)``
_`.type.visitor`: Type ``LandDeleteVisitor`` is a callback function that may
_`.type.deletevisitor`: Type ``LandDeleteVisitor`` is a callback function that may
be passed to ``LandIterateAndDelete()``. It is called for every isolated
contiguous range in address order. The function must return a ``Bool``
indicating whether to continue with the iteration. It may additionally
@ -187,6 +187,16 @@ _`.function.iterate.and.delete`: As ``LandIterate()``, but the visitor
function additionally returns a Boolean indicating whether the range
should be deleted from the land.
_`.function.iterate.and.delete.justify`: The reason for having both
``LandIterate()`` and ``LandIterateAndDelete()`` is that it may be
possible to use a more efficient algorithm, or to preserve more
properties of the data structure, when it is known that the land willl
not be modified during the iteration. For example, in the CBS
implementation, ``LandIterate()`` uses ``TreeTraverse()`` which
preserves the tree structure, whereas ``LandIterateAndDelete()`` uses
``TreeTraverseAndDelete()`` which flattens the tree structure, losing
information about recently accessed nodes.
``Bool LandFindFirst(Range rangeReturn, Range oldRangeReturn, Land land, Size size, FindDelete findDelete)``
_`.function.find.first`: Locate the first block (in address order)
@ -311,7 +321,7 @@ Document History
Copyright and License
---------------------
Copyright © 2014 Ravenbrook Limited. All rights reserved.
Copyright © 2014-2015 Ravenbrook Limited. All rights reserved.
<http://www.ravenbrook.com/>. This is an open source license. Contact
Ravenbrook for commercial licensing options.

View file

@ -128,8 +128,10 @@ AMC interface
pointers` keep objects alive.
* :c:macro:`MPS_KEY_EXTEND_BY` (type :c:type:`size_t`,
default 4096) is the default :term:`size` of block that the pool
will request from the :term:`arena`.
default 4096) is the minimum :term:`size` of the memory segments
that the pool requests from the :term:`arena`. Larger segments
reduce the per-segment overhead, but increase
:term:`fragmentation` and :term:`retention`.
For example::

View file

@ -12,6 +12,11 @@ Release 1.115.0
New features
............
#. When creating an :ref:`pool-amc` pool, :c:func:`mps_pool_create_k`
accepts the new keyword argument :c:macro:`MPS_KEY_EXTEND_BY`,
specifying the minimum size of the memory segments that the pool
requests from the :term:`arena`.
#. The function :c:func:`mps_arena_create_k` accepts two new
:term:`keyword arguments`. :c:macro:`MPS_KEY_ARENA_COMMIT_LIMIT`
sets the :term:`commit limit` for the arena, and
@ -49,6 +54,30 @@ Other changes
.. _job001887: https://www.ravenbrook.com/project/mps/issue/job001887/
#. :ref:`pool-amc` pools now assert that exact references into the
pool are aligned to the pool's alignment. See job002175_.
.. _job002175: https://www.ravenbrook.com/project/mps/issue/job002175/
#. Internal calculation of the address space available to the MPS no
longer takes time proportional to the number of times the arena has
been extended, speeding up allocation when memory is tight. See
job003814_.
.. _job003814: https://www.ravenbrook.com/project/mps/issue/job003814/
#. Setting :c:macro:`MPS_KEY_SPARE` for a :ref:`pool-mvff` pool now
works. See job003870_.
.. _job003870: https://www.ravenbrook.com/project/mps/issue/job003870/
#. When the arena is out of memory and cannot be extended without
hitting the :term:`commit limit`, the MPS now returns
:c:macro:`MPS_RES_COMMIT_LIMIT` rather than substituting
:c:macro:`MPS_RES_RESOURCE`. See job003899_.
.. _job003899: https://www.ravenbrook.com/project/mps/issue/job003899/
.. _release-notes-1.114:
@ -180,8 +209,8 @@ Other changes
#. Allocation into :ref:`pool-awl` pools again reliably provokes
garbage collections of the generation that the pool belongs to. (In
release 1.113.0, the generation would only be collected if a pool
of some other class allocated into it.) See job003772_.
version 1.113, the generation would only be collected if a pool of
some other class allocated into it.) See job003772_.
.. _job003772: https://www.ravenbrook.com/project/mps/issue/job003772/
@ -193,13 +222,21 @@ Other changes
.. _job003773: https://www.ravenbrook.com/project/mps/issue/job003773/
#. The :ref:`pool-mvt` and :ref:`pool-mvff` pool classes are now
around 25% faster (in our benchmarks) than they were in release
1.113.0.
around 25% faster (in our benchmarks) than they were in version
1.113.
#. The default assertion handler in the default :term:`plinth` now
flushes the telemetry stream before aborting. See
:c:func:`mps_lib_assert_fail`.
#. Garbage collection performance is substantially improved in the
situation where the arena has been extended many times. Critical
operations now take time logarithmic in the number of times the
arena has been extended (rather than linear, as in version 1.113
and earlier). See job003554_.
.. _job003554: https://www.ravenbrook.com/project/mps/issue/job003554/
.. _release-notes-1.113:

View file

@ -13,7 +13,7 @@ From the test directory::
PLATFORM=lii6ll # substitute your platform
CODE=../code # code directory of the branch you are testing
make -C $CODE -f $PLATFORM.gmk VARIETY=cool $PLATFORM/cool/mps.o
make -B -C $CODE -f $PLATFORM.gmk VARIETY=cool $PLATFORM/cool/mps.o
alias qa="perl test/qa -i $CODE -l $CODE/$PLATFORM/cool/mps.o"
qa clib
qa run function/5.c