diff options
author | jfrijters <jfrijters> | 2014-07-08 12:44:08 +0400 |
---|---|---|
committer | jfrijters <jfrijters> | 2014-07-08 12:44:08 +0400 |
commit | 77cfa0d12a2811ec6dde829edafaac46e3bbb615 (patch) | |
tree | 3b5af106e6b6bf8ba98d5eb9d015f7a65ef04447 | |
parent | 1cd5828b82a0998a92579757582c0ce321c317df (diff) |
Use the same nested type for lambdas that are created with an invokedynamic to the same constant pool item (so that deserialization uses the same class as the original).
-rw-r--r-- | runtime/LambdaMetafactory.cs | 19 | ||||
-rw-r--r-- | runtime/compiler.cs | 12 |
2 files changed, 16 insertions, 15 deletions
diff --git a/runtime/LambdaMetafactory.cs b/runtime/LambdaMetafactory.cs index c987f33d..afec4e13 100644 --- a/runtime/LambdaMetafactory.cs +++ b/runtime/LambdaMetafactory.cs @@ -35,16 +35,19 @@ using System.Reflection.Emit; namespace IKVM.Internal { - static class LambdaMetafactory + sealed class LambdaMetafactory { - internal static bool Emit(DynamicTypeWrapper.FinishContext context, ClassFile classFile, ClassFile.ConstantPoolItemInvokeDynamic cpi, CodeEmitter ilgen) + private MethodBuilder ctor; + + internal static bool Emit(DynamicTypeWrapper.FinishContext context, ClassFile classFile, int constantPoolIndex, ClassFile.ConstantPoolItemInvokeDynamic cpi, CodeEmitter ilgen) { ClassFile.BootstrapMethod bsm = classFile.GetBootstrapMethod(cpi.BootstrapMethod); if (!IsLambdaMetafactory(classFile, bsm) && !IsLambdaAltMetafactory(classFile, bsm)) { return false; } - if (!EmitImpl(context, classFile, cpi, bsm, ilgen)) + LambdaMetafactory lmf = context.GetValue<LambdaMetafactory>(constantPoolIndex); + if (lmf.ctor == null && !lmf.EmitImpl(context, classFile, cpi, bsm, ilgen)) { #if STATIC_COMPILER if (context.TypeWrapper.GetClassLoader().DisableDynamicBinding) @@ -54,10 +57,13 @@ namespace IKVM.Internal #endif return false; } + ilgen.Emit(OpCodes.Newobj, lmf.ctor); + // the CLR verification rules about type merging mean we have to explicitly cast to the interface type here + ilgen.Emit(OpCodes.Castclass, cpi.GetRetType().TypeAsBaseType); return true; } - private static bool EmitImpl(DynamicTypeWrapper.FinishContext context, ClassFile classFile, ClassFile.ConstantPoolItemInvokeDynamic cpi, ClassFile.BootstrapMethod bsm, CodeEmitter ilgen) + private bool EmitImpl(DynamicTypeWrapper.FinishContext context, ClassFile classFile, ClassFile.ConstantPoolItemInvokeDynamic cpi, ClassFile.BootstrapMethod bsm, CodeEmitter ilgen) { if (HasUnloadable(cpi)) { @@ -178,11 +184,8 @@ namespace IKVM.Internal { tb.AddInterfaceImplementation(CoreClasses.java.io.Serializable.Wrapper.TypeAsBaseType); } - MethodBuilder ctor = CreateConstructorAndDispatch(context, cpi.GetArgTypes(), tb, interfaceMethod, implParameters, samMethodType, implMethod, instantiatedMethodType, serializable); + 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 - ilgen.Emit(OpCodes.Castclass, interfaceType.TypeAsBaseType); return true; } diff --git a/runtime/compiler.cs b/runtime/compiler.cs index fc1f264a..e38729f8 100644 --- a/runtime/compiler.cs +++ b/runtime/compiler.cs @@ -1434,8 +1434,11 @@ sealed class Compiler { ClassFile.ConstantPoolItemInvokeDynamic cpi = classFile.GetInvokeDynamic(instr.Arg1); CastInterfaceArgs(null, cpi.GetArgTypes(), i, false); - EmitInvokeDynamic(cpi); - EmitReturnTypeConversion(cpi.GetRetType()); + if (!LambdaMetafactory.Emit(context, classFile, instr.Arg1, cpi, ilGenerator)) + { + EmitInvokeDynamic(cpi); + EmitReturnTypeConversion(cpi.GetRetType()); + } nonleaf = true; break; } @@ -3208,11 +3211,6 @@ sealed class Compiler private void EmitInvokeDynamic(ClassFile.ConstantPoolItemInvokeDynamic cpi) { - if (LambdaMetafactory.Emit(context, classFile, cpi, ilGenerator)) - { - // we intrinsified the lambda factory - return; - } CodeEmitter ilgen = ilGenerator; TypeWrapper[] args = cpi.GetArgTypes(); CodeEmitterLocal[] temps = new CodeEmitterLocal[args.Length]; |