public static SymbolicSlot Merge(SymbolicSlot first, SymbolicSlot second) { if (first == second) { return(first); } var result = new SymbolicSlot(); Merge(first, second, result); return(result); }
// store by address public void Store(SymbolicSlot value) { if (IsConstAfterSimplification() || value.IsConstAfterSimplification()) { return; } // store like a field because we should create a snapshot in the moment // and avoid cycled references in the "values" field MaterializeFields(); value.MaterializeFields(); if (IsConstAfterSimplification() || value.IsConstAfterSimplification()) { return; } var mergedEntity = SymbolicReference.Merge(entities, value.entities); entities = new[] { mergedEntity }; value.entities = new[] { mergedEntity }; }
public void StoreField(string name, SymbolicSlot value) { if (IsConstAfterSimplification() || value.IsConstAfterSimplification()) { return; } MaterializeFields(); value.MaterializeFields(); if (IsConstAfterSimplification() || value.IsConstAfterSimplification()) { return; } var targetEntity = SymbolicReference.Merge(value.entities); for (int i = 0; i < entities.Length; i++) { var entity = entities[i]; entity.StoreField(name, targetEntity); } }
private static List <SymbolicReference> MaterializeFields(SymbolicSlot value) { var newEntities = new List <SymbolicReference>(); var queue = new Queue <(SymbolicSlot, string[][])>(); queue.Enqueue((value, new string[0][])); // var context = new VisitingContext<SymbolicSlot>(); while (queue.Count > 0) { var(slot, topFields) = queue.Dequeue(); // if (!context.Visit(slot)) // continue; if (slot.values != null) { Debug.Assert(slot.entities == null); string[][] allFields; if (slot.fields != null) { allFields = new string[topFields.Length + 1][]; Array.Copy(topFields, allFields, topFields.Length); allFields[allFields.Length - 1] = slot.fields; } else { allFields = topFields; } for (int i = 0; i < slot.values.Length; i++) { queue.Enqueue((slot.values[i], allFields)); } } else if (slot.entities != null) { Debug.Assert(slot.values == null); for (int i = 0; i < slot.entities.Length; i++) { var entity = slot.entities[i]; if (slot.fields != null) { for (int f = 0; f < slot.fields.Length; f++) { var field = slot.fields[f]; entity = entity.LoadField(field); } } for (int j = topFields.Length - 1; j >= 0; j--) { var slotFields = topFields[j]; for (int f = 0; f < slotFields.Length; f++) { var field = slotFields[f]; entity = entity.LoadField(field); } } newEntities.Add(entity); } } else { Debug.Fail("SSlot must contain either values or entities"); } } return(newEntities); }
private static void Merge(SymbolicSlot first, SymbolicSlot second, SymbolicSlot result) { if (first.fields == null && second.fields == null) { if (first.entities != null && second.entities != null) { Debug.Assert(first.entities.Length > 0 && second.entities.Length > 0); Debug.Assert(first.values == null && second.values == null); var newEntities = new SymbolicReference[first.entities.Length + second.entities.Length]; Array.Copy(first.entities, newEntities, first.entities.Length); Array.Copy(second.entities, 0, newEntities, first.entities.Length, second.entities.Length); result.Reset(newEntities, null, null); return; } if (first.entities != null) { Debug.Assert(first.entities.Length > 0 && second.entities == null); Debug.Assert(first.values == null && second.values != null); var newValues = new SymbolicSlot[second.values.Length + 1]; Array.Copy(second.values, newValues, second.values.Length); newValues[newValues.Length - 1] = new SymbolicSlot(first.entities, null, null); result.Reset(null, newValues, null); return; } if (second.entities != null) { Debug.Assert(first.entities == null && second.entities.Length > 0); Debug.Assert(first.values != null && second.values == null); var newValues = new SymbolicSlot[first.values.Length + 1]; Array.Copy(first.values, newValues, first.values.Length); newValues[newValues.Length - 1] = new SymbolicSlot(second.entities, null, null); result.Reset(null, newValues, null); return; } { Debug.Assert(first.entities == null && second.entities == null); Debug.Assert(first.values != null && second.values != null); Debug.Assert(first.values.Length > 0 && second.values.Length > 0); var newValues = new SymbolicSlot[first.values.Length + second.values.Length]; Array.Copy(first.values, newValues, first.values.Length); Array.Copy(second.values, 0, newValues, first.values.Length, second.values.Length); result.Reset(null, newValues, null); return; } } if (first.fields == null && first.values != null) { Debug.Assert(first.entities == null); Debug.Assert(first.values.Length > 0); var newValues = new SymbolicSlot[first.values.Length + 1]; Array.Copy(first.values, newValues, first.values.Length); newValues[newValues.Length - 1] = second; result.Reset(null, newValues, null); return; } if (second.fields == null && second.values != null) { Debug.Assert(second.entities == null); Debug.Assert(second.values.Length > 0); var newValues = new SymbolicSlot[second.values.Length + 1]; Array.Copy(second.values, newValues, second.values.Length); newValues[newValues.Length - 1] = first; result.Reset(null, newValues, null); return; } result.Reset(null, new [] { first, second }, null); }