예제 #1
0
 internal sealed override void Generate(CodeGenContext context, CodeEmitter ilgen)
 {
     Debug.Assert(Name != null);
     if (Name == ".ctor")
     {
         Debug.Assert(Class == null && type != null);
         Type[]          argTypes = context.ClassLoader.ArgTypeListFromSig(Sig);
         ConstructorInfo ci       = StaticCompiler.GetType(context.ClassLoader, type).GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, CallingConventions.Standard, argTypes, null);
         if (ci == null)
         {
             throw new InvalidOperationException("Missing .ctor: " + type + "..ctor" + Sig);
         }
         ilgen.Emit(opcode, ci);
     }
     else
     {
         Debug.Assert(Class == null ^ type == null);
         if (Class != null)
         {
             Debug.Assert(Sig != null);
             MethodWrapper method = context.ClassLoader.LoadClassByDottedName(Class).GetMethodWrapper(Name, Sig, false);
             if (method == null)
             {
                 throw new InvalidOperationException("method not found: " + Class + "." + Name + Sig);
             }
             method.Link();
             // TODO this code is part of what Compiler.CastInterfaceArgs (in compiler.cs) does,
             // it would be nice if we could avoid this duplication...
             TypeWrapper[] argTypeWrappers = method.GetParameters();
             for (int i = 0; i < argTypeWrappers.Length; i++)
             {
                 if (argTypeWrappers[i].IsGhost)
                 {
                     LocalBuilder[] temps = new LocalBuilder[argTypeWrappers.Length + (method.IsStatic ? 0 : 1)];
                     for (int j = temps.Length - 1; j >= 0; j--)
                     {
                         TypeWrapper tw;
                         if (method.IsStatic)
                         {
                             tw = argTypeWrappers[j];
                         }
                         else
                         {
                             if (j == 0)
                             {
                                 tw = method.DeclaringType;
                             }
                             else
                             {
                                 tw = argTypeWrappers[j - 1];
                             }
                         }
                         if (tw.IsGhost)
                         {
                             tw.EmitConvStackTypeToSignatureType(ilgen, null);
                         }
                         temps[j] = ilgen.DeclareLocal(tw.TypeAsSignatureType);
                         ilgen.Emit(OpCodes.Stloc, temps[j]);
                     }
                     for (int j = 0; j < temps.Length; j++)
                     {
                         ilgen.Emit(OpCodes.Ldloc, temps[j]);
                     }
                     break;
                 }
             }
             if (opcode.Value == OpCodes.Call.Value)
             {
                 method.EmitCall(ilgen);
             }
             else if (opcode.Value == OpCodes.Callvirt.Value)
             {
                 method.EmitCallvirt(ilgen);
             }
             else if (opcode.Value == OpCodes.Newobj.Value)
             {
                 method.EmitNewobj(ilgen);
             }
             else
             {
                 throw new InvalidOperationException();
             }
         }
         else
         {
             Type[] argTypes;
             if (Sig.StartsWith("("))
             {
                 argTypes = context.ClassLoader.ArgTypeListFromSig(Sig);
             }
             else
             {
                 string[] types = Sig.Split(';');
                 argTypes = new Type[types.Length];
                 for (int i = 0; i < types.Length; i++)
                 {
                     argTypes[i] = StaticCompiler.GetType(context.ClassLoader, types[i]);
                 }
             }
             MethodInfo mi = StaticCompiler.GetType(context.ClassLoader, type).GetMethod(Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static, null, argTypes, null);
             if (mi == null)
             {
                 throw new InvalidOperationException("Missing method: " + type + "." + Name + Sig);
             }
             ilgen.Emit(opcode, mi);
         }
     }
 }
    /**
     * Emit an invoke for the given name, using the MemberName directly.
     */
    void emitStaticInvoke(MemberName member, Name name)
    {
        // push arguments
        emitPushArguments(name);

        // invocation
        if (member.isMethod())
        {
            if (IsMethodHandleLinkTo(member))
            {
                MethodType    mt   = member.getMethodType();
                TypeWrapper[] args = new TypeWrapper[mt.parameterCount()];
                for (int j = 0; j < args.Length; j++)
                {
                    args[j] = TypeWrapper.FromClass(mt.parameterType(j));
                    args[j].Finish();
                }
                TypeWrapper ret = TypeWrapper.FromClass(mt.returnType());
                ret.Finish();
                Compiler.MethodHandleMethodWrapper.EmitLinkToCall(ilgen, args, ret);
                ret.EmitConvSignatureTypeToStackType(ilgen);
            }
            else if (IsMethodHandleInvokeBasic(member))
            {
                EmitInvokeBasic(member.getMethodType());
            }
            else
            {
                switch (member.getReferenceKind())
                {
                case MethodHandleNatives.Constants.REF_invokeInterface:
                case MethodHandleNatives.Constants.REF_invokeSpecial:
                case MethodHandleNatives.Constants.REF_invokeStatic:
                case MethodHandleNatives.Constants.REF_invokeVirtual:
                    break;

                default:
                    throw new BailoutException(Bailout.UnsupportedRefKind, member);
                }
                MethodWrapper mw = GetMethodWrapper(member);
                if (!IsStaticallyInvocable(mw))
                {
                    throw new BailoutException(Bailout.NotStaticallyInvocable, member);
                }
                mw.Link();
                mw.DeclaringType.Finish();
                mw.ResolveMethod();
                if (mw.HasCallerID)
                {
                    EmitConstant(DynamicCallerIDProvider.Instance);
                    ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicCallerID);
                }
                if (mw.IsStatic || member.getReferenceKind() == MethodHandleNatives.Constants.REF_invokeSpecial)
                {
                    mw.EmitCall(ilgen);
                }
                else
                {
                    mw.EmitCallvirt(ilgen);
                }
                mw.ReturnType.EmitConvSignatureTypeToStackType(ilgen);
            }
        }
        else if (member.isField())
        {
            FieldWrapper fw = GetFieldWrapper(member);
            if (!IsStaticallyInvocable(fw))
            {
                throw new BailoutException(Bailout.NotStaticallyInvocable, member);
            }
            fw.Link();
            fw.DeclaringType.Finish();
            fw.ResolveField();
            switch (member.getReferenceKind())
            {
            case MethodHandleNatives.Constants.REF_getField:
            case MethodHandleNatives.Constants.REF_getStatic:
                fw.EmitGet(ilgen);
                fw.FieldTypeWrapper.EmitConvSignatureTypeToStackType(ilgen);
                break;

            case MethodHandleNatives.Constants.REF_putField:
            case MethodHandleNatives.Constants.REF_putStatic:
                fw.EmitSet(ilgen);
                break;

            default:
                throw new BailoutException(Bailout.UnsupportedRefKind, member);
            }
        }
        else
        {
            throw new BailoutException(Bailout.NotStaticallyInvocable, member);
        }
    }
