static void visitField(ErrorCollecting xform, AnnotationNode node, FieldNode fieldNode) { final Expression soft = node.getMember("soft"); final Expression init = getInitExpr(xform, fieldNode); String backingFieldName = "$" + fieldNode.getName(); fieldNode.rename(backingFieldName); fieldNode.setModifiers(ACC_PRIVATE | (fieldNode.getModifiers() & (~(ACC_PUBLIC | ACC_PROTECTED)))); PropertyNode pNode = fieldNode.getDeclaringClass().getProperty(backingFieldName); if (pNode != null) { fieldNode.getDeclaringClass().getProperties().remove(pNode); } if (soft instanceof ConstantExpression && ((ConstantExpression) soft).getValue().equals(true)) { createSoft(fieldNode, init); } else { create(fieldNode, init); // @Lazy not meaningful with primitive so convert to wrapper if needed if (ClassHelper.isPrimitiveType(fieldNode.getType())) { fieldNode.setType(ClassHelper.getWrapper(fieldNode.getType())); } } }
private static void createSoft(FieldNode fieldNode, Expression initExpr) { final ClassNode type = fieldNode.getType(); fieldNode.setType(SOFT_REF); createSoftGetter(fieldNode, initExpr, type); createSoftSetter(fieldNode, type); }
private static void create(FieldNode fieldNode, final Expression initExpr) { final BlockStatement body = new BlockStatement(); if (fieldNode.isStatic()) { addHolderClassIdiomBody(body, fieldNode, initExpr); } else if (fieldNode.isVolatile()) { addDoubleCheckedLockingBody(body, fieldNode, initExpr); } else { addNonThreadSafeBody(body, fieldNode, initExpr); } addMethod(fieldNode, body, fieldNode.getType()); }
private static void createSoftGetter(FieldNode fieldNode, Expression initExpr, ClassNode type) { final BlockStatement body = new BlockStatement(); final Expression fieldExpr = varX(fieldNode); final Expression resExpr = varX("res", type); final MethodCallExpression callExpression = callX(fieldExpr, "get"); callExpression.setSafe(true); body.addStatement(declS(resExpr, callExpression)); final Statement mainIf = ifElseS(notNullX(resExpr), stmt(resExpr), block( assignS(resExpr, initExpr), assignS(fieldExpr, ctorX(SOFT_REF, resExpr)), stmt(resExpr))); if (fieldNode.isVolatile()) { body.addStatement(ifElseS( notNullX(resExpr), stmt(resExpr), new SynchronizedStatement(syncTarget(fieldNode), block( assignS(resExpr, callExpression), mainIf) ) )); } else { body.addStatement(mainIf); } addMethod(fieldNode, body, type); }
private void createSoftGetter(FieldNode fieldNode, Expression initExpr, ClassNode type) { final BlockStatement body = new BlockStatement(); final Expression fieldExpr = new VariableExpression(fieldNode); final Expression resExpr = new VariableExpression("res", type); final MethodCallExpression callExpression = new MethodCallExpression(fieldExpr, "get", new ArgumentListExpression()); callExpression.setSafe(true); body.addStatement(declStatement(resExpr, callExpression)); final BlockStatement elseBlock = new BlockStatement(); elseBlock.addStatement(assignStatement(resExpr, initExpr)); elseBlock.addStatement(assignStatement(fieldExpr, new ConstructorCallExpression(SOFT_REF, resExpr))); elseBlock.addStatement(new ExpressionStatement(resExpr)); final Statement mainIf = new IfStatement(notNullExpr(resExpr), new ExpressionStatement(resExpr), elseBlock); if (notVolatile(fieldNode)) { body.addStatement(mainIf); } else { body.addStatement(new IfStatement( notNullExpr(resExpr), new ExpressionStatement(resExpr), new SynchronizedStatement(syncTarget(fieldNode), mainIf) )); } addMethod(fieldNode, body, type); }
private static void addDoubleCheckedLockingBody(BlockStatement body, FieldNode fieldNode, Expression initExpr) { final Expression fieldExpr = varX(fieldNode); final VariableExpression localVar = varX(fieldNode.getName() + "_local"); body.addStatement(declS(localVar, fieldExpr)); body.addStatement(ifElseS( notNullX(localVar), returnS(localVar), new SynchronizedStatement( syncTarget(fieldNode), ifElseS( notNullX(fieldExpr), returnS(fieldExpr), returnS(assignX(fieldExpr, initExpr)) ) ) )); }
private void addDoubleCheckedLockingBody(BlockStatement body, FieldNode fieldNode, Expression initExpr) { final Expression fieldExpr = new VariableExpression(fieldNode); final VariableExpression localVar = new VariableExpression(fieldNode.getName() + "_local"); body.addStatement(declStatement(localVar, fieldExpr)); body.addStatement(new IfStatement( notNullExpr(localVar), new ReturnStatement(localVar), new SynchronizedStatement( syncTarget(fieldNode), new IfStatement( notNullExpr(fieldExpr), new ReturnStatement(fieldExpr), new ReturnStatement(new BinaryExpression(fieldExpr, ASSIGN, initExpr)) ) ) )); }
public void visit(ASTNode[] nodes, SourceUnit source) { if (!(nodes[0] instanceof AnnotationNode) || !(nodes[1] instanceof AnnotatedNode)) { throw new RuntimeException("Internal error: wrong types: $node.class / $parent.class"); } AnnotatedNode parent = (AnnotatedNode) nodes[1]; AnnotationNode node = (AnnotationNode) nodes[0]; if (parent instanceof FieldNode) { FieldNode fieldNode = (FieldNode) parent; final Expression member = node.getMember("soft"); final Expression init = getInitExpr(fieldNode); fieldNode.rename("$" + fieldNode.getName()); fieldNode.setModifiers(ACC_PRIVATE | (fieldNode.getModifiers() & (~(ACC_PUBLIC|ACC_PROTECTED)))); if(member instanceof ConstantExpression && ((ConstantExpression)member).getValue().equals(true)) createSoft(fieldNode, init); else { create(fieldNode, init); } } }
private void createSoft(FieldNode fieldNode, Expression initExpr) { ClassNode type = fieldNode.getType(); fieldNode.setType(SOFT_REF); createSoftGetter(fieldNode, initExpr, type); createSoftSetter(fieldNode, type); }
private void create(FieldNode fieldNode, final Expression initExpr) { final BlockStatement body = new BlockStatement(); if (fieldNode.isStatic()) { addHolderClassIdiomBody(body, fieldNode, initExpr); } else if (notVolatile(fieldNode)) { addNonThreadSafeBody(body, fieldNode, initExpr); } else { addDoubleCheckedLockingBody(body, fieldNode, initExpr); } addMethod(fieldNode, body, fieldNode.getType()); }
public void visit(ASTNode[] nodes, SourceUnit source) { if (!(nodes[0] instanceof AnnotationNode) || !(nodes[1] instanceof AnnotatedNode)) { throw new RuntimeException("Internal error: wrong types: $node.class / $parent.class"); } AnnotatedNode parent = (AnnotatedNode) nodes[1]; AnnotationNode node = (AnnotationNode) nodes[0]; if (parent instanceof FieldNode) { FieldNode fieldNode = (FieldNode) parent; final Expression member = node.getMember("soft"); final Expression init = getInitExpr(fieldNode); fieldNode.rename("$" + fieldNode.getName()); fieldNode.setModifiers(ACC_PRIVATE | (fieldNode.getModifiers() & (~(ACC_PUBLIC|ACC_PROTECTED)))); if(member instanceof ConstantExpression && ((ConstantExpression)member).getValue().equals(true)) createSoft(fieldNode, init); else { create(fieldNode, init); } } }
private void createSoft(FieldNode fieldNode, Expression initExpr) { final ClassNode type = fieldNode.getType(); fieldNode.setType(SOFT_REF); createSoftGetter(fieldNode, initExpr, type); createSoftSetter(fieldNode, type); }
public void visit(ASTNode[] nodes, SourceUnit source) { if (nodes.length != 2 || !(nodes[0] instanceof AnnotationNode) || !(nodes[1] instanceof AnnotatedNode)) { throw new GroovyBugError("Internal error: expecting [AnnotationNode, AnnotatedNode] but got: " + Arrays.asList(nodes)); } AnnotatedNode parent = (AnnotatedNode) nodes[1]; AnnotationNode node = (AnnotationNode) nodes[0]; if (parent instanceof FieldNode) { final FieldNode fieldNode = (FieldNode) parent; final Expression soft = node.getMember("soft"); final Expression init = getInitExpr(fieldNode); fieldNode.rename("$" + fieldNode.getName()); fieldNode.setModifiers(ACC_PRIVATE | (fieldNode.getModifiers() & (~(ACC_PUBLIC | ACC_PROTECTED)))); if (soft instanceof ConstantExpression && ((ConstantExpression) soft).getValue().equals(true)) createSoft(fieldNode, init); else { create(fieldNode, init); // @Lazy not meaningful with primitive so convert to wrapper if needed if (ClassHelper.isPrimitiveType(fieldNode.getType())) { fieldNode.setType(ClassHelper.getWrapper(fieldNode.getType())); } } } }
private void createSoft(FieldNode fieldNode, Expression initExpr) { ClassNode type = fieldNode.getType(); fieldNode.setType(SOFT_REF); createSoftGetter(fieldNode, initExpr, type); createSoftSetter(fieldNode, type); }