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 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); }