/** * check if the field saves an object. * * @param instr * @return */ private boolean isFieldIsObjectBased(GCInstruction instr) { if (instr.getOpCode() == JavaInstructionsOpcodes.AALOAD || instr.getOpCode() == JavaInstructionsOpcodes.AASTORE) { return true; } if (instr.getOpCode() != JavaInstructionsOpcodes.PUTFIELD && instr.getOpCode() != JavaInstructionsOpcodes.GETFIELD && instr.getOpCode() != JavaInstructionsOpcodes.GETSTATIC && instr.getOpCode() != JavaInstructionsOpcodes.PUTSTATIC) { return false; } GlobalConstantPool pOne = GlobalConstantPool.getInstanceOf(); int index = instr.getOperandsData().intValueUnsigned(); FieldRefInfo fInfo = (FieldRefInfo) pOne.get(index, TagValues.CONSTANT_Fieldref); int nameAndTypeIndex = fInfo.getNameAndTypeIndex().intValueUnsigned(); NameAndTypeInfo nAtInfo = (NameAndTypeInfo) pOne.get(nameAndTypeIndex, TagValues.CONSTANT_NameAndType); String description = ((UTF8Info) pOne.get(nAtInfo.getDescriptorIndex().intValueUnsigned(), TagValues.CONSTANT_Utf8)) .convertBytes(); VerificationFrameFactory frameFactory = VerificationPlaceHolder.getInstanceOf().getFactory(); Type fieldType = frameFactory.createType(); InitializeFirstInstruction.getType(description, 0, fieldType); return fieldType.isReference(); }
/** * Should be called Before virtual execution of instructions putfield and putstatic so that all * corresponding getFields are set dirty. Similarly should also be called before virtual execution * of instructions AASTORE so that corresponding AALOAD are set dirty. * * @param method * @param callingParms * @param instr * @param stack * @param localVariables */ public void fixOrderRelatedInstrs( MethodInfo method, Vector callingParms, GCInstruction instr, GCOperandStack stack, GCLocalVariables localVariables) { if (!isFieldIsObjectBased(instr)) { return; } String methodStr = oracle.getMethodOrFieldString(method); if (instr.getOpCode() == JavaInstructionsOpcodes.PUTSTATIC || instr.getOpCode() == JavaInstructionsOpcodes.PUTFIELD || instr.getOpCode() == JavaInstructionsOpcodes.AASTORE) { GCType type = (GCType) stack.peep(); if (!type.isReference()) { return; } HashSet<TTReference> refSet = type.getReferences(); if (refSet.size() == 1) { TTReference ref = refSet.iterator().next(); if (ref.getClassThisPointer() == Type.NULL || ref.getNewId() < 0) { return; } } debugPrint("\n\n++++++++++ ", "fix-Order"); debugPrint("method Str =", oracle.getMethodOrFieldString(method)); debugPrint("instr =", instr); handlePutRecalls(new MethodCallInfo(method, callingParms), instr, stack); } }
/** * In case the method is still under-call then put the record of the method fields where get was * used in a seperate map. When a method any next instruction is called again then the record is * pop from the map and corresponding instructions are made dirty. * * <p>This method create that record of method fields. * * @param methodCallInfo * @param instrDataSettingInstr */ private void handlePutRecalls( MethodCallInfo methodCallInfo, GCInstruction instrDataSettingInstr, OperandStack stack) { if (true) return; try { /** * 1. Firstly get from input instructions the uniqueId for corresponding data reterival * instructions. 2. Subsequently, add those instructions in the two different maps depending * upon if the method is still under call or not. */ ControllerForFieldInstr contr = ControllerForFieldInstr.getInstanceOf(); HashSet<Integer> uniqueIdForDataRetrivalInstr = new HashSet<Integer>(); if (instrDataSettingInstr.getOpCode() != JavaInstructionsOpcodes.AASTORE) { int cpIndex = instrDataSettingInstr.getOperandsData().intValueUnsigned(); uniqueIdForDataRetrivalInstr.add(cpIndex); } else { uniqueIdForDataRetrivalInstr = getAAStoreNewIds(stack); } /** * following are the all getField or getStatic instruction for the given constant pool index. */ HashSet<FieldRecord> getFieldOrStateRecordSet = contr.getRecords( uniqueIdForDataRetrivalInstr, instrDataSettingInstr.getOpCode() == JavaInstructionsOpcodes.AASTORE); /** * Now we iterate from all of those instructions and put them in two different maps * depenending up if their method is still under call or not. */ Iterator<FieldRecord> fieldRectIt = getFieldOrStateRecordSet.iterator(); while (fieldRectIt.hasNext()) { FieldRecord fieldRec = fieldRectIt.next(); HashSet<FunctionStateKey> allTheMethodCallsForTheField = fieldRec.getStateKeys(); Iterator<FunctionStateKey> methodCallIt = allTheMethodCallsForTheField.iterator(); while (methodCallIt.hasNext()) { FunctionStateKey stateKey = methodCallIt.next(); GCDataFlowAnalyzer dataFlowAnalyzer = GCDataFlowAnalyzer.getInstanceOf(); HashSet<FunctionStateKey> allMethodInExecution = dataFlowAnalyzer.getMethodsInExecution(); String methodString = oracle.getMethodOrFieldString(stateKey.getMethod()); long instrId = fieldRec.getInstr().getInstructionId(); if (allMethodInExecution.contains(stateKey)) { putInMap(fieldsToSetDirtyInUnderCallMethod, stateKey, fieldRec); } else { putInMap(fieldsToSetDirtyAfterMethodCalled, stateKey, fieldRec); } } } } catch (Exception d) { d.printStackTrace(); Miscellaneous.exit(); } }
/** * This method is called when GetStatic or GetField or AALoad. It adds record of those * instructions so that they can be made dirty when putfield or putstatic is used for the same * field. * * @param method * @param callingParams * @param instr * @param stack * @param localVar */ public void addRecord( MethodInfo method, Vector callingParams, GCInstruction instr, GCOperandStack stack, GCLocalVariables localVar) { if (!isFieldIsObjectBased(instr) || (instr.getOpCode() != JavaInstructionsOpcodes.GETSTATIC && instr.getOpCode() != JavaInstructionsOpcodes.GETFIELD && instr.getOpCode() != JavaInstructionsOpcodes.AALOAD)) { return; } addRecord(new FunctionStateKey(method, callingParams), instr, stack, localVar); }
/** * Call it BEFORE executing an instruction virtually. * * @param instr * @param stack * @param localVar */ private void addRecord( FunctionStateKey stateKey, GCInstruction instr, GCOperandStack stack, GCLocalVariables localVar) { MethodInfo method = instr.getMethod(); String methodStr = oracle.getMethodOrFieldString(method); if (methodStr.contains("jvmTestCases.Main.fooGetOnly")) {} debugPrint("\n\n", "***** adding record *****"); debugPrint("method Str=", methodStr); debugPrint("instr =", instr); HashSet<Integer> unqiueForField = new HashSet<Integer>(); if (instr.getOpCode() != JavaInstructionsOpcodes.AALOAD) { int cpIndex = instr.getOperandsData().intValueUnsigned(); unqiueForField.add(cpIndex); } else { unqiueForField = getAALOADNewIds(stack); } Iterator<Integer> it = unqiueForField.iterator(); while (it.hasNext()) { contrForField.addRecord(stateKey, instr, it.next()); } }