Exemplo n.º 1
0
        /// <summary>
        /// Expects a reference to an array of the given element type and an index on the stack.
        ///
        /// Pops both, and pushes the address of the element at the given index.
        /// </summary>
        public Emit <DelegateType> LoadElementAddress(Type elementType)
        {
            if (!AllowsUnverifiableCIL)
            {
                FailUnverifiable("LoadElementAddress");
            }

            var arrayType = elementType.MakeArrayType();

            // needs to be markable so we can keep track of what makes use of this value
            var pushToStack = TypeOnStack.Get(elementType.MakeByRefType());

            // Shove this away, later on we'll figure out if we can insert a readonly here
            ReadonlyPatches.Add(SigilTuple.Create(IL.Index, pushToStack));

            var transitions =
                new[]
            {
                new StackTransition(new [] { TypeOnStack.Get <NativeIntType>(), TypeOnStack.Get(arrayType) }, new [] { pushToStack }),
                new StackTransition(new [] { TypeOnStack.Get <int>(), TypeOnStack.Get(arrayType) }, new [] { pushToStack })
            };

            UpdateState(OpCodes.Ldelema, elementType, Wrap(transitions, "LoadElementAddress"));

            return(this);
        }
Exemplo n.º 2
0
        private void InjectReadOnly()
        {
            while (ReadonlyPatches.Count > 0)
            {
                var elem = ReadonlyPatches[0];
                ReadonlyPatches.RemoveAt(0);

                var at    = elem.Item1;
                var value = elem.Item2;

                var asObjToLdfd  = value.CountMarks(OpCodes.Ldfld, 0);
                var asObjToLdfda = value.CountMarks(OpCodes.Ldflda, 0);
                var asObjToStfd  = value.CountMarks(OpCodes.Stfld, 0);

                var asObjToCall = value.CountMarks(OpCodes.Call, 0);

                var asPtrToLdobj = value.CountMarks(OpCodes.Ldobj, 0);
                var asPtrToLdind =
                    value.CountMarks(OpCodes.Ldind_I, 0) +
                    value.CountMarks(OpCodes.Ldind_I1, 0) +
                    value.CountMarks(OpCodes.Ldind_I2, 0) +
                    value.CountMarks(OpCodes.Ldind_I4, 0) +
                    value.CountMarks(OpCodes.Ldind_I8, 0) +
                    value.CountMarks(OpCodes.Ldind_R4, 0) +
                    value.CountMarks(OpCodes.Ldind_R8, 0) +
                    value.CountMarks(OpCodes.Ldind_Ref, 0) +
                    value.CountMarks(OpCodes.Ldind_U1, 0) +
                    value.CountMarks(OpCodes.Ldind_U2, 0) +
                    value.CountMarks(OpCodes.Ldind_U4, 0);

                var asSourceToCpobj = value.CountMarks(OpCodes.Cpobj, 0);

                var totalAllowedUses =
                    asObjToLdfd +
                    asObjToLdfda +
                    asObjToStfd +
                    asPtrToLdobj +
                    asPtrToLdind +
                    asSourceToCpobj +
                    asObjToCall;

                var totalActualUses = value.CountMarks();

                if (totalActualUses == totalAllowedUses)
                {
                    InsertInstruction(at, OpCodes.Readonly);
                }
            }
        }