Just let you know that this patch has been merged into the 2.3.x branch (which will be 2.3.24). Thanks for the contribution!
Afterwards I did some refactoring in the long existing architecture to get rid of some unnecessary complexity (which I have noticed during reviewing this patch), and thus I was able to replace TemplateElementsToVisit with a simple TemplateElement[], also those TemplateElement[] are now created during parsing, not for each executions of the elements. -- Thanks, Daniel Dekany Wednesday, October 14, 2015, 9:18:01 PM, Daniel Dekany wrote: > Thanks, I will review it more closely as soon as I get to it... like > there's a slight hope that it will happen this weekend. > > Others, please look at this patch and tell your opinions, if you find > the time! As of me, I have finally decided to let this change in > (unless I will find some new issue I haven't realized yet). > > > Wednesday, October 14, 2015, 2:35:40 PM, Kleine, Moritz wrote: > >> Hi, here¹s the 2.3-gae pull request >> https://github.com/apache/incubator-freemarker/pull/6 >> Regards, >> Moritz >> >> On 9/11/15, 7:49 PM, "Daniel Dekany" <[email protected]> wrote: >> >>>It surely consumes less stack this way, though stack usage doesn't >>>used to be an concern (barring FTL sequence concatenations in a loop, >>>but that's another topic). While less stack is just better regardless, >>>with this change the code becomes a bit more convoluted (especially if >>>you had to do something after the child elements ran; though if I saw >>>well, surprisingly, we don't have such case so far). So I would like >>>to understand why does your application need so deep stack. I would >>>think that you had to have some ridiculously high number of things >>>nested into each other to run into this, but maybe I'm wrong. >>> >>> >>>Thursday, September 10, 2015, 3:53:13 PM, Kleine, Moritz wrote: >>> >>>> Hi, >>>> >>>> we¹re building a website using a view-agnostic document store and a >>>> spring-based webapp that is capable of rendering views for documents >>>> that include views of linked documents. The views are typically >>>> small freemarker templates (at most some tenths of lines) using a >>>> custom include directive that determines the view for the included >>>> document and if it is a freemarker template ‹ tells that template to >>>>process itself. >>>> >>>> Now, we¹re frequently running into stackoverflowerrors which >>>> exhibit the level of inclusion and the whole structure of the >>>> freemarker templates from the root of up to the custom include. The >>>> stacktrace fragment shown below ([1]) is taken from such a >>>> stackoverflowerror. I¹d suggest to adjust the visitor pattern based >>>> implementation so that the accept calls do not invoke >>>> Environment#visit again but return the tempate elements to be >>>> visited. That way we obtain stacktraces that look as shown further >>>> down below ([2]). The patched code resides here: >>>> >>>>https://github.com/mkleine/incubator-freemarker/tree/avoid-too-much-recur >>>>sion-when-visiting-template-elements >>>> >>>> Are we misusing freemarker or is the approach to reduction of >>>>stackframes welcome? >>>> >>>> Kind regards, >>>> Moritz >>>> >>>> >>>> [1] >>>> at >>>> freemarker.ext.beans.BeansWrapper.invokeMethod(BeansWrapper.java:1458) >>>>[freemarker-2.3.22.jar:2.3.22] >>>> at >>>> freemarker.ext.beans.SimpleMethodModel.exec(SimpleMethodModel.java:71) >>>>[freemarker-2.3.22.jar:2.3.22] >>>> at freemarker.core.MethodCall._eval(MethodCall.java:62) >>>>[freemarker-2.3.22.jar:2.3.22] >>>> at freemarker.core.Expression.eval(Expression.java:78) >>>>[freemarker-2.3.22.jar:2.3.22] >>>> at >>>> freemarker.core.Expression.evalAndCoerceToString(Expression.java:82) >>>>[freemarker-2.3.22.jar:2.3.22] >>>> at >>>> freemarker.core.BuiltInForString._eval(BuiltInForString.java:26) >>>>[freemarker-2.3.22.jar:2.3.22] >>>> at freemarker.core.Expression.eval(Expression.java:78) >>>>[freemarker-2.3.22.jar:2.3.22] >>>> at >>>> freemarker.core.Expression.evalAndCoerceToString(Expression.java:82) >>>>[freemarker-2.3.22.jar:2.3.22] >>>> at >>>> freemarker.core.DollarVariable.accept(DollarVariable.java:40) >>>>[freemarker-2.3.22.jar:2.3.22] >>>> at freemarker.core.Environment.visit(Environment.java:312) >>>>[freemarker-2.3.22.jar:2.3.22] >>>> at >>>> freemarker.core.MixedContent.accept(MixedContent.java:62) >>>>[freemarker-2.3.22.jar:2.3.22] >>>> at >>>> freemarker.core.Environment.visitByHiddingParent(Environment.java:333) >>>>[freemarker-2.3.22.jar:2.3.22] >>>> at >>>> freemarker.core.ConditionalBlock.accept(ConditionalBlock.java:48) >>>>[freemarker-2.3.22.jar:2.3.22] >>>> at >>>> freemarker.core.Environment.visitByHiddingParent(Environment.java:333) >>>>[freemarker-2.3.22.jar:2.3.22] >>>> at >>>> freemarker.core.Environment.visitAndTransform(Environment.java:413) >>>>[freemarker-2.3.22.jar:2.3.22] >>>> at >>>> freemarker.core.CompressedBlock.accept(CompressedBlock.java:37) >>>>[freemarker-2.3.22.jar:2.3.22] >>>> at freemarker.core.Environment.visit(Environment.java:312) >>>>[freemarker-2.3.22.jar:2.3.22] >>>> at freemarker.core.Macro$Context.runMacro(Macro.java:178) >>>>[freemarker-2.3.22.jar:2.3.22] >>>> at freemarker.core.Environment.invoke(Environment.java:700) >>>>[freemarker-2.3.22.jar:2.3.22] >>>> at freemarker.core.UnifiedCall.accept(UnifiedCall.java:84) >>>>[freemarker-2.3.22.jar:2.3.22] >>>> at >>>> freemarker.core.Environment.visitByHiddingParent(Environment.java:333) >>>>[freemarker-2.3.22.jar:2.3.22] >>>> at >>>> freemarker.core.IteratorBlock$Context.runLoop(IteratorBlock.java:148) >>>>[freemarker-2.3.22.jar:2.3.22] >>>> at >>>> freemarker.core.Environment.visitIteratorBlock(Environment.java:559) >>>>[freemarker-2.3.22.jar:2.3.22] >>>> at >>>> freemarker.core.IteratorBlock.accept(IteratorBlock.java:67) >>>>[freemarker-2.3.22.jar:2.3.22] >>>> at freemarker.core.Environment.visit(Environment.java:312) >>>>[freemarker-2.3.22.jar:2.3.22] >>>> at >>>> freemarker.core.MixedContent.accept(MixedContent.java:62) >>>>[freemarker-2.3.22.jar:2.3.22] >>>> at >>>> freemarker.core.Environment.visitByHiddingParent(Environment.java:333) >>>>[freemarker-2.3.22.jar:2.3.22] >>>> at >>>> freemarker.core.ConditionalBlock.accept(ConditionalBlock.java:48) >>>>[freemarker-2.3.22.jar:2.3.22] >>>> at >>>> freemarker.core.Environment.visitByHiddingParent(Environment.java:333) >>>>[freemarker-2.3.22.jar:2.3.22] >>>> at >>>> freemarker.core.ConditionalBlock.accept(ConditionalBlock.java:48) >>>>[freemarker-2.3.22.jar:2.3.22] >>>> at freemarker.core.Environment.visit(Environment.java:312) >>>>[freemarker-2.3.22.jar:2.3.22] >>>> at >>>> freemarker.core.MixedContent.accept(MixedContent.java:62) >>>>[freemarker-2.3.22.jar:2.3.22] >>>> at freemarker.core.Environment.visit(Environment.java:312) >>>>[freemarker-2.3.22.jar:2.3.22] >>>> at freemarker.core.EscapeBlock.accept(EscapeBlock.java:48) >>>>[freemarker-2.3.22.jar:2.3.22] >>>> at freemarker.core.Environment.visit(Environment.java:312) >>>>[freemarker-2.3.22.jar:2.3.22] >>>> at >>>> freemarker.core.Environment.process(Environment.java:290) >>>>[freemarker-2.3.22.jar:2.3.22] >>>> at freemarker.template.Template.process(Template.java:312) >>>>[freemarker-2.3.22.jar:2.3.22] >>>> >>>> [2] >>>> >>>> at >>>> freemarker.ext.beans.BeansWrapper.invokeMethod(BeansWrapper.java:1458) >>>> at >>>> freemarker.ext.beans.SimpleMethodModel.exec(SimpleMethodModel.java:71) >>>> at freemarker.core.MethodCall._eval(MethodCall.java:62) >>>> at freemarker.core.Expression.eval(Expression.java:78) >>>> at freemarker.core.ReturnInstruction.accept(ReturnInstruction.java:35) >>>> at freemarker.core.Environment.visit(Environment.java:336) >>>> at freemarker.core.Macro$Context.runMacro(Macro.java:186) >>>> at freemarker.core.Environment.invoke(Environment.java:705) >>>> at freemarker.core.MethodCall._eval(MethodCall.java:74) >>>> at freemarker.core.Expression.eval(Expression.java:78) >>>> at >>>> freemarker.core.Expression.evalAndCoerceToString(Expression.java:82) >>>> at freemarker.core.DollarVariable.accept(DollarVariable.java:41) >>>> at freemarker.core.Environment.visit(Environment.java:336) >>>> at freemarker.core.Environment.visit(Environment.java:341) >>>> at >>>> freemarker.core.Environment.renderElementToString(Environment.java:2200) >>>> at >>>> >>>>freemarker.core.StringLiteral.evalAndCoerceToString(StringLiteral.java:96 >>>>) >>>> at freemarker.core.StringLiteral._eval(StringLiteral.java:73) >>>> at freemarker.core.Expression.eval(Expression.java:78) >>>> at >>>> >>>>freemarker.core.Environment.setMacroContextLocalsFromArguments(Environmen >>>>t.java:743) >>>> at freemarker.core.Environment.invoke(Environment.java:693) >>>> at freemarker.core.UnifiedCall.accept(UnifiedCall.java:85) >>>> at freemarker.core.Environment.visit(Environment.java:336) >>>> at freemarker.core.Environment.visit(Environment.java:341) >>>> at freemarker.core.Environment.visit(Environment.java:341) >>>> at freemarker.core.Environment.process(Environment.java:302) >>>> at freemarker.template.Template.process(Template.java:325) >>> >>>-- >>>Thanks, >>> Daniel Dekany >>> >> >> > --- This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus
