Exemple #1
0
        public override void Execute(MethodInfo aMethod, ILOpCode aOpCode)
        {
            DoNullReferenceCheck(Assembler, DebugEnabled, 0);
            OpType xType            = (OpType)aOpCode;
            string xBaseLabel       = GetLabel(aMethod, aOpCode) + ".";
            string xTypeID          = GetTypeIDLabel(xType.Value);
            uint   xTypeSize        = SizeOfType(xType.Value);
            string mReturnNullLabel = xBaseLabel + "_ReturnNull";

            new CPUx86.Compare {
                DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, SourceValue = 0
            };
            new CPUx86.ConditionalJump {
                Condition = CPUx86.ConditionalTestEnum.Zero, DestinationLabel = mReturnNullLabel
            };
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true
            };
            new CPUx86.Push {
                DestinationReg = CPUx86.Registers.EAX, DestinationIsIndirect = true
            };
            new CPUx86.Push {
                DestinationRef = Cosmos.Assembler.ElementReference.New(xTypeID), DestinationIsIndirect = true
            };
            SysReflection.MethodBase xMethodIsInstance = ReflectionUtilities.GetMethodBase(typeof(VTablesImpl), "IsInstance", "System.UInt32", "System.UInt32");
            Call.DoExecute(Assembler, aMethod, xMethodIsInstance, aOpCode, GetLabel(aMethod, aOpCode), xBaseLabel + "_After_IsInstance_Call", DebugEnabled);
            new Label(xBaseLabel + "_After_IsInstance_Call");
            new CPUx86.Pop {
                DestinationReg = CPUx86.Registers.EAX
            };
            new CPUx86.Compare {
                DestinationReg = CPUx86.Registers.EAX, SourceValue = 0
            };
            new CPUx86.ConditionalJump {
                Condition = CPUx86.ConditionalTestEnum.Equal, DestinationLabel = mReturnNullLabel
            };
            new CPUx86.Pop {
                DestinationReg = CPUx86.Registers.EAX
            };
            uint xSize = xTypeSize;

            if (xSize % 4 > 0)
            {
                xSize += 4 - (xSize % 4);
            }
            int xItems = (int)xSize / 4;

            for (int i = xItems - 1; i >= 0; i--)
            {
                new CPUx86.Push {
                    DestinationReg = CPUx86.Registers.EAX, DestinationIsIndirect = true, DestinationDisplacement = ((i * 4) + ObjectImpl.FieldDataOffset)
                };
            }
            new CPUx86.Jump {
                DestinationLabel = GetLabel(aMethod, aOpCode.NextPosition)
            };
            new Label(mReturnNullLabel);
            new CPUx86.Add {
                DestinationReg = CPUx86.Registers.ESP, SourceValue = 4
            };
            new CPUx86.Push {
                DestinationValue = 0
            };
        }
Exemple #2
0
        public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode)
        {
            string xCurrentMethodLabel = GetLabel(aMethod, aOpCode);

            Call.DoExecute(Assembler, aMethod, GCImplementationRefs.AllocNewObjectRef, aOpCode, xCurrentMethodLabel, DebugEnabled);
        }
