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); }
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); }
private static bool Class_desiredAssertionStatus(EmitIntrinsicContext eic) { if (eic.MatchRange(-1, 2) && eic.Match(-1, NormalizedByteCode.__ldc)) { TypeWrapper classLiteral = eic.GetClassLiteral(-1); if (!classLiteral.IsUnloadable && classLiteral.GetClassLoader().RemoveAsserts) { eic.Emitter.Emit(OpCodes.Pop); eic.Emitter.Emit_Ldc_I4(0); return(true); } } return(false); }
private static bool String_toCharArray(EmitIntrinsicContext eic) { if (eic.MatchRange(-1, 2) && eic.Match(-1, NormalizedByteCode.__ldc)) { string str = eic.ClassFile.GetConstantPoolConstantString(eic.Code[eic.OpcodeIndex - 1].Arg1); // arbitrary length for "big" strings if (str.Length > 128) { eic.Emitter.Emit(OpCodes.Pop); EmitLoadCharArrayLiteral(eic.Emitter, str, eic.Caller.DeclaringType); return(true); } } return(false); }
private static bool Unsafe_ensureClassInitialized(EmitIntrinsicContext eic) { if (eic.MatchRange(-1, 2) && eic.Match(-1, NormalizedByteCode.__ldc)) { TypeWrapper classLiteral = eic.GetClassLiteral(-1); if (!classLiteral.IsUnloadable) { eic.Emitter.Emit(OpCodes.Pop); eic.Emitter.EmitNullCheck(); classLiteral.EmitRunClassConstructor(eic.Emitter); return(true); } } return(false); }
private static bool String_toCharArray(EmitIntrinsicContext eic) { if (eic.MatchRange(-1, 2) && eic.Match(-1, NormalizedByteCode.__ldc_nothrow)) { string str = eic.GetStringLiteral(-1); // arbitrary length for "big" strings if (str.Length > 128) { eic.Emitter.Emit(OpCodes.Pop); EmitLoadCharArrayLiteral(eic.Emitter, str, eic.Caller.DeclaringType); return(true); } } return(false); }
private static bool Reflection_getCallerClass(EmitIntrinsicContext eic) { if (eic.Caller.HasCallerID && eic.MatchRange(-1, 2) && eic.Match(-1, NormalizedByteCode.__iconst, 2)) { eic.Emitter.Emit(OpCodes.Pop); int arg = eic.Caller.GetParametersForDefineMethod().Length - 1; if (!eic.Caller.IsStatic) { arg++; } eic.Emitter.Emit(OpCodes.Ldarg, (short)arg); MethodWrapper mw = [email protected]("getCallerClass", "()Ljava.lang.Class;", false); mw.Link(); mw.EmitCallvirt(eic.Emitter); return(true); } return(false); }
// 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); }
private static bool Util_getInstanceTypeFromClass(EmitIntrinsicContext eic) { if (eic.MatchRange(-1, 2) && eic.Match(-1, NormalizedByteCode.__ldc)) { TypeWrapper tw = eic.GetClassLiteral(-1); if (!tw.IsUnloadable) { eic.Emitter.Emit(OpCodes.Pop); if (tw.IsRemapped && tw.IsFinal) { eic.Emitter.Emit(OpCodes.Ldtoken, tw.TypeAsTBD); } else { eic.Emitter.Emit(OpCodes.Ldtoken, tw.TypeAsBaseType); } eic.Emitter.Emit(OpCodes.Call, Compiler.getTypeFromHandleMethod); return(true); } } return(false); }
// 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); }