Beispiel #1
0
        protected bool IsCopyAlwaysUnnecessaryForAssignmentTarget(JSExpression target)
        {
            target = JSReferenceExpression.Strip(target);

            var targetDot = target as JSDotExpressionBase;

            // The assignment is performing a write into an element proxy, so a copy is unnecessary
            //  because the element proxy immediately unpacks the value into the array.
            if ((targetDot != null) && PackedArrayUtil.IsElementProxy(targetDot.Target))
            {
                return(true);
            }

            return(false);
        }
Beispiel #2
0
        public void VisitNode(JSNewBoxedVariable nbv)
        {
            GenericParameter relevantParameter;

            var initialValue        = nbv.InitialValue;
            var initialValueDerefed = initialValue;

            initialValueDerefed = JSReferenceExpression.Strip(initialValueDerefed);

            var initialValueType = initialValueDerefed.GetActualType(TypeSystem);

            if (!nbv.SuppressClone &&
                IsCopyNeeded(nbv.InitialValue, out relevantParameter) &&
                // We don't need to make a copy if the source value is a reference (like T& this)
                !((initialValueType) != null && initialValueType.IsByReference)
                )
            {
                nbv.ReplaceChild(nbv.InitialValue, new JSStructCopyExpression(nbv.InitialValue));
            }

            VisitChildren(nbv);
        }
Beispiel #3
0
        protected bool IsCopyNeededForAssignmentTarget(JSExpression target)
        {
            target = JSReferenceExpression.Strip(target);

            if (!OptimizeCopies)
            {
                return(true);
            }

            if (IsImmutable(target))
            {
                return(false);
            }

            var variable = target as JSVariable;

            if (variable != null)
            {
                return(SecondPass.IsVariableModified(variable.Name));
            }

            return(true);
        }
Beispiel #4
0
        protected bool IsImmutable(JSExpression target)
        {
            target = JSReferenceExpression.Strip(target);

            var fieldAccess = target as JSFieldAccess;

            if (fieldAccess != null)
            {
                return(fieldAccess.Field.Field.Metadata.HasAttribute("JSIL.Meta.JSImmutable"));
            }

            var dot = target as JSDotExpressionBase;

            if (dot != null)
            {
                if (IsImmutable(dot.Target))
                {
                    return(true);
                }
                else if (IsImmutable(dot.Member))
                {
                    return(true);
                }
            }

            var indexer = target as JSIndexerExpression;

            if (indexer != null)
            {
                if (IsImmutable(indexer.Target))
                {
                    return(true);
                }
            }

            return(false);
        }
Beispiel #5
0
        protected bool IsCopyNeeded(
            JSExpression value,
            out GenericParameter relevantParameter,
            bool allowImmutabilityOptimizations = true
            )
        {
            relevantParameter = null;

            if ((value == null) || (value.IsNull))
            {
                return(false);
            }

            value = JSReferenceExpression.Strip(value);

            var sce = value as JSStructCopyExpression;

            if (sce != null)
            {
                return(false);
            }

            var valueType        = value.GetActualType(TypeSystem);
            var valueTypeDerefed = TypeUtil.DereferenceType(valueType) ?? valueType;

            var cte  = value as JSChangeTypeExpression;
            var cast = value as JSCastExpression;

            TypeReference originalType;
            int           temp;

            if (cte != null)
            {
                originalType = cte.Expression.GetActualType(TypeSystem);
            }
            else if (cast != null)
            {
                originalType = cast.Expression.GetActualType(TypeSystem);
            }
            else
            {
                originalType = null;
            }

            if (originalType != null)
            {
                originalType = TypeUtil.FullyDereferenceType(originalType, out temp);

                if (!IsStructOrGenericParameter(valueTypeDerefed) && !IsStructOrGenericParameter(originalType))
                {
                    return(false);
                }

                relevantParameter = (originalType as GenericParameter) ?? (valueTypeDerefed as GenericParameter);
            }
            else
            {
                if (!IsStructOrGenericParameter(valueTypeDerefed))
                {
                    return(false);
                }

                relevantParameter = (valueTypeDerefed as GenericParameter);
            }

            if (value is JSValueOfNullableExpression)
            {
                return(true);
            }

            if (IsTypeExcludedFromCopies(valueType))
            {
                return(false);
            }

            if (
                (value is JSLiteral) ||
                (value is JSNewExpression) ||
                (value is JSPassByReferenceExpression) ||
                (value is JSNewBoxedVariable) ||
                (value is JSDefaultValueLiteral) ||
                (value is JSFieldOfExpression)
                )
            {
                return(false);
            }

            if (!OptimizeCopies)
            {
                return(true);
            }

            if (IsImmutable(value) && allowImmutabilityOptimizations)
            {
                return(false);
            }

            var valueDot = value as JSDotExpressionBase;

            // The value is being read out of an element proxy, so no copy is necessary - the read unpacks the value
            //  on demand from the packed array.
            if (
                (valueDot != null) &&
                PackedArrayUtil.IsElementProxy(valueDot.Target)
                )
            {
                // return false;
            }

            var valueTypeInfo = TypeInfo.GetExisting(valueType);

            if ((valueTypeInfo != null) && valueTypeInfo.IsImmutable && allowImmutabilityOptimizations)
            {
                return(false);
            }

            // If the expression is a parameter that is only used once and isn't aliased,
            //  we don't need to copy it.
            var rightVar = value as JSVariable;

            if (rightVar != null)
            {
                int referenceCount;
                if (
                    ReferenceCounts.TryGetValue(rightVar.Identifier, out referenceCount) &&
                    (referenceCount == 1) &&
                    !rightVar.IsReference &&
                    rightVar.IsParameter &&
                    !SecondPass.VariableAliases.ContainsKey(rightVar.Identifier)
                    )
                {
                    if (TraceElidedCopies)
                    {
                        Console.WriteLine(String.Format("Returning false from IsCopyNeeded for parameter {0} because reference count is 1 and it has no aliases", value));
                    }

                    return(false);
                }
            }

            return(true);
        }