Exemplo n.º 1
0
        private static bool Unsafe_getObjectVolatile(EmitIntrinsicContext eic)
        {
            // the check here must be kept in sync with the hack in MethodAnalyzer.AnalyzeTypeFlow()
            TypeWrapper tw = eic.GetStackTypeWrapper(0, 1);

            if (IsSupportedArrayTypeForUnsafeOperation(tw))
            {
                CodeEmitterLocal index = eic.Emitter.AllocTempLocal(Types.Int32);
                CodeEmitterLocal obj   = eic.Emitter.AllocTempLocal(tw.TypeAsLocalOrStackType);
                eic.Emitter.Emit(OpCodes.Conv_Ovf_I4);
                eic.Emitter.Emit(OpCodes.Stloc, index);
                eic.Emitter.Emit(OpCodes.Stloc, obj);
                EmitConsumeUnsafe(eic);
                eic.Emitter.Emit(OpCodes.Ldloc, obj);
                eic.Emitter.Emit(OpCodes.Ldloc, index);
                eic.Emitter.ReleaseTempLocal(obj);
                eic.Emitter.ReleaseTempLocal(index);
                eic.Emitter.Emit(OpCodes.Ldelema, tw.TypeAsLocalOrStackType.GetElementType());
                eic.Emitter.Emit(OpCodes.Volatile);
                eic.Emitter.Emit(OpCodes.Ldind_Ref);
                // remove the redundant checkcast that usually follows
                if (eic.Code[eic.OpcodeIndex + 1].NormalizedOpCode == NormalizedByteCode.__checkcast &&
                    tw.ElementTypeWrapper.IsAssignableTo(eic.ClassFile.GetConstantPoolClassType(eic.Code[eic.OpcodeIndex + 1].Arg1)))
                {
                    eic.PatchOpCode(1, NormalizedByteCode.__nop);
                }
                eic.NonLeaf = false;
                return(true);
            }
            return(false);
        }
Exemplo n.º 2
0
 private static bool Object_getClass(EmitIntrinsicContext eic)
 {
     // this is the null-check idiom that javac uses (both in its own source and in the code it generates)
     if (eic.MatchRange(0, 2) &&
         eic.Match(1, NormalizedByteCode.__pop))
     {
         eic.Emitter.Emit(OpCodes.Dup);
         eic.Emitter.EmitNullCheck();
         return(true);
     }
     // this optimizes obj1.getClass() ==/!= obj2.getClass()
     else if (eic.MatchRange(0, 4) &&
              eic.Match(1, NormalizedByteCode.__aload) &&
              eic.Match(2, NormalizedByteCode.__invokevirtual) &&
              (eic.Match(3, NormalizedByteCode.__if_acmpeq) || eic.Match(3, NormalizedByteCode.__if_acmpne)) &&
              (IsSafeForGetClassOptimization(eic.GetStackTypeWrapper(0, 0)) || IsSafeForGetClassOptimization(eic.GetStackTypeWrapper(2, 0))))
     {
         ClassFile.ConstantPoolItemMI cpi = eic.GetMethodref(2);
         if (cpi.Class == "java.lang.Object" && cpi.Name == "getClass" && cpi.Signature == "()Ljava.lang.Class;")
         {
             // we can't patch the current opcode, so we have to emit the first call to GetTypeHandle here
             eic.Emitter.Emit(OpCodes.Callvirt, Compiler.getTypeMethod);
             eic.PatchOpCode(2, NormalizedByteCode.__intrinsic_gettype);
             return(true);
         }
     }
     return(false);
 }
Exemplo n.º 3
0
 private static bool Reflection_getCallerClass(EmitIntrinsicContext eic)
 {
     if (eic.Caller.HasCallerID)
     {
         int arg = eic.Caller.GetParametersForDefineMethod().Length - 1;
         if (!eic.Caller.IsStatic)
         {
             arg++;
         }
         eic.Emitter.EmitLdarg(arg);
         MethodWrapper mw;
         if (MatchInvokeStatic(eic, 1, "java.lang.ClassLoader", "getClassLoader", "(Ljava.lang.Class;)Ljava.lang.ClassLoader;"))
         {
             eic.PatchOpCode(1, NormalizedByteCode.__nop);
             mw = [email protected]("getCallerClassLoader", "()Ljava.lang.ClassLoader;", false);
         }
         else
         {
             mw = [email protected]("getCallerClass", "()Ljava.lang.Class;", false);
         }
         mw.Link();
         mw.EmitCallvirt(eic.Emitter);
         return(true);
     }
     else if (!DynamicTypeWrapper.RequiresDynamicReflectionCallerClass(eic.ClassFile.Name, eic.Caller.Name, eic.Caller.Signature))
     {
         StaticCompiler.IssueMessage(Message.ReflectionCallerClassRequiresCallerID, eic.ClassFile.Name, eic.Caller.Name, eic.Caller.Signature);
     }
     return(false);
 }
Exemplo n.º 4
0
 private static bool Object_getClass(EmitIntrinsicContext eic)
 {
     // this is the null-check idiom that javac uses (both in its own source and in the code it generates)
     if (eic.MatchRange(0, 2) &&
         eic.Match(1, NormalizedByteCode.__pop))
     {
         eic.Emitter.Emit(OpCodes.Dup);
         eic.Emitter.EmitNullCheck();
         return(true);
     }
     // this optimizes obj1.getClass() ==/!= obj2.getClass()
     else if (eic.MatchRange(0, 4) &&
              eic.Match(1, NormalizedByteCode.__aload) &&
              eic.Match(2, NormalizedByteCode.__invokevirtual) &&
              (eic.Match(3, NormalizedByteCode.__if_acmpeq) || eic.Match(3, NormalizedByteCode.__if_acmpne)) &&
              (IsSafeForGetClassOptimization(eic.GetStackTypeWrapper(0, 0)) || IsSafeForGetClassOptimization(eic.GetStackTypeWrapper(2, 0))))
     {
         ClassFile.ConstantPoolItemMI cpi = eic.GetMethodref(2);
         if (cpi.Class == "java.lang.Object" && cpi.Name == "getClass" && cpi.Signature == "()Ljava.lang.Class;")
         {
             // we can't patch the current opcode, so we have to emit the first call to GetTypeHandle here
             eic.Emitter.Emit(OpCodes.Callvirt, Compiler.getTypeMethod);
             eic.PatchOpCode(2, NormalizedByteCode.__intrinsic_gettype);
             return(true);
         }
     }
     // this optimizes obj.getClass() == Xxx.class
     else if (eic.MatchRange(0, 3) &&
              eic.Match(1, NormalizedByteCode.__ldc) && eic.GetConstantType(1) == ClassFile.ConstantType.Class &&
              (eic.Match(2, NormalizedByteCode.__if_acmpeq) || eic.Match(2, NormalizedByteCode.__if_acmpne)))
     {
         TypeWrapper tw = eic.GetClassLiteral(1);
         if (tw.IsGhost || tw.IsGhostArray || tw.IsUnloadable || (tw.IsRemapped && tw.IsFinal && tw is DotNetTypeWrapper))
         {
             return(false);
         }
         eic.Emitter.Emit(OpCodes.Callvirt, Compiler.getTypeMethod);
         eic.Emitter.Emit(OpCodes.Ldtoken, (tw.IsRemapped && tw.IsFinal) ? tw.TypeAsTBD : tw.TypeAsBaseType);
         eic.Emitter.Emit(OpCodes.Call, Compiler.getTypeFromHandleMethod);
         eic.PatchOpCode(1, NormalizedByteCode.__nop);
         return(true);
     }
     return(false);
 }
Exemplo n.º 5
0
 private static bool Reflection_getCallerClass(EmitIntrinsicContext eic)
 {
     if (eic.Caller.HasCallerID)
     {
         int arg = eic.Caller.GetParametersForDefineMethod().Length - 1;
         if (!eic.Caller.IsStatic)
         {
             arg++;
         }
         eic.Emitter.EmitLdarg(arg);
         MethodWrapper mw;
         if (MatchInvokeStatic(eic, 1, "java.lang.ClassLoader", "getClassLoader", "(Ljava.lang.Class;)Ljava.lang.ClassLoader;"))
         {
             eic.PatchOpCode(1, NormalizedByteCode.__nop);
             mw = [email protected]("getCallerClassLoader", "()Ljava.lang.ClassLoader;", false);
         }
         else
         {
             mw = [email protected]("getCallerClass", "()Ljava.lang.Class;", false);
         }
         mw.Link();
         mw.EmitCallvirt(eic.Emitter);
         return(true);
     }
     else if (DynamicTypeWrapper.RequiresDynamicReflectionCallerClass(eic.ClassFile.Name, eic.Caller.Name, eic.Caller.Signature))
     {
         // since the non-intrinsic version of Reflection.getCallerClass() always throws an exception, we have to redirect to the dynamic version
         MethodWrapper getCallerClass = ClassLoaderWrapper.LoadClassCritical("sun.reflect.Reflection").GetMethodWrapper("getCallerClass", "(I)Ljava.lang.Class;", false);
         getCallerClass.Link();
         eic.Emitter.EmitLdc_I4(2);
         getCallerClass.EmitCall(eic.Emitter);
         return(true);
     }
     else
     {
         StaticCompiler.IssueMessage(Message.ReflectionCallerClassRequiresCallerID, eic.ClassFile.Name, eic.Caller.Name, eic.Caller.Signature);
     }
     return(false);
 }
Exemplo n.º 6
0
 // this intrinsifies the unsafe.objectFieldOffset(XXX.class.getDeclaredField("xxx")) pattern
 // to avoid initializing the full reflection machinery at this point
 private static bool Class_getDeclaredField(EmitIntrinsicContext eic)
 {
     // validate that we're inside the XXX class and that xxx is an instance field of that class
     if (eic.MatchRange(-2, 4) &&
         eic.Match(-2, NormalizedByteCode.__ldc) && eic.GetClassLiteral(-2) == eic.Caller.DeclaringType &&
         eic.Match(-1, NormalizedByteCode.__ldc_nothrow) &&
         eic.Match(1, NormalizedByteCode.__invokevirtual))
     {
         FieldWrapper field     = null;
         string       fieldName = eic.GetStringLiteral(-1);
         foreach (FieldWrapper fw in eic.Caller.DeclaringType.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);
 }
Exemplo n.º 7
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);
        }