示例#1
0
        protected JSVariable GetConstructedReference(JSPassByReferenceExpression pbr)
        {
            JSVariable   referentVariable;
            JSExpression referent;

            if (!JSReferenceExpression.TryMaterialize(JSIL, pbr.Referent, out referent))
            {
                // If the reference can be dereferenced, but cannot be materialized, it is
                //  a constructed reference.
                if (JSReferenceExpression.TryDereference(JSIL, pbr.Referent, out referent))
                {
                    referentVariable = referent as JSVariable;

                    // Ignore variables we previously transformed.
                    if ((referentVariable != null) && TransformedVariables.Contains(referentVariable.Identifier))
                    {
                        return(null);
                    }

                    return(referentVariable);
                }
                else
                {
                    return(null);
                }
            }

            referentVariable = referent as JSVariable;
            if (referentVariable == null)
            {
                return(null);
            }

            // Ignore variables we previously transformed.
            if (TransformedVariables.Contains(referentVariable.Identifier))
            {
                return(null);
            }

            // If the variable does not match the one in the dictionary, it is a constructed
            //  reference to a parameter.
            if (!referentVariable.Equals(Variables[referentVariable.Identifier]))
            {
                // If the parameter is a reference, we don't care about it.
                if (Variables[referentVariable.Identifier].IsReference)
                {
                    return(null);
                }
                else
                {
                    return(referentVariable);
                }
            }

            return(null);
        }
示例#2
0
 public void VisitNode(JSReferenceExpression re)
 {
     if (re.Referent.IsConstant)
     {
         Visit(re.Referent);
     }
     else
     {
         Console.WriteLine("Can't translate {0}", re);
         Formatter.WriteSExpr("untranslatable.reference");
     }
 }
        public void VisitNode(JSBinaryOperatorExpression boe)
        {
            JSExpression left;

            if (!JSReferenceExpression.TryDereference(JSIL, boe.Left, out left))
            {
                left = boe.Left;
            }

            var leftVar        = left as JSVariable;
            var leftChangeType = left as JSChangeTypeExpression;

            if (leftChangeType != null)
            {
                leftVar = leftChangeType.Expression as JSVariable;
            }

            if (
                !(ParentNode is JSVariableDeclarationStatement) &&
                (leftVar != null) &&
                (leftVar.Identifier == Variable.Identifier)
                )
            {
                if (boe.Operator is JSAssignmentOperator)
                {
                    var replacement = new JSWriteThroughReferenceExpression(
                        Variable, boe.Right
                        );
                    ParentNode.ReplaceChild(boe, replacement);
                    VisitReplacement(replacement);
                }
                else
                {
                    VisitChildren(boe);
                }
            }
            else if (ParentNode is JSVariableDeclarationStatement)
            {
                // Don't walk through the left-hand side of variable declarations.
                VisitChildren(
                    boe,
                    (node, name) => name != "Left"
                    );
            }
            else
            {
                VisitChildren(boe);
            }
        }
示例#4
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);
        }
示例#5
0
        public void VisitNode(JSPassByReferenceExpression byref)
        {
            JSExpression referent;

            if (JSReferenceExpression.TryMaterialize(JSIL, byref.Referent, out referent))
            {
                Output.Comment("ref");
                Visit(referent);
            }
            else
            {
                Output.Identifier("JSIL.UnmaterializedReference", null);
                Output.LPar();
                Output.RPar();
            }
        }
        public void VisitNode(JSUnaryOperatorExpression uoe)
        {
            JSExpression expr;

            if (!JSReferenceExpression.TryDereference(JSIL, uoe.Expression, out expr))
            {
                expr = uoe.Expression;
            }

            var eVar        = expr as JSVariable;
            var eChangeType = expr as JSChangeTypeExpression;

            if (eChangeType != null)
            {
                eVar = eChangeType.Expression as JSVariable;
            }

            var type = uoe.Expression.GetActualType(TypeSystem);

            if (
                (eVar != null) &&
                (eVar.Identifier == Variable.Identifier) &&
                (uoe.Operator is JSUnaryMutationOperator)
                )
            {
                var newValue = DecomposeMutationOperators.DecomposeUnaryMutation(
                    uoe, () => TemporaryVariable.ForFunction(
                        Stack.Last() as JSFunctionExpression, type
                        ), type, TypeSystem
                    );
                var replacement = new JSWriteThroughReferenceExpression(
                    Variable, newValue
                    );
                ParentNode.ReplaceChild(uoe, replacement);
                VisitReplacement(replacement);
            }
            else
            {
                VisitChildren(uoe);
            }
        }
        protected JSVariable GetReferentVariable(JSPassByReferenceExpression pbr)
        {
            JSVariable   referentVariable;
            JSExpression referent;

            if (!JSReferenceExpression.TryMaterialize(JSIL, pbr.Referent, out referent))
            {
                if (JSReferenceExpression.TryDereference(JSIL, pbr.Referent, out referent))
                {
                    referentVariable = referent as JSVariable;
                    return(referentVariable);
                }
                else
                {
                    return(null);
                }
            }

            referentVariable = referent as JSVariable;
            return(referentVariable);
        }
