/// <summary> /// Processes single merge operation - prepares all valid values and alias informations from the source indexes. /// When the source indexes contains some array values prepares operation for every descendant index and merge the /// array into one which will be stored in the target memory entry. /// </summary> /// <param name="operation">The operation.</param> private void processMergeOperation(MergeOperation operation) { HashSet <Value> values = new HashSet <Value>(); foreach (var operationData in operation.Indexes) { MemoryIndex index = operationData.Item1; Snapshot snapshot = operationData.Item2; MemoryEntry entry = SnapshotDataUtils.GetMemoryEntry(snapshot, snapshot.Infos.Readonly, index); CollectionMemoryUtils.AddAll(values, entry.PossibleValues); } if (Structure.Readonly.HasArray(operation.TargetIndex)) { mergeArrays(operation); } if (operation.IsUndefined) { values.Add(targetSnapshot.UndefinedValue); } Infos.Writeable.SetMemoryEntry(operation.TargetIndex, targetSnapshot.CreateMemoryEntry(values)); }
/// <summary> /// Prepares operation for every descendant index of target array. /// </summary> /// <param name="operation">The operation.</param> /// <returns>Array where the input arrays is merged into.</returns> private void mergeArrays(MergeOperation operation) { AssociativeArray targetArray = Structure.Readonly.GetArray(operation.TargetIndex); IArrayDescriptor targetDescriptor = Structure.Readonly.GetDescriptor(targetArray); ContainerOperations collectIndexes = new ContainerOperations(this, targetDescriptor, operation.TargetIndex, targetDescriptor.UnknownIndex); foreach (var operationData in operation.Indexes) { MemoryIndex index = operationData.Item1; Snapshot snapshot = operationData.Item2; AssociativeArray arrayValue; if (snapshot.Structure.Readonly.TryGetArray(index, out arrayValue)) { IArrayDescriptor descriptor = snapshot.Structure.Readonly.GetDescriptor(arrayValue); collectIndexes.AddContainer(descriptor, snapshot); } else { collectIndexes.SetUndefined(); } } collectIndexes.MergeContainers(); }
/// <summary> /// Creates merge operations for all indexes in the target collection. Source indexes for the operation are /// retreived from the source collections. When there is missing index in some collection the operation set /// to undefined. /// /// This method is for both phases of analysis. /// </summary> public void MergeContainers() { // Process all names which has unassociated index and creates one foreach (string indexName in undefinedIndexes) { writeableTargetContainer.AddIndex(indexName, targetIndex.CreateIndex(indexName)); } foreach (var index in targetContainer.Indexes) { MergeOperation operation = new MergeOperation(index.Value); worker.addOperation(operation); if (isUndefined) { operation.SetUndefined(); } foreach (var source in sources) { IReadonlyIndexContainer container = source.Item1; Snapshot snapshot = source.Item2; MemoryIndex containerIndex; if (container.TryGetIndex(index.Key, out containerIndex)) { operation.Add(containerIndex, snapshot); } else { operation.Add(container.UnknownIndex, snapshot); } } } }
/// <summary> /// Gets the operation at the top of operation stack. Operation is removed from stack. /// </summary> /// <returns>First operation in the memory stack</returns> private MergeOperation getOperation() { MergeOperation operation = operationStack.First.Value; operationStack.RemoveFirst(); return(operation); }
/// <summary> /// Process all merge operations. Continues processing until operation stack is empty. /// </summary> private void processMerge() { while (operationStack.Count > 0) { MergeOperation operation = getOperation(); processMergeOperation(operation); } }
/// <summary> /// Prepares operation for every descendant index and merge the array into one which will be /// stored in the target memory entry. /// </summary> /// <param name="operation">The operation.</param> /// <returns>Array where the input arrays is merged into.</returns> private Value mergeArrays(MergeOperation operation) { var structure = writeableStrucure; IArrayDescriptorBuilder builder = Factories.StructuralContainersFactories.ArrayDescriptorFactory.CreateArrayDescriptor(writeableStrucure, null, operation.TargetIndex).Builder(structure); builder.SetUnknownIndex(operation.TargetIndex.CreateUnknownIndex()); ContainerOperations collectVariables = new ContainerOperations(this, builder, operation.TargetIndex, builder.UnknownIndex); // Collecting possible indexes of merged array AssociativeArray targetArray = null; foreach (var operationData in operation.Indexes) { MemoryIndex index = operationData.Item1; Snapshot snapshot = operationData.Item2; AssociativeArray arrayValue; if (snapshot.Structure.Readonly.TryGetArray(index, out arrayValue)) { // Target array value will be the firs one if (targetArray == null) { if (index.Equals(operation.TargetIndex)) { targetArray = arrayValue; } } IArrayDescriptor descriptor = snapshot.Structure.Readonly.GetDescriptor(arrayValue); collectVariables.CollectIndexes(snapshot, index, descriptor); } else { collectVariables.SetUndefined(); } } if (targetArray == null) { targetArray = targetSnapshot.CreateArray(); } builder.SetArrayValue(targetArray); collectVariables.MergeContainers(); structure.SetArray(operation.TargetIndex, targetArray); structure.SetDescriptor(targetArray, builder.Build(structure)); return(targetArray); }
/// <summary> /// Main method of merge algorithm. /// /// iI first phase prepares new empty data collection. Then collects all root memory locations and /// prepares their operations. As the final step process all merge operations which traverses the /// memory tree and merges data from all source indexes. /// </summary> internal void Merge() { ContainerOperations[] collectVariables = new ContainerOperations[targetCallLevel + 1]; ContainerOperations[] collectControl = new ContainerOperations[targetCallLevel + 1]; MergeOperation returnOperation = new MergeOperation(); for (int x = 0; x <= targetCallLevel; x++) { IReadonlyIndexContainer variables = Structure.Readonly.GetReadonlyStackContext(x).ReadonlyVariables; collectVariables[x] = new ContainerOperations(this, variables, variables.UnknownIndex, variables.UnknownIndex); IReadonlyIndexContainer control = Structure.Readonly.GetReadonlyStackContext(x).ReadonlyControllVariables; collectControl[x] = new ContainerOperations(this, control, control.UnknownIndex, control.UnknownIndex); } foreach (Snapshot snapshot in sourceSnapshots) { for (int sourceLevel = 0, targetLevel = 0; targetLevel <= targetCallLevel; sourceLevel++, targetLevel++) { if (sourceLevel == snapshot.CallLevel && snapshot.CallLevel != targetCallLevel) { if (isCallMerge) { break; } else { targetLevel = targetCallLevel; } } IReadonlyIndexContainer variables = snapshot.Structure.Readonly.GetReadonlyStackContext(sourceLevel).ReadonlyVariables; collectVariables[targetLevel].AddContainer(variables, snapshot); IReadonlyIndexContainer control = snapshot.Structure.Readonly.GetReadonlyStackContext(sourceLevel).ReadonlyControllVariables; collectControl[targetLevel].AddContainer(control, snapshot); } } mergeObjects(); for (int x = 0; x <= targetCallLevel; x++) { collectVariables[x].MergeContainers(); collectControl[x].MergeContainers(); mergeTemporary(x); } processMerge(); }
/// <summary> /// Initializes a new instance of the <see cref="ContainerOperations"/> class. /// </summary> /// <param name="worker">The worker.</param> /// <param name="targetContainer">The target container.</param> /// <param name="targetIndex">Index of the target.</param> /// <param name="unknownIndex">Index of the unknown.</param> public ContainerOperations( IMergeWorker worker, IWriteableIndexContainer targetContainer, MemoryIndex targetIndex, MemoryIndex unknownIndex) { this.targetContainer = targetContainer; this.writeableTargetContainer = targetContainer; this.worker = worker; this.targetIndex = targetIndex; unknownOperation = new MergeOperation(unknownIndex); worker.addOperation(unknownOperation); }
public void MergeIndexes(MemoryIndex targetIndex, MemoryIndex sourceIndex) { if (!sourceIndex.IsPrefixOf(targetIndex) && !targetIndex.IsPrefixOf(sourceIndex)) { MergeOperation operation = new MergeOperation(targetIndex); operation.Add(targetIndex, targetSnapshot); operation.Add(sourceIndex, targetSnapshot); operation.IsRoot = true; addOperation(operation); arrayCount = 2; processMerge(); } }
/// <summary> /// Gets all values which can be in target memory entry. If sources contains some arrays merge this arrays together /// and traverse their indexes. /// </summary> /// <param name="operation">The operation.</param> /// <param name="visitor">The visitor.</param> /// <returns>Values for the target memory entry.</returns> private HashSet <Value> getValues(MergeOperation operation, CollectComposedValuesVisitor visitor) { HashSet <Value> values = visitor.Values; bool noScalarValue = visitor.Values.Count == 0; if (visitor.Arrays.Count > 0) { values.Add(mergeArrays(operation)); } foreach (ObjectValue value in visitor.Objects) { values.Add(value); } return(values); }
/// <summary> /// Creates merge operations for all temporary indexes in the target structure. /// </summary> /// <param name="index">The index.</param> private void mergeTemporary(int index) { foreach (var temp in Structure.Readonly.GetReadonlyStackContext(index).ReadonlyTemporaryVariables) { MergeOperation operation = new MergeOperation(temp); addOperation(operation); foreach (Snapshot snapshot in sourceSnapshots) { if (snapshot.Structure.Readonly.IsDefined(temp)) { operation.Add(temp, snapshot); } else { operation.SetUndefined(); } } } }
/// <summary> /// Processes single merge operation - prepares all valid values and alias informations from the source indexes. /// When the source indexes contains some array values prepares operation for every descendant index and merge the /// array into one which will be stored in the target memory entry. /// </summary> /// <param name="operation">The operation.</param> private void processMergeOperation(MergeOperation operation) { CollectComposedValuesVisitor visitor = new CollectComposedValuesVisitor(); ReferenceCollector references = new ReferenceCollector(); // Collect all data from source indexes foreach (var operationData in operation.Indexes) { MemoryIndex index = operationData.Item1; Snapshot snapshot = operationData.Item2; MemoryEntry entry = SnapshotDataUtils.GetMemoryEntry(snapshot, snapshot.CurrentData.Readonly, index); visitor.VisitMemoryEntry(entry); IMemoryAlias aliases; if (snapshot.Structure.Readonly.TryGetAliases(index, out aliases)) { references.CollectMust(aliases.MustAliases, targetSnapshotCallLevel); references.CollectMay(aliases.MayAliases, targetSnapshotCallLevel); } else { references.InvalidateMust(); } } references.SetAliases(operation.TargetIndex, this, !operation.IsUndefined); //repares the set of values - array values are traversed HashSet <Value> values = getValues(operation, visitor); // If some index in operation can be undefined add undefined value into result if (operation.IsUndefined) { values.Add(targetSnapshot.UndefinedValue); } Data.Writeable.SetMemoryEntry(operation.TargetIndex, targetSnapshot.CreateMemoryEntry(values)); writeableStrucure.SetObjects(operation.TargetIndex, Factories.StructuralContainersFactories.ObjectValueContainerFactory.CreateObjectValueContainer(writeableStrucure, visitor.Objects)); }
/// <summary> /// Creates merge operations for all temporary indexes in the target structure. /// </summary> /// <param name="index">The index.</param> private void mergeTemporary(int index) { IWriteableSet <MemoryIndex> temporary = writeableStrucure.GetWriteableStackContext(index).WriteableTemporaryVariables; foreach (var temp in temporary) { MergeOperation operation = new MergeOperation(temp); addOperation(operation); foreach (Snapshot snapshot in sourceSnapshots) { if (snapshot.Structure.Readonly.IsDefined(temp)) { operation.Add(temp, snapshot); } else { operation.SetUndefined(); } } } }
private AssociativeArray mergeArrays( MemoryIndex targetIndex, HashSet <AssociativeArray> arrays, bool includeUndefined) { AssociativeArray arrayValue; if (!targetSnapshot.Structure.Readonly.TryGetArray(targetIndex, out arrayValue)) { arrayValue = targetSnapshot.CreateArray(targetIndex); } IArrayDescriptor newDescriptor = targetSnapshot.Structure.Readonly.GetDescriptor(arrayValue); MergeOperation unknownMerge = new MergeOperation(newDescriptor.UnknownIndex); unknownMerge.SetUndefined(); addOperation(unknownMerge); HashSet <string> indexNames = new HashSet <string>(); foreach (AssociativeArray array in arrays) { foreach (Tuple <Snapshot, IArrayDescriptor> item in getIArrayDescriptor(array)) { Snapshot snapshot = item.Item1; IArrayDescriptor descriptor = item.Item2; unknownMerge.Add(descriptor.UnknownIndex, snapshot); foreach (var index in descriptor.Indexes) { indexNames.Add(index.Key); } } } foreach (string indexName in indexNames) { MergeOperation operation = new MergeOperation(); if (includeUndefined) { operation.SetUndefined(); } foreach (var array in arrays) { foreach (Tuple <Snapshot, IArrayDescriptor> item in getIArrayDescriptor(array)) { Snapshot snapshot = item.Item1; IArrayDescriptor descriptor = item.Item2; MemoryIndex sourceIndex; if (descriptor.TryGetIndex(indexName, out sourceIndex)) { operation.Add(sourceIndex, snapshot); } else { operation.Add(descriptor.UnknownIndex, snapshot); } } } MemoryIndex arrayIndex; if (!newDescriptor.TryGetIndex(indexName, out arrayIndex)) { arrayIndex = targetSnapshot.CreateIndex(indexName, arrayValue, true, false); } operation.SetTargetIndex(arrayIndex); addOperation(operation); } return(arrayValue); }
/// <summary> /// Adds operation into stack of merge worker. /// </summary> /// <param name="operation">The operation.</param> public void addOperation(MergeOperation operation) { operationStack.AddLast(operation); }
private void processMergeOperation(MergeOperation operation) { CollectComposedValuesVisitor visitor = new CollectComposedValuesVisitor(); ReferenceCollector references = new ReferenceCollector(); foreach (var item in operation.Indexes) { Snapshot snapshot = item.Item2; MemoryIndex index = item.Item1; MemoryEntry entry = SnapshotDataUtils.GetMemoryEntry(snapshot, snapshot.CurrentData.Readonly, index); visitor.VisitMemoryEntry(entry); IMemoryAlias aliases; if (snapshot.Structure.Readonly.TryGetAliases(index, out aliases)) { references.CollectMust(aliases.MustAliases, snapshot.CallLevel); references.CollectMay(aliases.MayAliases, snapshot.CallLevel); } else { references.InvalidateMust(); } } if (references.HasAliases && !operation.IsRoot) { if (!operation.IsUndefined && operation.Indexes.Count == 1 && references.HasMustAliases) { if (targetSnapshot == operation.Indexes.First().Item2) { references.AddMustAlias(operation.Indexes.First().Item1); } } else { HashSet <MemoryIndex> referenceIndexes = new HashSet <MemoryIndex>(); foreach (var item in operation.Indexes) { MemoryIndex index = item.Item1; Snapshot snapshot = item.Item2; if (index != operation.TargetIndex && targetSnapshot == snapshot) { referenceIndexes.Add(index); } } references.CollectMay(referenceIndexes, targetSnapshot.CallLevel); } } references.SetAliases(operation.TargetIndex, targetSnapshot, !operation.IsUndefined); HashSet <Value> values = getValues(operation.TargetIndex, visitor, operation.IsUndefined); if (operation.IsUndefined) { values.Add(targetSnapshot.UndefinedValue); } targetSnapshot.CurrentData.Writeable.SetMemoryEntry(operation.TargetIndex, targetSnapshot.CreateMemoryEntry(values)); }
/// <summary> /// Main method of merge algorithm. /// /// in first phase prepares new empty structure and data collections. Then collects all root memory locations /// and prepares their operations. As the final step process all merge operations which traverses the memory tree /// and creates new memory locations in target structure with the data from all source indexes. /// </summary> internal void Merge() { ContainerOperations[] collectVariables = new ContainerOperations[targetSnapshotCallLevel + 1]; ContainerOperations[] collectControl = new ContainerOperations[targetSnapshotCallLevel + 1]; MergeOperation returnOperation = new MergeOperation(); // Prepares empty structure for target snapshot for (int x = 0; x <= targetSnapshotCallLevel; x++) { writeableStrucure.AddLocalLevel(); IWriteableIndexContainer variables = writeableStrucure.GetWriteableStackContext(x).WriteableVariables; collectVariables[x] = new ContainerOperations(this, variables, variables.UnknownIndex, variables.UnknownIndex); IWriteableIndexContainer control = writeableStrucure.GetWriteableStackContext(x).WriteableControllVariables; collectControl[x] = new ContainerOperations(this, control, control.UnknownIndex, control.UnknownIndex); } // Collects all objects and root locations from the source objects foreach (Snapshot snapshot in sourceSnapshots) { collectObjects(snapshot); for (int sourceLevel = 0, targetLevel = 0; targetLevel <= targetSnapshotCallLevel; sourceLevel++, targetLevel++) { // Local levels of snaphot has to be merged together no matter to call level of each snapshot. if (sourceLevel == snapshot.CallLevel && snapshot.CallLevel != targetSnapshotCallLevel) { if (isCallMerge) { // When this is the call merge the local level is forgotten break; } else { targetLevel = targetSnapshotCallLevel; } } // Gets all root locations IWriteableIndexContainer targetVariables = writeableStrucure.GetWriteableStackContext(targetLevel).WriteableVariables; IReadonlyIndexContainer sourceVariables = snapshot.Structure.Readonly.GetReadonlyStackContext(sourceLevel).ReadonlyVariables; collectVariables[targetLevel].CollectIndexes(snapshot, targetVariables.UnknownIndex, sourceVariables); IWriteableIndexContainer targetControlls = writeableStrucure.GetWriteableStackContext(targetLevel).WriteableControllVariables; IReadonlyIndexContainer sourceControlls = snapshot.Structure.Readonly.GetReadonlyStackContext(sourceLevel).ReadonlyControllVariables; collectControl[targetLevel].CollectIndexes(snapshot, targetControlls.UnknownIndex, sourceControlls); collectTemporary(snapshot, sourceLevel, targetLevel); } foreach (var name in snapshot.Structure.Readonly.GetFunctions()) { foreach (var decl in snapshot.Structure.Readonly.GetFunction(name)) { writeableStrucure.AddFunctiondeclaration(name, decl); } } foreach (var name in snapshot.Structure.Readonly.GetClasses()) { foreach (var decl in snapshot.Structure.Readonly.GetClass(name)) { writeableStrucure.AddClassDeclaration(name, decl); } } // When is it call merge remember which arrays was forgotten in order to support arrays in returns if (isCallMerge) { foreach (AssociativeArray array in snapshot.Structure.Readonly.ReadonlyLocalContext.ReadonlyArrays) { writeableStrucure.AddCallArray(array, snapshot); } } } mergeObjects(); // Prepares operations for all root locations for (int x = 0; x <= targetSnapshotCallLevel; x++) { collectVariables[x].MergeContainers(); collectControl[x].MergeContainers(); mergeTemporary(x); } processMerge(); // Build aliases foreach (var alias in memoryAliases) { writeableStrucure.SetAlias(alias.Key, alias.Value.Build(writeableStrucure)); } }
private void addOperation(MergeOperation operation) { operationStack.AddLast(operation); }