private DynamicMethod BuildMain(ExecutionPath executionPath, out object[] closure) { var ilBuilderContext = new ILBuilderContext(ContextFieldInfo); if (executionPath.EnterReturnNodes.Length > 0) { if (IsOverriden(nameof(BuildBeginExecutionPath))) { BuildBeginExecutionPath(ilBuilderContext, executionPath.StackEvalDelta); } ilBuilderContext.EmitLdStack(); ilBuilderContext.IL.Emit(OpCodes.Ldc_I4, executionPath.StackEvalDelta); ilBuilderContext.IL.Emit(OpCodes.Call, EnsureDeltaMethodInfo); } { if (executionPath.PathSourceNode is LeaveStateNode leaveStateNode) { EmitDebugNode(ilBuilderContext, executionPath.PathSourceNode, executionPath); var subGraph = leaveStateNode.SubGraph; if (subGraph.StateEntry != null) { if (IsOverriden(nameof(BuildLeaveStateEntry))) { BuildLeaveStateEntry(ilBuilderContext, subGraph.StateEntry); } } } } EmitDebugExecutionPath(ilBuilderContext, executionPath); for (var index = 0; index < executionPath.Nodes.Length; index++) { var node = executionPath.Nodes[index]; switch (node) { case LeaveStateNode leaveStateNode: { EmitDebugNode(ilBuilderContext, executionPath.PathSourceNode, executionPath); var subGraph = leaveStateNode.SubGraph; if (subGraph.StateEntry != null) { if (IsOverriden(nameof(BuildLeaveStateEntry))) { BuildLeaveStateEntry(ilBuilderContext, subGraph.StateEntry); } } break; } case ActionNode actionNode: { var action = actionNode.ActionEntry.Action; if (action.Target != null) { ilBuilderContext.EmitLdValue(action.Target); ilBuilderContext.EmitLdContext(); ilBuilderContext.IL.Emit(OpCodes.Callvirt, action.Method); } else { ilBuilderContext.EmitLdContext(); ilBuilderContext.IL.Emit(OpCodes.Call, action.Method); } break; } case BeginStateNode beginStateNode: { EmitDebugNode(ilBuilderContext, node, executionPath); break; } case BeginProductionNode beginProductionNode: { EmitDebugNode(ilBuilderContext, node, executionPath); if (IsOverriden(nameof(BuildEnterProduction))) { BuildEnterProduction(ilBuilderContext, beginProductionNode.Production); } break; } case EndProductionNode endProductionNode: { EmitDebugNode(ilBuilderContext, node, executionPath); if (IsOverriden(nameof(BuildLeaveProduction))) { BuildLeaveProduction(ilBuilderContext, endProductionNode.Production); } break; } case EnterStateNode enterStateNode: { EmitDebugNode(ilBuilderContext, node, executionPath); var subGraph = enterStateNode.SubGraph; if (IsOverriden(nameof(BuildEnterStateEntry))) { BuildEnterStateEntry(ilBuilderContext, subGraph.StateEntry); } //stack.Push(subGraph); ilBuilderContext.EmitLdStack(); ilBuilderContext.IL.Emit(OpCodes.Ldc_I4, subGraph.Id); ilBuilderContext.IL.Emit(OpCodes.Call, PushSafeIdMethodInfo); break; } case InlineEnterStateNode inlineEnterStateNode: { EmitDebugNode(ilBuilderContext, node, executionPath); var stateEntry = inlineEnterStateNode.StateEntry; if (IsOverriden(nameof(BuildEnterStateEntry))) { BuildEnterStateEntry(ilBuilderContext, stateEntry); } break; } case InlineLeaveStateNode inlineLeaveStateNode: { EmitDebugNode(ilBuilderContext, node, executionPath); var stateEntry = inlineLeaveStateNode.StateEntry; if (IsOverriden(nameof(BuildLeaveStateEntry))) { BuildLeaveStateEntry(ilBuilderContext, stateEntry); } break; } case OperandNode operandNode: { EmitDebugNode(ilBuilderContext, node, executionPath); if (IsOverriden(nameof(BuildInvoke))) { BuildInvoke(ilBuilderContext, operandNode.MatchEntry, true); } //_instructionPointer.MoveNext(); ilBuilderContext.EmitLdProcess(); ilBuilderContext.IL.Emit(OpCodes.Call, MoveNextMethodInfo); break; } case PredicateNode predicateNode: { EmitDebugNode(ilBuilderContext, node, executionPath); //if (predicate.Predicate.Predicate(Context) == false) // return null; var returnPredicateLabel = ilBuilderContext.IL.DefineLabel(); var callPredicateLabel = ilBuilderContext.IL.DefineLabel(); var predicate = predicateNode.PredicateEntry; var consumeResult = predicate.ConsumeResult && IsOverriden(nameof(BuildConsumePredicateResult)); var trueLabel = ilBuilderContext.IL.DefineLabel(); var forkLabel = ilBuilderContext.IL.DefineLabel(); var resultLocal = ilBuilderContext.IL.DeclareLocal(typeof(PredicateResult)); ilBuilderContext.EmitLdProcess(); ilBuilderContext.IL.Emit(OpCodes.Ldfld, ExecuteThreadQueueFieldInfo); ilBuilderContext.IL.Emit(OpCodes.Brfalse, callPredicateLabel); // Get Result from Process Result Queue if (consumeResult) { // if (predicate.PopResult == false) // return ilBuilderContext.EmitLdContext(); ilBuilderContext.EmitExecutionPath(); ilBuilderContext.IL.Emit(OpCodes.Call, ShouldPopPredicateResultMethodInfo); ilBuilderContext.IL.Emit(OpCodes.Brfalse, returnPredicateLabel); ilBuilderContext.EmitLdProcess(); ilBuilderContext.IL.Emit(OpCodes.Call, ProcessDequePredicateResultMethodInfo); ilBuilderContext.IL.Emit(OpCodes.Stloc, resultLocal); BuildConsumePredicateResult(ilBuilderContext, resultLocal, predicateNode.PredicateEntry.GetActualPredicateEntry()); ilBuilderContext.IL.Emit(OpCodes.Ldloc, resultLocal); ilBuilderContext.IL.Emit(OpCodes.Callvirt, PredicateResultDisposeMethodInfo); } ilBuilderContext.IL.Emit(OpCodes.Br, returnPredicateLabel); ilBuilderContext.IL.MarkLabel(callPredicateLabel); ilBuilderContext.EmitLdContext(); ilBuilderContext.EmitExecutionPath(); ilBuilderContext.IL.Emit(OpCodes.Call, CallPredicateMethodInfo); ilBuilderContext.IL.Emit(OpCodes.Stloc, resultLocal); ilBuilderContext.IL.Emit(OpCodes.Ldloc, resultLocal); ilBuilderContext.IL.Emit(OpCodes.Brtrue, forkLabel); ilBuilderContext.IL.Emit(OpCodes.Ldnull); ilBuilderContext.IL.Emit(OpCodes.Ret); ilBuilderContext.IL.MarkLabel(forkLabel); // ForkPredicate ilBuilderContext.IL.Emit(OpCodes.Ldloc, resultLocal); ilBuilderContext.IL.Emit(OpCodes.Callvirt, PredicateResultIsForkMethodInfo); ilBuilderContext.IL.Emit(OpCodes.Brfalse, trueLabel); ilBuilderContext.EmitLdProcess(); ilBuilderContext.IL.Emit(OpCodes.Ldc_I4, index); ilBuilderContext.EmitExecutionPath(); ilBuilderContext.IL.Emit(OpCodes.Ldloc, resultLocal); ilBuilderContext.IL.Emit(OpCodes.Call, BuildForkNodeMethodInfo); ilBuilderContext.IL.Emit(OpCodes.Ret); ilBuilderContext.IL.MarkLabel(trueLabel); if (consumeResult) { BuildConsumePredicateResult(ilBuilderContext, resultLocal, predicateNode.PredicateEntry.GetActualPredicateEntry()); ilBuilderContext.IL.Emit(OpCodes.Ldloc, resultLocal); ilBuilderContext.IL.Emit(OpCodes.Callvirt, PredicateResultDisposeMethodInfo); } else { ilBuilderContext.IL.Emit(OpCodes.Ldloc, resultLocal); ilBuilderContext.IL.Emit(OpCodes.Callvirt, PredicateResultDisposeMethodInfo); } ilBuilderContext.IL.MarkLabel(returnPredicateLabel); break; } case ReturnStateNode returnStateNode: { EmitDebugNode(ilBuilderContext, node, executionPath); var lastNode = index == executionPath.Nodes.Length - 1; var leaveNodeLocal = lastNode ? ilBuilderContext.IL.DeclareLocal(typeof(Node)) : null; ilBuilderContext.EmitLdStack(); if (lastNode) { ilBuilderContext.IL.Emit(OpCodes.Call, PopSafeNodeMethodInfo); ilBuilderContext.IL.Emit(OpCodes.Stloc, leaveNodeLocal); } else { ilBuilderContext.IL.Emit(OpCodes.Call, PopSafeMethodInfo); } if (lastNode) { ilBuilderContext.IL.Emit(OpCodes.Ldloc, leaveNodeLocal); ilBuilderContext.IL.Emit(OpCodes.Ret); closure = ilBuilderContext.Values.ToArray(); return(ilBuilderContext.DynMethod); } break; } } } ilBuilderContext.EmitLdValue(executionPath.Output); ilBuilderContext.IL.Emit(OpCodes.Ret); closure = ilBuilderContext.Values.ToArray(); return(ilBuilderContext.DynMethod); }
private void EmitDebugExecutionPath(ILBuilderContext ilBuilderContext, ExecutionPath executionPath) { ilBuilderContext.EmitLdValue(executionPath); ilBuilderContext.IL.Emit(OpCodes.Call, DebugExecutionPathMethodInfo); }
private DynamicMethod BuildParallel(ExecutionPath executionPath, out object[] closure) { var ilBuilderContext = new ILBuilderContext(ContextFieldInfo); for (var index = 0; index < executionPath.Nodes.Length; index++) { var node = executionPath.Nodes[index]; switch (node) { case EnterStateNode enterStateNode: { var subGraph = enterStateNode.SubGraph; //stack.Push(subGraph); ilBuilderContext.EmitLdStack(); ilBuilderContext.EmitLdValue(subGraph); ilBuilderContext.IL.Emit(OpCodes.Call, PushMethodInfo); break; } case ActionNode actionNode: { var action = actionNode.ActionEntry.Action; if (action.Target != null) { ilBuilderContext.EmitLdValue(action.Target); ilBuilderContext.EmitLdContext(); ilBuilderContext.IL.Emit(OpCodes.Callvirt, action.Method); } else { ilBuilderContext.EmitLdContext(); ilBuilderContext.IL.Emit(OpCodes.Call, action.Method); } break; } case OperandNode operandNode: { if (IsOverriden(nameof(BuildInvoke))) { BuildInvoke(ilBuilderContext, operandNode.MatchEntry, false); } //_instructionPointer.MoveNext(); ilBuilderContext.EmitLdProcess(); ilBuilderContext.IL.Emit(OpCodes.Call, MoveNextMethodInfo); break; } case PredicateNode predicateNode: { //if (predicate.Predicate.Predicate(Context) == false) // return null; var predicate = predicateNode.PredicateEntry; var trueLabel = ilBuilderContext.IL.DefineLabel(); var forkLabel = ilBuilderContext.IL.DefineLabel(); var resultLocal = ilBuilderContext.IL.DeclareLocal(typeof(PredicateResult)); ilBuilderContext.EmitLdContext(); ilBuilderContext.EmitExecutionPath(); ilBuilderContext.IL.Emit(OpCodes.Call, CallPredicateMethodInfo); ilBuilderContext.IL.Emit(OpCodes.Stloc, resultLocal); ilBuilderContext.IL.Emit(OpCodes.Ldloc, resultLocal); ilBuilderContext.IL.Emit(OpCodes.Brtrue, forkLabel); ilBuilderContext.IL.Emit(OpCodes.Ldnull); ilBuilderContext.IL.Emit(OpCodes.Ret); ilBuilderContext.IL.MarkLabel(forkLabel); // ForkPredicate ilBuilderContext.IL.Emit(OpCodes.Ldloc, resultLocal); ilBuilderContext.IL.Emit(OpCodes.Callvirt, PredicateResultIsForkMethodInfo); ilBuilderContext.IL.Emit(OpCodes.Brfalse, trueLabel); ilBuilderContext.EmitLdProcess(); ilBuilderContext.IL.Emit(OpCodes.Ldc_I4, index); ilBuilderContext.EmitExecutionPath(); ilBuilderContext.IL.Emit(OpCodes.Ldloc, resultLocal); ilBuilderContext.IL.Emit(OpCodes.Call, BuildForkNodeMethodInfo); ilBuilderContext.IL.Emit(OpCodes.Ret); ilBuilderContext.IL.MarkLabel(trueLabel); if (predicate.ConsumeResult) { ilBuilderContext.EmitLdProcess(); ilBuilderContext.IL.Emit(OpCodes.Ldloc, resultLocal); ilBuilderContext.IL.Emit(OpCodes.Call, ProcessEnqueuePredicateResultMethodInfo); } break; } case ReturnStateNode _: { //return stack.Pop().LeaveNode; ilBuilderContext.EmitLdStack(); ilBuilderContext.IL.Emit(OpCodes.Call, PopMethodInfo); ilBuilderContext.IL.Emit(OpCodes.Ldfld, LeaveNodeFieldInfo); if (index == executionPath.Nodes.Length - 1) { ilBuilderContext.IL.Emit(OpCodes.Ret); closure = ilBuilderContext.Values.ToArray(); return(ilBuilderContext.DynMethod); } ilBuilderContext.IL.Emit(OpCodes.Pop); break; } } } ilBuilderContext.EmitLdValue(executionPath.Output); ilBuilderContext.IL.Emit(OpCodes.Ret); closure = ilBuilderContext.Values.ToArray(); return(ilBuilderContext.DynMethod); }
private void EmitDebugValue(ILBuilderContext ilBuilderContext, object value) { ilBuilderContext.EmitLdContext(); ilBuilderContext.EmitLdValue(value); ilBuilderContext.IL.Emit(OpCodes.Call, DebugMethodInfo); }