예제 #1
0
        public void VisitNode(JSResultReferenceExpression rre)
        {
            var invocation = (rre.Referent as JSInvocationExpression);

            // When passing a packed array element directly to a function, use a proxy instead.
            // This allows hoisting to operate when the call is inside a loop, and it reduces GC pressure (since we basically make the struct unpack occur on-demand).
            if (
                (ParentNode is JSInvocationExpression) &&
                (invocation != null) &&
                (invocation.JSMethod != null) &&
                invocation.JSMethod.Reference.FullName.Contains("JSIL.Runtime.IPackedArray") &&
                invocation.JSMethod.Reference.FullName.Contains("get_Item(") &&
                Configuration.CodeGenerator.AggressivelyUseElementProxies.GetValueOrDefault(false)
                )
            {
                var elementType = invocation.GetActualType(TypeSystem);
                var replacement = new JSNewPackedArrayElementProxy(
                    invocation.ThisReference, invocation.Arguments.First(),
                    elementType
                    );

                ParentNode.ReplaceChild(rre, replacement);
                VisitReplacement(replacement);
                return;
            }

            VisitChildren(rre);
        }
예제 #2
0
        public void VisitNode (JSResultReferenceExpression rre) {
            var invocation = (rre.Referent as JSInvocationExpression);

            // When passing a packed array element directly to a function, use a proxy instead.
            // This allows hoisting to operate when the call is inside a loop, and it reduces GC pressure (since we basically make the struct unpack occur on-demand).
            if (
                (ParentNode is JSInvocationExpression) &&
                (invocation != null) &&
                (invocation.JSMethod != null) &&
                invocation.JSMethod.Reference.FullName.Contains("JSIL.Runtime.IPackedArray") &&
                invocation.JSMethod.Reference.FullName.Contains("get_Item(") &&
                Configuration.CodeGenerator.AggressivelyUseElementProxies.GetValueOrDefault(false)
            ) {
                var elementType = invocation.GetActualType(TypeSystem);
                var replacement = new JSNewPackedArrayElementProxy(
                    invocation.ThisReference, invocation.Arguments.First(),
                    elementType
                );

                ParentNode.ReplaceChild(rre, replacement);
                VisitReplacement(replacement);
                return;
            }

            VisitChildren(rre);
        }
예제 #3
0
        public void VisitNode(JSResultReferenceExpression rre)
        {
            VisitChildren(rre);

            if (ResultReferenceReplacement != null)
            {
                var newRre = ResultReferenceReplacement;
                ResultReferenceReplacement = null;
                ParentNode.ReplaceChild(rre, newRre);
                VisitReplacement(newRre);
            }
        }
예제 #4
0
        public void VisitNode(JSResultReferenceExpression rre)
        {
            VisitChildren(rre);

            if (_ResultReferenceReplacement != null)
            {
                var replacement = _ResultReferenceReplacement;
                _ResultReferenceReplacement = null;

                ParentNode.ReplaceChild(rre, replacement);
                VisitReplacement(replacement);
            }
        }
예제 #5
0
        public void VisitNode(JSResultReferenceExpression rre)
        {
            ReplacedInvocation = false;

            VisitChildren(rre);

            // If a getter invocation that returned a struct was replaced, there's
            //  now a result reference expression that needs to be removed
            if (ReplacedInvocation && !(rre.Children.First() is JSInvocationExpressionBase))
            {
                var replacement = rre.Children.First();
                ParentNode.ReplaceChild(rre, replacement);
            }
        }
예제 #6
0
        public void VisitNode (JSResultReferenceExpression rre) {
            VisitChildren(rre);

            if (_ResultReferenceReplacement != null) {
                var replacement = _ResultReferenceReplacement;
                _ResultReferenceReplacement = null;

                ParentNode.ReplaceChild(rre, replacement);
                VisitReplacement(replacement);
            }
        }
