Ejemplo n.º 1
0
        public static void DoExecute(Cosmos.Assembler.Assembler aAssembler, MethodInfo aMethod, string aFieldId, Type aDeclaringObject, bool aNeedsGC, bool debugEnabled)
        {
            var xType = aMethod.MethodBase.DeclaringType;

            var xFields    = GetFieldsInfo(aDeclaringObject, false);
            var xFieldInfo = (from item in xFields
                              where item.Id == aFieldId
                              select item).Single();
            var xActualOffset = Ldfld.GetFieldOffset(aDeclaringObject, aFieldId);
            var xSize         = xFieldInfo.Size;

            new Comment("Field: " + xFieldInfo.Id);
            new Comment("Type: " + xFieldInfo.FieldType.ToString());
            new Comment("Size: " + xFieldInfo.Size);
            new Comment("Offset: " + xActualOffset + " (includes object header)");

            uint xRoundedSize = Align(xSize, 4);

            DoNullReferenceCheck(aAssembler, debugEnabled, xRoundedSize);
            new Comment("After Nullref check");
            new CPUx86.Mov {
                DestinationReg = CPUx86.Registers.ECX, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = (int)xRoundedSize
            };
            // ECX contains the object pointer now
            if (aNeedsGC)
            {
                // for reference types (or boxed types), ECX actually contains the handle now, so we need to convert it to a memory address
                new Comment("Dereference memory handle now");
                new CPUx86.Mov {
                    DestinationReg = CPUx86.Registers.ECX, SourceReg = CPUx86.Registers.ECX, SourceIsIndirect = true
                };
            }
            if (debugEnabled)
            {
                new CPUx86.Push {
                    DestinationReg = CPUx86.RegistersEnum.ECX
                };
                new CPUx86.Pop {
                    DestinationReg = CPUx86.RegistersEnum.ECX
                };
            }
            new CPUx86.Add {
                DestinationReg = CPUx86.Registers.ECX, SourceValue = (uint)(xActualOffset)
            };
            //TODO: Can't we use an x86 op to do a byte copy instead and be faster?
            for (int i = 0; i < (xSize / 4); i++)
            {
                new CPUx86.Pop {
                    DestinationReg = CPUx86.Registers.EAX
                };
                new CPUx86.Mov {
                    DestinationReg = CPUx86.Registers.ECX, DestinationIsIndirect = true, DestinationDisplacement = (int)((i * 4)), SourceReg = CPUx86.Registers.EAX
                };
            }

            switch (xSize % 4)
            {
            case 1: {
                new CPUx86.Pop {
                    DestinationReg = CPUx86.Registers.EAX
                };
                new CPUx86.Mov {
                    DestinationReg = CPUx86.Registers.ECX, DestinationIsIndirect = true, DestinationDisplacement = (int)((xSize / 4) * 4), SourceReg = CPUx86.Registers.AL
                };
                break;
            }

            case 2: {
                new CPUx86.Pop {
                    DestinationReg = CPUx86.Registers.EAX
                };
                new CPUx86.Mov {
                    DestinationReg = CPUx86.Registers.ECX, DestinationIsIndirect = true, DestinationDisplacement = (int)((xSize / 4) * 4), SourceReg = CPUx86.Registers.AX
                };
                break;
            }

            case 3: {
                new CPUx86.Pop {
                    DestinationReg = CPUx86.Registers.EAX
                };
                // move 2 lower bytes
                new CPUx86.Mov {
                    DestinationReg = CPUx86.Registers.ECX, DestinationIsIndirect = true, DestinationDisplacement = (int)((xSize / 4) * 4), SourceReg = CPUx86.Registers.AX
                };
                // shift third byte to lowest
                new CPUx86.ShiftRight {
                    DestinationReg = CPUx86.Registers.EAX, SourceValue = 16
                };
                new CPUx86.Mov {
                    DestinationReg = CPUx86.Registers.ECX, DestinationIsIndirect = true, DestinationDisplacement = (int)((xSize / 4) * 4) + 2, SourceReg = CPUx86.Registers.AL
                };
                break;
            }

            case 0: {
                break;
            }

            default:
                throw new Exception("Remainder size " + (xSize % 4) + " not supported!");
            }

#if !SKIP_GC_CODE
            if (aNeedsGC)
            {
                new CPUx86.Push {
                    DestinationReg = CPUx86.Registers.ECX
                };
                new CPUx86.Push {
                    DestinationReg = CPUx86.Registers.EAX
                };
                new CPUx86.Call {
                    DestinationLabel = LabelName.Get(GCImplementationRefs.DecRefCountRef)
                };
                new CPUx86.Call {
                    DestinationLabel = LabelName.Get(GCImplementationRefs.DecRefCountRef)
                };
            }
#endif
            new CPUx86.Add {
                DestinationReg = CPUx86.Registers.ESP, SourceValue = 4
            };
        }
