/*
* Copyright 2009-2010 MBTE Sweden AB.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mbte.groovypp.compiler;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.FieldNode;
import org.codehaus.groovy.ast.ClassHelper;
import org.codehaus.groovy.ast.expr.StaticMethodCallExpression;
import org.codehaus.groovy.ast.expr.ArgumentListExpression;
import org.codehaus.groovy.ast.expr.ClassExpression;
import org.codehaus.groovy.ast.expr.ConstantExpression;
import org.objectweb.asm.Opcodes;
import java.util.List;
import java.util.LinkedList;
public class VolatileFieldUpdaterTransform {
public static void addUpdaterForVolatileFields(ClassNode classNode) {
List<FieldNode> toAdd = null;
for (FieldNode fieldNode : classNode.getFields()) {
if((fieldNode.getModifiers() & Opcodes.ACC_VOLATILE) != 0) {
final String fieldName = fieldNode.getName() + "$updater";
if(classNode.getDeclaredField(fieldName) != null)
continue;
if (fieldNode.getType().equals(ClassHelper.int_TYPE)) {
ClassNode type = TypeUtil.withGenericTypes(TypeUtil.ATOMIC_INTEGER_FIELD_UPDATER, classNode);
FieldNode newField = new FieldNode(fieldName, Opcodes.ACC_PUBLIC| Opcodes.ACC_STATIC| Opcodes.ACC_FINAL, type, classNode, null);
newField.setInitialValueExpression(
new StaticMethodCallExpression(
TypeUtil.ATOMIC_INTEGER_FIELD_UPDATER,
"newUpdater",
new ArgumentListExpression(
new ClassExpression(classNode),
new ConstantExpression(fieldNode.getName())
)
)
);
if (toAdd == null)
toAdd = new LinkedList<FieldNode>();
toAdd.add(newField);
continue;
}
if (fieldNode.getType().equals(ClassHelper.long_TYPE)) {
ClassNode type = TypeUtil.withGenericTypes(TypeUtil.ATOMIC_LONG_FIELD_UPDATER, classNode);
FieldNode newField = new FieldNode(fieldName, Opcodes.ACC_PUBLIC| Opcodes.ACC_STATIC| Opcodes.ACC_FINAL, type, classNode, null);
newField.setInitialValueExpression(
new StaticMethodCallExpression(
TypeUtil.ATOMIC_LONG_FIELD_UPDATER,
"newUpdater",
new ArgumentListExpression(
new ClassExpression(classNode),
new ConstantExpression(fieldNode.getName())
)
)
);
if (toAdd == null)
toAdd = new LinkedList<FieldNode> ();
toAdd.add(newField);
continue;
}
if (!ClassHelper.isPrimitiveType(fieldNode.getType())) {
ClassNode type = TypeUtil.withGenericTypes(TypeUtil.ATOMIC_REFERENCE_FIELD_UPDATER, classNode, fieldNode.getType());
FieldNode newField = new FieldNode(fieldName, Opcodes.ACC_PUBLIC| Opcodes.ACC_STATIC| Opcodes.ACC_FINAL, type, classNode, null);
newField.setInitialValueExpression(
new StaticMethodCallExpression(
TypeUtil.ATOMIC_REFERENCE_FIELD_UPDATER,
"newUpdater",
new ArgumentListExpression(
new ClassExpression(classNode),
new ClassExpression(fieldNode.getType().redirect()),
new ConstantExpression(fieldNode.getName())
)
)
);
if (toAdd == null)
toAdd = new LinkedList<FieldNode> ();
toAdd.add(newField);
}
}
}
if (toAdd != null)
for (FieldNode fieldNode : toAdd) {
classNode.addField(fieldNode);
}
}
}