Exemple #3
0
        public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode)
        {
            var xType    = ((OpType)aOpCode).Value;
            var xOpLabel = GetLabel(aMethod, aOpCode);
            var xAfterIsInstanceCallLabel = xOpLabel + ".AfterIsInstanceCall";
            var xAfterInstanceCheckLabel  = xOpLabel + ".AfterInstanceCheck";

            XS.Add(ESP, 4);

            var xIsNullable = xType.IsGenericType && xType.GetGenericTypeDefinition() == typeof(Nullable <>);

            if (xIsNullable)
            {
                xType = xType.GenericTypeArguments[0];

                XS.Compare(ESP, 0, destinationIsIndirect: true);
                XS.Jump(ConditionalTestEnum.Equal, xAfterInstanceCheckLabel);
            }
            else
            {
                DoNullReferenceCheck(Assembler, DebugEnabled, 0);
            }

            var xTypeId = GetTypeIDLabel(xType);

            XS.Set(EAX, ESP, sourceIsIndirect: true);
            XS.Push(EAX, isIndirect: true);
            XS.Push(xTypeId, isIndirect: true);
            XS.Push(Convert.ToUInt32(xType.IsInterface));
            Call.DoExecute(Assembler, aMethod, VTablesImplRefs.IsInstanceRef, aOpCode, GetLabel(aMethod, aOpCode), xAfterIsInstanceCallLabel, DebugEnabled);

            XS.Label(xAfterIsInstanceCallLabel);

            XS.Pop(EAX);

            XS.Compare(EAX, 0);
            XS.Jump(ConditionalTestEnum.NotEqual, xAfterInstanceCheckLabel);

            XS.Call(LabelName.Get(ExceptionHelperRefs.ThrowInvalidCastExceptionRef));

            XS.Label(xAfterInstanceCheckLabel);

            if (xIsNullable)
            {
                // from ECMA 335:
                //
                // [Note: Typically, unbox simply computes the address of the value type that is already present
                // inside of the boxed object. This approach is not possible when unboxing nullable value types.
                // Because Nullable<T> values are converted to boxed Ts during the box operation, an
                // implementation often must manufacture a new Nullable<T> on the heap and compute the address
                // to the newly allocated object. end note]

                // todo:
                // - manufacture new Nullable<T>
                // - hasValue = (obj != null)
                // - if (obj == null) value = default(T)
                // - else value = obj data

                throw new NotImplementedException();
            }

            // the result is a managed pointer, it should be tracked by GC
            XS.Add(ESP, ObjectUtils.FieldDataOffset, destinationIsIndirect: true);
        }
Exemple #4
0
        public static void Assemble(Assembler aAssembler, uint aElementSize, _MethodInfo aMethod, ILOpCode aOpCode, bool debugEnabled)
        {
            DoNullReferenceCheck(aAssembler, debugEnabled, (int)(8 + Align(aElementSize, 4)));

            uint xStackSize = aElementSize;

            if (xStackSize % 4 != 0)
            {
                xStackSize += 4 - xStackSize % 4;
            }
            // Do index out of range check
            var xBaseLabel = GetLabel(aMethod, aOpCode);
            var xNoIndexOutOfRangeExeptionLabel = xBaseLabel + "_NoIndexOutOfRangeException";
            var xIndexOutOfRangeExeptionLabel   = xBaseLabel + "_IndexOutOfRangeException";

            XS.Push(ESP, displacement: 4 + 4 + (int)xStackSize); // _, array, 0, index, value * n  => _, array, 0, index, value * n, array
            XS.Push(0);                                          // _, array, 0, index, value * n, array => _, array, 0, index, value * n, array, 0
            Ldlen.Assemble(aAssembler, debugEnabled, false);     // _, array, 0, index, value * n, array, 0 -> _, array, 0, index, value * n, length
            XS.Pop(EAX);                                         //Length of array _, array, 0, index, value * n, length -> _, array, 0, index, value * n
            XS.Compare(EAX, ESP, sourceIsIndirect: true, sourceDisplacement: (int)xStackSize);
            XS.Jump(CPUx86.ConditionalTestEnum.LessThanOrEqualTo, xIndexOutOfRangeExeptionLabel);

            XS.Compare(EAX, 0);
            XS.Jump(CPUx86.ConditionalTestEnum.GreaterThanOrEqualTo, xNoIndexOutOfRangeExeptionLabel);

            XS.Label(xIndexOutOfRangeExeptionLabel);
            Call.DoExecute(aAssembler, aMethod, ExceptionHelperRefs.ThrowIndexOutOfRangeException, aOpCode, xNoIndexOutOfRangeExeptionLabel, debugEnabled);

            XS.Label(xNoIndexOutOfRangeExeptionLabel);

            // calculate element offset into array memory (including header)
            XS.Set(EAX, ESP, sourceDisplacement: (int)xStackSize); // the index
            XS.Set(EDX, aElementSize);
            XS.Multiply(EDX);
            XS.Add(EAX, ObjectUtils.FieldDataOffset + 4);

            XS.Set(EDX, ESP, sourceDisplacement: (int)xStackSize + 8); // the array
            XS.Add(EDX, EAX);
            XS.Push(EDX);

            XS.Pop(ECX);
            for (int i = (int)(aElementSize / 4) - 1; i >= 0; i -= 1)
            {
                new Comment(aAssembler, "Start 1 dword");
                XS.Pop(EBX);
                XS.Set(ECX, EBX, destinationIsIndirect: true);
                XS.Add(ECX, 4);
            }
            switch (aElementSize % 4)
            {
            case 1:
            {
                new Comment(aAssembler, "Start 1 byte");
                XS.Pop(EBX);
                XS.Set(ECX, BL, destinationIsIndirect: true);
                break;
            }

            case 2:
            {
                new Comment(aAssembler, "Start 1 word");
                XS.Pop(EBX);
                XS.Set(ECX, BX, destinationIsIndirect: true);
                break;
            }

            case 3:
            {
                new Comment(aAssembler, "Start 3 word");
                XS.Pop(EBX);
                XS.And(EBX, 0xFFFFFF); // Only take the value of the lower three bytes
                XS.Set(ECX, EBX, destinationIsIndirect: true);
                break;
            }

            case 0:
            {
                break;
            }

            default:
                throw new Exception("Remainder size " + (aElementSize % 4) + " not supported!");
            }
            XS.Add(ESP, 12);
        }
Exemple #5
0
        public static void CheckOverflowForLong(uint xResultSize, bool xSourceIsSigned, bool xResultIsSigned, Assembler assembler, _MethodInfo aMethod, ILOpCode aOpCode, string xSuccessLabel, string xOverflowLabel, string xPositiveLabel, string xNegativeLabel)
        {
            // long is
            // low
            // high
            XS.Set(EAX, ESP, sourceIsIndirect: true, sourceDisplacement: 4); // read high
            if (xSourceIsSigned)
            {
                XS.ShiftRight(EAX, 31); // get highest bit of high to determine sign
                XS.Compare(EAX, 0);
                XS.Jump(ConditionalTestEnum.Equal, xPositiveLabel);
                XS.Compare(EAX, 1);
                XS.Jump(ConditionalTestEnum.Equal, xResultIsSigned ? xNegativeLabel : xOverflowLabel);
            }
            else
            {
                XS.Compare(EAX, 0); // as unsigned high must be positive
                XS.Jump(ConditionalTestEnum.Equal, xPositiveLabel);
            }
            XS.Label(xOverflowLabel);
            XS.Pop(EAX); //remove long from stack
            XS.Pop(EAX);
            Call.DoExecute(assembler, aMethod, ExceptionHelperRefs.ThrowOverflowExceptionRef, aOpCode, xSuccessLabel, false);

            // Positive check
            XS.Label(xPositiveLabel);
            XS.Set(EAX, ESP, sourceIsIndirect: true, sourceDisplacement: 4); // read high to refresh
            XS.Set(EBX, ESP, sourceIsIndirect: true);                        // read low
            XS.Compare(EAX, 0);
            XS.Jump(ConditionalTestEnum.NotEqual, xOverflowLabel);
            if (xResultSize == 4 && !xResultIsSigned)
            {
                XS.Jump(xSuccessLabel);
            }
            else
            {
                var v = xResultSize * 8;
                if (xResultIsSigned)
                {
                    v -= 1;
                }
                XS.ShiftRight(EBX, (byte)v); // now check if low does not overflow
                XS.Compare(EBX, 0);
                XS.Jump(ConditionalTestEnum.NotEqual, xOverflowLabel);
                XS.Jump(xSuccessLabel);
            }

            //Negative check
            if (xSourceIsSigned)
            {
                XS.Label(xNegativeLabel);
                if (!xResultIsSigned)
                {
                    XS.Jump(xOverflowLabel);
                }
                XS.Set(EAX, ESP, sourceIsIndirect: true, sourceDisplacement: 4); // read high to refresh
                XS.Compare(EAX, 0xffff_ffff);                                    // high should be fully set
                XS.Jump(ConditionalTestEnum.NotEqual, xOverflowLabel);
                XS.Set(EBX, ESP, sourceIsIndirect: true);                        // read low
                XS.ShiftRight(EBX, (byte)(xResultSize * 8));                     // now check if low does not overflow
                XS.Not(EBX);
                XS.Compare(EBX, 0);
                XS.Jump(ConditionalTestEnum.NotEqual, xOverflowLabel);
            }

            XS.Label(xSuccessLabel);
        }