Enable ldc <MethodType> to work for unloadable types in dynamic mode.

This commit is contained in:
jfrijters 2013-01-29 16:43:52 +00:00
Родитель ead034f0f5
Коммит ec831d3bc1
2 изменённых файлов: 52 добавлений и 21 удалений

Просмотреть файл

@ -2963,37 +2963,68 @@ sealed class Compiler
ilgen.Emit(OpCodes.Ldstr, classFile.GetConstantPoolConstantString(constant));
break;
case ClassFile.ConstantType.Class:
{
TypeWrapper tw = classFile.GetConstantPoolClassType(constant);
if (tw.IsUnloadable)
{
Profiler.Count("EmitDynamicClassLiteral");
ilgen.Emit(OpCodes.Ldtoken, clazz.TypeAsTBD);
ilgen.Emit(OpCodes.Ldstr, tw.Name);
ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicClassLiteral);
java_lang_Class.EmitCheckcast(clazz, ilgen);
}
else
{
tw.EmitClassLiteral(ilgen);
}
EmitLoadClass(ilgen, classFile.GetConstantPoolClassType(constant));
break;
}
case ClassFile.ConstantType.MethodHandle:
context.GetValue<MethodHandleConstant>(constant).Emit(this, ilgen, constant);
break;
case ClassFile.ConstantType.MethodType:
{
ClassFile.ConstantPoolItemMethodType cpi = classFile.GetConstantPoolConstantMethodType(constant);
Type delegateType = MethodHandleUtil.CreateDelegateTypeForLoadConstant(cpi.GetArgTypes(), cpi.GetRetType());
ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.LoadMethodType.MakeGenericMethod(delegateType));
EmitLoadMethodType(ilgen, classFile.GetConstantPoolConstantMethodType(constant));
break;
}
default:
throw new InvalidOperationException();
}
}
private void EmitLoadClass(CodeEmitter ilgen, TypeWrapper tw)
{
if (tw.IsUnloadable)
{
Profiler.Count("EmitDynamicClassLiteral");
ilgen.Emit(OpCodes.Ldtoken, clazz.TypeAsTBD);
ilgen.Emit(OpCodes.Ldstr, tw.Name);
ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicClassLiteral);
java_lang_Class.EmitCheckcast(clazz, ilgen);
}
else
{
tw.EmitClassLiteral(ilgen);
}
}
private void EmitLoadMethodType(CodeEmitter ilgen, ClassFile.ConstantPoolItemMethodType cpi)
{
TypeWrapper ret = cpi.GetRetType();
TypeWrapper[] args = cpi.GetArgTypes();
TypeWrapper tw = ret;
for (int i = 0; !tw.IsUnloadable && i < args.Length; i++)
{
tw = args[i];
}
if (tw.IsUnloadable)
{
EmitLoadClass(ilgen, ret);
ilgen.EmitLdc_I4(args.Length);
ilgen.Emit(OpCodes.Newarr, CoreClasses.java.lang.Class.Wrapper.TypeAsArrayType);
for (int i = 0; i < args.Length; i++)
{
ilgen.Emit(OpCodes.Dup);
ilgen.EmitLdc_I4(i);
EmitLoadClass(ilgen, args[i]);
ilgen.Emit(OpCodes.Stelem_Ref);
}
MethodWrapper methodType = ClassLoaderWrapper.LoadClassCritical("java.lang.invoke.MethodType")
.GetMethodWrapper("methodType", "(Ljava.lang.Class;[Ljava.lang.Class;)Ljava.lang.invoke.MethodType;", false);
methodType.Link();
methodType.EmitCall(ilgen);
}
else
{
Type delegateType = MethodHandleUtil.CreateDelegateTypeForLoadConstant(cpi.GetArgTypes(), cpi.GetRetType());
ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.LoadMethodType.MakeGenericMethod(delegateType));
}
}
private static class InvokeDynamicBuilder
{
private static readonly Type typeofOpenIndyCallSite;

Просмотреть файл

@ -2574,7 +2574,6 @@ sealed class MethodAnalyzer
}
break;
}
#endif
case ClassFile.ConstantType.MethodType:
{
ClassFile.ConstantPoolItemMethodType cpi = classFile.GetConstantPoolConstantMethodType(instructions[i].Arg1);
@ -2590,6 +2589,7 @@ sealed class MethodAnalyzer
}
break;
}
#endif
case ClassFile.ConstantType.MethodHandle:
PatchLdcMethodHandle(ref instructions[i]);
break;