mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-02-24 05:47:36 +00:00
Mps wiki article on gc: allocation points: how it's supposed to be.
Also note that must make at least one ambiguous ref and no exact refs to new object before calling commit. Copied from Perforce Change: 159174 ServerID: perforce.ravenbrook.com
This commit is contained in:
parent
86c0d3a324
commit
da70c79fa0
1 changed files with 181 additions and 2 deletions
|
|
@ -48,11 +48,19 @@ <h2>Introduction</h2>
|
|||
|
||||
<p>The essential MPS concepts for GC are:</p>
|
||||
<ul>
|
||||
<li> Format -- lets the MPS ask the client a question about an object;</li>
|
||||
<li> <a href="#Format">Format</a> -- lets the MPS ask the client a question about an object;</li>
|
||||
<li> Root -- tell the MPS which things (eg. stack, globals) are always alive.</li>
|
||||
</ul>
|
||||
|
||||
<h2><a id="Formats">Formats</a></h2>
|
||||
<p>The advanced MPS concepts for GC are:</p>
|
||||
<ul>
|
||||
<li> <a href="#Allocation-Point">Allocation Point</a>
|
||||
-- reserve memory, construct and connect a new object, and commit it to MPS management.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2><a id="Format">Format</a></h2>
|
||||
|
||||
<p>The client can choose how to format its objects, but the MPS will
|
||||
sometimes need to ask the client some questions about an object, such
|
||||
|
|
@ -181,12 +189,183 @@ <h3><a id="format-variants">Format Variants</a></h3>
|
|||
|
||||
<p>It's a bit messy -- sorry.</p>
|
||||
|
||||
|
||||
<h2><a id="Allocation-Point">Allocation Point</a></h2>
|
||||
|
||||
<h3>Overview of two-phase allocation</h3>
|
||||
|
||||
<p>The client should:</p>
|
||||
<ol>
|
||||
<li> <code>mps_reserve</code> some memory,</li>
|
||||
<li> construct a new object in it,</li>
|
||||
<li> write a reference to the new object into some older object,
|
||||
thereby connecting the new object into the client's graph of
|
||||
objects </li>
|
||||
<li> <code>mps_commit</code> the new object to MPS management.</li>
|
||||
</ol>
|
||||
|
||||
<h3>The graph of managed references to mobile objects</h3>
|
||||
|
||||
<p>The MPS is a moving garbage collector: it supports
|
||||
preserve-by-copying pools, whose objects are 'mobile'.
|
||||
Whenever the MPS moves an object, it will ensure that
|
||||
all managed references are updated to point to the
|
||||
new location -- and this happens instantaneously as far
|
||||
as the client sees it.</p>
|
||||
|
||||
<p>The client should assume that, between <em>any pair of
|
||||
instructions</em>, the MPS may 'shake' this graph, moving
|
||||
all the mobile objects, and updating all the managed
|
||||
references.</p>
|
||||
|
||||
<p>The client usually takes care to ensure that the
|
||||
references it
|
||||
holds are managed. To be managed, the reference must be
|
||||
in a formatted object that is reachable from a root, or
|
||||
actually in a root (such as a scanned stack). </p>
|
||||
|
||||
<p>It is okay for a careful client to hold unmanaged references,
|
||||
but:</p>
|
||||
<ul>
|
||||
<li> they'd better not be to a mobile object! Remember, mobile
|
||||
objects could move at any time, and unmanaged references
|
||||
will be left 'dangling'.</li>
|
||||
<li> they'd better not be the only reference to an object,
|
||||
or that object might get collected, again leaving a dangling
|
||||
reference!</li>
|
||||
</ul>
|
||||
|
||||
<h3>mps_reserve</h3>
|
||||
|
||||
<p><code>mps_reserve</code> returns a reference to a piece
|
||||
of new memory for the client to build a new object in.
|
||||
During this build, the MPS pins the piece of memory, and
|
||||
treats it as raw data.</p>
|
||||
|
||||
<p>"Pinned" means: it will not move, be collected, be unmapped,
|
||||
or anything like that.</p>
|
||||
|
||||
<p>"Raw data" means two things:</p>
|
||||
|
||||
<p>Firstly, "raw data" means that any references stored IN the
|
||||
new object are <em>unmanaged</em>. This means:</p>
|
||||
<ul>
|
||||
<li> references in the new object will not get updated if
|
||||
the graph of managed references to mobile objects is 'shaken';</li>
|
||||
<li> references in the new object do not
|
||||
preserve any old objects they point to.</li>
|
||||
</ul>
|
||||
|
||||
<p>Secondly, "raw data" means that any references TO the new
|
||||
object are treated like other references to unmanaged memory.
|
||||
[.belief.refs-to-uninit-safe:
|
||||
We're 'sure', but I need to check this. What does Fix
|
||||
actually do with a pointer into the init-alloc zone? We
|
||||
hope it ignores it. RHSK 2006-06-09]
|
||||
Because of this, you are permitted to connect the new object
|
||||
into your graph of managed objects immediately. The MPS gives
|
||||
you these guarantees:</p>
|
||||
<ul>
|
||||
<li> the new object is pinned (won't move), so references to it
|
||||
that you write in old objects won't become stale at this time
|
||||
(but see <code>mps_commit</code> below!)</li>
|
||||
<li> although the new object is reachable, the MPS knows it
|
||||
is not yet managed, and will leave it in peace;</li>
|
||||
<li> the MPS will not call the client's format code to answer
|
||||
questions about the new object.</li>
|
||||
</ul>
|
||||
|
||||
<h3>Building the object</h3>
|
||||
|
||||
<p>The client will typically do all these things:</p>
|
||||
<ul>
|
||||
<li> write data to make the new object 'valid' for the client's format;</li>
|
||||
<li> write other data into the new object;</li>
|
||||
<li> write references (to existing objects) into the new object;</li>
|
||||
<li> write a reference TO the new object into an existing object
|
||||
-- this connects the new object into the client's graph of
|
||||
managed objects;</li>
|
||||
</ul>
|
||||
|
||||
<p>However, during the build, the client <strong>MUST NOT</strong> read
|
||||
(from the new object) a reference to an existing mobile object --
|
||||
because the reference is unmanaged and may be stale.</p>
|
||||
|
||||
<p>(Actually, the restriction is: the moment a reference to an
|
||||
existing mobile object is written into the new object, that
|
||||
reference (in the new object) may become stale. And you'd better
|
||||
not use (dereference) a stale reference. And you'd better not
|
||||
write it into any existing object. Writing it back into another
|
||||
part of the new object is okay. Just don't trust it to be a valid
|
||||
reference.)</p>
|
||||
|
||||
<h3>mps_commit</h3>
|
||||
|
||||
<p>When you call <code>mps_commit</code>, it will either fail or succeed.</p>
|
||||
|
||||
<p>Almost always, <code>mps_commit</code> succeeds.
|
||||
If it succeeds, that means: </p>
|
||||
<ul>
|
||||
<li> the new object is now just a normal object like any other;</li>
|
||||
<li> all the references written IN the new object are valid (in
|
||||
other words, a successful commit is the MPS's way of telling
|
||||
you that they did not become stale while they were sitting
|
||||
unmanaged in the new object);</li>
|
||||
<li> all the references TO the new object are valid.</li>
|
||||
</ul>
|
||||
|
||||
<p>Occasionally but rarely, <code>mps_commit</code> fails.
|
||||
This means that the new object no longer exists.
|
||||
The memory may even be unmapped by the time
|
||||
<code>mps_commit</code> returns.</p>
|
||||
|
||||
<p>When this happens the client should take care to clear up any
|
||||
managed references to the (now vanished) new object.</p>
|
||||
|
||||
<p>[But there's a hole here, before the client does this.
|
||||
Are managed (aka scanned) references TO
|
||||
it still safe? They were safe during building
|
||||
(by .belief.refs-to-uninit-safe). But now the AP pointers have
|
||||
gone away. Are they still safe?
|
||||
Clearly, if they are only RankAMBIG, they are safe.
|
||||
What if they are RankEXACT?
|
||||
RHSK 2006-06-09]</p>
|
||||
|
||||
<p>[Discussion with RB 2006-06-09: yes, that's a problem for exact
|
||||
references. Must not make any exact refs to a new object. And
|
||||
unmanaged refs are not sufficient, because they won't preserve the
|
||||
new object during commit. So must make at least one ambiguous
|
||||
ref to new object before calling commit. That's the truth
|
||||
currently. There are various ways to solve this to allow
|
||||
purely-exact mutators. For instance,
|
||||
keep the old init..alloc address-space flagged as a zombie zone,
|
||||
until some communication with mutator (perhaps another reserve
|
||||
from same AP?) indicates that mutator has removed all those
|
||||
pesky exact refs to the now-dead ex-new object. RHSK 2006-06-09]</p>
|
||||
|
||||
<p>The client will also have to re-create the object. For this
|
||||
reason the standard allocation point idiom is:</p>
|
||||
|
||||
<pre><code>
|
||||
do {
|
||||
if (mps_reserve != MPS_RES_OK) {
|
||||
goto fail_nomemory;
|
||||
}
|
||||
/* initialize my new object */
|
||||
/* make an ambiguous reference to new object */
|
||||
} while (! mps_commit);
|
||||
/* link new object into my object graph */
|
||||
</code></pre>
|
||||
|
||||
|
||||
<h2><a id="section-B" name="section-B">B. Document History</a></h2>
|
||||
|
||||
<pre>
|
||||
2006-06-02 RHSK Created.
|
||||
2006-06-02 RHSK Introduction to MPS Formats
|
||||
2006-06-06 RHSK Formats: clarify explanation of methods, copy method is obsolete, mention format variants.
|
||||
2006-06-09 RHSK Allocation points: how it's supposed to be, from RB 2006-06-09.
|
||||
2006-06-09 RHSK Allocation points: must make at least one ambiguous ref and no exact refs to new object before calling commit.
|
||||
</pre>
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue