public override bool CanExecute(mmchecker.vm.ThreadState threadState) { //VMValue v1 = threadState.GetValue(threadState.ThreadStack.Peek()); VMValue v2 = threadState.GetValue(threadState.ThreadStack.Peek(1)); VMValue v3 = threadState.GetValue(threadState.ThreadStack.Peek(2)); // NOTE: No need for v1 to be concrete, data dependency // will stop the DelayedWriteArray to complete return (v2.IsConcrete && v3.IsConcrete); }
public override CILInstruction Execute(mmchecker.vm.ThreadState threadState) { if(CanExecute(threadState) == false) throw new Exception("This blt instruction is not ready to execute"); if(threadState.GetValue(threadState.ThreadStack.Peek()) is VMValue_int32) { VMValue_int32 value2 = (VMValue_int32)threadState.GetValue(threadState.ThreadStack.Pop()); VMValue_int32 value1 = (VMValue_int32)threadState.GetValue(threadState.ThreadStack.Pop()); if(value1.Value > value2.Value) return threadState.CurrentMethod.GetInstruction(branchLabel); else return threadState.CurrentMethod.GetNextInstruction(this); } else if(threadState.GetValue(threadState.ThreadStack.Peek()) is VMValue_double) { VMValue_double value2 = (VMValue_double)threadState.GetValue(threadState.ThreadStack.Pop()); VMValue_double value1 = (VMValue_double)threadState.GetValue(threadState.ThreadStack.Pop()); if(value1.Value > value2.Value) return threadState.CurrentMethod.GetInstruction(branchLabel); else return threadState.CurrentMethod.GetNextInstruction(this); } else if(threadState.GetValue(threadState.ThreadStack.Peek()) is VMValue_int64) { VMValue_int64 value2 = (VMValue_int64)threadState.GetValue(threadState.ThreadStack.Pop()); VMValue_int64 value1 = (VMValue_int64)threadState.GetValue(threadState.ThreadStack.Pop()); if(value1.Value > value2.Value) return threadState.CurrentMethod.GetInstruction(branchLabel); else return threadState.CurrentMethod.GetNextInstruction(this); }else throw new Exception("Unknown value type on stack for bgt"); }
public override CILInstruction Execute(mmchecker.vm.ThreadState threadState) { if(CanExecute(threadState) == false) throw new Exception("This blt instruction is not ready to execute"); VMValue_int32 value2 = (VMValue_int32)threadState.GetValue(threadState.ThreadStack.Pop()); VMValue_int32 value1 = (VMValue_int32)threadState.GetValue(threadState.ThreadStack.Pop()); if(value1.Value < value2.Value) return threadState.CurrentMethod.GetInstruction(branchLabel); else return threadState.CurrentMethod.GetNextInstruction(this); }
public override CILInstruction Execute(mmchecker.vm.ThreadState threadState) { if(CanExecute(threadState) == false) throw new Exception("This stelem is not ready to execute"); int gValue = threadState.ThreadStack.Pop(); int index = ((VMValue_int32)threadState.GetValue(threadState.ThreadStack.Pop())).Value; VMValue_array arr = (VMValue_array)threadState.GetValue(threadState.ThreadStack.Pop()); VMValue_arrayinst arrinst = (VMValue_arrayinst)threadState.GetValue(arr.ArrayInstGuid); DelayedWrite dw = new DelayedWrite(arrinst.GetElement(index), gValue, this); threadState.AddPendingAction(dw); return threadState.CurrentMethod.GetNextInstruction(this); }
public override CILInstruction Execute(mmchecker.vm.ThreadState threadState) { if(CanExecute(threadState) == false) throw new Exception("This stfld is not ready to execute"); VMValue source = threadState.GetValue(threadState.ThreadStack.Pop()); VMValue target = threadState.GetValue(threadState.SystemState.GetStaticVariable(classType, field)); DelayedWrite dw = new DelayedWrite(target.GUID, source.GUID, this); dw.SourceInstruction = this; // target.AddDelayedAction(dw); threadState.AddPendingAction(dw); return threadState.CurrentMethod.GetNextInstruction(this); }
public override CILInstruction Execute(mmchecker.vm.ThreadState threadState) { if(CanExecute(threadState) == false) throw new Exception("This ldelem is not ready to execute"); VMValue_array arr = (VMValue_array)threadState.GetValue(threadState.ThreadStack.Pop()); VMValue_arrayinst arrinst = (VMValue_arrayinst)threadState.GetValue(arr.ArrayInstGuid); VMValue_int32 lengthValue = (VMValue_int32)threadState.SystemState.Values.MakeValue(new CILVar_int32("")); lengthValue.IsConcrete = true; lengthValue.IsThreadLocal = true; lengthValue.Value = arrinst.GetLength(); threadState.ThreadStack.Push(lengthValue.GUID); return threadState.CurrentMethod.GetNextInstruction(this); }
public override CILInstruction Execute(mmchecker.vm.ThreadState threadState) { // TODO: must support other types of data beside int32 if(CanExecute(threadState) == false) throw new Exception("This add instruction is not ready to execute"); VMValue v = threadState.GetValue(threadState.ThreadStack.Pop()); if(v is VMValue_int32) { VMValue_int32 value1 = (VMValue_int32)v; if(value1.Value != 0) return threadState.CurrentMethod.GetInstruction(branchLabel); else return threadState.CurrentMethod.GetNextInstruction(this); } else if(v is VMValue_object) { VMValue_object value1 = (VMValue_object)v; if(value1.ValueGUID == -1) return threadState.CurrentMethod.GetNextInstruction(this); else return threadState.CurrentMethod.GetInstruction(branchLabel); } else if(v is VMValue_double) { VMValue_double value1 = (VMValue_double)v; if(value1.Value != 0) return threadState.CurrentMethod.GetInstruction(branchLabel); else return threadState.CurrentMethod.GetNextInstruction(this); } throw new Exception("Unknown data type for brtrue"); }
public override CILInstruction Execute(mmchecker.vm.ThreadState threadState) { if(CanExecute(threadState) == false) throw new Exception("This ldelem is not ready to execute"); int index = ((VMValue_int32)threadState.GetValue(threadState.ThreadStack.Pop())).Value; VMValue_array arr = (VMValue_array)threadState.GetValue(threadState.ThreadStack.Pop()); VMValue_arrayinst arrinst = (VMValue_arrayinst)threadState.GetValue(arr.ArrayInstGuid); VMValue destValue = threadState.SystemState.Values.MakeValue(threadState.GetValue(arrinst.GetElement(index))); destValue.IsThreadLocal = true; threadState.ThreadStack.Push(destValue.GUID); DelayedRead dr = new DelayedRead(destValue.GUID, arrinst.GetElement(index), this); threadState.AddPendingAction(dr); return threadState.CurrentMethod.GetNextInstruction(this); }
public override CILInstruction Execute(mmchecker.vm.ThreadState threadState) { int src = threadState.SystemState.GetStaticVariable(classType, field); int dest = threadState.SystemState.Values.MakeValue(threadState.GetValue(src)).GUID; DelayedRead dr = new DelayedRead(dest, src, this); dr.SourceInstruction = this; threadState.ThreadStack.Push(dest); threadState.AddPendingAction(dr); return threadState.CurrentMethod.GetNextInstruction(this); }
public override CILInstruction Execute(mmchecker.vm.ThreadState threadState) { if(CanExecute(threadState) == false) throw new Exception("ldfld is not ready to execute now"); VMValue_object objptr = (VMValue_object)threadState.GetValue(threadState.ThreadStack.Pop()); VMValue_objectinst obj = (VMValue_objectinst)threadState.GetValue(objptr.ValueGUID); int src = obj.GetFieldGUID(className, fieldName); int dest = threadState.SystemState.Values.MakeValue(threadState.GetValue(src)).GUID; threadState.GetValue(dest).IsThreadLocal = true; DelayedRead dr; if(isVolatile) dr = new DelayedVolatileRead(dest, src, this); else dr = new DelayedRead(dest, src, this); dr.SourceInstruction = this; threadState.ThreadStack.Push(dest); threadState.AddPendingAction(dr); return threadState.CurrentMethod.GetNextInstruction(this); }
public override CILInstruction Execute(mmchecker.vm.ThreadState threadState) { // TODO: must support other types of data beside int32 if(CanExecute(threadState) == false) throw new Exception("This add instruction is not ready to execute"); VMValue_int32 value1 = (VMValue_int32)threadState.GetValue(threadState.ThreadStack.Pop()); if(value1.Value == 0) return threadState.CurrentMethod.GetInstruction(branchLabel); else return threadState.CurrentMethod.GetNextInstruction(this); }
public override CILInstruction Execute(mmchecker.vm.ThreadState threadState) { // TODO: This instruction must be able to support float too if(CanExecute(threadState) == false) throw new Exception("This add instruction is not ready to execute"); VMValue v1 = threadState.GetValue(threadState.ThreadStack.Pop()); VMValue v2 = threadState.GetValue(threadState.ThreadStack.Pop()); if((v1 is VMValue_int32) && (v2 is VMValue_int32)) { VMValue_int32 vi1, vi2; vi1 = (VMValue_int32)v1; vi2 = (VMValue_int32)v2; if(vi1.Value != vi2.Value) return threadState.CurrentMethod.GetInstruction(branchLabel); else return threadState.CurrentMethod.GetNextInstruction(this); } else { double d1, d2; if(v1 is VMValue_int32) d1 = ((VMValue_int32)v1).Value; else if(v1 is VMValue_double) d1 = ((VMValue_double)v1).Value; else throw new Exception("Unknown data type for bne"); if(v2 is VMValue_int32) d2 = ((VMValue_int32)v2).Value; else if(v2 is VMValue_double) d2 = ((VMValue_double)v2).Value; else throw new Exception("Unknown data type for bne"); if(d1 != d2) return threadState.CurrentMethod.GetInstruction(branchLabel); else return threadState.CurrentMethod.GetNextInstruction(this); } }
public override CILInstruction Execute(mmchecker.vm.ThreadState threadState) { // TODONOW: Fix this when semantic for ldarg and starg is clear if(CanExecute(threadState) == false) throw new Exception("This instruction is not ready to execute"); VMValue source = threadState.GetValue(threadState.ThreadStack.Pop()); VMValue target = threadState.GetLocalArgument(argIndex); target.IsThreadLocal = true; DelayedWrite dw = new DelayedWrite(target.GUID, source.GUID, this); threadState.AddPendingAction(dw); return threadState.CurrentMethod.GetNextInstruction(this); }
public override bool CanExecute(mmchecker.vm.ThreadState threadState) { // now the obj is concrete, we only check for locking instructions if(theMethod.ParentClass.Name == "[mscorlib]System.Threading.Thread") { if (threadState.GetValue(threadState.ThreadStack.Peek()).IsConcrete == false) return false; if (theMethod.Name == "Start") { // Ensure that every actions are complete before starting a new thread // This is reasonable since starting a thread is a very "complex" requiring // many synchronization actions so these incomplete actions should be completed // on the way. if (threadState.pendingActions.Count != 0) return false; return true; } else if(theMethod.Name == "Join") { // Checks whether the thread that this thread is waiting to join has ended or not // No instruction after this join() is allowed to be issued before this join() is executed. VMValue_object threadptr = (VMValue_object)threadState.GetValue(threadState.ThreadStack.Peek()); VMValue_thread th = (VMValue_thread)threadState.GetValue(threadptr.ValueGUID); ThreadState tstate = (ThreadState)threadState.SystemState.GetThreadByID(th.GUID); return tstate.HasEnded(); } else throw new Exception("Not supported yet"); } else { // for callvirt, we need the pointer to the object be concrete if (threadState.GetValue(threadState.ThreadStack.Peek(theMethod.ParameterCount)).IsConcrete == false) return false; return true; } }
public override bool CanExecute(mmchecker.vm.ThreadState threadState) { VMValue v1 = threadState.GetValue(threadState.ThreadStack.Peek()); VMValue v2 = threadState.GetValue(threadState.ThreadStack.Peek(1)); return (v1.IsConcrete && v2.IsConcrete); }
public override CILInstruction Execute(mmchecker.vm.ThreadState threadState) { if(CanExecute(threadState) == false) throw new Exception("This instruction is not ready to start"); if(theMethod.ParentClass.Name == "[mscorlib]System.Threading.Thread") { if(theMethod.Name == "Start") { // Gets the needed details and then add the thread to global datastructure // The new thread is ready to be executed in the next step // TODO: Do POR on initial bytecodes of the thread to reduce one step VMValue_object threadptr = (VMValue_object)threadState.GetValue(threadState.ThreadStack.Pop()); VMValue_thread threadobj = (VMValue_thread)threadState.GetValue(threadptr.ValueGUID); ThreadState newThread = new ThreadState(threadState.SystemState, threadobj); // no need to refer back // TODO: we may need the details later, but it causes problems for dynamic escape analysis // by letting the original thread keep the pointer to the object threadobj.ThreadStartGUID = -1; threadState.SystemState.AddThread(newThread); return threadState.CurrentMethod.GetNextInstruction(this); } else if(theMethod.Name == "Join") { // Only need to pop the thread id, because the CanExecute() already // make sure the thread that this thread must join has already ended threadState.ThreadStack.Pop(); return threadState.CurrentMethod.GetNextInstruction(this); }else throw new Exception("Not supported yet"); } else { return threadState.CallFunction(theMethod); } }
public override bool CanExecute(mmchecker.vm.ThreadState threadState) { if(theMethod.ParentClass.Name == "[mscorlib]System.Object") { if(theMethod.Name == ".ctor") return true; } else if(theMethod.ParentClass.Name == "[mscorlib]System.Threading.Thread") { if(theMethod.Name == "MemoryBarrier") { // effectively blocks all instructions from completing out of order with // this barrier return threadState.pendingActions.Count == 0; } else { throw new Exception("Not supported function " + theMethod.ParentClass.Name + "::" + theMethod.Name); } } else if(theMethod.ParentClass.Name == "[mscorlib]System.Threading.Monitor") { if(theMethod.Name == "Enter") { // Can execute enter a lock first if the ld is completed // so that the pointer is concrete // and then the lock on that must either be open // or locked by the same thread VMValue_object v = (VMValue_object)threadState.GetValue(threadState.ThreadStack.Peek()); if(v.IsConcrete == false) return false; // TODO: This should crash the vm because we call lock on a // null pointer, now we block the execution by saying that // this instruction is not yet ready to be executed if(v.ValueGUID == -1) return false; // we can start the lock even if we don't own the lock now // we only need to own the lock when the instruction completes return true; } else if((theMethod.Name == "Exit") || (theMethod.Name == "Wait") || (theMethod.Name == "Pulse") || (theMethod.Name == "PulseAll")) { // these wait/pulse instructions requires an object pointer to issue VMValue v = threadState.GetValue(threadState.ThreadStack.Peek()); return v.IsConcrete; } else throw new Exception("Not supported function of [mscorlib]System.Threading.Monitor"); } else if(theMethod.ParentClass.Name == "MMC") { if(theMethod.Name == "Report") { // requires a number on the stack to execute VMValue v = threadState.GetValue(threadState.ThreadStack.Peek()); return v.IsConcrete; } } else if(theMethod.ParentClass.Name == "[mscorlib]System.Math") { // math operations, require the approriate number of numbers on the stack switch(theMethod.Name) { case "Abs": case "Sin": case "Cos": return threadState.GetValue(threadState.ThreadStack.Peek()).IsConcrete; case "Pow": return ( threadState.GetValue(threadState.ThreadStack.Peek()).IsConcrete && threadState.GetValue(threadState.ThreadStack.Peek(1)).IsConcrete); default: throw new Exception("Not supported function from [mscorlib]System.Math"); } } return true; }
public override CILInstruction Execute(mmchecker.vm.ThreadState threadState) { VMValue_double v, vnew, vpower, vbase; VMValue_int32 vint; if(CanExecute(threadState) == false) throw new Exception("Something's wrong, executing assertion when value is not ready"); if(theMethod.ParentClass.Name == "[mscorlib]System.Object") { if(theMethod.Name == ".ctor") return threadState.CurrentMethod.GetNextInstruction(this); } else if(theMethod.ParentClass.Name == "MMC") { // this is the checker's assertion class if(theMethod.Name == "Report") { vint = (VMValue_int32)threadState.GetValue(threadState.ThreadStack.Pop()); threadState.SystemState.Report(vint.Value); } return threadState.CurrentMethod.GetNextInstruction(this); } else if(theMethod.ParentClass.Name == "[mscorlib]System.Threading.Thread") { // just go pass this instruction because the CanExecute() has made sure // that there is incomplete bytecodes if(theMethod.Name == "MemoryBarrier") return threadState.CurrentMethod.GetNextInstruction(this); else throw new Exception("Not supported function " + theMethod.ParentClass.Name + "::" + theMethod.Name); } else if(theMethod.ParentClass.Name == "[mscorlib]System.Threading.Monitor") { if(theMethod.Name == "Enter") { VMValue_object obj = (VMValue_object)threadState.GetValue(threadState.ThreadStack.Pop()); DelayedLock dl = new DelayedLock(obj.ValueGUID, this); threadState.AddPendingAction(dl); return threadState.CurrentMethod.GetNextInstruction(this); } else if(theMethod.Name == "Exit") { VMValue_object obj = (VMValue_object)threadState.GetValue(threadState.ThreadStack.Pop()); DelayedUnlock du = new DelayedUnlock(obj.ValueGUID, this); threadState.AddPendingAction(du); return threadState.CurrentMethod.GetNextInstruction(this); } else if(theMethod.Name == "Wait") { VMValue_object obj = (VMValue_object)threadState.GetValue(threadState.ThreadStack.Pop()); DelayedWait du = new DelayedWait(obj.ValueGUID, this, 0); threadState.AddPendingAction(du); // set this thread to waiting threadState.syncState = ThreadState.SyncState.WAITING; threadState.waitingOn = obj.ValueGUID; // release the lock VMValue_objectinst objinst = (VMValue_objectinst)threadState.GetValue(obj.ValueGUID); du.lockCount = objinst.HoldingLockCount; objinst.HoldingLockCount = 0; objinst.HoldingLockThreadID = -1; // TODO: Now wait always return 1, change to reflect the result of the call VMValue_int32 theConstant = (VMValue_int32)threadState.SystemState.Values.MakeValue(new CILVar_int32("")); theConstant.Value = 1; theConstant.IsThreadLocal = true; theConstant.IsConcrete = true; threadState.ThreadStack.Push(theConstant.GUID); return threadState.CurrentMethod.GetNextInstruction(this); } else if(theMethod.Name == "Pulse") { VMValue_object obj = (VMValue_object)threadState.GetValue(threadState.ThreadStack.Pop()); DelayedPulse du = new DelayedPulse(obj.ValueGUID, this, false); threadState.AddPendingAction(du); return threadState.CurrentMethod.GetNextInstruction(this); } else if(theMethod.Name == "PulseAll") { VMValue_object obj = (VMValue_object)threadState.GetValue(threadState.ThreadStack.Pop()); DelayedPulse du = new DelayedPulse(obj.ValueGUID, this, true); threadState.AddPendingAction(du); return threadState.CurrentMethod.GetNextInstruction(this); }else throw new Exception("Function " + theMethod.Name + " of class Monitor is not supported"); } else if(theMethod.ParentClass.Name == "[mscorlib]System.Math") { // arithmetic instructions, just do the mathematics associated with each switch(theMethod.Name) { case "Abs": v = (VMValue_double)threadState.GetValue(threadState.ThreadStack.Pop()); vnew = (VMValue_double)threadState.SystemState.Values.MakeValue(v); vnew.IsThreadLocal = true; vnew.IsConcrete = true; vnew.Value = Math.Abs(v.Value); threadState.ThreadStack.Push(vnew.GUID); break; case "Sin": v = (VMValue_double)threadState.GetValue(threadState.ThreadStack.Pop()); vnew = (VMValue_double)threadState.SystemState.Values.MakeValue(v); vnew.IsThreadLocal = true; vnew.IsConcrete = true; vnew.Value = Math.Sin(v.Value); threadState.ThreadStack.Push(vnew.GUID); break; case "Cos": v = (VMValue_double)threadState.GetValue(threadState.ThreadStack.Pop()); vnew = (VMValue_double)threadState.SystemState.Values.MakeValue(v); vnew.IsThreadLocal = true; vnew.IsConcrete = true; vnew.Value = Math.Cos(v.Value); threadState.ThreadStack.Push(vnew.GUID); break; case "Pow": vpower = (VMValue_double)threadState.GetValue(threadState.ThreadStack.Pop()); vbase = (VMValue_double)threadState.GetValue(threadState.ThreadStack.Pop()); vnew = (VMValue_double)threadState.SystemState.Values.MakeValue(vpower); vnew.IsThreadLocal = true; vnew.IsConcrete = true; vnew.Value = Math.Pow(vbase.Value, vpower.Value); threadState.ThreadStack.Push(vnew.GUID); break; default: throw new Exception("Not supported function of [mscorlib]System.Math"); } return threadState.CurrentMethod.GetNextInstruction(this); } return threadState.CallFunction(theMethod); }