[Ikvm-commit] ikvm/runtime LambdaMetafactory.cs,1.5,1.6
Brought to you by:
jfrijters
|
From: Jeroen F. <jfr...@us...> - 2014-07-08 14:30:33
|
Update of /cvsroot/ikvm/ikvm/runtime In directory sfp-cvs-1.v30.ch3.sourceforge.com:/tmp/cvs-serv31414 Modified Files: LambdaMetafactory.cs Log Message: Added support for bridge methods. Index: LambdaMetafactory.cs =================================================================== RCS file: /cvsroot/ikvm/ikvm/runtime/LambdaMetafactory.cs,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** LambdaMetafactory.cs 8 Jul 2014 13:22:29 -0000 1.5 --- LambdaMetafactory.cs 8 Jul 2014 14:30:31 -0000 1.6 *************** *** 73,76 **** --- 73,77 ---- bool serializable = false; TypeWrapper[] markers = TypeWrapper.EmptyArray; + ClassFile.ConstantPoolItemMethodType[] bridges = null; if (bsm.ArgumentCount > 3) { *************** *** 92,100 **** if ((flags & AltFlags.Bridges) != 0) { ! int bridgeCount = classFile.GetConstantPoolConstantInteger(bsm.GetArgument(argpos++)); ! if (bridgeCount != 0) { ! Fail("bridges"); ! return false; } } --- 93,105 ---- if ((flags & AltFlags.Bridges) != 0) { ! bridges = new ClassFile.ConstantPoolItemMethodType[classFile.GetConstantPoolConstantInteger(bsm.GetArgument(argpos++))]; ! for (int i = 0; i < bridges.Length; i++) { ! bridges[i] = classFile.GetConstantPoolConstantMethodType(bsm.GetArgument(argpos++)); ! if (HasUnloadable(bridges[i])) ! { ! Fail("unloadable bridge"); ! return false; ! } } } *************** *** 112,116 **** TypeWrapper interfaceType = cpi.GetRetType(); MethodWrapper[] methodList; ! if (!CheckSupportedInterfaces(context.TypeWrapper, interfaceType, markers, out methodList)) { Fail("unsupported interface"); --- 117,121 ---- TypeWrapper interfaceType = cpi.GetRetType(); MethodWrapper[] methodList; ! if (!CheckSupportedInterfaces(context.TypeWrapper, interfaceType, markers, bridges, out methodList)) { Fail("unsupported interface"); *************** *** 127,155 **** return false; } - if (!IsSubTypeOf(instantiatedMethodType, samMethodType)) - { - Fail("instantiatedMethodType <= samMethodType"); - return false; - } TypeWrapper[] implParameters = GetImplParameters(implMethod); ! if (cpi.GetArgTypes().Length + samMethodType.GetArgTypes().Length != implParameters.Length) ! { ! Fail("K + N = M"); ! return false; ! } ! for (int i = 0, K = cpi.GetArgTypes().Length; i < K; i++) ! { ! if (!cpi.GetArgTypes()[i].IsSubTypeOf(implParameters[i])) ! { ! Fail("For i=1..K, Di = Ai"); ! return false; ! } ! } ! for (int i = 0, N = samMethodType.GetArgTypes().Length, k = cpi.GetArgTypes().Length; i < N; i++) { ! if (!IsAdaptable(instantiatedMethodType.GetArgTypes()[i], implParameters[i + k], false)) { ! Fail("For i=1..N, Ti is adaptable to Aj, where j=i+k (in" + context.TypeWrapper.Name + ")"); ! return false; } } --- 132,151 ---- return false; } TypeWrapper[] implParameters = GetImplParameters(implMethod); ! CheckConstraints(instantiatedMethodType, samMethodType, cpi.GetArgTypes(), implParameters); ! if (bridges != null) { ! foreach (ClassFile.ConstantPoolItemMethodType bridge in bridges) { ! if (bridge.Signature == samMethodType.Signature) ! { ! Fail("bridge signature matches sam"); ! return false; ! } ! if (!CheckConstraints(instantiatedMethodType, bridge, cpi.GetArgTypes(), implParameters)) ! { ! Fail("bridge constraints"); ! return false; ! } } } *************** *** 161,170 **** { Fail("The return type Rt is void, or the return type Ra is not void and is adaptable to Rt"); - Console.WriteLine("Ra = " + Ra.SigName); - Console.WriteLine("Rt = " + Rt.SigName); return false; } } MethodWrapper interfaceMethod = null; foreach (MethodWrapper mw in methodList) { --- 157,165 ---- { Fail("The return type Rt is void, or the return type Ra is not void and is adaptable to Rt"); return false; } } MethodWrapper interfaceMethod = null; + List<MethodWrapper> methods = new List<MethodWrapper>(); foreach (MethodWrapper mw in methodList) { *************** *** 172,176 **** { interfaceMethod = mw; ! break; } } --- 167,175 ---- { interfaceMethod = mw; ! methods.Add(mw); ! } ! else if (mw.IsAbstract && !IsObjectMethod(mw)) ! { ! methods.Add(mw); } } *************** *** 193,197 **** tb.AddInterfaceImplementation(marker.TypeAsBaseType); } ! ctor = CreateConstructorAndDispatch(context, interfaceType, cpi.GetArgTypes(), tb, interfaceMethod, implParameters, samMethodType, implMethod, instantiatedMethodType, serializable); AddDefaultInterfaceMethods(context, methodList, tb); return true; --- 192,196 ---- tb.AddInterfaceImplementation(marker.TypeAsBaseType); } ! ctor = CreateConstructorAndDispatch(context, cpi, tb, methods, implParameters, samMethodType, implMethod, instantiatedMethodType, serializable); AddDefaultInterfaceMethods(context, methodList, tb); return true; *************** *** 204,207 **** --- 203,237 ---- } + private static bool CheckConstraints(ClassFile.ConstantPoolItemMethodType instantiatedMethodType, ClassFile.ConstantPoolItemMethodType methodType, TypeWrapper[] args, TypeWrapper[] implParameters) + { + if (!IsSubTypeOf(instantiatedMethodType, methodType)) + { + Fail("instantiatedMethodType <= methodType"); + return false; + } + if (args.Length + methodType.GetArgTypes().Length != implParameters.Length) + { + Fail("K + N = M"); + return false; + } + for (int i = 0, K = args.Length; i < K; i++) + { + if (!args[i].IsSubTypeOf(implParameters[i])) + { + Fail("For i=1..K, Di = Ai"); + return false; + } + } + for (int i = 0, N = methodType.GetArgTypes().Length, k = args.Length; i < N; i++) + { + if (!IsAdaptable(instantiatedMethodType.GetArgTypes()[i], implParameters[i + k], false)) + { + Fail("For i=1..N, Ti is adaptable to Aj, where j=i+k"); + return false; + } + } + return true; + } + private static TypeWrapper[] GetImplParameters(ClassFile.ConstantPoolItemMethodHandle implMethod) { *************** *** 357,364 **** } ! private static MethodBuilder CreateConstructorAndDispatch(DynamicTypeWrapper.FinishContext context, TypeWrapper interfaceType, TypeWrapper[] args, TypeBuilder tb, ! MethodWrapper interfaceMethod, TypeWrapper[] implParameters, ClassFile.ConstantPoolItemMethodType samMethodType, ClassFile.ConstantPoolItemMethodHandle implMethod, ClassFile.ConstantPoolItemMethodType instantiatedMethodType, bool serializable) { // captured values Type[] capturedTypes = new Type[args.Length]; --- 387,396 ---- } ! private static MethodBuilder CreateConstructorAndDispatch(DynamicTypeWrapper.FinishContext context, ClassFile.ConstantPoolItemInvokeDynamic cpi, TypeBuilder tb, ! List<MethodWrapper> methods, TypeWrapper[] implParameters, ClassFile.ConstantPoolItemMethodType samMethodType, ClassFile.ConstantPoolItemMethodHandle implMethod, ClassFile.ConstantPoolItemMethodType instantiatedMethodType, bool serializable) { + TypeWrapper[] args = cpi.GetArgTypes(); + // captured values Type[] capturedTypes = new Type[args.Length]; *************** *** 389,396 **** ilgen.DoEmit(); ! // 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++) { ilgen.EmitLdarg(0); --- 421,479 ---- ilgen.DoEmit(); ! // dispatch methods ! foreach (MethodWrapper mw in methods) ! { ! EmitDispatch(context, args, tb, mw, implParameters, implMethod, instantiatedMethodType, capturedFields); ! } ! ! // 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, cpi.GetRetType().Name.Replace('.', '/')); ! ilgen.Emit(OpCodes.Ldstr, cpi.Name); ! ilgen.Emit(OpCodes.Ldstr, samMethodType.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; ! } ! ! private static void EmitDispatch(DynamicTypeWrapper.FinishContext context, TypeWrapper[] args, TypeBuilder tb, MethodWrapper interfaceMethod, TypeWrapper[] implParameters, ! ClassFile.ConstantPoolItemMethodHandle implMethod, ClassFile.ConstantPoolItemMethodType instantiatedMethodType, FieldBuilder[] capturedFields) ! { MethodBuilder mb = interfaceMethod.GetDefineMethodHelper().DefineMethod(context.TypeWrapper, tb, interfaceMethod.RealName, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final); ! CodeEmitter ilgen = CodeEmitter.Create(mb); ! for (int i = 0; i < capturedFields.Length; i++) { ilgen.EmitLdarg(0); *************** *** 412,416 **** { ilgen.EmitLdarg(i + 1); ! TypeWrapper Ui = samMethodType.GetArgTypes()[i]; TypeWrapper Ti = instantiatedMethodType.GetArgTypes()[i]; TypeWrapper Aj = implParameters[i + k]; --- 495,499 ---- { ilgen.EmitLdarg(i + 1); ! TypeWrapper Ui = interfaceMethod.GetParameters()[i]; TypeWrapper Ti = instantiatedMethodType.GetArgTypes()[i]; TypeWrapper Aj = implParameters[i + k]; *************** *** 547,592 **** ilgen.Emit(OpCodes.Ret); 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, interfaceType.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; } --- 630,633 ---- *************** *** 700,704 **** } ! private static bool CheckSupportedInterfaces(TypeWrapper caller, TypeWrapper tw, TypeWrapper[] markers, out MethodWrapper[] methodList) { // we don't need to check for unloadable, because we already did that while validating the invoke signature --- 741,745 ---- } ! private static bool CheckSupportedInterfaces(TypeWrapper caller, TypeWrapper tw, TypeWrapper[] markers, ClassFile.ConstantPoolItemMethodType[] bridges, out MethodWrapper[] methodList) { // we don't need to check for unloadable, because we already did that while validating the invoke signature *************** *** 710,714 **** Dictionary<MethodKey, MethodWrapper> methods = new Dictionary<MethodKey,MethodWrapper>(); int abstractMethodCount = 0; ! if (GatherAllInterfaceMethods(tw, methods, ref abstractMethodCount) && abstractMethodCount == 1) { foreach (TypeWrapper marker in markers) --- 751,756 ---- Dictionary<MethodKey, MethodWrapper> methods = new Dictionary<MethodKey,MethodWrapper>(); int abstractMethodCount = 0; ! int bridgeMethodCount = 0; ! if (GatherAllInterfaceMethods(tw, bridges, methods, ref abstractMethodCount, ref bridgeMethodCount) && abstractMethodCount == 1) { foreach (TypeWrapper marker in markers) *************** *** 719,723 **** return false; } ! if (!GatherAllInterfaceMethods(marker, methods, ref abstractMethodCount) || abstractMethodCount != 1) { methodList = null; --- 761,765 ---- return false; } ! if (!GatherAllInterfaceMethods(marker, null, methods, ref abstractMethodCount, ref bridgeMethodCount) || abstractMethodCount != 1) { methodList = null; *************** *** 725,728 **** --- 767,775 ---- } } + if (bridges != null && bridgeMethodCount != bridges.Length) + { + methodList = null; + return false; + } methodList = new MethodWrapper[methods.Count]; methods.Values.CopyTo(methodList, 0); *************** *** 733,737 **** } ! private static bool GatherAllInterfaceMethods(TypeWrapper tw, Dictionary<MethodKey, MethodWrapper> methods, ref int abstractMethodCount) { foreach (MethodWrapper mw in tw.GetMethods()) --- 780,785 ---- } ! private static bool GatherAllInterfaceMethods(TypeWrapper tw, ClassFile.ConstantPoolItemMethodType[] bridges, Dictionary<MethodKey, MethodWrapper> methods, ! ref int abstractMethodCount, ref int bridgeMethodCount) { foreach (MethodWrapper mw in tw.GetMethods()) *************** *** 763,767 **** if (mw.IsAbstract && !IsObjectMethod(mw)) { ! abstractMethodCount++; } } --- 811,822 ---- if (mw.IsAbstract && !IsObjectMethod(mw)) { ! if (bridges != null && IsBridge(mw, bridges)) ! { ! bridgeMethodCount++; ! } ! else ! { ! abstractMethodCount++; ! } } } *************** *** 775,779 **** foreach (TypeWrapper tw1 in tw.Interfaces) { ! if (!GatherAllInterfaceMethods(tw1, methods, ref abstractMethodCount)) { return false; --- 830,834 ---- foreach (TypeWrapper tw1 in tw.Interfaces) { ! if (!GatherAllInterfaceMethods(tw1, bridges, methods, ref abstractMethodCount, ref bridgeMethodCount)) { return false; *************** *** 783,786 **** --- 838,853 ---- } + private static bool IsBridge(MethodWrapper mw, ClassFile.ConstantPoolItemMethodType[] bridges) + { + foreach (ClassFile.ConstantPoolItemMethodType bridge in bridges) + { + if (bridge.Signature == mw.Signature) + { + return true; + } + } + return false; + } + private static bool IsObjectMethod(MethodWrapper mw) { |