示例#8
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);
        }
示例#9
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);
        }
示例#10
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);
        }
示例#11
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);
        }
示例#12
0
        public void VisitNode(JSBinaryOperatorExpression boe)
        {
            JSExpression left, right, nestedLeft;

            if (!JSReferenceExpression.TryDereference(JSIL, boe.Left, out left))
            {
                left = boe.Left;
            }
            if (!JSReferenceExpression.TryDereference(JSIL, boe.Right, out right))
            {
                right = boe.Right;
            }

            var nestedBoe    = right as JSBinaryOperatorExpression;
            var isAssignment = (boe.Operator == JSOperator.Assignment);
            var leftNew      = left as JSNewExpression;
            var rightNew     = right as JSNewExpression;
            var leftVar      = left as JSVariable;

            if (
                isAssignment && (nestedBoe != null) &&
                (left.IsConstant || (leftVar != null) || left is JSDotExpressionBase) &&
                !(ParentNode is JSVariableDeclarationStatement)
                )
            {
                JSUnaryOperator      prefixOperator;
                JSAssignmentOperator compoundOperator;

                if (!JSReferenceExpression.TryDereference(JSIL, nestedBoe.Left, out nestedLeft))
                {
                    nestedLeft = nestedBoe.Left;
                }

                var rightLiteral = nestedBoe.Right as JSIntegerLiteral;
                var areEqual     = left.Equals(nestedLeft);

                if (
                    areEqual &&
                    PrefixOperators.TryGetValue(nestedBoe.Operator, out prefixOperator) &&
                    (rightLiteral != null) && (rightLiteral.Value == 1)
                    )
                {
                    var newUoe = new JSUnaryOperatorExpression(
                        prefixOperator, boe.Left,
                        boe.GetActualType(TypeSystem)
                        );

                    ParentNode.ReplaceChild(boe, newUoe);
                    VisitReplacement(newUoe);

                    return;
                }
                else if (
                    areEqual &&
                    CompoundAssignments.TryGetValue(nestedBoe.Operator, out compoundOperator)
                    )
                {
                    var newBoe = new JSBinaryOperatorExpression(
                        compoundOperator, boe.Left, nestedBoe.Right,
                        boe.GetActualType(TypeSystem)
                        );

                    ParentNode.ReplaceChild(boe, newBoe);
                    VisitReplacement(newBoe);

                    return;
                }
            }
            else if (
                isAssignment && (leftNew != null) &&
                (rightNew != null)
                )
            {
                var rightType = rightNew.Type as JSDotExpressionBase;
                if (
                    (rightType != null) &&
                    (rightType.Member.Identifier == "CollectionInitializer")
                    )
                {
                    var newInitializer = new JSInitializerApplicationExpression(
                        boe.Left, new JSArrayExpression(
                            TypeSystem.Object,
                            rightNew.Arguments.ToArray()
                            )
                        );

                    ParentNode.ReplaceChild(boe, newInitializer);
                    VisitReplacement(newInitializer);

                    return;
                }
            }
            else if (
                isAssignment && (leftVar != null) &&
                leftVar.IsThis
                )
            {
                var leftType = leftVar.GetActualType(TypeSystem);
                if (!TypeUtil.IsStruct(leftType))
                {
                    ParentNode.ReplaceChild(boe, new JSUntranslatableExpression(boe));

                    return;
                }
                else
                {
                    var newInvocation = JSInvocationExpression.InvokeStatic(
                        JSIL.CopyMembers, new[] { boe.Right, leftVar }
                        );

                    ParentNode.ReplaceChild(boe, newInvocation);
                    VisitReplacement(newInvocation);

                    return;
                }
            }

            VisitChildren(boe);
        }
示例#13
0
 public void VisitNode(JSReferenceExpression reference)
 {
     Visit(reference.Referent);
 }