/****************************************************************************** * 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.concurrent.memory.jmm; import static com.ibm.wala.memsat.frontEnd.InlinedInstruction.Action.END; 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.SPECIAL; import static com.ibm.wala.memsat.frontEnd.InlinedInstruction.Action.START; 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 java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Set; import com.ibm.wala.memsat.concurrent.Program; import com.ibm.wala.types.MethodReference; import kodkod.ast.Expression; import kodkod.ast.Formula; import kodkod.ast.Variable; /** * Implements the original definition of the JMM, given by * Manson, Pugh and Adve. * * @see [1] J.�Manson, W.�Pugh, and S.�V. Adve. The java memory model. In POPL �05: Proc. of * the 32nd ACM SIGPLAN-SIGACT symposium on Principles of programming languages, pages 378�391, New York, NY, USA, 2005. ACM. * @author etorlak */ public final class JMMOriginal extends JavaMemoryModel { /** * @param maxSpeculations * @param memoryInstructions */ public JMMOriginal(int maxSpeculations, Set<MethodReference> memoryInstructions) { super(maxSpeculations, memoryInstructions); } /** * @return relation & (set -> set) */ private final Expression restrict(Expression relation, Expression set) { return relation.intersection(set.product(set)); } /** * Returns the JMMOriginal rule for hb relations: hb_i |_{C_i} = hb |_{C_i} * @see com.ibm.wala.memsat.concurrent.memory.jmm.JavaMemoryModel#rule2(com.ibm.wala.memsat.concurrent.Program, com.ibm.wala.memsat.concurrent.memory.jmm.JMMExecution, java.util.List, java.util.List) */ @Override protected Formula rule2(Program prog, JMMExecution main, List<JMMExecution> speculations, List<? extends Expression> commits) { final Collection<Formula> ret = new ArrayList<Formula>(maxSpeculations); final Expression hb = main.hb(); for(int i = 1; i < maxSpeculations; i++) { final Expression C_i = commits.get(i); final Expression hb_i = speculations.get(i).hb(); ret.add( restrict(hb_i, C_i).eq(restrict(hb, C_i)) ); } return Formula.and(ret); } /** * Returns the JMMOriginal rule for so relations: so_i |_{C_i} = so |_{C_i} * @see com.ibm.wala.memsat.concurrent.memory.jmm.JavaMemoryModel#rule3(com.ibm.wala.memsat.concurrent.Program, com.ibm.wala.memsat.concurrent.memory.jmm.JMMExecution, java.util.List, java.util.List) */ @Override protected Formula rule3(Program prog, JMMExecution main, List<JMMExecution> speculations, List<? extends Expression> commits) { final Collection<Formula> ret = new ArrayList<Formula>(maxSpeculations); final Expression so = main.so(); for(int i = 1; i < maxSpeculations; i++) { final Expression C_i = commits.get(i); final Expression so_i = speculations.get(i).so(); ret.add( restrict(so_i, C_i).eq(restrict(so, C_i)) ); } return Formula.and(ret); } /** * Returns the JMMOriginal rule for the visibility of committed writes: * for all reads r in C_i - C_{i-1}, W_i(r) in C_{i-1} W(r) in C_{i-1} * @see com.ibm.wala.memsat.concurrent.memory.jmm.JavaMemoryModel#rule7(com.ibm.wala.memsat.concurrent.Program, com.ibm.wala.memsat.concurrent.memory.jmm.JMMExecution, java.util.List, java.util.List) */ @Override protected Formula rule7(Program prog, JMMExecution main, List<JMMExecution> speculations, List<? extends Expression> commits) { final Collection<Formula> ret = new ArrayList<Formula>(maxSpeculations); final Expression reads = prog.allOf(NORMAL_READ,VOLATILE_READ); final Expression w = main.w(); for(int i = 1; i < maxSpeculations; i++) { final Expression w_i = speculations.get(i).w(); final Expression C_i = commits.get(i), C_j = commits.get(i-1); final Variable r = Variable.unary("r" + i); ret.add( (r.join(w_i).in(C_j)).and(r.join(w).in(C_j)).forAll(r.oneOf(C_i.difference(C_j).intersection(reads))) ); } return Formula.and(ret); } /** * Returns the ssw relation for the given execution. These are the edges that are in * the transitive reduction of e.hb but not in e.po. * @return ssw relation for the given execution */ private final Expression ssw(JMMExecution e) { final Variable a = Variable.unary("a"), b = Variable.unary("b"); final Expression swDpo = e.sw().difference(e.po()); final Expression hb = e.hb(); final Formula sswEdge = hb.difference(a.product(b)).closure().eq(hb.closure()).not(); return sswEdge.comprehension(a.oneOf(e.actions()).and(b.oneOf(a.join(swDpo)))); } /** * Returns the JMMOriginal rule for sufficient synchronizes-with edges. * @see com.ibm.wala.memsat.concurrent.memory.jmm.JavaMemoryModel#rule8(com.ibm.wala.memsat.concurrent.Program, com.ibm.wala.memsat.concurrent.memory.jmm.JMMExecution, java.util.List, java.util.List) */ @Override protected Formula rule8(Program prog, JMMExecution main, List<JMMExecution> speculations, List<? extends Expression> commits) { final Collection<Formula> ret = new ArrayList<Formula>(maxSpeculations); final Expression syncs = prog.allOf(START,END,VOLATILE_READ,VOLATILE_WRITE,LOCK,UNLOCK); for(int i = 1; i < maxSpeculations; i++) { final JMMExecution E_i = speculations.get(i); final Expression ssw_i = ssw(E_i); final Expression hb_i = E_i.hb(); final Expression C_i = commits.get(i), C_j = commits.get(i-1); final Variable x = Variable.unary("x"), y = Variable.unary("y"), z = Variable.unary("z"); final Expression xExpr = E_i.actions().intersection(syncs); final Expression yExpr = x.join(ssw_i); final Expression zExpr = y.join(hb_i).intersection(C_i.difference(C_j)); final Collection<Formula> body = new ArrayList<Formula>(maxSpeculations-i); for(int j = i; j < maxSpeculations; j++) { body.add(x.product(y).in(speculations.get(j).sw())); } ret.add( Formula.and(body).forAll(x.oneOf(xExpr).and(y.oneOf(yExpr)).and(z.oneOf(zExpr))) ); } return Formula.and(ret); } /** * Returns the JMMOriginal rule for external actions: if y in C_i, x is an external action * and x <=_{hb_i} y, then x in C_i * @see com.ibm.wala.memsat.concurrent.memory.jmm.JavaMemoryModel#rule9(com.ibm.wala.memsat.concurrent.Program, com.ibm.wala.memsat.concurrent.memory.jmm.JMMExecution, java.util.List, java.util.List) */ @Override protected Formula rule9(Program prog, JMMExecution main, List<JMMExecution> speculations, List<? extends Expression> commits) { final Collection<Formula> ret = new ArrayList<Formula>(maxSpeculations); final Expression externals = prog.allOf(SPECIAL); for(int i = 1; i < maxSpeculations; i++) { final Expression hb_i = speculations.get(i).hb(); final Expression C_i = commits.get(i); final Variable y = Variable.unary("y"+i); ret.add( hb_i.join(y).intersection(externals).in(C_i).forAll(y.oneOf(C_i)) ); } return Formula.and(ret); } }