Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
package org.checkerframework.checker.lock;
import java.util.List;
import org.checkerframework.javacutil.InternalUtils;
import org.checkerframework.javacutil.TreeUtils;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.type.TypeMirror;
import org.checkerframework.framework.flow.CFAbstractTransfer;
import org.checkerframework.framework.flow.CFValue;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.MethodTree;
import org.checkerframework.dataflow.analysis.FlowExpressions;
import org.checkerframework.dataflow.analysis.FlowExpressions.Receiver;
import org.checkerframework.dataflow.analysis.TransferInput;
import org.checkerframework.dataflow.analysis.TransferResult;
import org.checkerframework.dataflow.cfg.UnderlyingAST;
import org.checkerframework.dataflow.cfg.UnderlyingAST.CFGMethod;
import org.checkerframework.dataflow.cfg.UnderlyingAST.Kind;
import org.checkerframework.dataflow.cfg.node.LocalVariableNode;
import org.checkerframework.dataflow.cfg.node.Node;
import org.checkerframework.dataflow.cfg.node.SynchronizedNode;
/*
* LockTransfer handles constructors, initializers, synchronized methods, and synchronized blocks.
*/
public class LockTransfer extends
CFAbstractTransfer {
/** Type-specific version of super.analysis. */
protected LockAnalysis analysis;
protected LockChecker checker;
private LockAnnotatedTypeFactory atypeFactory;
public LockTransfer(LockAnalysis analysis, LockChecker checker) {
// Always run the Lock Checker with -AconcurrentSemantics turned on.
super(analysis, true /* useConcurrentSemantics */);
// This assignment is needed (even though the super constructor is called) because
// LockTransfer.analysis shadows CFAbstractTransfer.analysis,
this.analysis = analysis;
this.checker = checker;
this.atypeFactory = (LockAnnotatedTypeFactory) analysis.getTypeFactory();
}
/**
* Sets a given {@link Node} to @LockHeld in the given {@code store}.
*/
protected void makeLockHeld(LockStore store, Node node) {
Receiver internalRepr = FlowExpressions.internalReprOf(
atypeFactory, node);
store.insertValue(internalRepr, atypeFactory.LOCKHELD);
}
/**
* Sets a given {@link Node} to @LockPossiblyHeld in the given {@code store}.
*/
protected void makeLockPossiblyHeld(LockStore store, Node node) {
Receiver internalRepr = FlowExpressions.internalReprOf(
atypeFactory, node);
// insertValue cannot change an annotation to a less
// specific type (e.g. LockHeld to LockPossiblyHeld),
// so insertLockPossiblyHeld is called.
store.insertLockPossiblyHeld(internalRepr);
}
/**
* Sets a given {@link Node} {@code node} to LockHeld in the given
* {@link TransferResult}.
*/
protected void makeLockHeld(
TransferResult result, Node node) {
if (result.containsTwoStores()) {
makeLockHeld(result.getThenStore(), node);
makeLockHeld(result.getElseStore(), node);
} else {
makeLockHeld(result.getRegularStore(), node);
}
}
/**
* Sets a given {@link Node} {@code node} to LockPossiblyHeld in the given
* {@link TransferResult}.
*/
protected void makeLockPossiblyHeld(
TransferResult result, Node node) {
if (result.containsTwoStores()) {
makeLockPossiblyHeld(result.getThenStore(), node);
makeLockPossiblyHeld(result.getElseStore(), node);
} else {
makeLockPossiblyHeld(result.getRegularStore(), node);
}
}
@Override
public LockStore initialStore(UnderlyingAST underlyingAST,
/*@Nullable */ List parameters) {
LockStore store = super.initialStore(underlyingAST, parameters);
Kind astKind = underlyingAST.getKind();
// Methods with the 'synchronized' modifier are
// holding the 'this' lock.
// There is a subtle difference between synchronized methods
// and constructors/initializers. A synchronized method is only
// taking the intrinsic lock of the current object. It says nothing
// about any fields of the current object.
// Furthermore, since the current object already exists,
// other objects may be guarded by the current object. So
// a synchronized method can affect the locking behavior of other
// objects.
// A constructor/initializer behaves as if the current object
// and all its non-static fields were held as locks. But in
// reality no locks are held.
// Furthermore, since the current object is being constructed,
// no other object can be guarded by it or any of its non-static
// fields.
// Handle synchronized methods and constructors.
if (astKind == Kind.METHOD) {
CFGMethod method = (CFGMethod) underlyingAST;
MethodTree methodTree = method.getMethod();
ExecutableElement methodElement = TreeUtils.elementFromDeclaration(methodTree);
if (methodElement.getModifiers().contains(Modifier.SYNCHRONIZED)) {
final ClassTree classTree = method.getClassTree();
TypeMirror classType = InternalUtils.typeOf(classTree);
if (methodElement.getModifiers().contains(Modifier.STATIC)) {
store.insertValue(new FlowExpressions.ClassName(classType), atypeFactory.LOCKHELD);
} else {
store.insertThisValue(atypeFactory.LOCKHELD, classType);
}
} else if (methodElement.getKind() == ElementKind.CONSTRUCTOR) {
store.setInConstructorOrInitializer();
}
} else if (astKind == Kind.ARBITRARY_CODE) { // Handle initializers
store.setInConstructorOrInitializer();
}
return store;
}
@Override
public TransferResult visitSynchronized(SynchronizedNode n,
TransferInput p) {
TransferResult result = super.visitSynchronized(n,
p);
// Handle the entering and leaving of the synchronized block
if (n.getIsStartOfBlock()) {
makeLockHeld(result, n.getExpression());
} else {
makeLockPossiblyHeld(result, n.getExpression());
}
return result;
}
}