// Enter a state and push it onto the 'virtual callstack'. // Stackframe describing state to enter, along with the // locals in that state. public void EnterState(VirtualStackFrame stackFrame) { if (stackFrame != null && stackFrame.State != null) { this.callStack.Push(stackFrame); this.controller.EnterState(stackFrame); } else { // signify "Uninstrumented call" this.callStack.Push(null); } }
internal void EnterState(VirtualStackFrame newFrame) { this.eventCode = EventCode.Enter; this.enterStackParameter = newFrame; this.eventSend.Set(); // Block until Island executes Nop, // giving BPs a chance to be hit. // Must block here if the island is stopped at a breakpoint. this.eventDone.WaitOne(); }
// Common helper to invoke an Stack frame. // This handles marshaling the args. // islandArguments - arbitrary argument passed ot the islands. // [DebuggerHidden] internal void InvokeWorker(object islandArguments, VirtualStackFrame stackFrame) { State state = stackFrame.State; if (!state.DebuggingEnabled) { // We need to short circuit and call IslandWorker because that is what the generated code // would have done, if we had generated it. This causes the thread to finish up. ThreadWorkerController.IslandWorker((ThreadWorkerController)islandArguments); return; } MethodInfo methodInfo = this.dynamicModuleManager.GetIsland(state, this.IsPriming); IDictionary <string, object> allLocals = stackFrame.Locals; // Package up the raw arguments array. const int numberOfBaseArguments = 2; int numberOfEarlyLocals = state.NumberOfEarlyLocals; object[] arguments = new object[numberOfBaseArguments + numberOfEarlyLocals]; // +1 for IslandArguments and +1 for IsPriming arguments[0] = this.IsPriming; arguments[1] = islandArguments; if (numberOfEarlyLocals > 0) { int i = numberOfBaseArguments; foreach (LocalsItemDescription localsItemDescription in state.EarlyLocals) { string name = localsItemDescription.Name; object value; if (allLocals.TryGetValue(name, out value)) { // We could assert that val.GetType() is assignable to localsItemDescription.Type. // MethodInfo invoke will check this anyways; but we could check // it and give a better error. } else { // Local not supplied in the array! Use a default. value = Activator.CreateInstance(localsItemDescription.Type); } arguments[i] = value; i++; } } methodInfo.Invoke(null, arguments); }
// Pop the state most recently pushed by EnterState. //[SuppressMessage(FxCop.Category.Usage, FxCop.Rule.ReviewUnusedParameters, Justification = "Revisit for bug 36860")] public void LeaveState(State state) { if (this.callStack.Count > 0) { VirtualStackFrame stackFrame = this.callStack.Pop(); Fx.Assert( (state == null && stackFrame == null) || (stackFrame != null && stackFrame.State == state), "Unmatched LeaveState: " + ((state == null) ? "null" : state.Name) + " with top stack frame: " + ((stackFrame == null || stackFrame.State == null) ? "null" : stackFrame.State.Name)); if (stackFrame != null) // Matches with an uninstrumented Activity. { this.controller.LeaveState(); } } else { Fx.Assert("Unmatched LeaveState: " + ((state != null) ? state.Name : "null")); } }
// Enter a state and push it onto the 'virtual callstack'. // Stackframe describing state to enter, along with the // locals in that state. internal void EnterState(int threadIndex, VirtualStackFrame stackFrame) { Fx.Assert(threadIndex < this.threads.Count, "Index out of range for thread"); Fx.Assert(this.threads[threadIndex] != null, "LogicalThread is null"); this.threads[threadIndex].EnterState(stackFrame); }