Skip to content
Snippets Groups Projects
Commit 1a9023b7 authored by Jesper's avatar Jesper
Browse files

Fix race conditions for grammar-declared NTAs

fixes #291 (bitbucket)
fixes #292 (bitbucket)
parent 53c693bd
No related branches found
No related tags found
No related merge requests found
2018-04-04 Jesper Öqvist <jesper.oqvist@cs.lth.se> 2018-04-04 Jesper Öqvist <jesper.oqvist@cs.lth.se>
* Fixed aliasing issue for parameterized NTAs in concurrent mode. * Fixed aliasing issue for parameterized NTAs in concurrent mode.
* Fixed race conditions for grammar-declared NTAs in concurrent mode.
See issue 291 and 292 on the issue tracker.
* Grammar-declared NTAs have been moved out of the child vector in
concurrent mode.
* Added a new internal helper method to ASTNode:
getChildNoTransformBase().
2018-03-22 Jesper Öqvist <jesper.oqvist@cs.lth.se> 2018-03-22 Jesper Öqvist <jesper.oqvist@cs.lth.se>
......
...@@ -105,6 +105,43 @@ aspect JaddCodeGen { ...@@ -105,6 +105,43 @@ aspect JaddCodeGen {
return i; return i;
} }
public void ASTDecl.emitConcurrentGetChild(PrintWriter out) {
// Build list of NTA indices.
String getNta = "";
int numNta = 0;
int i = 0;
for (Component c : components()) {
if (c instanceof TokenComponent) {
// Tokens are not stored in the child array.
continue;
}
String attrName = null;
if (c instanceof ListComponentNTA) {
attrName = "get" + c.name() + "List";
} else if (c instanceof OptionalComponentNTA) {
attrName = "get" + c.name() + "Opt";
} else if (c instanceof AggregateComponentNTA) {
attrName = "get" + c.name();
}
if (attrName != null) {
getNta += "case " + i + ":\n";
getNta += " _value = " + attrName + "_value.get();\n";
getNta += " break;\n";
numNta += 1;
}
i += 1;
}
TemplateContext tt = templateContext();
if (numNta > 0) {
tt.bind("GetNTAs", getNta);
tt.expand("ASTDecl.getChildNoTransform:concurrent", out);
} else {
tt.expand("ASTDecl.getChildNoTransform:concurrent:empty", out);
}
}
/** /**
* Default constructor: creates list and opt nodes for * Default constructor: creates list and opt nodes for
* all list and opt children. Initializes NTAs. * all list and opt children. Initializes NTAs.
...@@ -558,6 +595,14 @@ aspect JaddCodeGen { ...@@ -558,6 +595,14 @@ aspect JaddCodeGen {
emitCopyNode(out); emitCopyNode(out);
emitFullCopy(out); emitFullCopy(out);
emitIsEqualMethods(out); emitIsEqualMethods(out);
if (config().concurrentEval()
&& !isASTNodeDecl()
&& !isOptDecl()
&& !isListDecl()) {
emitConcurrentGetChild(out);
}
genIncremental(out); genIncremental(out);
} }
......
...@@ -731,7 +731,8 @@ aspect JragCodeGen { ...@@ -731,7 +731,8 @@ aspect JragCodeGen {
|| attrName.equals(comp.name() + "Opt") && comp instanceof OptionalComponentNTA || attrName.equals(comp.name() + "Opt") && comp instanceof OptionalComponentNTA
|| attrName.equals(comp.name() + "List") && comp instanceof ListComponentNTA) { || attrName.equals(comp.name() + "List") && comp instanceof ListComponentNTA) {
if (config().concurrentEval()) { if (config().concurrentEval()) {
return "setChild(_result, get" + attrName + "ChildPosition());\n"; // Only link result with parent. Child vector is not used for NTAs in concurrent mode.
return "_result.setParent(this);\n";
} else { } else {
return "setChild(" + signature() + "_value, get" + attrName + "ChildPosition());\n"; return "setChild(" + signature() + "_value, get" + attrName + "ChildPosition());\n";
} }
......
...@@ -495,15 +495,18 @@ $endif ...@@ -495,15 +495,18 @@ $endif
ASTNode.getChildNoTransform [[ ASTNode.getChildNoTransform [[
/** /**
* <p><em>This method does not invoke AST transformations.</em></p> * Gets a child without triggering rewrites.
* @apilevel low-level * @apilevel low-level
*/ */
$if(IncrementalEnabled)
public T $ASTNode.getChildNoTransform(int i) { public T $ASTNode.getChildNoTransform(int i) {
// Must be able to override get child methods for incremental evaluation return getChildNoTransformBase(i);
$else }
public final T $ASTNode.getChildNoTransform(int i) {
$endif /**
* Directly accesses the child vector.
* @apilevel internal
*/
public T $ASTNode.getChildNoTransformBase(int i) {
if (children == null) { if (children == null) {
return null; return null;
} }
......
# Copyright (c) 2013-2017, The JastAdd Team # Copyright (c) 2013-2018, The JastAdd Team
# All rights reserved. # All rights reserved.
# #
# Redistribution and use in source and binary forms, with or without # Redistribution and use in source and binary forms, with or without
...@@ -209,8 +209,17 @@ if (#(signature)_computed) { ...@@ -209,8 +209,17 @@ if (#(signature)_computed) {
$else $else
Object cached_value = #(signature)_value.get(); Object cached_value = #(signature)_value.get();
if (cached_value != AttributeValue.NONE) { if (cached_value != AttributeValue.NONE) {
#boxedType _value = (#boxedType) cached_value;
$include(AttrDecl.traceCacheRead) $include(AttrDecl.traceCacheRead)
#boxedType _value = (#boxedType) cached_value;
$if(#isAttrNTA)$if(RewriteEnabled)
if (_value != null && _value.mayHaveRewrite()) {
$ASTNode rewritten = _value.rewrittenNode();
if (rewritten != _value) {
rewritten.setParent(this);
_value = (#boxedType) rewritten;
}
}
$endif$endif
return _value; return _value;
$endif $endif
$endif $endif
...@@ -339,3 +348,24 @@ if (state.inCircle()) { ...@@ -339,3 +348,24 @@ if (state.inCircle()) {
$endif $endif
$endif $endif
]] ]]
# Delegates child lookups to corresponding higher-order attributes.
ASTDecl.getChildNoTransform:concurrent [[
public $ASTNode #name.getChildNoTransform(int i) {
Object _value = AttributeValue.NONE;
switch (i) {
$GetNTAs
}
if (_value != AttributeValue.NONE) {
return ($ASTNode) _value;
}
return super.getChildNoTransformBase(i);
}
]]
ASTDecl.getChildNoTransform:concurrent:empty [[
public $ASTNode #name.getChildNoTransform(int i) {
return super.getChildNoTransformBase(i);
}
]]
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment