Пример #1
0
        public void GenerateFromTypeSpec(Compiler compiler, TypeSpecTag typeSpec, VTableGenerationCache vtCache)
        {
            List<MethodHandle> methodHandles;
            if (typeSpec is TypeSpecClassTag)
                methodHandles = GenerateVTableForClass(compiler, (TypeSpecClassTag)typeSpec);
            else if (typeSpec is TypeSpecBoxTag)
                methodHandles = GenerateVTableForBox(compiler, (TypeSpecBoxTag)typeSpec, vtCache);
            else if (typeSpec is TypeSpecDelegateTag)
                methodHandles = GenerateVTableForDelegate(compiler, (TypeSpecDelegateTag)typeSpec, vtCache);
            else if (typeSpec is TypeSpecArrayTag)
                methodHandles = GenerateVTableForArray(compiler, (TypeSpecArrayTag)typeSpec);
            else if (typeSpec is TypeSpecMulticastDelegateTag)
                methodHandles = GenerateVTableForMulticastDelegate(compiler, (TypeSpecMulticastDelegateTag)typeSpec, vtCache);
            else
                throw new ArgumentException("Invalid typespec to generate an array from");

            List<MethodHandle> finalHandles = new List<MethodHandle>();
            m_instrSlotToRealSlot = new Dictionary<uint, uint>();
            uint realSlot = 0;
            uint instrSlot = 0;
            foreach (MethodHandle hdl in methodHandles)
            {
                if (hdl == null)
                {
                    instrSlot++;
                    continue;
                }

                finalHandles.Add(hdl);

                m_instrSlotToRealSlot.Add(instrSlot, realSlot);

                instrSlot++;
                realSlot++;
            }

            m_methods = finalHandles.ToArray();
        }
Пример #2
0
        private List<MethodHandle> GenerateVTableForMulticastDelegate(Compiler compiler, TypeSpecMulticastDelegateTag typeSpec, VTableGenerationCache vtCache)
        {
            TypeSpecClassTag delegateType = typeSpec.DelegateType;
            CliClass cls = compiler.GetClosedClass(delegateType);

            List<MethodHandle> methodHandles = new List<MethodHandle>();

            List<MethodSpecTag> methodSpecs = new List<MethodSpecTag>();
            foreach (CliVtableSlot vtableSlot in cls.VTable)
            {
                CliMethodIndex methodIndex = vtableSlot.MethodIndex;
                if (methodIndex == null)
                    methodSpecs.Add(null);
                else
                    methodSpecs.Add(ResolveVirtualMethod(compiler, cls, methodIndex));
            }

            int numSlots = methodSpecs.Count;
            for (int i = 0; i < numSlots; i++)
                methodHandles.Add(null);

            foreach (KeyValuePair<MethodDeclTag, uint> dtvs in cls.DeclTagToVTableSlot)
            {
                int slot = (int)dtvs.Value;
                MethodDeclTag methodDecl = dtvs.Key;

                if (methodDecl.Name == "Invoke")
                {
                    methodHandles[slot] = compiler.InstantiateMethod(new GeneratedMethods.GMMulticastDelegateInvoke(typeSpec.DelegateType, vtCache), m_instantiationPath);
                    methodSpecs[slot] = null;
                }
            }

            for (int i = 0; i < numSlots; i++)
            {
                MethodSpecTag methodSpec = methodSpecs[i];
                if (methodSpec != null)
                    methodHandles[i] = compiler.InstantiateMethod(new MethodSpecMethodKey(methodSpec), m_instantiationPath);
            }

            return methodHandles;
        }
Пример #3
0
        private List<MethodHandle> GenerateVTableForBox(Compiler compiler, TypeSpecBoxTag typeSpec, VTableGenerationCache vtCache)
        {
            TypeSpecClassTag containedType = typeSpec.ContainedType;
            List<MethodSpecTag> baseSpecs = GenerateMethodSpecsForClass(compiler, containedType);

            IList<MethodSpecTag> vtMethodSpecs = vtCache.ValueTypeMethodSpecs;

            if (vtMethodSpecs == null)
            {
                TypeNameTag valueTypeName = new TypeNameTag("mscorlib", "System", "ValueType");
                valueTypeName = compiler.TagRepository.InternTypeName(valueTypeName);

                TypeSpecClassTag valueTypeSpec = new TypeSpecClassTag(valueTypeName, new TypeSpecTag[0]);
                valueTypeSpec = (TypeSpecClassTag)compiler.TagRepository.InternTypeSpec(valueTypeSpec);

                vtMethodSpecs = GenerateMethodSpecsForClass(compiler, valueTypeSpec);
                vtCache.ValueTypeMethodSpecs = vtMethodSpecs;
            }

            List<MethodHandle> methodHandles = new List<MethodHandle>();

            for (int slotIndex = 0; slotIndex < baseSpecs.Count; slotIndex++)
            {
                MethodSpecTag methodSpec = baseSpecs[slotIndex];
                if (methodSpec == null)
                {
                    methodHandles.Add(null);
                    continue;
                }

                if (slotIndex < vtMethodSpecs.Count && vtMethodSpecs[slotIndex] == methodSpec)
                {
                    MethodSpecTag slotSpec = vtMethodSpecs[slotIndex];
                    if (slotSpec == methodSpec)
                    {
                        MethodDeclTag slotDecl = vtMethodSpecs[slotIndex].MethodDecl;

                        // Generate implementations for value-sensitive slots
                        if (slotDecl.Name == "Equals")
                        {
                            methodHandles.Add(compiler.InstantiateMethod(new GeneratedMethods.GMBoxedValueTypeEquals(typeSpec, vtCache), m_instantiationPath));
                            continue;
                        }
                        else if (slotDecl.Name == "GetHashCode")
                        {
                            methodHandles.Add(compiler.InstantiateMethod(new GeneratedMethods.GMBoxedValueTypeGetHashCode(typeSpec, vtCache), m_instantiationPath));
                            continue;
                        }
                    }
                }

                // If not sensitive, then use the method spec and generate a box thunk
                methodHandles.Add(compiler.InstantiateMethod(new GeneratedMethods.GMBoxThunk(methodSpec), m_instantiationPath));
            }

            return methodHandles;
        }