예제 #7
0
        public void VisitNode(JSResultReferenceExpression rre)
        {
            ReplacedInvocation = false;

            VisitChildren(rre);

            // If a getter invocation that returned a struct was replaced, there's
            //  now a result reference expression that needs to be removed
            if (ReplacedInvocation && !(rre.Children.First() is JSInvocationExpressionBase)) {
                var replacement = rre.Children.First();
                ParentNode.ReplaceChild(rre, replacement);
            }
        }
        private JSExpression ConstructInvocation (
            JSPropertyAccess pa, JSExpression argument = null
        ) {
            JSExpression[] arguments;

            if (argument == null)
                arguments = new JSExpression[0];
            else
                arguments = new JSExpression[] { argument };

            var originalMethod = pa.OriginalMethod;
            var declaringType = originalMethod.Reference.DeclaringType;
            var declaringTypeDef = TypeUtil.GetTypeDefinition(originalMethod.Reference.DeclaringType);
            var thisReferenceType = pa.ThisReference.GetActualType(TypeSystem);
            var isSelf = TypeUtil.TypesAreAssignable(
                TypeInfo, thisReferenceType, declaringType
            );

            // ILSpy converts compound assignments from:
            //  x.set_Value(x.get_Value + n)
            // to
            //  x.get_Value += n;
            // so we have to detect this and reconstruct the correct method
            //  references.
            var actualMethod = originalMethod;
            var correctName = String.Format(
                "{0}_{1}", pa.IsWrite ? "set" : "get",
                pa.Property.Property.ShortName
            );

            if (!actualMethod.Reference.Name.Contains(correctName)) {
                var dt = originalMethod.Method.DeclaringType;

                var actualMethodInfo = dt.Members.Values
                    .OfType<MethodInfo>().FirstOrDefault(
                        (m) => (
                            m.Name.Contains(correctName) &&
                            m.DeclaringType == originalMethod.Method.DeclaringType
                        )
                    );

                MethodReference actualMethodReference = actualMethodInfo.Member;
                if (originalMethod.Reference is GenericInstanceMethod) {
                    throw new InvalidDataException("Reconstructing an invocation of a generic instance method? Shouldn't be possible.");
                } else if (declaringType is GenericInstanceType) {
                    var declaringGit = (GenericInstanceType)declaringType;
                    var returnType = actualMethodReference.ReturnType;

                    if (TypeUtil.IsOpenType(returnType)) {
                        var actualReturnType = JSExpression.SubstituteTypeArgs(TypeInfo, actualMethodReference.ReturnType, actualMethodReference);
                        returnType = actualReturnType;
                    }

                    actualMethodReference = new MethodReference(
                        actualMethodReference.Name, returnType, declaringGit
                    );
                }

                actualMethod = new JSMethod(
                    actualMethodReference, actualMethodInfo,
                    originalMethod.MethodTypes, originalMethod.GenericArguments
                );
            }

            bool needsExplicitThis = !pa.IsVirtualCall && ILBlockTranslator.NeedsExplicitThis(
                declaringType, declaringTypeDef,
                originalMethod.Method.DeclaringType,
                isSelf, thisReferenceType,
                originalMethod.Method
            );
                
            JSInvocationExpressionBase invocation;
            if (pa.Property.Property.IsStatic)
                invocation = JSInvocationExpression.InvokeStatic(
                    actualMethod.Reference.DeclaringType,
                    actualMethod, 
                    arguments
                );
            else if (needsExplicitThis)
                invocation = JSInvocationExpression.InvokeBaseMethod(
                    actualMethod.Reference.DeclaringType,
                    actualMethod, pa.ThisReference,
                    arguments
                );
            else
                invocation = JSInvocationExpression.InvokeMethod(
                    pa.OriginalType, actualMethod, pa.ThisReference, arguments
                );

            JSExpression replacement;
            if (TypeUtil.IsStruct(pa.Property.Property.ReturnType))
                replacement = new JSResultReferenceExpression(invocation);
            else
                replacement = invocation;

            return replacement;
        }
예제 #9
0
        public void VisitNode (JSResultReferenceExpression rre) {
            VisitChildren(rre);

            if (ResultReferenceReplacement != null) {
                var newRre = ResultReferenceReplacement;
                ResultReferenceReplacement = null;
                ParentNode.ReplaceChild(rre, newRre);
                VisitReplacement(newRre);
            }
        }
        private JSExpression ConstructInvocation(
            JSPropertyAccess pa, JSExpression argument = null
            )
        {
            JSExpression[] arguments;

            if (argument == null)
            {
                arguments = new JSExpression[0];
            }
            else
            {
                arguments = new JSExpression[] { argument }
            };

            var originalMethod    = pa.OriginalMethod;
            var declaringType     = originalMethod.Reference.DeclaringType;
            var declaringTypeDef  = TypeUtil.GetTypeDefinition(originalMethod.Reference.DeclaringType);
            var thisReferenceType = pa.ThisReference.GetActualType(TypeSystem);
            var isSelf            = TypeUtil.TypesAreAssignable(
                TypeInfo, thisReferenceType, declaringType
                );

            // ILSpy converts compound assignments from:
            //  x.set_Value(x.get_Value + n)
            // to
            //  x.get_Value += n;
            // so we have to detect this and reconstruct the correct method
            //  references.
            var actualMethod = originalMethod;
            var correctName  = String.Format(
                "{0}_{1}", pa.IsWrite ? "set" : "get",
                pa.Property.Property.ShortName
                );

            if (!actualMethod.Reference.Name.Contains(correctName))
            {
                var dt = originalMethod.Method.DeclaringType;

                var actualMethodInfo = dt.Members.Values
                                       .OfType <MethodInfo>().FirstOrDefault(
                    (m) => (
                        m.Name.Contains(correctName) &&
                        m.DeclaringType == originalMethod.Method.DeclaringType
                        )
                    );

                MethodReference actualMethodReference = actualMethodInfo.Member;
                if (originalMethod.Reference is GenericInstanceMethod)
                {
                    throw new InvalidDataException("Reconstructing an invocation of a generic instance method? Shouldn't be possible.");
                }
                else if (declaringType is GenericInstanceType)
                {
                    var declaringGit = (GenericInstanceType)declaringType;
                    var returnType   = actualMethodReference.ReturnType;

                    if (TypeUtil.IsOpenType(returnType))
                    {
                        var actualReturnType = JSExpression.SubstituteTypeArgs(TypeInfo, actualMethodReference.ReturnType, actualMethodReference);
                        returnType = actualReturnType;
                    }

                    actualMethodReference = new MethodReference(
                        actualMethodReference.Name, returnType, declaringGit
                        );
                }

                actualMethod = new JSMethod(
                    actualMethodReference, actualMethodInfo,
                    originalMethod.MethodTypes, originalMethod.GenericArguments
                    );
            }

            bool needsExplicitThis = !pa.IsVirtualCall && ILBlockTranslator.NeedsExplicitThis(
                declaringType, declaringTypeDef,
                originalMethod.Method.DeclaringType,
                isSelf, thisReferenceType,
                originalMethod.Method
                );

            JSInvocationExpressionBase invocation;

            if (pa.Property.Property.IsStatic)
            {
                invocation = JSInvocationExpression.InvokeStatic(
                    actualMethod.Reference.DeclaringType,
                    actualMethod,
                    arguments
                    );
            }
            else if (needsExplicitThis)
            {
                invocation = JSInvocationExpression.InvokeBaseMethod(
                    actualMethod.Reference.DeclaringType,
                    actualMethod, pa.ThisReference,
                    arguments
                    );
            }
            else
            {
                invocation = JSInvocationExpression.InvokeMethod(
                    pa.OriginalType, actualMethod, pa.ThisReference, arguments
                    );
            }

            JSExpression replacement;

            if (TypeUtil.IsStruct(pa.Property.Property.ReturnType))
            {
                replacement = new JSResultReferenceExpression(invocation);
            }
            else
            {
                replacement = invocation;
            }

            return(replacement);
        }
        private JSExpression ConstructInvocation(
            JSPropertyAccess pa, JSExpression argument = null
        )
        {
            JSExpression[] arguments;

            if (argument == null)
                arguments = new JSExpression[0];
            else
                arguments = new JSExpression[] { argument };

            var originalMethod = pa.OriginalMethod;
            var declaringType = originalMethod.Reference.DeclaringType;
            var declaringTypeDef = TypeUtil.GetTypeDefinition(originalMethod.Reference.DeclaringType);
            var thisReferenceType = pa.ThisReference.GetActualType(TypeSystem);
            var isSelf = TypeUtil.TypesAreAssignable(
                TypeInfo, thisReferenceType, declaringType
            );

            bool needsExplicitThis = !pa.IsVirtualCall && ILBlockTranslator.NeedsExplicitThis(
                declaringType, declaringTypeDef,
                originalMethod.Method.DeclaringType,
                isSelf, thisReferenceType,
                originalMethod.Method
            );

            JSInvocationExpressionBase invocation;
            if (pa.Property.Property.IsStatic)
                invocation = JSInvocationExpression.InvokeStatic(
                    pa.OriginalMethod.Reference.DeclaringType,
                    pa.OriginalMethod,
                    arguments
                );
            else if (needsExplicitThis)
                invocation = JSInvocationExpression.InvokeBaseMethod(
                    pa.OriginalMethod.Reference.DeclaringType,
                    pa.OriginalMethod, pa.ThisReference,
                    arguments
                );
            else
                invocation = JSInvocationExpression.InvokeMethod(
                    pa.OriginalMethod, pa.ThisReference, arguments
                );

            JSExpression replacement;
            if (TypeUtil.IsStruct(pa.Property.Property.ReturnType))
                replacement = new JSResultReferenceExpression(invocation);
            else
                replacement = invocation;

            return replacement;
        }