mirror of
https://gitlab.gnome.org/GNOME/libxslt
synced 2025-08-08 21:42:07 +03:00
Rewrite memory management of local RVTs
The psvi slot of RVTs documents is used to store ownership information. XSLT_RVT_LOCAL for RVTs that are destroyed after the current instructions ends. XSLT_RVT_VARIABLE for RVTs that are part of a local variable and are destroyed after the variable goes out of scope. XSLT_RVT_FUNC_RESULT for RVTs that are part of results returned with func:result. These RVTs won't be destroyed after exiting a template and will be reset to XSLT_RVT_LOCAL or XSLT_RVT_VARIABLE in the template that receives the return value. XSLT_RVT_GLOBAL for RVTs that are part of a global variable. The function xsltFlagRVTs is used for the following ownership transitions: - LOCAL or VARIABLE to FUNC_RESULT when returning a value with func:result. - FUNC_RESULT to LOCAL or VARIABLE when receiving a func:result. - LOCAL to GLOBAL after evaluating global variables or parameters. This obsoletes the element localRVTBase in the context struct and the xsltExtensionInstructionResultRegister function. Aside from the func:result implementation, the only reason for the old mechanism was to protect RVTs (which can only be returned from extension functions) in global variables from being destroyed too early. This is done automatically now, so there's no need for extension authors to call this function anymore. The function xsltExtensionInstructionResultFinalize is unsupported now. To the best of my knowledge, it isn't used outside of libxslt. Another benefit is that, in some cases, RVTs are freed earlier now. Also fixes bug #602531.
This commit is contained in:
@@ -35,7 +35,6 @@ struct _exsltFuncData {
|
||||
xmlHashTablePtr funcs; /* pointer to the stylesheet module data */
|
||||
xmlXPathObjectPtr result; /* returned by func:result */
|
||||
int error; /* did an error occur? */
|
||||
xmlDocPtr RVT; /* result tree fragment */
|
||||
};
|
||||
|
||||
typedef struct _exsltFuncResultPreComp exsltFuncResultPreComp;
|
||||
@@ -428,6 +427,12 @@ exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
|
||||
|
||||
if (data->result != NULL) {
|
||||
ret = data->result;
|
||||
/*
|
||||
* IMPORTANT: This enables previously tree fragments marked as
|
||||
* being results of a function, to be garbage-collected after
|
||||
* the calling process exits.
|
||||
*/
|
||||
xsltFlagRVTs(tctxt, ret, XSLT_RVT_LOCAL);
|
||||
} else
|
||||
ret = xmlXPathNewCString("");
|
||||
|
||||
@@ -452,12 +457,6 @@ exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
|
||||
valuePush(ctxt, ret);
|
||||
|
||||
error:
|
||||
/*
|
||||
* IMPORTANT: This enables previously tree fragments marked as
|
||||
* being results of a function, to be garbage-collected after
|
||||
* the calling process exits.
|
||||
*/
|
||||
xsltExtensionInstructionResultFinalize(tctxt);
|
||||
tctxt->funcLevel--;
|
||||
}
|
||||
|
||||
@@ -724,7 +723,7 @@ exsltFuncResultElem (xsltTransformContextPtr ctxt,
|
||||
* Mark it as a function result in order to avoid garbage
|
||||
* collecting of tree fragments before the function exits.
|
||||
*/
|
||||
xsltExtensionInstructionResultRegister(ctxt, ret);
|
||||
xsltFlagRVTs(ctxt, ret, XSLT_RVT_FUNC_RESULT);
|
||||
} else if (inst->children != NULL) {
|
||||
/* If the func:result element does not have a select attribute
|
||||
* and has non-empty content (i.e. the func:result element has
|
||||
@@ -741,7 +740,8 @@ exsltFuncResultElem (xsltTransformContextPtr ctxt,
|
||||
data->error = 1;
|
||||
return;
|
||||
}
|
||||
xsltRegisterLocalRVT(ctxt, container);
|
||||
/* Mark as function result. */
|
||||
container->psvi = XSLT_RVT_FUNC_RESULT;
|
||||
|
||||
oldInsert = ctxt->insert;
|
||||
ctxt->insert = (xmlNodePtr) container;
|
||||
@@ -756,11 +756,6 @@ exsltFuncResultElem (xsltTransformContextPtr ctxt,
|
||||
data->error = 1;
|
||||
} else {
|
||||
ret->boolval = 0; /* Freeing is not handled there anymore */
|
||||
/*
|
||||
* Mark it as a function result in order to avoid garbage
|
||||
* collecting of tree fragments before the function exits.
|
||||
*/
|
||||
xsltExtensionInstructionResultRegister(ctxt, ret);
|
||||
}
|
||||
} else {
|
||||
/* If the func:result element has empty content and does not
|
||||
|
Reference in New Issue
Block a user