private void InvocationsReExecutor( SecondaryEntity state, MyGssNode stack, Node position, MyTransition currentTransition, PrimaryEntity newType) { var invocation = (ResolvedInvocationStatement <Node>)currentTransition.Statement; if (newType is IInvokable <Node> invocable) { //Logging.Log("dynamic re-invocation"); if (state is UnknownEntity) { Push(state, new MyStackData(currentTransition, state, true), invocable.EntryPoint); invocable.MarkAsInvoked(); } else { var recipientId = invocation.PassedParameters[state]; var exists = invocable.Variables.TryGetValue(recipientId.Value, out var recipient); if (exists) { Push(recipient, new MyStackData(currentTransition, state, true), invocable.EntryPoint); } } } if (newType is ResolvedClassId classId) { var target = myProcessingProgram .FindClassById(classId) .FindMethodInFullHierarchy(invocation.TargetMethodId); if (target == null) { return; } if (state is UnknownEntity) { Push(state, new MyStackData(currentTransition, state, true), target.EntryPoint); target.MarkAsInvoked(); } else { var recipientId = invocation.PassedParameters[state]; var exists = target.Variables.TryGetValue(recipientId.Value, out var recipient); if (exists) { Push(recipient, new MyStackData(currentTransition, state, true), target.Start); } } } }
public override void Action(SecondaryEntity state, MyGssNode stack) { if (stack.Symbol.Trampoline) { if (state is FakeTrampolineEntity fake) { Pop(fake.OriginalTarget, stack.Symbol.CallingEdge.Target); } else { Push(state, new MyStackData(stack.Symbol.CallingEdge, stack.Symbol.TrackedEntity, false)); } } }
public override void Step(SecondaryEntity state, MyGssNode stack, Node position, MyTransition currentTransition) { if (stack.Symbol.Trampoline) { return; } var statement = currentTransition.Statement; switch (statement.Type) { case StatementType.Internal: var internalStatement = (InternalStatement)statement; ParameterIndex recipientId; bool exists; switch (internalStatement.InternalType) { case InternalStatementType.ResolvedInvocation: var invocation = (ResolvedInvocationStatement <Node>)internalStatement; exists = invocation.PassedParameters.TryGetValue(state, out recipientId); var scanning = state is UnknownEntity; Skip(state); if (exists || scanning) { if (invocation.TargetEntity is SecondaryEntity variable) { var instances = CollectInstances( variable, invocation.TargetMethodId); foreach (var instance in instances.ToList()) { //Logging.Log("dynamic invocation"); if (exists) { instance.Variables.TryGetValue(recipientId.Value, out var recipient); if (recipient != null) { Push(recipient, new MyStackData(currentTransition, state, true), instance.EntryPoint); //Logging.Log("recipient is not null"); } else { //Logging.Log($"recipient is null: {myProcessingProgram.GetMethodByStartPoint(instance.EntryPoint)}, {recipientId.Value}"); } } if (scanning) { Push(state, new MyStackData(currentTransition, state, true), instance.EntryPoint); instance.MarkAsInvoked(); } } var head = ExtractHead(); variable.Subscriptions.OnNewPrimaryAdded += newType => { myForcedExecutor(head, currentTransition, InvocationsReExecutor, newType); }; } if (invocation.TargetEntity is ResolvedClassId classId) { var clazz = myProcessingProgram.FindClassById(classId); var method = clazz.FindMethodInFullHierarchy(invocation.TargetMethodId); if (method != null) { if (exists) { method.Variables.TryGetValue(recipientId.Value, out var recipient); if (recipient != null) { Push(recipient, new MyStackData(currentTransition, state, true), method.Start); //Logging.Log("recipient is not null"); } else { //Logging.Log($"recipient is null: {myProcessingProgram.GetMethodByStartPoint(method.EntryPoint)}, {recipientId.Value}"); } } if (scanning) { Push(state, new MyStackData(currentTransition, state, true), method.EntryPoint); method.MarkAsInvoked(); } } } } break; case InternalStatementType.Return: var stackTop = stack.Symbol; if (stackTop.CallingEdge.Statement is NopStatement) { break; } var callingStatement = (ResolvedInvocationStatement <Node>)stackTop.CallingEdge.Statement; if (state is ResolvedLocalVariable localVariable) { var id = new ParameterIndex(localVariable.LocalId); exists = callingStatement.ReturnedValues.TryGetValue(id, out var recipient); if (exists) { Pop(new FakeTrampolineEntity(recipient)); } } break; case InternalStatementType.ResolvedAssignment: var assignment = (ResolvedAssignmentStatement)currentTransition.Statement; Skip(state); //Trace.Assert(assignment.Target != null); if (assignment.Target == null) { break; } if (state is UnknownEntity) { if (assignment.Source is PrimaryEntity primary) { assignment.Target.AddPrimary(primary); Accept(assignment.Target); } else { ((SecondaryEntity)assignment.Source).PropagateForward(assignment.Target); if (assignment.Target is ResolvedLocalVariable) { Accept(assignment.Target); } } } /* * if ((assignment.Source is ResolvedObjectField || * assignment.Source is ResolvedClassField || * assignment.Source is ResolvedObjectMethodReference<Node>) && * state is UnknownEntity) * { * var asSecondary = (SecondaryEntity) assignment.Source; * asSecondary.PropagateForward(assignment.Target); * Accept(assignment.Target); * } */ if (ReferenceEquals(assignment.Source, state)) { Accept(assignment.Target); } break; } break; default: Skip(state); break; } }