Hi,

The mechanism described below is now implemented in the CVS HEAD.
Hope it's robust enough.
There's now a new xsltRegisterLocalRVT(), which substitutes the
now deprecated xsltRegisterTmpRVT(); the lifetime of the registered
fragment will be restricted to the instruction where the fragment
was created. Changed all code in LibXSLT and LibEXSLT to use
xsltRegisterLocalRVT().

Regards,

Kasimier

> -----Original Message-----
> From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] 
> On Behalf Of Buchcik, Kasimier

> 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
> 
> 
_______________________________________________
xslt mailing list, project page http://xmlsoft.org/XSLT/
[email protected]
http://mail.gnome.org/mailman/listinfo/xslt

Reply via email to