Skip to content
Snippets Groups Projects
Commit 62d28e6f authored by Jesper's avatar Jesper
Browse files

Safe caching of non-circular attributes

Added --safeLazy option which enables safe in-cycle caching of non-circular
attributes.
parent eb487dcd
No related branches found
No related tags found
No related merge requests found
2016-03-21 Jesper Öqvist <jesper.oqvist@cs.lth.se>
* Added --safeLazy option which allows non-circular attributes to be
safely cached during circular evaluation, even if the attribute is
effectively circular. The --safeLazy option adds an extra cache field for
each attributes which tracks the last cycle on which the attribute was
evaluated. The next time the attribute is accessed it checks if it can
reuse the last cached value based on the current cycle state and the last
cached cycle state.
2016-03-16 Jesper Öqvist <jesper.oqvist@cs.lth.se>
* Improved circular NTA rewrite implementation: implicit rewrite
......
......@@ -226,6 +226,10 @@ aspect JragCodeGen {
sb.append(String.format("if (%s_visited == null) %s_visited = %s;\n",
signature(), signature(), config().createDefaultSet()));
}
if (getNumParameter() != 0 && isLazy() && !simpleCacheCheck()) {
sb.append(String.format("if (%s_computed == null) %s_computed = %s;\n",
signature(), signature(), config().createDefaultMap()));
}
}
if (getNumParameter() != 0 && (isLazy() || isCircular())) {
sb.append(String.format("if (%s_values == null) %s_values = %s;\n",
......@@ -791,4 +795,9 @@ aspect Compute {
eq CollDecl.circularComputeRhs() = String.format("combine_%s_contributions(%s)",
signature(), getBottomValue());
syn boolean AttrDecl.simpleCacheCheck() =
config().safeLazy()
? (isCircular() || declaredNTA() || isAttrNTA())
: true;
}
......@@ -381,6 +381,10 @@ public class Configuration {
Option<Boolean> dotOption = new FlagOption("dot", "generate a Dot graph from the grammar")
.nonStandard();
Option<Boolean> safeLazyOption = new FlagOption("safeLazy",
"safe in-cycle caching of non-circular attributes")
.nonStandard();
Collection<String> filenames = new LinkedList<String>();
/**
......@@ -458,6 +462,9 @@ public class Configuration {
// New since 2.1.12.
allOptions.add(stateClassNameOption);
// New since 2.2.1:
allOptions.add(safeLazyOption);
// Deprecated in 2.1.5.
allOptions.add(doxygenOption);
allOptions.add(cacheAllOption);
......@@ -1264,4 +1271,11 @@ public class Configuration {
public boolean generateImplicits() {
return generateImplicitsOption.value();
}
/**
* @return {@code true} if safe lazy attribute caching in circular evaluation should be used.
*/
public boolean safeLazy() {
return safeLazyOption.value();
}
}
......@@ -274,6 +274,14 @@ public class JastAddTask extends Task {
setOption(config.minListSizeOption, arg);
}
public void setDot(boolean enable) {
setOption(config.dotOption, enable);
}
public void setSafeLazy(boolean enable) {
setOption(config.safeLazyOption, enable);
}
@Override
public void execute() throws BuildException {
System.err.println("generating node types and weaving aspects");
......
......@@ -199,8 +199,9 @@ $if(DebugMode)
while (node != null && !node.debugNodeAttachmentIsRoot()) {
$if(LegacyRewrite)
if (node.in$$Circle())
if (node.in$$Circle()) {
return;
}
$endif
$ASTNode parent = ($ASTNode) node.parent;
if (parent != null && parent.getIndexOfChild(node) == -1) {
......
......@@ -41,7 +41,11 @@ $endif
AttrDecl.cacheDeclarations [[
$if(!#isParameterized)
/** @apilevel internal */
$if(#simpleCacheCheck)
protected boolean #(signature)_computed = false;
$else
protected $StateClass.Cycle #(signature)_computed = null;
$endif
/** @apilevel internal */
protected #getType #(signature)_value;
......@@ -61,9 +65,14 @@ $else
/** @apilevel internal */
protected $DefaultMapType #(signature)_values = $CreateDefaultMap;
$endif
$if(!#simpleCacheCheck)
/** @apilevel internal */
protected $DefaultMapType #(signature)_computed;
$endif
$endif
]]
# Method headers for attribute declarations.
AttrDecl.synDecl = AttrDecl.inhDecl [[
#docComment
#annotations
......@@ -291,7 +300,11 @@ AttrDecl.cacheCheck [[
$if(#hasCache)
$include(AttrDecl.incHookAttrRead)
$if(!#isParameterized)
$if(#simpleCacheCheck)
if (#(signature)_computed) {
$else
if (#(signature)_computed == $StateClass.NON_CYCLE || #(signature)_computed == state().cycle()) {
$endif
$include(AttrDecl.traceCacheRead)
$if(#isAttrNTA)
return (#boxedType) getChild(#(signature)ChildPosition());
......@@ -300,7 +313,13 @@ if (#(signature)_computed) {
$endif
}
$else
$if(#simpleCacheCheck)
if (#(signature)_values.containsKey(_parameters)) {
$else
if (#(signature)_values.containsKey(_parameters) && #(signature)_computed != null
&& #(signature)_computed.containsKey(_parameters)
&& (#(signature)_computed.get(_parameters) == $StateClass.NON_CYCLE || #(signature)_computed.get(_parameters) == state().cycle())) {
$endif
$include(AttrDecl.traceCacheRead)
$if(#isAttrNTA)
return (#boxedType) getChild(#(signature)ChildPosition()));
......@@ -318,6 +337,7 @@ $if(#isLazy)
$if(LegacyRewrite)
if (#cacheStoreCondition) {
$endif
$if(#simpleCacheCheck)
$if(#isParameterized)
$include(AttrDecl.incHookAttrCompBeforeStore)
#(signature)_values.put(_parameters, #(signature)_value);
......@@ -327,6 +347,31 @@ if (#cacheStoreCondition) {
#(signature)_computed = true;
$include(AttrDecl.traceCacheStore)
$endif
$else
if (state().inCircle()) {
$if(#isParameterized)
$include(AttrDecl.incHookAttrCompBeforeStore)
#(signature)_values.put(_parameters, #(signature)_value);
#(signature)_computed.put(_parameters, state().cycle());
$include(AttrDecl.traceCacheStore)
$else
$include(AttrDecl.incHookAttrCompBeforeStore)
#(signature)_computed = state().cycle();
$include(AttrDecl.traceCacheStore)
$endif
} else {
$if(#isParameterized)
$include(AttrDecl.incHookAttrCompBeforeStore)
#(signature)_values.put(_parameters, #(signature)_value);
#(signature)_computed.put(_parameters, $StateClass.NON_CYCLE);
$include(AttrDecl.traceCacheStore)
$else
$include(AttrDecl.incHookAttrCompBeforeStore)
#(signature)_computed = $StateClass.NON_CYCLE;
$include(AttrDecl.traceCacheStore)
$endif
}
$endif
$if(LegacyRewrite)
} else {
$include(AttrDecl.traceCacheAbort)
......@@ -363,9 +408,11 @@ state().assertSameCircle(#(signature)_circle, "#hostClassName.#signatureJavaStyl
state().enterLazyAttribute();
$else
$if(#isLazy)
$if(#simpleCacheCheck)
state().enterLazyAttribute();
$endif
$endif
$endif
]]
AttrDecl.leaveLazyAttribute [[
......@@ -373,7 +420,9 @@ $if(ComponentCheck)
state().leaveLazyAttribute();
$else
$if(#isLazy)
$if(#simpleCacheCheck)
state().leaveLazyAttribute();
$endif
$endif
$endif
]]
......@@ -41,6 +41,9 @@ public class $StateClass {
protected static class Cycle {
}
/** The cycle ID used outside of circular evaluation. */
public static final Cycle NON_CYCLE = new Cycle();
/**
* Tracks the state of the current circular evaluation. This class defines a
* stack structure where the next element on the stack is pointed to by the
......@@ -67,7 +70,7 @@ $if(ComponentCheck)
$endif
/** Cycle ID of the latest cycle in this circular evaluation. */
Cycle cycle = null;
Cycle cycle = NON_CYCLE;
protected CircleState(CircleState next) {
this.next = next;
......
......@@ -128,6 +128,9 @@ $endif
AttrDecl.resetAttrCache [[
$if(#isLazy)
$if(#isParameterized)
$if(!#simpleCacheCheck)
#(signature)_computed = $CreateDefaultMap;
$endif
$if(LazyMaps)
#(signature)_values = null;
$else
......@@ -137,10 +140,14 @@ $if(#isLazy)
#(signature)_list = null;
$endif
$else
$if(#simpleCacheCheck)
#(signature)_computed = false;
$if(#isCircular)
#(signature)_initialized = false;
$endif
$else
#(signature)_computed = null;
$endif
$if(!#isPrimitive)
#(signature)_value = null;
$endif
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment