X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=Robust%2Fsrc%2FAnalysis%2FSSJava%2FLinearTypeCheck.java;h=77b7de65ac7fce791395279587d2f816ee0a2272;hb=e7c8e9210252cff4bae7cb0551182bd179fa98a2;hp=4ba5d38bd43ee883483ef8325be0e33f8c0ebcbd;hpb=8ba79a42dd7cc1004f9a6f0669ad7619c93c80d5;p=IRC.git diff --git a/Robust/src/Analysis/SSJava/LinearTypeCheck.java b/Robust/src/Analysis/SSJava/LinearTypeCheck.java index 4ba5d38b..77b7de65 100644 --- a/Robust/src/Analysis/SSJava/LinearTypeCheck.java +++ b/Robust/src/Analysis/SSJava/LinearTypeCheck.java @@ -1,15 +1,19 @@ package Analysis.SSJava; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; +import java.util.List; import java.util.Set; import java.util.Vector; import Analysis.Liveness; import IR.AnnotationDescriptor; import IR.ClassDescriptor; -import IR.Descriptor; +import IR.FieldDescriptor; import IR.MethodDescriptor; import IR.Operation; import IR.State; @@ -52,7 +56,7 @@ public class LinearTypeCheck { State state; SSJavaAnalysis ssjava; String needToNullify = null; - AssignmentNode prevAssignNode; + TreeNode prevAssignNode; Set linearTypeCheckSet; @@ -62,6 +66,8 @@ public class LinearTypeCheck { Liveness liveness; + boolean deterministic = true; + public LinearTypeCheck(SSJavaAnalysis ssjava, State state) { this.ssjava = ssjava; this.state = state; @@ -84,12 +90,49 @@ public class LinearTypeCheck { } // second, check the linear type - it = state.getClassSymbolTable().getDescriptorsIterator(); - while (it.hasNext()) { - ClassDescriptor cd = (ClassDescriptor) it.next(); - for (Iterator method_it = cd.getMethods(); method_it.hasNext();) { - MethodDescriptor md = (MethodDescriptor) method_it.next(); - checkMethodBody(cd, md); + if (deterministic) { + + SymbolTable classtable = state.getClassSymbolTable(); + + List toanalyzeList = new ArrayList(); + List toanalyzeMethodList = new ArrayList(); + + toanalyzeList.addAll(classtable.getValueSet()); + Collections.sort(toanalyzeList, new Comparator() { + public int compare(ClassDescriptor o1, ClassDescriptor o2) { + return o1.getClassName().compareTo(o2.getClassName()); + } + }); + + for (int i = 0; i < toanalyzeList.size(); i++) { + ClassDescriptor cd = toanalyzeList.get(i); + + SymbolTable methodtable = cd.getMethodTable(); + toanalyzeMethodList.clear(); + toanalyzeMethodList.addAll(methodtable.getValueSet()); + Collections.sort(toanalyzeMethodList, new Comparator() { + public int compare(MethodDescriptor o1, MethodDescriptor o2) { + return o1.getSymbol().compareTo(o2.getSymbol()); + } + }); + + for (int mdIdx = 0; mdIdx < toanalyzeMethodList.size(); mdIdx++) { + MethodDescriptor md = toanalyzeMethodList.get(mdIdx); + if (ssjava.needToCheckLinearType(md)) { + checkMethodBody(cd, md); + } + } + + } + + } else { + it = state.getClassSymbolTable().getDescriptorsIterator(); + while (it.hasNext()) { + ClassDescriptor cd = (ClassDescriptor) it.next(); + for (Iterator method_it = cd.getMethods(); method_it.hasNext();) { + MethodDescriptor md = (MethodDescriptor) method_it.next(); + checkMethodBody(cd, md); + } } } @@ -159,6 +202,9 @@ public class LinearTypeCheck { } private void checkMethodBody(ClassDescriptor cd, MethodDescriptor md) { + if (state.SSJAVADEBUG) { + System.out.println("SSJAVA: Linear Type Checking: " + md); + } BlockNode bn = state.getMethodBody(md); checkBlockNode(md, md.getParameterTable(), bn); } @@ -324,9 +370,10 @@ public class LinearTypeCheck { } } - private void checkTertiaryNode(MethodDescriptor md, SymbolTable nametable, TertiaryNode en) { - // TODO Auto-generated method stub - + private void checkTertiaryNode(MethodDescriptor md, SymbolTable nametable, TertiaryNode tn) { + checkExpressionNode(md, nametable, tn.getCond()); + checkExpressionNode(md, nametable, tn.getTrueExpr()); + checkExpressionNode(md, nametable, tn.getFalseExpr()); } private void checkOffsetNode(MethodDescriptor md, SymbolTable nametable, OffsetNode en) { @@ -383,7 +430,7 @@ public class LinearTypeCheck { TypeDescriptor paramType = calleeMethodDesc.getParamType(i); - if (isReference(argNode.getType())) { + if (isReference(argNode.getType()) && !argNode.getType().isNull()) { boolean isParamOwnedByCallee = false; if (paramType.getExtension() != null) { @@ -395,6 +442,12 @@ public class LinearTypeCheck { if (isParamOwnedByCallee) { + // cannot pass field reference through ownership transition + if (isField(argNode)) { + throw new Error("Caller cannot transfer its ownership of the field reference at " + + md.getClassDesc() + "::" + min.getNumLine()); + } + // method expects that argument is owned by caller SSJavaType locationType = (SSJavaType) argType.getExtension(); @@ -402,6 +455,10 @@ public class LinearTypeCheck { throw new Error("Caller passes an argument not owned by itself at " + md.getClassDesc() + "::" + min.getNumLine()); } + + // delegated arg is no longer to be available from here + linearTypeCheckSet.add(argNode); + mapTreeNode2FlatMethod.put(argNode, state.getMethodFlat(md)); } } @@ -456,15 +513,19 @@ public class LinearTypeCheck { if (en.kind() == Kind.AssignmentNode) { AssignmentNode an = (AssignmentNode) en; - String destName = an.getDest().printNode(0); - if (destName.startsWith("this.")) { - destName = destName.substring(5); - } + boolean postinc = isPostIncAssignment(an); - if (an.getSrc().getType().isNull() && destName.equals(needToNullify)) { - needToNullify = null; - return true; + if (!postinc) { + String destName = an.getDest().printNode(0); + if (destName.startsWith("this.")) { + destName = destName.substring(5); + } + if (an.getSrc().getType().isNull() && destName.equals(needToNullify)) { + needToNullify = null; + return true; + } } + } } @@ -490,86 +551,45 @@ public class LinearTypeCheck { } } - private void checkAssignmentNode(MethodDescriptor md, SymbolTable nametable, AssignmentNode an) { - - boolean postinc = true; + public boolean isPostIncAssignment(AssignmentNode an) { if (an.getOperation().getBaseOp() == null || (an.getOperation().getBaseOp().getOp() != Operation.POSTINC && an.getOperation() - .getBaseOp().getOp() != Operation.POSTDEC)) - postinc = false; + .getBaseOp().getOp() != Operation.POSTDEC)) { + return false; + } else { + return true; + } + } - if (!postinc) { + private void checkAssignmentNode(MethodDescriptor md, SymbolTable nametable, AssignmentNode an) { - checkExpressionNode(md, nametable, an.getSrc()); + boolean postinc = isPostIncAssignment(an); + if (!postinc) { + checkExpressionNode(md, nametable, an.getSrc()); if (isReference(an.getSrc().getType()) && isReference(an.getDest().getType())) { - if (an.getSrc().kind() == Kind.NameNode) { - - NameNode nn = (NameNode) an.getSrc(); - - if (nn.getField() != null) { - needToNullify = nn.getField().getSymbol(); - prevAssignNode = an; - } else if (nn.getExpression() != null) { - if (nn.getExpression() instanceof FieldAccessNode) { - FieldAccessNode fan = (FieldAccessNode) nn.getExpression(); - needToNullify = fan.printNode(0); - prevAssignNode = an; - - } - - } else { - // local variable case - linearTypeCheckSet.add(an.getSrc()); - mapTreeNode2FlatMethod.put(an.getSrc(), state.getMethodFlat(md)); - } - } else if (an.getSrc().kind() == Kind.FieldAccessNode) { - FieldAccessNode fan = (FieldAccessNode) an.getSrc(); - needToNullify = fan.printNode(0); - if (needToNullify.startsWith("this.")) { - needToNullify = needToNullify.substring(5); - } - prevAssignNode = an; - } else if (an.getSrc().kind() == Kind.ArrayAccessNode) { - throw new Error( - "Not allowed to create an alias to the middle of the multidimensional array at " - + md.getClassDesc() + "::" + an.getNumLine()); - } - - if (!an.getSrc().getType().isNull()) { - - TypeDescriptor srcType = getTypeDescriptor(an.getSrc()); - boolean isSourceOwned = false; + checkAlias(md, an, an.getSrc()); + } - if (srcType.getExtension() != null) { - SSJavaType srcLocationType = (SSJavaType) srcType.getExtension(); - isSourceOwned = srcLocationType.isOwned(); - } + } - if (!isField(an.getDest()) && isSourceOwned) { - // here, transfer ownership from LHS to RHS when it creates alias - TypeDescriptor destType = getTypeDescriptor(an.getDest()); - destType.setExtension(new SSJavaType(isSourceOwned)); - } else { - // if instance is not owned by the method, not able to store - // instance into field - if (!isSourceOwned) { - throw new Error( - "Method is not allowed to store an instance not owned by itself into a field at " - + md.getClassDesc() + "::" + an.getNumLine()); - } - } + } - } + private boolean isFieldOfClass(ClassDescriptor classDesc, String varName) { + return classDesc.getFieldTable().contains(varName); + } - } + private boolean isCreatingAlias(ExpressionNode en) { + int kind = en.kind(); + if (kind == Kind.NameNode || kind == Kind.ArrayAccessNode || kind == Kind.FieldAccessNode) { + return true; } + return false; } private TypeDescriptor getTypeDescriptor(ExpressionNode en) { - if (en.kind() == Kind.NameNode) { NameNode nn = (NameNode) en; if (nn.getField() != null) { @@ -585,6 +605,29 @@ public class LinearTypeCheck { } else if (en.kind() == Kind.CreateObjectNode) { CreateObjectNode con = (CreateObjectNode) en; return con.getType(); + } else if (en.kind() == Kind.ArrayAccessNode) { + ArrayAccessNode aan = (ArrayAccessNode) en; + return aan.getExpression().getType(); + } + + return null; + } + + private FieldDescriptor getFieldDescriptorFromExpressionNode(ExpressionNode en) { + + if (en.kind() == Kind.NameNode) { + NameNode nn = (NameNode) en; + if (nn.getField() != null) { + return nn.getField(); + } + + if (nn.getName() != null && nn.getName().getBase() != null) { + return getFieldDescriptorFromExpressionNode(nn.getExpression()); + } + + } else if (en.kind() == Kind.FieldAccessNode) { + FieldAccessNode fan = (FieldAccessNode) en; + return fan.getField(); } return null; @@ -608,19 +651,109 @@ public class LinearTypeCheck { return false; } - private void checkDeclarationNode(MethodDescriptor md, SymbolTable nametable, DeclarationNode dn) { - if (dn.getExpression() != null) { - checkExpressionNode(md, nametable, dn.getExpression()); - if (dn.getExpression().kind() == Kind.CreateObjectNode) { + private void checkAlias(MethodDescriptor md, TreeNode node, ExpressionNode src) { + + if (src.kind() == Kind.NameNode) { + + NameNode nn = (NameNode) src; + + if (nn.getField() != null) { + needToNullify = nn.getField().getSymbol(); + prevAssignNode = node; + } else if (nn.getExpression() != null) { + if (nn.getExpression() instanceof FieldAccessNode) { + FieldAccessNode fan = (FieldAccessNode) nn.getExpression(); + needToNullify = fan.printNode(0); + prevAssignNode = node; + } + } else { + // local variable case + linearTypeCheckSet.add(src); + mapTreeNode2FlatMethod.put(src, state.getMethodFlat(md)); + } + } else if (src.kind() == Kind.FieldAccessNode) { + FieldAccessNode fan = (FieldAccessNode) src; + needToNullify = fan.printNode(0); + if (needToNullify.startsWith("this.")) { + needToNullify = needToNullify.substring(5); + } + prevAssignNode = node; + } else if (src.kind() == Kind.ArrayAccessNode) { + ArrayAccessNode aan = (ArrayAccessNode) src; + TypeDescriptor srcType = src.getType(); + if (srcType.isPtr() && srcType.getArrayCount() > 0) { + throw new Error( + "Not allowed to create an alias to the middle of the multidimensional array at " + + md.getClassDesc().getSourceFileName() + "::" + node.getNumLine()); + } else { + needToNullify = aan.printNode(0); + prevAssignNode = node; + } + } else if (src.kind() == Kind.CreateObjectNode || src.kind() == Kind.MethodInvokeNode + || src.kind() == Kind.ArrayInitializerNode || src.kind() == Kind.LiteralNode) { + if (node.kind() == Kind.DeclarationNode) { + DeclarationNode dn = (DeclarationNode) node; dn.getVarDescriptor().getType().setExtension(new SSJavaType(true)); } + } else { + throw new Error("Not allowed this type of assignment at " + + md.getClassDesc().getSourceFileName() + "::" + node.getNumLine()); + } + + if (isCreatingAlias(src)) { + + TypeDescriptor srcType = getTypeDescriptor(src); + boolean isSourceOwned = false; + + if (srcType.getExtension() != null) { + SSJavaType srcLocationType = (SSJavaType) srcType.getExtension(); + isSourceOwned = srcLocationType.isOwned(); + + if (isSourceOwned) { + if (isField(src)) { + ssjava.setFieldOnwership(md, getFieldDescriptorFromExpressionNode(src)); + } + } + + } else if (md.isConstructor() && isFieldOfClass(md.getClassDesc(), src.printNode(0))) { + isSourceOwned = true; + ssjava.setFieldOnwership(md, getFieldDescriptorFromExpressionNode(src)); + } + + if (node.kind() == Kind.AssignmentNode) { + AssignmentNode an = (AssignmentNode) node; + if (isField(an.getDest())) { + // if instance is not owned by the method, not able to store + // instance into field + if (!isSourceOwned) { + throw new Error( + "Method is not allowed to store an instance not owned by itself into a field at " + + md.getClassDesc().getSourceFileName() + "::" + node.getNumLine()); + } + } else { + if (isSourceOwned) { + // here, transfer ownership from LHS to RHS when it creates alias + TypeDescriptor destType = getTypeDescriptor(an.getDest()); + destType.setExtension(new SSJavaType(isSourceOwned)); + } + } + } } } + private void checkDeclarationNode(MethodDescriptor md, SymbolTable nametable, DeclarationNode dn) { + if (dn.getExpression() != null) { + ExpressionNode src = dn.getExpression(); + if (isReference(src.getType())) { + checkAlias(md, dn, src); + } + } + } + private boolean isReference(TypeDescriptor td) { - if (td.isPtr()) { + if (td.isPtr() && (!td.isString())) { return true; } return false;