[Ikvm-commit] ikvm/runtime DynamicTypeWrapper.cs, 1.253, 1.254 LambdaMetafactory.cs, 1.1, 1.2 TypeW
Brought to you by:
jfrijters
|
From: Jeroen F. <jfr...@us...> - 2014-07-08 08:23:44
|
Update of /cvsroot/ikvm/ikvm/runtime In directory sfp-cvs-1.v30.ch3.sourceforge.com:/tmp/cvs-serv9277 Modified Files: DynamicTypeWrapper.cs LambdaMetafactory.cs TypeWrapper.cs Log Message: Added support for intrinsifying serializable lambdas. Index: TypeWrapper.cs =================================================================== RCS file: /cvsroot/ikvm/ikvm/runtime/TypeWrapper.cs,v retrieving revision 1.475 retrieving revision 1.476 diff -C2 -d -r1.475 -r1.476 *** TypeWrapper.cs 7 Jul 2014 07:40:35 -0000 1.475 --- TypeWrapper.cs 8 Jul 2014 08:23:41 -0000 1.476 *************** *** 5747,5750 **** --- 5747,5766 ---- { } + + protected override void LazyPublishMembers() + { + MethodInfo mi = type.GetMethod("writeReplace", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly, null, Type.EmptyTypes, null); + if (mi != null) + { + SetMethods(new MethodWrapper[] { + new TypicalMethodWrapper(this, "writeReplace", "()Ljava.lang.Object;", mi, CoreClasses.java.lang.Object.Wrapper, TypeWrapper.EmptyArray, Modifiers.Private, MemberFlags.None) + }); + } + else + { + SetMethods(MethodWrapper.EmptyArray); + } + SetFields(FieldWrapper.EmptyArray); + } } } Index: LambdaMetafactory.cs =================================================================== RCS file: /cvsroot/ikvm/ikvm/runtime/LambdaMetafactory.cs,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** LambdaMetafactory.cs 1 Jul 2014 15:12:34 -0000 1.1 --- LambdaMetafactory.cs 8 Jul 2014 08:23:41 -0000 1.2 *************** *** 41,45 **** { ClassFile.BootstrapMethod bsm = classFile.GetBootstrapMethod(cpi.BootstrapMethod); ! if (!IsLambdaMetafactory(classFile, bsm)) { return false; --- 41,45 ---- { ClassFile.BootstrapMethod bsm = classFile.GetBootstrapMethod(cpi.BootstrapMethod); ! if (!IsLambdaMetafactory(classFile, bsm) && !IsLambdaAltMetafactory(classFile, bsm)) { return false; *************** *** 65,68 **** --- 65,88 ---- return false; } + bool serializable = false; + if (bsm.ArgumentCount > 3) + { + AltFlags flags = (AltFlags)classFile.GetConstantPoolConstantInteger(bsm.GetArgument(3)); + serializable = (flags & AltFlags.Serializable) != 0; + if ((flags & AltFlags.Markers) != 0) + { + Fail("markers"); + return false; + } + if ((flags & AltFlags.Bridges) != 0) + { + int bridgeCount = classFile.GetConstantPoolConstantInteger(bsm.GetArgument(4)); + if (bridgeCount != 0) + { + Fail("bridges"); + return false; + } + } + } ClassFile.ConstantPoolItemMethodType samMethodType = classFile.GetConstantPoolConstantMethodType(bsm.GetArgument(0)); ClassFile.ConstantPoolItemMethodHandle implMethod = classFile.GetConstantPoolConstantMethodHandle(bsm.GetArgument(1)); *************** *** 87,90 **** --- 107,115 ---- return false; } + if (serializable && Array.Exists(methodList, delegate(MethodWrapper mw) { return mw.Name == "writeReplace" && mw.Signature == "()Ljava.lang.Object;"; })) + { + Fail("writeReplace"); + return false; + } if (!IsSupportedImplMethod(implMethod, context.TypeWrapper, cpi.GetArgTypes(), instantiatedMethodType)) { *************** *** 150,156 **** // but should we decide to do that, we'd need to somehow communicate to AnonymousTypeWrapper what the 'real' interface is tb.AddInterfaceImplementation(interfaceType.TypeAsBaseType); ! TypeWrapperFactory factory = context.TypeWrapper.GetClassLoader().GetTypeWrapperFactory(); ! MethodBuilder ctor = CreateConstructorAndDispatch(factory, cpi.GetArgTypes(), tb, interfaceMethod, implParameters, samMethodType, implMethod, instantiatedMethodType); ! AddDefaultInterfaceMethods(factory, methodList, tb); ilgen.Emit(OpCodes.Newobj, ctor); // the CLR verification rules about type merging mean we have to explicitly cast to the interface type here --- 175,184 ---- // but should we decide to do that, we'd need to somehow communicate to AnonymousTypeWrapper what the 'real' interface is tb.AddInterfaceImplementation(interfaceType.TypeAsBaseType); ! if (serializable) ! { ! tb.AddInterfaceImplementation(CoreClasses.java.io.Serializable.Wrapper.TypeAsBaseType); ! } ! MethodBuilder ctor = CreateConstructorAndDispatch(context, cpi.GetArgTypes(), tb, interfaceMethod, implParameters, samMethodType, implMethod, instantiatedMethodType, serializable); ! AddDefaultInterfaceMethods(context, methodList, tb); ilgen.Emit(OpCodes.Newobj, ctor); // the CLR verification rules about type merging mean we have to explicitly cast to the interface type here *************** *** 318,323 **** } ! private static MethodBuilder CreateConstructorAndDispatch(TypeWrapperFactory context, TypeWrapper[] args, TypeBuilder tb, MethodWrapper interfaceMethod, TypeWrapper[] implParameters, ! ClassFile.ConstantPoolItemMethodType samMethodType, ClassFile.ConstantPoolItemMethodHandle implMethod, ClassFile.ConstantPoolItemMethodType instantiatedMethodType) { // captured values --- 346,352 ---- } ! private static MethodBuilder CreateConstructorAndDispatch(DynamicTypeWrapper.FinishContext context, TypeWrapper[] args, TypeBuilder tb, ! MethodWrapper interfaceMethod, TypeWrapper[] implParameters, ClassFile.ConstantPoolItemMethodType samMethodType, ClassFile.ConstantPoolItemMethodHandle implMethod, ! ClassFile.ConstantPoolItemMethodType instantiatedMethodType, bool serializable) { // captured values *************** *** 350,354 **** // dispatch method ! MethodBuilder mb = interfaceMethod.GetDefineMethodHelper().DefineMethod(context, tb, interfaceMethod.RealName, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final); ilgen = CodeEmitter.Create(mb); for (int i = 0; i < capturedTypes.Length; i++) --- 379,383 ---- // dispatch method ! MethodBuilder mb = interfaceMethod.GetDefineMethodHelper().DefineMethod(context.TypeWrapper, tb, interfaceMethod.RealName, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final); ilgen = CodeEmitter.Create(mb); for (int i = 0; i < capturedTypes.Length; i++) *************** *** 508,511 **** --- 537,580 ---- ilgen.DoEmit(); + // writeReplace method + if (serializable) + { + MethodBuilder writeReplace = tb.DefineMethod("writeReplace", MethodAttributes.Private, Types.Object, Type.EmptyTypes); + ilgen = CodeEmitter.Create(writeReplace); + context.TypeWrapper.EmitClassLiteral(ilgen); + ilgen.Emit(OpCodes.Ldstr, interfaceMethod.DeclaringType.Name.Replace('.', '/')); + ilgen.Emit(OpCodes.Ldstr, interfaceMethod.Name); + ilgen.Emit(OpCodes.Ldstr, interfaceMethod.Signature.Replace('.', '/')); + ilgen.EmitLdc_I4((int)implMethod.Kind); + ilgen.Emit(OpCodes.Ldstr, implMethod.Class.Replace('.', '/')); + ilgen.Emit(OpCodes.Ldstr, implMethod.Name); + ilgen.Emit(OpCodes.Ldstr, implMethod.Signature.Replace('.', '/')); + ilgen.Emit(OpCodes.Ldstr, instantiatedMethodType.Signature.Replace('.', '/')); + ilgen.EmitLdc_I4(capturedFields.Length); + ilgen.Emit(OpCodes.Newarr, Types.Object); + for (int i = 0; i < capturedFields.Length; i++) + { + ilgen.Emit(OpCodes.Dup); + ilgen.EmitLdc_I4(i); + ilgen.EmitLdarg(0); + ilgen.Emit(OpCodes.Ldfld, capturedFields[i]); + if (args[i].IsPrimitive) + { + Boxer.EmitBox(ilgen, args[i]); + } + else if (args[i].IsGhost) + { + args[i].EmitConvSignatureTypeToStackType(ilgen); + } + ilgen.Emit(OpCodes.Stelem, Types.Object); + } + MethodWrapper ctorSerializedLambda = ClassLoaderWrapper.LoadClassCritical("java.lang.invoke.SerializedLambda").GetMethodWrapper(StringConstants.INIT, + "(Ljava.lang.Class;Ljava.lang.String;Ljava.lang.String;Ljava.lang.String;ILjava.lang.String;Ljava.lang.String;Ljava.lang.String;Ljava.lang.String;[Ljava.lang.Object;)V", false); + ctorSerializedLambda.Link(); + ctorSerializedLambda.EmitNewobj(ilgen); + ilgen.Emit(OpCodes.Ret); + ilgen.DoEmit(); + } + return ctor; } *************** *** 551,566 **** } ! private static void AddDefaultInterfaceMethods(TypeWrapperFactory context, MethodWrapper[] methodList, TypeBuilder tb) { foreach (MethodWrapper mw in methodList) { if (!mw.IsAbstract) { ! MethodBuilder mb = mw.GetDefineMethodHelper().DefineMethod(context, tb, mw.RealName, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final); DynamicTypeWrapper.FinishContext.EmitCallDefaultInterfaceMethod(mb, mw); } else if (IsObjectMethod(mw)) { ! MethodBuilder mb = mw.GetDefineMethodHelper().DefineMethod(context, tb, mw.RealName, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final); CodeEmitter ilgen = CodeEmitter.Create(mb); for (int i = 0, count = mw.GetParameters().Length; i <= count; i++) --- 620,636 ---- } ! private static void AddDefaultInterfaceMethods(DynamicTypeWrapper.FinishContext context, MethodWrapper[] methodList, TypeBuilder tb) { + TypeWrapperFactory factory = context.TypeWrapper.GetClassLoader().GetTypeWrapperFactory(); foreach (MethodWrapper mw in methodList) { if (!mw.IsAbstract) { ! MethodBuilder mb = mw.GetDefineMethodHelper().DefineMethod(factory, tb, mw.RealName, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final); DynamicTypeWrapper.FinishContext.EmitCallDefaultInterfaceMethod(mb, mw); } else if (IsObjectMethod(mw)) { ! MethodBuilder mb = mw.GetDefineMethodHelper().DefineMethod(factory, tb, mw.RealName, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final); CodeEmitter ilgen = CodeEmitter.Create(mb); for (int i = 0, count = mw.GetParameters().Length; i <= count; i++) *************** *** 742,745 **** --- 812,874 ---- } + [Flags] + enum AltFlags + { + Serializable = 1, + Markers = 2, + Bridges = 4, + Mask = Serializable | Markers | Bridges + } + + private static bool IsLambdaAltMetafactory(ClassFile classFile, ClassFile.BootstrapMethod bsm) + { + ClassFile.ConstantPoolItemMethodHandle mh; + AltFlags flags; + int argpos = 4; + return bsm.ArgumentCount >= 4 + && (mh = classFile.GetConstantPoolConstantMethodHandle(bsm.BootstrapMethodIndex)).Kind == ClassFile.RefKind.invokeStatic + && IsLambdaAltMetafactory(mh.Member) + && classFile.GetConstantPoolConstantType(bsm.GetArgument(0)) == ClassFile.ConstantType.MethodType + && classFile.GetConstantPoolConstantType(bsm.GetArgument(1)) == ClassFile.ConstantType.MethodHandle + && classFile.GetConstantPoolConstantType(bsm.GetArgument(2)) == ClassFile.ConstantType.MethodType + && classFile.GetConstantPoolConstantType(bsm.GetArgument(3)) == ClassFile.ConstantType.Integer + && ((flags = (AltFlags)classFile.GetConstantPoolConstantInteger(bsm.GetArgument(3))) & ~AltFlags.Mask) == 0 + && ((flags & AltFlags.Markers) == 0 || CheckOptionalArgs(classFile, bsm, ClassFile.ConstantType.Class, ref argpos)) + && ((flags & AltFlags.Bridges) == 0 || CheckOptionalArgs(classFile, bsm, ClassFile.ConstantType.MethodType, ref argpos)) + && argpos == bsm.ArgumentCount; + } + + private static bool IsLambdaAltMetafactory(MemberWrapper mw) + { + return mw.Name == "altMetafactory" + && mw.Signature == "(Ljava.lang.invoke.MethodHandles$Lookup;Ljava.lang.String;Ljava.lang.invoke.MethodType;[Ljava.lang.Object;)Ljava.lang.invoke.CallSite;" + && mw.DeclaringType.Name == "java.lang.invoke.LambdaMetafactory"; + } + + private static bool CheckOptionalArgs(ClassFile classFile, ClassFile.BootstrapMethod bsm, ClassFile.ConstantType type, ref int argpos) + { + if (bsm.ArgumentCount - argpos < 1) + { + return false; + } + if (classFile.GetConstantPoolConstantType(bsm.GetArgument(argpos)) != ClassFile.ConstantType.Integer) + { + return false; + } + int count = classFile.GetConstantPoolConstantInteger(bsm.GetArgument(argpos++)); + if (count < 0 || bsm.ArgumentCount - argpos < count) + { + return false; + } + for (int i = 0; i < count; i++) + { + if (classFile.GetConstantPoolConstantType(bsm.GetArgument(argpos++)) != type) + { + return false; + } + } + return true; + } + private static bool HasUnloadable(ClassFile.ConstantPoolItemInvokeDynamic cpi) { Index: DynamicTypeWrapper.cs =================================================================== RCS file: /cvsroot/ikvm/ikvm/runtime/DynamicTypeWrapper.cs,v retrieving revision 1.253 retrieving revision 1.254 diff -C2 -d -r1.253 -r1.254 *** DynamicTypeWrapper.cs 4 Jul 2014 11:06:06 -0000 1.253 --- DynamicTypeWrapper.cs 8 Jul 2014 08:23:41 -0000 1.254 *************** *** 4000,4004 **** } ! internal TypeWrapper TypeWrapper { get { return wrapper; } --- 4000,4004 ---- } ! internal DynamicTypeWrapper TypeWrapper { get { return wrapper; } |