Beispiel #1
0
        public static SymbolicSlot Merge(SymbolicSlot first, SymbolicSlot second)
        {
            if (first == second)
            {
                return(first);
            }

            var result = new SymbolicSlot();

            Merge(first, second, result);
            return(result);
        }
Beispiel #2
0
        // 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 };
        }
Beispiel #3
0
        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);
            }
        }
Beispiel #4
0
        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);
        }
Beispiel #5
0
        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);
        }