/****************************************************************************** * Copyright (c) 2009 - 2015 IBM Corporation. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *****************************************************************************/ /** * */ package com.ibm.wala.memsat.translation.concurrent; import static com.ibm.wala.memsat.frontEnd.InlinedInstruction.Action.LOCK; import static com.ibm.wala.memsat.frontEnd.InlinedInstruction.Action.NORMAL_READ; import static com.ibm.wala.memsat.frontEnd.InlinedInstruction.Action.NORMAL_WRITE; import static com.ibm.wala.memsat.frontEnd.InlinedInstruction.Action.UNLOCK; import static com.ibm.wala.memsat.frontEnd.InlinedInstruction.Action.VOLATILE_READ; import static com.ibm.wala.memsat.frontEnd.InlinedInstruction.Action.VOLATILE_WRITE; import static com.ibm.wala.memsat.util.Programs.instructions; import static com.ibm.wala.memsat.util.Programs.instructionsOfType; import static com.ibm.wala.memsat.util.Programs.visibleWrites; import java.util.EnumSet; import java.util.Iterator; import java.util.Set; import com.ibm.wala.memsat.concurrent.Execution; import com.ibm.wala.memsat.concurrent.Program.BoundsBuilder; import com.ibm.wala.memsat.frontEnd.InlinedInstruction; import com.ibm.wala.memsat.frontEnd.WalaInformation; import com.ibm.wala.ssa.SSAFieldAccessInstruction; import com.ibm.wala.util.graph.Graph; import kodkod.ast.Relation; import kodkod.instance.Bounds; import kodkod.instance.TupleFactory; import kodkod.instance.TupleSet; /** * Implementation of the {@linkplain BoundsBuilder} interface based on the * Miniatur translation. * @author etorlak */ final class ConcurrentBoundsBuilder implements BoundsBuilder { private final Bounds bounds; private final TupleFactory tuples; private final ConcurrentFactory factory; private final Set<InlinedInstruction> all, writes, memoryAccesses, monitorAccesses; private final Graph<InlinedInstruction> visibleWrites; /** * Constructs a new bounds builder with the given expression factory, initial bounds, and * action factory. */ public ConcurrentBoundsBuilder(Bounds bounds, ConcurrentFactory acts) { this.bounds = bounds; this.tuples = bounds.universe().factory(); this.factory = acts; final WalaInformation info = acts.base().info(); this.visibleWrites = visibleWrites(info); this.all = instructions(info); this.writes = instructionsOfType(all, EnumSet.of(NORMAL_WRITE,VOLATILE_WRITE)); this.memoryAccesses = instructionsOfType(all, EnumSet.of(NORMAL_WRITE,VOLATILE_WRITE,NORMAL_READ,VOLATILE_READ)); this.monitorAccesses = instructionsOfType(all, EnumSet.of(LOCK, UNLOCK)); } /** * Returns the upper bound on the actions that can be performed by the given instructions. * @return bounds.upperBound(instructions.get(inst)) */ private TupleSet actionAtoms(InlinedInstruction inst) { return factory.actionAtoms(tuples, inst); } /** * {@inheritDoc} * @see com.ibm.wala.memsat.concurrent.Program.BoundsBuilder#boundExecution(com.ibm.wala.memsat.concurrent.Execution) */ public void boundExecution(Execution exec) { for(InlinedInstruction inst : all) { bounds.bound(exec.action(inst), actionAtoms(inst)); } boundValues(exec); boundLocations(exec); boundMonitors(exec); boundOrdering(exec.w(), visibleWrites); } /** * {@inheritDoc} * @see com.ibm.wala.memsat.concurrent.Program.BoundsBuilder#boundActions(kodkod.ast.Relation, java.util.Set) */ public void boundActions(Relation r, Set<InlinedInstruction> insts) { final TupleSet u = tuples.noneOf(1); for(InlinedInstruction inst : insts) { u.addAll( actionAtoms(inst) ); } bounds.bound(r,u); } /** * {@inheritDoc} * @see com.ibm.wala.memsat.concurrent.Program.BoundsBuilder#boundOrdering(kodkod.ast.Relation, com.ibm.wala.util.graph.Graph) */ public void boundOrdering(Relation r, Graph<InlinedInstruction> insts) { final TupleSet u = tuples.noneOf(2); for(InlinedInstruction inst : insts) { for(Iterator<? extends InlinedInstruction> succs = insts.getSuccNodes(inst); succs.hasNext(); ) { final InlinedInstruction succ = succs.next(); u.addAll( actionAtoms(inst).product(actionAtoms(succ)) ); } } bounds.bound(r,u); } /** * {@inheritDoc} * @see com.ibm.wala.memsat.concurrent.Program.BoundsBuilder#build() */ public Bounds build() { return bounds; } /** * Adds bounds for exec.v to this.bounds. * @effects this.bounds.relations' = this.bounds.relations + exec.v */ private void boundValues(Execution exec) { final TupleSet u = tuples.noneOf(2); for(InlinedInstruction inst : writes) { u.addAll( actionAtoms(inst).product(factory.valueAtoms(tuples, inst)) ); } bounds.bound(exec.v(),u); } /** * Adds bounds for exec.location to this.bounds. * @effects this.bounds.relations' = this.bounds.relations + exec.location */ private void boundLocations(Execution exec) { final TupleSet l = tuples.noneOf(2), u = tuples.noneOf(2); for(InlinedInstruction inst : memoryAccesses) { final TupleSet instAtoms = actionAtoms(inst); final TupleSet locAtoms = factory.locationAtoms(tuples, inst); u.addAll( instAtoms.product(locAtoms) ); if (inst.instruction() instanceof SSAFieldAccessInstruction) { if (locAtoms.size()==1 || (locAtoms.size()==2 && instAtoms.size()==1)) // statically known location, bound exactly l.addAll( instAtoms.product(locAtoms) ); } } bounds.bound(exec.location(), l, u); } /** * Adds bounds for exec.monitor to this.bounds. * @effects this.bounds.relations' = this.bounds.relations + exec.monitor */ private void boundMonitors(Execution exec) { final TupleSet l = tuples.noneOf(2), u = tuples.noneOf(2); for(InlinedInstruction inst : monitorAccesses) { final TupleSet instAtoms = actionAtoms(inst); final TupleSet monitorAtoms = factory.monitorAtoms(tuples, inst); u.addAll( instAtoms.product(monitorAtoms) ); if (instAtoms.size()==1 && monitorAtoms.size()==1) { // statically known monitor, bound exactly l.addAll( instAtoms.product(monitorAtoms) ); } } bounds.bound(exec.monitor(), l, u); } }