예제 #3
0
 internal void Callvirt(MethodWrapper mw)
 {
     mw.EmitCallvirt(ilgen);
 }
예제 #4
0
        // this intrinsifies the following two patterns:
        //   unsafe.objectFieldOffset(XXX.class.getDeclaredField("xxx"));
        // and
        //   Class k = XXX.class;
        //   unsafe.objectFieldOffset(k.getDeclaredField("xxx"));
        // to avoid initializing the full reflection machinery at this point
        private static bool Class_getDeclaredField(EmitIntrinsicContext eic)
        {
            if (eic.Caller.DeclaringType.GetClassLoader() != CoreClasses.java.lang.Object.Wrapper.GetClassLoader())
            {
                // we can only do this optimization when compiling the trusted core classes
                return(false);
            }
            TypeWrapper fieldClass;

            if (eic.MatchRange(-2, 4) &&
                eic.Match(-2, NormalizedByteCode.__ldc) &&
                eic.Match(-1, NormalizedByteCode.__ldc_nothrow) &&
                eic.Match(1, NormalizedByteCode.__invokevirtual))
            {
                // unsafe.objectFieldOffset(XXX.class.getDeclaredField("xxx"));
                fieldClass = eic.GetClassLiteral(-2);
            }
            else if (eic.MatchRange(-5, 7) &&
                     eic.Match(-5, NormalizedByteCode.__ldc) &&
                     eic.Match(-4, NormalizedByteCode.__astore) &&
                     eic.Match(-3, NormalizedByteCode.__getstatic) &&
                     eic.Match(-2, NormalizedByteCode.__aload, eic.Code[eic.OpcodeIndex - 4].NormalizedArg1) &&
                     eic.Match(-1, NormalizedByteCode.__ldc_nothrow) &&
                     eic.Match(1, NormalizedByteCode.__invokevirtual))
            {
                // Class k = XXX.class;
                // unsafe.objectFieldOffset(k.getDeclaredField("xxx"));
                fieldClass = eic.GetClassLiteral(-5);
            }
            else
            {
                return(false);
            }
            FieldWrapper field     = null;
            string       fieldName = eic.GetStringLiteral(-1);

            foreach (FieldWrapper fw in fieldClass.GetFields())
            {
                if (fw.Name == fieldName)
                {
                    if (field != null)
                    {
                        return(false);
                    }
                    field = fw;
                }
            }
            if (field == null || field.IsStatic)
            {
                return(false);
            }
            ClassFile.ConstantPoolItemMI cpi = eic.GetMethodref(1);
            if (cpi.Class == "sun.misc.Unsafe" && cpi.Name == "objectFieldOffset" && cpi.Signature == "(Ljava.lang.reflect.Field;)J")
            {
                MethodWrapper mw = ClassLoaderWrapper.LoadClassCritical("sun.misc.Unsafe")
                                   .GetMethodWrapper("objectFieldOffset", "(Ljava.lang.Class;Ljava.lang.String;)J", false);
                mw.Link();
                mw.EmitCallvirt(eic.Emitter);
                eic.PatchOpCode(1, NormalizedByteCode.__nop);
                return(true);
            }
            return(false);
        }