Ejemplo n.º 2
0
        public static void DoExecute(Cosmos.Assembler.Assembler aAssembler, MethodInfo aMethod, string aFieldId, Type aDeclaringObject, bool aNeedsGC, bool debugEnabled)
        {
            var xType = aMethod.MethodBase.DeclaringType;

            var xFields    = GetFieldsInfo(aDeclaringObject, false);
            var xFieldInfo = (from item in xFields
                              where item.Id == aFieldId
                              select item).Single();
            var xActualOffset = Ldfld.GetFieldOffset(aDeclaringObject, aFieldId);
            var xSize         = xFieldInfo.Size;

            XS.Comment("Field: " + xFieldInfo.Id);
            XS.Comment("Type: " + xFieldInfo.FieldType.ToString());
            XS.Comment("Size: " + xFieldInfo.Size);
            XS.Comment("Offset: " + xActualOffset + " (includes object header)");

            uint xRoundedSize = Align(xSize, 4);

            if (aNeedsGC)
            {
                DoNullReferenceCheck(aAssembler, debugEnabled, (int)xRoundedSize + 4);
            }
            else
            {
                DoNullReferenceCheck(aAssembler, debugEnabled, (int)xRoundedSize);
            }

            XS.Comment("After Nullref check");

            if (aNeedsGC)
            {
                XS.Set(XSRegisters.ECX, XSRegisters.ESP, sourceDisplacement: (int)xRoundedSize + 4);
            }
            else
            {
                XS.Set(XSRegisters.ECX, XSRegisters.ESP, sourceDisplacement: (int)xRoundedSize);
            }

            if (xActualOffset != 0)
            {
                XS.Add(XSRegisters.ECX, (uint)(xActualOffset));
            }

            //TODO: Can't we use an x86 op to do a byte copy instead and be faster?
            for (int i = 0; i < (xSize / 4); i++)
            {
                XS.Pop(XSRegisters.EAX);
                XS.Set(XSRegisters.ECX, XSRegisters.EAX, destinationDisplacement: (int)((i * 4)));
            }

            switch (xSize % 4)
            {
            case 1: {
                XS.Pop(XSRegisters.EAX);
                new CPUx86.Mov {
                    DestinationReg = CPUx86.RegistersEnum.ECX, DestinationIsIndirect = true, DestinationDisplacement = (int)((xSize / 4) * 4), SourceReg = CPUx86.RegistersEnum.AL
                };
                break;
            }

            case 2: {
                XS.Pop(XSRegisters.EAX);
                new CPUx86.Mov {
                    DestinationReg = CPUx86.RegistersEnum.ECX, DestinationIsIndirect = true, DestinationDisplacement = (int)((xSize / 4) * 4), SourceReg = CPUx86.RegistersEnum.AX
                };
                break;
            }

            case 3: {
                XS.Pop(XSRegisters.EAX);
                // move 2 lower bytes
                new CPUx86.Mov {
                    DestinationReg = CPUx86.RegistersEnum.ECX, DestinationIsIndirect = true, DestinationDisplacement = (int)((xSize / 4) * 4), SourceReg = CPUx86.RegistersEnum.AX
                };
                // shift third byte to lowest
                XS.ShiftRight(XSRegisters.EAX, 16);
                new CPUx86.Mov {
                    DestinationReg = CPUx86.RegistersEnum.ECX, DestinationIsIndirect = true, DestinationDisplacement = (int)((xSize / 4) * 4) + 2, SourceReg = CPUx86.RegistersEnum.AL
                };
                break;
            }

            case 0: {
                break;
            }

            default:
                throw new Exception("Remainder size " + (xSize % 4) + " not supported!");
            }
            XS.Add(XSRegisters.ESP, 4);
            if (aNeedsGC)
            {
                XS.Add(XSRegisters.ESP, 4);
            }
        }