Hi,
> -----Original Message-----
> From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED]
> On Behalf Of Daniel Veillard
> On Mon, Jul 10, 2006 at 05:43:18PM +0200, Buchcik, Kasimier wrote:
> > > I think we could easily change this further to cleanup
> tree fragments,
> > > which were created in/underneath an instruction, directly after an
> > > instruction exits - if this is what you mean. Taking xsl:for-each
> >
> > [...]
> >
> > While implementing the cleanup of temporary tree fragments directly
> > when an instruction exits, I noticed that we'll get problems if
> > trying to do the same for extension elements. With the current
> > implementation of EXSLT's functions, this won't work:
> >
> > <func:function name="foo:foo">
> > <func:result>result</func:result>
> > </func:function>
> >
> > When <func:result> exits, we still need to preserve the
> tree fragment,
> > until <func:function> exits. With xsltRegisterTmpRVT(), there's no
> > way to define the scope of the tree fragment; e.g. one cannot bind
> > it to the <func:function> (e.g. with a unique stamp for a specific
> > instruction/extension element). Since this cannot be undone
> > (xsltRegisterTmpRVT() is probably also used in other extension
> > elements),
> > I'll leave out extension elements from this optimization.
> Maybe we can
> > optimize this also for EXSLT's functions; we'll need an other
> > registration
> > function for this.
>
> Now that you raise it, I remember being really annoyed by
> func:function
> precisely because the RVT outlived the scope of the current
> template, I
> don't remember how I did actually :-)
>
> Daniel
I realized today that the rabbit whole goes deeper than I thought.
This means that you actually did not do it :-)
First: Mark, you are right, the local tree fragments are not
freed until xsl:template leaves. I'm so used to look at my changed
code that I overlooked that in the old code, the fragments are
only freed on the exit of xsltApplyOneTemplate() if @templ is *not*
NULL; and this is only the case when we leave an xsl:template.
The EXSLT function:
The main issue here is that func:function is a function, thus
*returns* a value. This makes any attempts to predict the lifetime
of tree fragments fail.
Example:
<func:function name="my:boo">
<xsl:variable name="var-1">
<var-1/>
</xsl:variable>
<xsl:variable name="var-2">
<var-2/>
</xsl:variable>
<func:result select="common:node-set($var-1)/* |
common:node-set($var-2)/*"/>
</func:function>
Now what happens here?
The nodes of the tree fragments of both local variables are
selected and returned. The current mechanism will
free the tree fragments of the variables before the result is
returned; and consequently free the selected nodes to be returned.
This is a scenario where a non-reference counting machinery
is bound to keep alive _all_ items created inside a function,
since it does not know what is actually returned and still
referenced.
What can we do here?
One could inspect the result generated by func:result: if it's a
node set, then iterate over all nodes and gather all docs of those
nodes which are tree fragments, then register those docs somewhere,
then let the variable-freeing process skip those docs. Not very nice
if the node set is large; but, on the other hand, adding
reference-counting to the XPath machinery for this scenario, is even
worse.
The result would need to be kept alive until the calling function exits.
Example:
<xsl:apply-templates select="common:node-set(my:boo())/*"/>
When xsl:apply-templates is finished, the result can be freed.
A fragment manager could work in the following way:
- Are we inside a function?
If yes, then:
- Was the result was already evaluated? And can
the evaluated result reference local fragments?
Yes if we used the "select" attribute on func:result.
If the result was built using a sequence
constructor then there won't be references.
If yes, then:
- When locally registered fragments
(e.g the value of a variable) are about to be freed,
they need to be checked against the fragments in
use by the result.
Gather a set of all local result free fragments of all
nodes in the result. Do not add global fragments
(values of global vars/params, results of the
document() function, etc.).
If a locally registered fragment is part of the
result, then don't free it.
When the calling process exits, all remaining "function result"
fragments are freed.
Since we would probably break too much user-code, we should leave
the xsltRegisterTmpRVT() mechanism as-is, mark it as obsolete,
and don't use it internally.
Regards,
Kasimier
_______________________________________________
xslt mailing list, project page http://xmlsoft.org/XSLT/
[email protected]
http://mail.gnome.org/mailman/listinfo/xslt