1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-31 09:20:54 -08:00
emacs/mps/manual/wiki/trace.html
Richard Kistruck 3f74e5a986 Mps wiki: trace: .scan.loop.terminate thoughts. poolamc clarify.
Copied from Perforce
 Change: 161752
 ServerID: perforce.ravenbrook.com
2007-02-14 18:01:09 +00:00

226 lines
11 KiB
HTML

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>MPS Wiki: Trace</title>
<style type = "text/css">
<!--
div.banner {text-align:center}
dt {font-weight:bold}
-->
</style>
</head>
<body>
<div class="banner">
<p>
<a href="/">Ravenbrook</a>
/ <a href="/project/">Projects</a>
/ <a href="/project/mps/">Memory Pool System</a>
/ <a href="/project/mps/master/">Master Product Sources</a>
/ <a href="/project/mps/master/manual/">Manuals</a>
/ <a href="/project/mps/master/manual/wiki/">Wiki</a>
</p>
<p><i><a href="/project/mps/">Memory Pool System Project</a></i></p>
<hr />
<h1>MPS Wiki: Trace</h1>
<address>
<a href="mailto:rhsk@ravenbrook.com">Richard Kistruck</a>,
<a href="http://www.ravenbrook.com/">Ravenbrook Limited</a>,
2007-01-12
</address>
</div>
<p> This wiki article contains incomplete and informal notes about the MPS, the precursor to more formal documentation. Not confidential. Readership: MPS users and developers. </p>
<h2>Introduction</h2>
<p>Tracing is when the MPS follows the dag of references to find all reachable objects.</p>
<h2>Setting up a trace</h2>
<p><a href="trace.png"><img src="trace.png" alt="MPS Trace setup. Original drawing: trace.graffle, derived from //info.ravenbrook.com/project/mps/master/code/trace.c#18, 2007-01-08" /></a></p>
<h2>Scan: advance a trace</h2>
<p>The unit of trace scanning is the segment. Trace calls <code>PoolScan(&amp;wasTotal, &amp;ss, SegPool(seg), seg)</code>. PoolScan must make the seg <strong>non-grey</strong>, or return a failure code.</p>
<h3>.scan.change:</h3>
<p>When scan encounters a ref, the ref and the referent object get fixed. Fixing can cause several kinds of change; these changes happen immediately, right in the middle of scanning. WARNING: These changes can be <strong>on the same segment</strong> we are scanning:</p>
<ul>
<li>.scan.change.ref: the ref encountered by scan may get updated or splatted (if the fixed object is relocated or dies);</li>
<li>.scan.change.obj: the fixed object may get overwritten with a forward or pad;</li>
<li>.scan.change.obj-colour: the fixed object may change colour (eg. get a nailboard mark);</li>
<li>.scan.change.buffer: the mechanics of forwarding may cause arbitrary buffer changes, as follows:
<ul>
<li>.scan.change.buffer.attach: a forwarding buffer may be attached;</li>
<li>.scan.change.buffer.new-obj: the fixed object may get forwarded into the segment (using the buffer);</li>
<li>.scan.change.buffer.detach: the forwarding buffer may be detached;</li>
</ul>
</li>
<li>.scan.change.mode: fixing may cause an immediate change in the segment's mode (mono-colour to mixed; unnailed to nailed; etc). Mode change can cause object colour change. The details depend on the pool class.</li>
</ul>
<p>Scanning code must behave correctly when these changes affect the segment currently being scanned. The tricky issues are: not crashing, completeness of de-greying, getting the final summary correct, doing the accounting correctly, etc.</p>
<h3>.scan.loop:</h3>
<p>Looping is all about <strong>completeness of de-greying</strong>; it is affected by both colour and buffers.</p>
<p>.scan.loop.once: If the seg is full and non-white (eg. all grey) when scanning starts, then a single linear scan will make the seg non-grey (in fact: all black). In this case only, we do not need a loop.</p>
<p>Otherwise, there are two ways <strong>new grey objects</strong> can appear in the segment while we are scanning it:</p>
<p>.scan.loop.white: If the seg contains some white objects when we start a linear scan, then a Ref that points backwards into the same seg can fix and grey an object that was skipped as white when the linear scan passed over it. So scanning must loop until it the whole seg is non-grey. (This condition is a case of .scan.change.obj-colour).</p>
<p>.scan.loop.buffer: If the seg has, or could get, a Forwarding-grey (or Mutator-grey, not yet implemented) buffer, then new grey objects can arrive during the scan. WARNING: buffers move around during scanning: a buffer could be attached, or detached, several times during scanning a single segment, especially in low memory situations. (This condition is a case of .scan.change.buffer).</p>
<p>.scan.loop.terminate: There needs to be communication between the thing that makes new grey objects, and the scan loop termination condition.</p>
<p>.scan.loop.terminate.no-new-marks: The usual termination condition for .scan.loop.white is that the last iteration produced no new marks. A newMarks boolean is used by AMC and AMS. (Perhaps it is also needed for other reasons?). [Note: It might be reasonable to make buffers touch the same newMarks boolean, to provide the termination condition for .scan.loop.buffer. RHSK 2007-01-18].</p>
<p>[.scan.loop.terminate.seggrey: An alternative would be for newly fixed or forwarded objects to do SegSetGrey to trigger another iteration. They have to do this anyway, for the case that the preserved object is on a different seg. To use this to control scan loop termination, scan would have to de-grey the seg at scan start, which is slightly alarming. But I can't think of any actual problem with it, except that the mutator musn't see the seg yet, which mucks up the shield abstraction. Hmmm. It still might be better than lots of special-case code in pools though? RHSK 2007-01-18]</p>
<p>.scan.loop.de-grey: After a resOK scan, the seg is set non-grey by traceScanSegRes() in trace.c.</p>
<p>.scan.loop.no-escape: So there is no way to 'escape from' the complete-degrey requirement, and no way to mark this seg as 'still grey' at the end of the scan, except by returning an error.</p>
<p>.scan.loop.emergency: Any error returned by scan (which must be in the ResIsAllocFailure category) will put the traces into emergency mode and cause an immediate re-scan.</p>
<h3>.scan.total:</h3>
<p>Total versus non-Total scans is all about <strong>updating the segment summary</strong>; it is affected by both colour and buffers.</p>
<p>The current design is that the segment summary is <strong>not updated</strong> as new refs (from relocating fixes or splats) are written into the seg during the scan. Instead, the summary of the old and new refs seen by the scan is kept in the scan state: <code>ss-&gt;unfixedSummary</code> and <code>ss-&gt;fixedSummary</code>.</p>
<p>.scan.total.not: A scan does not necessarily see all objects: objects that were already black at scan start are usually skipped; and objects that remain white at scan end are always skipped. This is the <code>!wasTotal</code> case, and the fixedSummary resulting from the scan must be unioned into the segment summary.</p>
<p>.scan.total.yes: But if all objects in the segment were scanned*, PoolScan sets <code>wasTotal</code> to true. (*: for example, if the whole seg was grey at scan start). The trace then uses <code>ss-&gt;fixedSummary</code> to replace the old segment summary.</p>
<h3>Scan details</h3>
<p>This is how a non-trivial scan of a seg happens in AMC:</p>
<pre>
traceScanSeg /* without fail: if needed triggers emergency retry (cannot fail) */
traceScanSegRes
ScanStateInit
ss->fix = TraceFix, or TraceFixEmergency
ShieldExpose
PoolScan
(*pool->class->scan)
AMCScan
while (buffer still leaving trail)
(*pool->format->scan)(ss, base, limit);
[for example]
dylan_scan
mps_fix
MPS_FIX12
ss->unfixedSummary += ref
(*ss->fix)(ss, ref_io)
TraceFix
TraceSetInter(TractWhite(tract(ref)), ss->traces)?
TRACT_SEG?
PoolFix(pool, ss, seg, refIO)
= (*pool->fix)(pool, ss, seg, refIO)
...see below...
ss->fixedSummary += newRef
ShieldCover
</pre>
<p>Where:</p>
<pre>
PoolFix(pool, ss, seg, refIO)
= (*pool->fix)(pool, ss, seg, refIO)
AMCFix, AMCHeaderFix
ShieldExpose(ref)
(*pool->format->isMoved)(ref)?
no:
/* Forward */
newRef = BUFFER_RESERVE(seg->gen->forward)
ShieldExpose(newRef)
union colour
union summary
AddrCopy(*newRef = *ref)
ShieldCover(newRef)
BUFFER_COMMIT
(*pool->format->move)(ref, newRef)
ref = newRef
yes:
/* Snap out */
ref = newRef
ShieldCover(ref)
</pre>
<h2><a id="section-B" name="section-B">B. Document History</a></h2>
<pre>
2007-01-12 RHSK Created.
2007-01-16 RHSK .scan.loop, .scan.total.
2007-01-18 RHSK .scan.change.
</pre>
<h2><a id="section-C" name="section-C">C. Copyright and License</a></h2>
<p> This document is copyright &copy; 2007 <a href="http://www.ravenbrook.com/">Ravenbrook Limited</a>. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options. </p>
<p> Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: </p>
<ol>
<li> Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. </li>
<li> Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. </li>
<li> Redistributions in any form must be accompanied by information on how to obtain complete source code for the this software and any accompanying software that uses this software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs. </li>
</ol>
<p> <strong> This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement, are disclaimed. In no event shall the copyright holders and contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage. </strong> </p>
<hr />
<div class="banner">
<p><code>$Id$</code></p>
<p>
<a href="/">Ravenbrook</a>
/ <a href="/project/">Projects</a>
/ <a href="/project/mps/">Memory Pool System</a>
/ <a href="/project/mps/master/">Master Product Sources</a>
/ <a href="/project/mps/master/manual/">Manuals</a>
/ <a href="/project/mps/master/manual/wiki/">Wiki</a>
</p>
</div>
</body>
</html>