Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/ikvm-fork.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjfrijters <jfrijters>2014-06-16 15:36:14 +0400
committerjfrijters <jfrijters>2014-06-16 15:36:14 +0400
commiteb783d1a9bddd9361997635fa65f2f78ab6e80e2 (patch)
tree7ff75c1896e7563c219d35e71d907370ba8359c5
parent839b1b6b19c2b4f44a9fd024b2781d37031caa98 (diff)
Bug fix. Invokedynamic bootstrap method can also be a constructor.
-rw-r--r--runtime/compiler.cs1097
1 files changed, 536 insertions, 561 deletions
diff --git a/runtime/compiler.cs b/runtime/compiler.cs
index 8b8a30e4..2145a68b 100644
--- a/runtime/compiler.cs
+++ b/runtime/compiler.cs
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2002-2013 Jeroen Frijters
+ Copyright (C) 2002-2014 Jeroen Frijters
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -60,13 +60,9 @@ static class ByteCodeHelperMethods
internal static readonly MethodInfo DynamicAaload;
internal static readonly MethodInfo DynamicAastore;
internal static readonly MethodInfo DynamicClassLiteral;
- internal static readonly MethodInfo DynamicGetfield;
- internal static readonly MethodInfo DynamicGetstatic;
internal static readonly MethodInfo DynamicMultianewarray;
internal static readonly MethodInfo DynamicNewarray;
internal static readonly MethodInfo DynamicNewCheckOnly;
- internal static readonly MethodInfo DynamicPutfield;
- internal static readonly MethodInfo DynamicPutstatic;
internal static readonly MethodInfo DynamicCreateDelegate;
internal static readonly MethodInfo DynamicLoadMethodType;
internal static readonly MethodInfo DynamicLoadMethodHandle;
@@ -81,8 +77,8 @@ static class ByteCodeHelperMethods
internal static readonly MethodInfo mapException;
internal static readonly MethodInfo GetDelegateForInvokeExact;
internal static readonly MethodInfo GetDelegateForInvoke;
+ internal static readonly MethodInfo GetDelegateForInvokeBasic;
internal static readonly MethodInfo LoadMethodType;
- internal static readonly MethodInfo MethodHandleFromDelegate;
internal static readonly MethodInfo LinkIndyCallSite;
static ByteCodeHelperMethods()
@@ -92,47 +88,60 @@ static class ByteCodeHelperMethods
#else
Type typeofByteCodeHelper = typeof(IKVM.Runtime.ByteCodeHelper);
#endif
- multianewarray = typeofByteCodeHelper.GetMethod("multianewarray");
- multianewarray_ghost = typeofByteCodeHelper.GetMethod("multianewarray_ghost");
- anewarray_ghost = typeofByteCodeHelper.GetMethod("anewarray_ghost");
- f2i = typeofByteCodeHelper.GetMethod("f2i");
- d2i = typeofByteCodeHelper.GetMethod("d2i");
- f2l = typeofByteCodeHelper.GetMethod("f2l");
- d2l = typeofByteCodeHelper.GetMethod("d2l");
- arraycopy_fast = typeofByteCodeHelper.GetMethod("arraycopy_fast");
- arraycopy_primitive_8 = typeofByteCodeHelper.GetMethod("arraycopy_primitive_8");
- arraycopy_primitive_4 = typeofByteCodeHelper.GetMethod("arraycopy_primitive_4");
- arraycopy_primitive_2 = typeofByteCodeHelper.GetMethod("arraycopy_primitive_2");
- arraycopy_primitive_1 = typeofByteCodeHelper.GetMethod("arraycopy_primitive_1");
- arraycopy = typeofByteCodeHelper.GetMethod("arraycopy");
- DynamicCast = typeofByteCodeHelper.GetMethod("DynamicCast");
- DynamicAaload = typeofByteCodeHelper.GetMethod("DynamicAaload");
- DynamicAastore = typeofByteCodeHelper.GetMethod("DynamicAastore");
- DynamicClassLiteral = typeofByteCodeHelper.GetMethod("DynamicClassLiteral");
- DynamicGetfield = typeofByteCodeHelper.GetMethod("DynamicGetfield");
- DynamicGetstatic = typeofByteCodeHelper.GetMethod("DynamicGetstatic");
- DynamicMultianewarray = typeofByteCodeHelper.GetMethod("DynamicMultianewarray");
- DynamicNewarray = typeofByteCodeHelper.GetMethod("DynamicNewarray");
- DynamicNewCheckOnly = typeofByteCodeHelper.GetMethod("DynamicNewCheckOnly");
- DynamicPutfield = typeofByteCodeHelper.GetMethod("DynamicPutfield");
- DynamicPutstatic = typeofByteCodeHelper.GetMethod("DynamicPutstatic");
- DynamicCreateDelegate = typeofByteCodeHelper.GetMethod("DynamicCreateDelegate");
- DynamicLoadMethodType = typeofByteCodeHelper.GetMethod("DynamicLoadMethodType");
- DynamicLoadMethodHandle = typeofByteCodeHelper.GetMethod("DynamicLoadMethodHandle");
- DynamicBinderMemberLookup = typeofByteCodeHelper.GetMethod("DynamicBinderMemberLookup");
- VerboseCastFailure = typeofByteCodeHelper.GetMethod("VerboseCastFailure");
- SkipFinalizer = typeofByteCodeHelper.GetMethod("SkipFinalizer");
- DynamicInstanceOf = typeofByteCodeHelper.GetMethod("DynamicInstanceOf");
- volatileReadDouble = typeofByteCodeHelper.GetMethod("VolatileRead", new Type[] { Types.Double.MakeByRefType() });
- volatileReadLong = typeofByteCodeHelper.GetMethod("VolatileRead", new Type[] { Types.Int64.MakeByRefType() });
- volatileWriteDouble = typeofByteCodeHelper.GetMethod("VolatileWrite", new Type[] { Types.Double.MakeByRefType(), Types.Double });
- volatileWriteLong = typeofByteCodeHelper.GetMethod("VolatileWrite", new Type[] { Types.Int64.MakeByRefType(), Types.Int64 });
- mapException = typeofByteCodeHelper.GetMethod("MapException");
- GetDelegateForInvokeExact = typeofByteCodeHelper.GetMethod("GetDelegateForInvokeExact");
- GetDelegateForInvoke = typeofByteCodeHelper.GetMethod("GetDelegateForInvoke");
- LoadMethodType = typeofByteCodeHelper.GetMethod("LoadMethodType");
- MethodHandleFromDelegate = typeofByteCodeHelper.GetMethod("MethodHandleFromDelegate");
- LinkIndyCallSite = typeofByteCodeHelper.GetMethod("LinkIndyCallSite");
+ multianewarray = GetHelper(typeofByteCodeHelper, "multianewarray");
+ multianewarray_ghost = GetHelper(typeofByteCodeHelper, "multianewarray_ghost");
+ anewarray_ghost = GetHelper(typeofByteCodeHelper, "anewarray_ghost");
+ f2i = GetHelper(typeofByteCodeHelper, "f2i");
+ d2i = GetHelper(typeofByteCodeHelper, "d2i");
+ f2l = GetHelper(typeofByteCodeHelper, "f2l");
+ d2l = GetHelper(typeofByteCodeHelper, "d2l");
+ arraycopy_fast = GetHelper(typeofByteCodeHelper, "arraycopy_fast");
+ arraycopy_primitive_8 = GetHelper(typeofByteCodeHelper, "arraycopy_primitive_8");
+ arraycopy_primitive_4 = GetHelper(typeofByteCodeHelper, "arraycopy_primitive_4");
+ arraycopy_primitive_2 = GetHelper(typeofByteCodeHelper, "arraycopy_primitive_2");
+ arraycopy_primitive_1 = GetHelper(typeofByteCodeHelper, "arraycopy_primitive_1");
+ arraycopy = GetHelper(typeofByteCodeHelper, "arraycopy");
+ DynamicCast = GetHelper(typeofByteCodeHelper, "DynamicCast");
+ DynamicAaload = GetHelper(typeofByteCodeHelper, "DynamicAaload");
+ DynamicAastore = GetHelper(typeofByteCodeHelper, "DynamicAastore");
+ DynamicClassLiteral = GetHelper(typeofByteCodeHelper, "DynamicClassLiteral");
+ DynamicMultianewarray = GetHelper(typeofByteCodeHelper, "DynamicMultianewarray");
+ DynamicNewarray = GetHelper(typeofByteCodeHelper, "DynamicNewarray");
+ DynamicNewCheckOnly = GetHelper(typeofByteCodeHelper, "DynamicNewCheckOnly");
+ DynamicCreateDelegate = GetHelper(typeofByteCodeHelper, "DynamicCreateDelegate");
+ DynamicLoadMethodType = GetHelper(typeofByteCodeHelper, "DynamicLoadMethodType");
+ DynamicLoadMethodHandle = GetHelper(typeofByteCodeHelper, "DynamicLoadMethodHandle");
+ DynamicBinderMemberLookup = GetHelper(typeofByteCodeHelper, "DynamicBinderMemberLookup");
+ VerboseCastFailure = GetHelper(typeofByteCodeHelper, "VerboseCastFailure");
+ SkipFinalizer = GetHelper(typeofByteCodeHelper, "SkipFinalizer");
+ DynamicInstanceOf = GetHelper(typeofByteCodeHelper, "DynamicInstanceOf");
+ volatileReadDouble = GetHelper(typeofByteCodeHelper, "VolatileRead", new Type[] { Types.Double.MakeByRefType() });
+ volatileReadLong = GetHelper(typeofByteCodeHelper, "VolatileRead", new Type[] { Types.Int64.MakeByRefType() });
+ volatileWriteDouble = GetHelper(typeofByteCodeHelper, "VolatileWrite", new Type[] { Types.Double.MakeByRefType(), Types.Double });
+ volatileWriteLong = GetHelper(typeofByteCodeHelper, "VolatileWrite", new Type[] { Types.Int64.MakeByRefType(), Types.Int64 });
+ mapException = GetHelper(typeofByteCodeHelper, "MapException");
+ GetDelegateForInvokeExact = GetHelper(typeofByteCodeHelper, "GetDelegateForInvokeExact");
+ GetDelegateForInvoke = GetHelper(typeofByteCodeHelper, "GetDelegateForInvoke");
+ GetDelegateForInvokeBasic = GetHelper(typeofByteCodeHelper, "GetDelegateForInvokeBasic");
+ LoadMethodType = GetHelper(typeofByteCodeHelper, "LoadMethodType");
+ LinkIndyCallSite = GetHelper(typeofByteCodeHelper, "LinkIndyCallSite");
+ }
+
+ private static MethodInfo GetHelper(Type type, string method)
+ {
+ return GetHelper(type, method, null);
+ }
+
+ private static MethodInfo GetHelper(Type type, string method, Type[] parameters)
+ {
+ MethodInfo mi = parameters == null ? type.GetMethod(method) : type.GetMethod(method, parameters);
+#if STATIC_COMPILER
+ if (mi == null)
+ {
+ throw new FatalCompilerErrorException(Message.RuntimeMethodMissing, method);
+ }
+#endif
+ return mi;
}
}
@@ -162,66 +171,6 @@ struct MethodKey : IEquatable<MethodKey>
static partial class MethodHandleUtil
{
- internal const int MaxArity = 8;
- private static readonly Type typeofMHA;
- private static readonly Type[] typeofMHV;
- private static readonly Type[] typeofMH;
-
- static MethodHandleUtil()
- {
-#if STATIC_COMPILER
- typeofMHA = StaticCompiler.GetRuntimeType("IKVM.Runtime.MHA`8");
- typeofMHV = new Type[] {
- StaticCompiler.GetRuntimeType("IKVM.Runtime.MHV"),
- StaticCompiler.GetRuntimeType("IKVM.Runtime.MHV`1"),
- StaticCompiler.GetRuntimeType("IKVM.Runtime.MHV`2"),
- StaticCompiler.GetRuntimeType("IKVM.Runtime.MHV`3"),
- StaticCompiler.GetRuntimeType("IKVM.Runtime.MHV`4"),
- StaticCompiler.GetRuntimeType("IKVM.Runtime.MHV`5"),
- StaticCompiler.GetRuntimeType("IKVM.Runtime.MHV`6"),
- StaticCompiler.GetRuntimeType("IKVM.Runtime.MHV`7"),
- StaticCompiler.GetRuntimeType("IKVM.Runtime.MHV`8"),
- };
- typeofMH = new Type[] {
- null,
- StaticCompiler.GetRuntimeType("IKVM.Runtime.MH`1"),
- StaticCompiler.GetRuntimeType("IKVM.Runtime.MH`2"),
- StaticCompiler.GetRuntimeType("IKVM.Runtime.MH`3"),
- StaticCompiler.GetRuntimeType("IKVM.Runtime.MH`4"),
- StaticCompiler.GetRuntimeType("IKVM.Runtime.MH`5"),
- StaticCompiler.GetRuntimeType("IKVM.Runtime.MH`6"),
- StaticCompiler.GetRuntimeType("IKVM.Runtime.MH`7"),
- StaticCompiler.GetRuntimeType("IKVM.Runtime.MH`8"),
- StaticCompiler.GetRuntimeType("IKVM.Runtime.MH`9"),
- };
-#else
- typeofMHA = typeof(IKVM.Runtime.MHA<,,,,,,,>);
- typeofMHV = new Type[] {
- typeof(IKVM.Runtime.MHV),
- typeof(IKVM.Runtime.MHV<>),
- typeof(IKVM.Runtime.MHV<,>),
- typeof(IKVM.Runtime.MHV<,,>),
- typeof(IKVM.Runtime.MHV<,,,>),
- typeof(IKVM.Runtime.MHV<,,,,>),
- typeof(IKVM.Runtime.MHV<,,,,,>),
- typeof(IKVM.Runtime.MHV<,,,,,,>),
- typeof(IKVM.Runtime.MHV<,,,,,,,>),
- };
- typeofMH = new Type[] {
- null,
- typeof(IKVM.Runtime.MH<>),
- typeof(IKVM.Runtime.MH<,>),
- typeof(IKVM.Runtime.MH<,,>),
- typeof(IKVM.Runtime.MH<,,,>),
- typeof(IKVM.Runtime.MH<,,,,>),
- typeof(IKVM.Runtime.MH<,,,,,>),
- typeof(IKVM.Runtime.MH<,,,,,,>),
- typeof(IKVM.Runtime.MH<,,,,,,,>),
- typeof(IKVM.Runtime.MH<,,,,,,,,>),
- };
-#endif
- }
-
internal static void EmitCallDelegateInvokeMethod(CodeEmitter ilgen, Type delegateType)
{
if (delegateType.IsGenericType)
@@ -243,7 +192,7 @@ static partial class MethodHandleUtil
private static void WrapArgs(CodeEmitter ilgen, Type type)
{
Type last = type.GetGenericArguments()[MaxArity - 1];
- if (MethodHandleUtil.IsPackedArgsContainer(last))
+ if (IsPackedArgsContainer(last))
{
WrapArgs(ilgen, last);
}
@@ -274,28 +223,6 @@ static partial class MethodHandleUtil
}
}
- internal static Type CreateDelegateType(TypeWrapper tw, MethodWrapper mw)
- {
- TypeWrapper[] args = mw.GetParameters();
- if (!mw.IsStatic)
- {
- Array.Resize(ref args, args.Length + 1);
- Array.Copy(args, 0, args, 1, args.Length - 1);
- args[0] = tw;
- }
- return CreateDelegateType(args, mw.ReturnType);
- }
-
- internal static Type CreateDelegateType(TypeWrapper[] args, TypeWrapper ret)
- {
- Type[] typeArgs = new Type[args.Length];
- for (int i = 0; i < args.Length; i++)
- {
- typeArgs[i] = args[i].TypeAsSignatureType;
- }
- return CreateDelegateType(typeArgs, ret.TypeAsSignatureType);
- }
-
// for delegate types used for "ldc <MethodType>" we don't want ghost arrays to be erased
internal static Type CreateDelegateTypeForLoadConstant(TypeWrapper[] args, TypeWrapper ret)
{
@@ -323,57 +250,6 @@ static partial class MethodHandleUtil
return tw.TypeAsSignatureType;
}
}
-
- private static Type CreateDelegateType(Type[] types, Type retType)
- {
- if (types.Length == 0 && retType == Types.Void)
- {
- return typeofMHV[0];
- }
- else if (types.Length > MaxArity)
- {
- int arity = types.Length;
- int remainder = (arity - 8) % 7;
- int count = (arity - 8) / 7;
- if (remainder == 0)
- {
- remainder = 7;
- count--;
- }
- Type last = typeofMHA.MakeGenericType(SubArray(types, types.Length - 8, 8));
- for (int i = 0; i < count; i++)
- {
- Type[] temp = SubArray(types, types.Length - 8 - 7 * (i + 1), 8);
- temp[7] = last;
- last = typeofMHA.MakeGenericType(temp);
- }
- types = SubArray(types, 0, remainder + 1);
- types[remainder] = last;
- }
- if (retType == Types.Void)
- {
- return typeofMHV[types.Length].MakeGenericType(types);
- }
- else
- {
- Array.Resize(ref types, types.Length + 1);
- types[types.Length - 1] = retType;
- return typeofMH[types.Length].MakeGenericType(types);
- }
- }
-
- private static Type[] SubArray(Type[] inArray, int start, int length)
- {
- Type[] outArray = new Type[length];
- Array.Copy(inArray, start, outArray, 0, length);
- return outArray;
- }
-
- internal static bool IsPackedArgsContainer(Type type)
- {
- return type.IsGenericType
- && type.GetGenericTypeDefinition() == typeofMHA;
- }
}
sealed class Compiler
@@ -448,7 +324,7 @@ sealed class Compiler
getClassFromTypeHandle2.Link();
}
- private Compiler(DynamicTypeWrapper.FinishContext context, DynamicTypeWrapper clazz, MethodWrapper mw, ClassFile classFile, ClassFile.Method m, CodeEmitter ilGenerator, ClassLoaderWrapper classLoader)
+ private Compiler(DynamicTypeWrapper.FinishContext context, TypeWrapper host, DynamicTypeWrapper clazz, MethodWrapper mw, ClassFile classFile, ClassFile.Method m, CodeEmitter ilGenerator, ClassLoaderWrapper classLoader)
{
this.context = context;
this.clazz = clazz;
@@ -467,6 +343,17 @@ sealed class Compiler
replacedMethodWrappers = clazz.GetReplacedMethodsFor(mw);
#endif
+ TypeWrapper[] args = mw.GetParameters();
+ for(int i = 0; i < args.Length; i++)
+ {
+ if(args[i].IsUnloadable)
+ {
+ ilGenerator.EmitLdarg(i + (m.IsStatic ? 0 : 1));
+ EmitDynamicCast(args[i]);
+ ilGenerator.Emit(OpCodes.Pop);
+ }
+ }
+
Profiler.Enter("MethodAnalyzer");
try
{
@@ -474,7 +361,7 @@ sealed class Compiler
{
JsrInliner.InlineJsrs(classLoader, mw, classFile, m);
}
- MethodAnalyzer verifier = new MethodAnalyzer(clazz, mw, classFile, m, classLoader);
+ MethodAnalyzer verifier = new MethodAnalyzer(host, clazz, mw, classFile, m, classLoader);
exceptions = MethodAnalyzer.UntangleExceptionBlocks(classFile, m);
ma = verifier.GetCodeInfoAndErrors(exceptions, out harderrors);
localVars = new LocalVarInfo(ma, classFile, m, exceptions, mw, classLoader);
@@ -528,7 +415,6 @@ sealed class Compiler
}
}
- TypeWrapper[] args = mw.GetParameters();
LocalVar[] locals = localVars.GetAllLocalVars();
foreach(LocalVar v in locals)
{
@@ -542,14 +428,13 @@ sealed class Compiler
}
else if(arg == 0)
{
- tw = clazz;
+ continue;
}
else
{
tw = args[arg - 1];
}
if(!tw.IsUnloadable &&
- v.type != VerifierTypeWrapper.UninitializedThis &&
(v.type != tw || tw.TypeAsLocalOrStackType != tw.TypeAsSignatureType))
{
v.builder = ilGenerator.DeclareLocal(GetLocalBuilderType(v.type));
@@ -645,7 +530,7 @@ sealed class Compiler
{
int startIndex = SafeFindPcIndex(lvt[i].start_pc);
int endIndex = SafeFindPcIndex(lvt[i].start_pc + lvt[i].length);
- if(startIndex != -1 && endIndex != -1)
+ if(startIndex != -1 && endIndex != -1 && startIndex < endIndex)
{
if(startIndex > 0)
{
@@ -840,7 +725,7 @@ sealed class Compiler
}
}
- internal static void Compile(DynamicTypeWrapper.FinishContext context, DynamicTypeWrapper clazz, MethodWrapper mw, ClassFile classFile, ClassFile.Method m, CodeEmitter ilGenerator, ref bool nonleaf)
+ internal static void Compile(DynamicTypeWrapper.FinishContext context, TypeWrapper host, DynamicTypeWrapper clazz, MethodWrapper mw, ClassFile classFile, ClassFile.Method m, CodeEmitter ilGenerator, ref bool nonleaf)
{
ClassLoaderWrapper classLoader = clazz.GetClassLoader();
if(classLoader.EmitDebugInfo)
@@ -870,26 +755,13 @@ sealed class Compiler
}
}
}
- TypeWrapper[] args = mw.GetParameters();
- for(int i = 0; i < args.Length; i++)
- {
- if(args[i].IsUnloadable)
- {
- Profiler.Count("EmitDynamicCast");
- ilGenerator.EmitLdarg(i + (m.IsStatic ? 0 : 1));
- ilGenerator.Emit(OpCodes.Ldstr, args[i].Name);
- context.EmitCallerID(ilGenerator);
- ilGenerator.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicCast);
- ilGenerator.Emit(OpCodes.Pop);
- }
- }
Compiler c;
try
{
Profiler.Enter("new Compiler");
try
{
- c = new Compiler(context, clazz, mw, classFile, m, ilGenerator, classLoader);
+ c = new Compiler(context, host, clazz, mw, classFile, m, ilGenerator, classLoader);
}
finally
{
@@ -1294,9 +1166,7 @@ sealed class Compiler
if(exceptionTypeWrapper.IsUnloadable)
{
Profiler.Count("EmitDynamicExceptionHandler");
- ilGenerator.Emit(OpCodes.Ldstr, exceptionTypeWrapper.Name);
- context.EmitCallerID(ilGenerator);
- ilGenerator.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicInstanceOf);
+ EmitDynamicInstanceOf(exceptionTypeWrapper);
}
CodeEmitterLabel leave = ilGenerator.DefineLabel();
ilGenerator.EmitBrtrue(leave);
@@ -1452,6 +1322,19 @@ sealed class Compiler
{
ClassFile.ConstantPoolItemFieldref cpi = classFile.GetFieldref(instr.Arg1);
FieldWrapper field = cpi.GetField();
+ if (ma.GetStackTypeWrapper(i, 0).IsUnloadable)
+ {
+ if (field.IsProtected)
+ {
+ // downcast receiver to our type
+ clazz.EmitCheckcast(ilGenerator);
+ }
+ else
+ {
+ // downcast receiver to field declaring type
+ field.DeclaringType.EmitCheckcast(ilGenerator);
+ }
+ }
field.EmitGet(ilGenerator);
field.FieldTypeWrapper.EmitConvSignatureTypeToStackType(ilGenerator);
break;
@@ -1483,6 +1366,22 @@ sealed class Compiler
ClassFile.ConstantPoolItemFieldref cpi = classFile.GetFieldref(instr.Arg1);
FieldWrapper field = cpi.GetField();
TypeWrapper tw = field.FieldTypeWrapper;
+ if (ma.GetStackTypeWrapper(i, 1).IsUnloadable)
+ {
+ CodeEmitterLocal temp = ilGenerator.UnsafeAllocTempLocal(tw.TypeAsLocalOrStackType);
+ ilGenerator.Emit(OpCodes.Stloc, temp);
+ if (field.IsProtected)
+ {
+ // downcast receiver to our type
+ clazz.EmitCheckcast(ilGenerator);
+ }
+ else
+ {
+ // downcast receiver to field declaring type
+ field.DeclaringType.EmitCheckcast(ilGenerator);
+ }
+ ilGenerator.Emit(OpCodes.Ldloc, temp);
+ }
tw.EmitConvStackTypeToSignatureType(ilGenerator, ma.GetStackTypeWrapper(i, 0));
if(strictfp)
{
@@ -1541,7 +1440,9 @@ sealed class Compiler
break;
}
case NormalizedByteCode.__dynamic_invokestatic:
+ case NormalizedByteCode.__privileged_invokestatic:
case NormalizedByteCode.__invokestatic:
+ case NormalizedByteCode.__methodhandle_link:
{
MethodWrapper method = GetMethodCallEmitter(instr.NormalizedOpCode, instr.Arg1);
if(method.IsIntrinsic && method.EmitIntrinsic(new EmitIntrinsicContext(method, context, ilGenerator, ma, i, mw, classFile, code, flags)))
@@ -1553,7 +1454,7 @@ sealed class Compiler
CastInterfaceArgs(method.DeclaringType, method.GetParameters(), i, false);
if(method.HasCallerID)
{
- context.EmitCallerID(ilGenerator);
+ context.EmitCallerID(ilGenerator, m.IsLambdaFormCompiled);
}
method.EmitCall(ilGenerator);
EmitReturnTypeConversion(method.ReturnType);
@@ -1563,17 +1464,20 @@ sealed class Compiler
case NormalizedByteCode.__dynamic_invokeinterface:
case NormalizedByteCode.__dynamic_invokevirtual:
case NormalizedByteCode.__dynamic_invokespecial:
+ case NormalizedByteCode.__privileged_invokevirtual:
+ case NormalizedByteCode.__privileged_invokespecial:
case NormalizedByteCode.__invokevirtual:
case NormalizedByteCode.__invokeinterface:
case NormalizedByteCode.__invokespecial:
case NormalizedByteCode.__methodhandle_invoke:
- case NormalizedByteCode.__methodhandle_invokeexact:
{
- bool isinvokespecial = instr.NormalizedOpCode == NormalizedByteCode.__invokespecial || instr.NormalizedOpCode == NormalizedByteCode.__dynamic_invokespecial;
+ bool isinvokespecial = instr.NormalizedOpCode == NormalizedByteCode.__invokespecial
+ || instr.NormalizedOpCode == NormalizedByteCode.__dynamic_invokespecial
+ || instr.NormalizedOpCode == NormalizedByteCode.__privileged_invokespecial;
MethodWrapper method = GetMethodCallEmitter(instr.NormalizedOpCode, instr.Arg1);
int argcount = method.GetParameters().Length;
TypeWrapper type = ma.GetRawStackTypeWrapper(i, argcount);
- TypeWrapper thisType = SigTypeToClassName(type, method.DeclaringType);
+ TypeWrapper thisType = ComputeThisType(type, method, instr.NormalizedOpCode);
EmitIntrinsicContext eic = new EmitIntrinsicContext(method, context, ilGenerator, ma, i, mw, classFile, code, flags);
if(method.IsIntrinsic && method.EmitIntrinsic(eic))
@@ -1791,7 +1695,7 @@ sealed class Compiler
{
if(method.HasCallerID)
{
- context.EmitCallerID(ilGenerator);
+ context.EmitCallerID(ilGenerator, m.IsLambdaFormCompiled);
}
if(isinvokespecial)
@@ -2002,8 +1906,7 @@ sealed class Compiler
Profiler.Count("EmitDynamicNewCheckOnly");
// this is here to make sure we throw the exception in the right location (before
// evaluating the constructor arguments)
- ilGenerator.Emit(OpCodes.Ldstr, wrapper.Name);
- context.EmitCallerID(ilGenerator);
+ EmitDynamicClassLiteral(wrapper);
ilGenerator.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicNewCheckOnly);
}
else if(wrapper != clazz && RequiresExplicitClassInit(wrapper, i + 1, flags))
@@ -2033,9 +1936,8 @@ sealed class Compiler
if(wrapper.IsUnloadable)
{
Profiler.Count("EmitDynamicMultianewarray");
- ilGenerator.Emit(OpCodes.Ldstr, wrapper.Name);
ilGenerator.Emit(OpCodes.Ldloc, localArray);
- context.EmitCallerID(ilGenerator);
+ EmitDynamicClassLiteral(wrapper);
ilGenerator.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicMultianewarray);
}
else if(wrapper.IsGhost || wrapper.IsGhostArray)
@@ -2066,8 +1968,7 @@ sealed class Compiler
if(wrapper.IsUnloadable)
{
Profiler.Count("EmitDynamicNewarray");
- ilGenerator.Emit(OpCodes.Ldstr, wrapper.Name);
- context.EmitCallerID(ilGenerator);
+ EmitDynamicClassLiteral(wrapper);
ilGenerator.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicNewarray);
}
else if(wrapper.IsGhost || wrapper.IsGhostArray)
@@ -2133,9 +2034,7 @@ sealed class Compiler
TypeWrapper wrapper = classFile.GetConstantPoolClassType(instr.Arg1);
if(wrapper.IsUnloadable)
{
- ilGenerator.Emit(OpCodes.Ldstr, wrapper.Name);
- context.EmitCallerID(ilGenerator);
- ilGenerator.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicCast);
+ EmitDynamicCast(wrapper);
}
else
{
@@ -2148,9 +2047,7 @@ sealed class Compiler
TypeWrapper wrapper = classFile.GetConstantPoolClassType(instr.Arg1);
if(wrapper.IsUnloadable)
{
- ilGenerator.Emit(OpCodes.Ldstr, wrapper.Name);
- context.EmitCallerID(ilGenerator);
- ilGenerator.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicInstanceOf);
+ EmitDynamicInstanceOf(wrapper);
}
else
{
@@ -2164,8 +2061,6 @@ sealed class Compiler
if(tw.IsUnloadable)
{
Profiler.Count("EmitDynamicAaload");
- ilGenerator.Emit(OpCodes.Ldtoken, clazz.TypeAsTBD);
- ilGenerator.Emit(OpCodes.Ldstr, tw.Name);
ilGenerator.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicAaload);
}
else
@@ -2238,8 +2133,6 @@ sealed class Compiler
if(tw.IsUnloadable)
{
Profiler.Count("EmitDynamicAastore");
- ilGenerator.Emit(OpCodes.Ldtoken, clazz.TypeAsTBD);
- ilGenerator.Emit(OpCodes.Ldstr, tw.Name);
ilGenerator.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicAastore);
}
else
@@ -2955,19 +2848,56 @@ sealed class Compiler
case ClassFile.ConstantType.MethodType:
context.GetValue<MethodTypeConstant>(constant).Emit(this, ilgen, constant);
break;
+#if !STATIC_COMPILER
+ case ClassFile.ConstantType.LiveObject:
+ context.EmitLiveObjectLoad(ilgen, classFile.GetConstantPoolConstantLiveObject(constant));
+ break;
+#endif
default:
throw new InvalidOperationException();
}
}
+ private void EmitDynamicCast(TypeWrapper tw)
+ {
+ Debug.Assert(tw.IsUnloadable);
+ Profiler.Count("EmitDynamicCast");
+ // NOTE it's important that we don't try to load the class if obj == null
+ CodeEmitterLabel ok = ilGenerator.DefineLabel();
+ ilGenerator.Emit(OpCodes.Dup);
+ ilGenerator.EmitBrfalse(ok);
+ EmitDynamicClassLiteral(tw);
+ ilGenerator.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicCast);
+ ilGenerator.MarkLabel(ok);
+ }
+
+ private void EmitDynamicInstanceOf(TypeWrapper tw)
+ {
+ // NOTE it's important that we don't try to load the class if obj == null
+ CodeEmitterLabel notnull = ilGenerator.DefineLabel();
+ CodeEmitterLabel end = ilGenerator.DefineLabel();
+ ilGenerator.Emit(OpCodes.Dup);
+ ilGenerator.EmitBrtrue(notnull);
+ ilGenerator.Emit(OpCodes.Pop);
+ ilGenerator.EmitLdc_I4(0);
+ ilGenerator.EmitBr(end);
+ ilGenerator.MarkLabel(notnull);
+ EmitDynamicClassLiteral(tw);
+ ilGenerator.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicInstanceOf);
+ ilGenerator.MarkLabel(end);
+ }
+
+ private void EmitDynamicClassLiteral(TypeWrapper tw)
+ {
+ context.EmitDynamicClassLiteral(ilGenerator, tw, m.IsLambdaFormCompiled);
+ }
+
private void EmitLoadClass(CodeEmitter ilgen, TypeWrapper tw)
{
if (tw.IsUnloadable)
{
Profiler.Count("EmitDynamicClassLiteral");
- ilgen.Emit(OpCodes.Ldstr, tw.Name);
- context.EmitCallerID(ilgen);
- ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicClassLiteral);
+ context.EmitDynamicClassLiteral(ilgen, tw, m.IsLambdaFormCompiled);
}
else
{
@@ -2989,23 +2919,20 @@ sealed class Compiler
{
private static readonly Type typeofOpenIndyCallSite;
private static readonly Type typeofCallSite;
- private static readonly MethodInfo methodLookup;
+ private static readonly MethodWrapper methodLookup;
static InvokeDynamicBuilder()
{
- Type typeofMethodHandles;
#if STATIC_COMPILER
typeofOpenIndyCallSite = StaticCompiler.GetRuntimeType("IKVM.Runtime.IndyCallSite`1");
typeofCallSite = ClassLoaderWrapper.LoadClassCritical("java.lang.invoke.CallSite").TypeAsSignatureType;
- typeofMethodHandles = ClassLoaderWrapper.LoadClassCritical("java.lang.invoke.MethodHandles").TypeAsBaseType;
-#elif FIRST_PASS
- typeofMethodHandles = null;
-#else
+#elif !FIRST_PASS
typeofOpenIndyCallSite = typeof(IKVM.Runtime.IndyCallSite<>);
typeofCallSite = typeof(java.lang.invoke.CallSite);
- typeofMethodHandles = typeof(java.lang.invoke.MethodHandles);
#endif
- methodLookup = typeofMethodHandles.GetMethod("lookup", new Type[] { CoreClasses.ikvm.@internal.CallerID.Wrapper.TypeAsSignatureType });
+ methodLookup = ClassLoaderWrapper.LoadClassCritical("java.lang.invoke.MethodHandles")
+ .GetMethodWrapper("lookup", "()Ljava.lang.invoke.MethodHandles$Lookup;", false);
+ methodLookup.Link();
}
internal static void Emit(Compiler compiler, ClassFile.ConstantPoolItemInvokeDynamic cpi, Type delegateType)
@@ -3025,7 +2952,7 @@ sealed class Compiler
}
TypeBuilder tb = compiler.context.DefineIndyCallSiteType();
FieldBuilder fb = tb.DefineField("value", typeofIndyCallSite, FieldAttributes.Static | FieldAttributes.Assembly);
- CodeEmitter ilgen = CodeEmitter.Create(ReflectUtil.DefineTypeInitializer(tb));
+ CodeEmitter ilgen = CodeEmitter.Create(ReflectUtil.DefineTypeInitializer(tb, compiler.clazz.GetClassLoader()));
ilgen.Emit(OpCodes.Ldnull);
ilgen.Emit(OpCodes.Ldftn, CreateBootstrapStub(compiler, cpi, delegateType, tb, fb, methodGetTarget));
ilgen.Emit(OpCodes.Newobj, MethodHandleUtil.GetDelegateConstructor(delegateType));
@@ -3040,19 +2967,24 @@ sealed class Compiler
private static MethodBuilder CreateBootstrapStub(Compiler compiler, ClassFile.ConstantPoolItemInvokeDynamic cpi, Type delegateType, TypeBuilder tb, FieldBuilder fb, MethodInfo methodGetTarget)
{
- TypeWrapper[] args = cpi.GetArgTypes();
- Type[] argTypes = new Type[args.Length];
- for (int i = 0; i < args.Length; i++)
+ Type[] args = Type.EmptyTypes;
+ if (delegateType.IsGenericType)
{
- argTypes[i] = args[i].TypeAsSignatureType;
+ // MONOBUG we don't look at the invoke method directly here, because Mono doesn't support GetParameters() on a builder instantiation
+ args = delegateType.GetGenericArguments();
+ if (cpi.GetRetType() != PrimitiveTypeWrapper.VOID)
+ {
+ Array.Resize(ref args, args.Length - 1);
+ }
}
- MethodBuilder mb = tb.DefineMethod("BootstrapStub", MethodAttributes.Static | MethodAttributes.PrivateScope, cpi.GetRetType().TypeAsSignatureType, argTypes);
+ MethodBuilder mb = tb.DefineMethod("BootstrapStub", MethodAttributes.Static | MethodAttributes.PrivateScope, cpi.GetRetType().TypeAsSignatureType, args);
CodeEmitter ilgen = CodeEmitter.Create(mb);
CodeEmitterLocal cs = ilgen.DeclareLocal(typeofCallSite);
CodeEmitterLocal ex = ilgen.DeclareLocal(Types.Exception);
+ CodeEmitterLocal ok = ilgen.DeclareLocal(Types.Boolean);
CodeEmitterLabel label = ilgen.DefineLabel();
ilgen.BeginExceptionBlock();
- if (EmitCallBootstrapMethod(compiler, cpi, delegateType, ilgen))
+ if (EmitCallBootstrapMethod(compiler, cpi, ilgen, ok))
{
ilgen.Emit(OpCodes.Isinst, typeofCallSite);
ilgen.Emit(OpCodes.Stloc, cs);
@@ -3060,28 +2992,31 @@ sealed class Compiler
ilgen.EmitLeave(label);
ilgen.BeginCatchBlock(Types.Exception);
ilgen.Emit(OpCodes.Stloc, ex);
+ ilgen.Emit(OpCodes.Ldloc, ok);
+ CodeEmitterLabel label2 = ilgen.DefineLabel();
+ ilgen.EmitBrtrue(label2);
+ ilgen.Emit(OpCodes.Rethrow);
+ ilgen.MarkLabel(label2);
ilgen.EmitLeave(label);
- ilgen.BeginFinallyBlock();
+ ilgen.EndExceptionBlock();
+ ilgen.MarkLabel(label);
ilgen.Emit(OpCodes.Ldsflda, fb);
ilgen.Emit(OpCodes.Ldloc, cs);
ilgen.Emit(OpCodes.Ldloc, ex);
ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.LinkIndyCallSite.MakeGenericMethod(delegateType));
- ilgen.Emit(OpCodes.Endfinally);
- ilgen.EndExceptionBlock();
- ilgen.MarkLabel(label);
ilgen.Emit(OpCodes.Ldsfld, fb);
ilgen.Emit(OpCodes.Call, methodGetTarget);
for (int i = 0; i < args.Length; i++)
{
ilgen.EmitLdarg(i);
}
- MethodHandleUtil.EmitCallDelegateInvokeMethod(ilgen, delegateType);
+ ilgen.Emit(OpCodes.Callvirt, MethodHandleUtil.GetDelegateInvokeMethod(delegateType));
ilgen.Emit(OpCodes.Ret);
ilgen.DoEmit();
return mb;
}
- private static bool EmitCallBootstrapMethod(Compiler compiler, ClassFile.ConstantPoolItemInvokeDynamic cpi, Type delegateType, CodeEmitter ilgen)
+ private static bool EmitCallBootstrapMethod(Compiler compiler, ClassFile.ConstantPoolItemInvokeDynamic cpi, CodeEmitter ilgen, CodeEmitterLocal ok)
{
ClassFile.BootstrapMethod bsm = compiler.classFile.GetBootstrapMethod(cpi.BootstrapMethod);
if (3 + bsm.ArgumentCount > 255)
@@ -3094,10 +3029,12 @@ sealed class Compiler
ClassFile.ConstantPoolItemMI cpiMI;
if (mw == null && (cpiMI = mh.MemberConstantPoolItem as ClassFile.ConstantPoolItemMI) != null)
{
- mw = new DynamicBinder().Get(compiler.context, ClassFile.RefKind.invokeStatic, cpiMI);
+ mw = new DynamicBinder().Get(compiler, mh.Kind, cpiMI, false);
}
- if (mw == null || !mw.IsStatic)
+ if (mw == null || (!mw.IsStatic && !mw.IsConstructor))
{
+ ilgen.EmitLdc_I4(1);
+ ilgen.Emit(OpCodes.Stloc, ok);
ilgen.EmitThrow("java.lang.invoke.WrongMethodTypeException");
return false;
}
@@ -3112,6 +3049,8 @@ sealed class Compiler
}
else if (extraArgs != bsm.ArgumentCount)
{
+ ilgen.EmitLdc_I4(1);
+ ilgen.Emit(OpCodes.Stloc, ok);
ilgen.EmitThrow("java.lang.invoke.WrongMethodTypeException");
return false;
}
@@ -3120,11 +3059,11 @@ sealed class Compiler
fixedArgs = extraArgs;
varArgs = -1;
}
- compiler.context.EmitCallerID(ilgen);
- ilgen.Emit(OpCodes.Call, methodLookup);
+ compiler.context.EmitCallerID(ilgen, compiler.m.IsLambdaFormCompiled);
+ methodLookup.EmitCall(ilgen);
ilgen.Emit(OpCodes.Ldstr, cpi.Name);
parameters[1].EmitConvStackTypeToSignatureType(ilgen, CoreClasses.java.lang.String.Wrapper);
- ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.LoadMethodType.MakeGenericMethod(delegateType));
+ ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.LoadMethodType.MakeGenericMethod(MethodHandleUtil.CreateDelegateTypeForLoadConstant(cpi.GetArgTypes(), cpi.GetRetType())));
parameters[2].EmitConvStackTypeToSignatureType(ilgen, CoreClasses.java.lang.invoke.MethodType.Wrapper);
for (int i = 0; i < fixedArgs; i++)
{
@@ -3143,7 +3082,16 @@ sealed class Compiler
ilgen.Emit(OpCodes.Stelem_Ref);
}
}
- mw.EmitCall(ilgen);
+ ilgen.EmitLdc_I4(1);
+ ilgen.Emit(OpCodes.Stloc, ok);
+ if (mw.IsConstructor)
+ {
+ mw.EmitNewobj(ilgen);
+ }
+ else
+ {
+ mw.EmitCall(ilgen);
+ }
return true;
}
@@ -3243,7 +3191,7 @@ sealed class Compiler
temps[i] = ilgen.DeclareLocal(args[i].TypeAsSignatureType);
ilgen.Emit(OpCodes.Stloc, temps[i]);
}
- Type delegateType = MethodHandleUtil.CreateDelegateType(args, cpi.GetRetType());
+ Type delegateType = MethodHandleUtil.CreateMethodHandleDelegateType(args, cpi.GetRetType());
InvokeDynamicBuilder.Emit(this, cpi, delegateType);
for (int i = 0; i < args.Length; i++)
{
@@ -3255,225 +3203,21 @@ sealed class Compiler
private sealed class MethodHandleConstant
{
private FieldBuilder field;
- private bool dynamic;
internal void Emit(Compiler compiler, CodeEmitter ilgen, int index)
{
if (field == null)
{
- field = CreateField(compiler, index, ref dynamic);
- }
- if (dynamic)
- {
- ClassFile.ConstantPoolItemMethodHandle mh = compiler.classFile.GetConstantPoolConstantMethodHandle(index);
- ilgen.Emit(OpCodes.Ldsflda, field);
- ilgen.EmitLdc_I4((int)mh.Kind);
- ilgen.Emit(OpCodes.Ldstr, mh.Class);
- ilgen.Emit(OpCodes.Ldstr, mh.Name);
- ilgen.Emit(OpCodes.Ldstr, mh.Signature);
- compiler.context.EmitCallerID(ilgen);
- ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicLoadMethodHandle);
- }
- else
- {
- ilgen.Emit(OpCodes.Ldsfld, field);
+ field = compiler.context.DefineDynamicMethodHandleCacheField();
}
- }
-
- private static FieldBuilder CreateField(Compiler compiler, int index, ref bool dynamic)
- {
ClassFile.ConstantPoolItemMethodHandle mh = compiler.classFile.GetConstantPoolConstantMethodHandle(index);
- if (mh.GetClassType().IsUnloadable)
- {
- dynamic = true;
- return compiler.context.DefineDynamicMethodHandleCacheField();
- }
- TypeWrapper[] args;
- TypeWrapper arg0 = null;
- TypeWrapper ret;
- switch (mh.Kind)
- {
- case ClassFile.RefKind.getField:
- args = new TypeWrapper[] { mh.Member.DeclaringType };
- ret = ((FieldWrapper)mh.Member).FieldTypeWrapper;
- break;
- case ClassFile.RefKind.putField:
- args = new TypeWrapper[] { mh.Member.DeclaringType, ((FieldWrapper)mh.Member).FieldTypeWrapper };
- ret = PrimitiveTypeWrapper.VOID;
- break;
- case ClassFile.RefKind.getStatic:
- args = TypeWrapper.EmptyArray;
- ret = ((FieldWrapper)mh.Member).FieldTypeWrapper;
- break;
- case ClassFile.RefKind.putStatic:
- args = new TypeWrapper[] { ((FieldWrapper)mh.Member).FieldTypeWrapper };
- ret = PrimitiveTypeWrapper.VOID;
- break;
- case ClassFile.RefKind.invokeInterface:
- case ClassFile.RefKind.invokeSpecial:
- case ClassFile.RefKind.invokeVirtual:
- case ClassFile.RefKind.invokeStatic:
- if (mh.Member == null)
- {
- // it's MethodHandle.invoke[Exact]
- ClassFile.ConstantPoolItemMI cpi = (ClassFile.ConstantPoolItemMI)mh.MemberConstantPoolItem;
- args = cpi.GetArgTypes();
- arg0 = mh.GetClassType();
- ret = cpi.GetRetType();
- }
- else
- {
- MethodWrapper mw = (MethodWrapper)mh.Member;
- args = mw.GetParameters();
- ret = mw.ReturnType;
- if (mw.IsStatic)
- {
- // no receiver type
- }
- else if (mw.IsProtected && !mw.IsAccessibleFrom(mh.GetClassType(), compiler.clazz, mh.GetClassType()))
- {
- arg0 = compiler.clazz;
- }
- else
- {
- arg0 = mh.GetClassType();
- }
- }
- break;
- case ClassFile.RefKind.newInvokeSpecial:
- args = ((MethodWrapper)mh.Member).GetParameters();
- ret = mh.Member.DeclaringType;
- break;
- default:
- throw new InvalidOperationException();
- }
- if (arg0 != null)
- {
- TypeWrapper[] newArgs = new TypeWrapper[args.Length + 1];
- newArgs[0] = arg0;
- Array.Copy(args, 0, newArgs, 1, args.Length);
- args = newArgs;
- }
- if (HasUnloadable(args, ret))
- {
- dynamic = true;
- return compiler.context.DefineDynamicMethodHandleCacheField();
- }
-
- Type delegateType = MethodHandleUtil.CreateDelegateType(args, ret);
- MethodInfo method;
- if (mh.Kind == ClassFile.RefKind.invokeStatic
- && (method = (MethodInfo)((MethodWrapper)mh.Member).GetMethod()) != null
- && ((MethodWrapper)mh.Member).GetParameters().Length <= MethodHandleUtil.MaxArity)
- {
- // we can create a delegate that directly points to the target method
- }
- else
- {
- method = CreateDispatchStub(compiler, mh, delegateType);
- }
- TypeBuilder tb = compiler.context.DefineMethodHandleConstantType(index);
- FieldBuilder field = tb.DefineField("value", CoreClasses.java.lang.invoke.MethodHandle.Wrapper.TypeAsSignatureType, FieldAttributes.Assembly | FieldAttributes.Static | FieldAttributes.InitOnly);
- CodeEmitter ilgen = CodeEmitter.Create(ReflectUtil.DefineTypeInitializer(tb));
- ilgen.Emit(OpCodes.Ldnull);
- ilgen.Emit(OpCodes.Ldftn, method);
- ilgen.Emit(OpCodes.Newobj, MethodHandleUtil.GetDelegateConstructor(delegateType));
- ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.MethodHandleFromDelegate);
- ilgen.Emit(OpCodes.Stsfld, field);
- ilgen.Emit(OpCodes.Ret);
- ilgen.DoEmit();
- return field;
- }
-
- private static MethodInfo CreateDispatchStub(Compiler compiler, ClassFile.ConstantPoolItemMethodHandle mh, Type delegateType)
- {
- // the dispatch stub lives in the actual type (not the nested type that caches the value) to make sure
- // we have access to everything that the actual type has access to
- Type[] args = delegateType.GetGenericArguments();
- Type ret = Types.Void;
- // NOTE we can't use the method returned by GetDelegateInvokeMethod to determine the parameter types, due to Mono and CLR bugs
- if (MethodHandleUtil.GetDelegateInvokeMethod(delegateType).ReturnType != Types.Void)
- {
- ret = args[args.Length - 1];
- Array.Resize(ref args, args.Length - 1);
- }
- MethodBuilder mb = compiler.context.DefineMethodHandleDispatchStub(ret, args);
- CodeEmitter ilgen = CodeEmitter.Create(mb);
- if (args.Length > 0 && MethodHandleUtil.IsPackedArgsContainer(args[args.Length - 1]))
- {
- int packedArgPos = args.Length - 1;
- Type packedArgType = args[packedArgPos];
- for (int i = 0; i < packedArgPos; i++)
- {
- ilgen.EmitLdarg(i);
- }
- List<FieldInfo> fields = new List<FieldInfo>();
- next:
- args = args[args.Length - 1].GetGenericArguments();
- for (int i = 0; i < MethodHandleUtil.MaxArity; i++)
- {
- if (i == MethodHandleUtil.MaxArity - 1 && MethodHandleUtil.IsPackedArgsContainer(args[i]))
- {
- FieldInfo field = packedArgType.GetField("t" + (i + 1));
- packedArgType = field.FieldType;
- fields.Add(field);
- goto next;
- }
- else
- {
- ilgen.EmitLdarga(packedArgPos);
- foreach (FieldInfo field in fields)
- {
- ilgen.Emit(OpCodes.Ldflda, field);
- }
- ilgen.Emit(OpCodes.Ldfld, packedArgType.GetField("t" + (i + 1)));
- }
- }
- }
- else
- {
- for (int i = 0; i < args.Length; i++)
- {
- ilgen.EmitLdarg(i);
- }
- }
- switch (mh.Kind)
- {
- case ClassFile.RefKind.getField:
- case ClassFile.RefKind.getStatic:
- ((FieldWrapper)mh.Member).EmitGet(ilgen);
- break;
- case ClassFile.RefKind.putField:
- case ClassFile.RefKind.putStatic:
- ((FieldWrapper)mh.Member).EmitSet(ilgen);
- break;
- case ClassFile.RefKind.invokeInterface:
- case ClassFile.RefKind.invokeVirtual:
- if (mh.Member == null)
- {
- // it's a MethodHandle.invoke[Exact] constant MethodHandle
- new MethodHandleMethodWrapper(compiler.context, compiler.clazz, (ClassFile.ConstantPoolItemMI)mh.MemberConstantPoolItem, mh.Name == "invokeExact").EmitCallvirt(ilgen);
- }
- else
- {
- ((MethodWrapper)mh.Member).EmitCallvirt(ilgen);
- }
- break;
- case ClassFile.RefKind.invokeStatic:
- ((MethodWrapper)mh.Member).EmitCall(ilgen);
- break;
- case ClassFile.RefKind.invokeSpecial:
- ilgen.Emit(OpCodes.Callvirt, compiler.context.GetInvokeSpecialStub((MethodWrapper)mh.Member));
- break;
- case ClassFile.RefKind.newInvokeSpecial:
- ((MethodWrapper)mh.Member).EmitNewobj(ilgen);
- break;
- default:
- throw new InvalidOperationException();
- }
- ilgen.Emit(OpCodes.Ret);
- ilgen.DoEmit();
- return mb;
+ ilgen.Emit(OpCodes.Ldsflda, field);
+ ilgen.EmitLdc_I4((int)mh.Kind);
+ ilgen.Emit(OpCodes.Ldstr, mh.Class);
+ ilgen.Emit(OpCodes.Ldstr, mh.Name);
+ ilgen.Emit(OpCodes.Ldstr, mh.Signature);
+ compiler.context.EmitCallerID(ilgen, compiler.m.IsLambdaFormCompiled);
+ ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicLoadMethodHandle);
}
}
@@ -3492,7 +3236,7 @@ sealed class Compiler
{
ilgen.Emit(OpCodes.Ldsflda, field);
ilgen.Emit(OpCodes.Ldstr, compiler.classFile.GetConstantPoolConstantMethodType(index).Signature);
- compiler.context.EmitCallerID(ilgen);
+ compiler.context.EmitCallerID(ilgen, compiler.m.IsLambdaFormCompiled);
ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicLoadMethodType);
}
else
@@ -3516,7 +3260,7 @@ sealed class Compiler
{
TypeBuilder tb = compiler.context.DefineMethodTypeConstantType(index);
FieldBuilder field = tb.DefineField("value", CoreClasses.java.lang.invoke.MethodType.Wrapper.TypeAsSignatureType, FieldAttributes.Assembly | FieldAttributes.Static | FieldAttributes.InitOnly);
- CodeEmitter ilgen = CodeEmitter.Create(ReflectUtil.DefineTypeInitializer(tb));
+ CodeEmitter ilgen = CodeEmitter.Create(ReflectUtil.DefineTypeInitializer(tb, compiler.clazz.GetClassLoader()));
Type delegateType = MethodHandleUtil.CreateDelegateTypeForLoadConstant(args, ret);
ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.LoadMethodType.MakeGenericMethod(delegateType));
ilgen.Emit(OpCodes.Stsfld, field);
@@ -3655,6 +3399,16 @@ sealed class Compiler
// we're calling a java.lang.Object method through a ghost interface reference,
// no ghost handling is needed
}
+ else if(VerifierTypeWrapper.IsThis(ma.GetRawStackTypeWrapper(instructionIndex, args.Length - 1 - i)))
+ {
+ // we're an instance method in a ghost interface, so the this pointer is a managed pointer to the
+ // wrapper value and if we're not calling another instance method on ourself, we need to load
+ // the wrapper value onto the stack
+ if(!instanceMethod || i != 0)
+ {
+ ilGenerator.Emit(OpCodes.Ldobj, args[i].TypeAsSignatureType);
+ }
+ }
else
{
CodeEmitterLocal ghost = ilGenerator.AllocTempLocal(Types.Object);
@@ -3718,42 +3472,47 @@ sealed class Compiler
private void DynamicGetPutField(Instruction instr, int i)
{
- NormalizedByteCode bytecode = instr.NormalizedOpCode;
- ClassFile.ConstantPoolItemFieldref cpi = classFile.GetFieldref(instr.Arg1);
- bool write = (bytecode == NormalizedByteCode.__dynamic_putfield || bytecode == NormalizedByteCode.__dynamic_putstatic);
- TypeWrapper wrapper = cpi.GetClassType();
- TypeWrapper fieldTypeWrapper = cpi.GetFieldType();
- if(write && !fieldTypeWrapper.IsUnloadable && fieldTypeWrapper.IsPrimitive)
- {
- ilGenerator.Emit(OpCodes.Box, fieldTypeWrapper.TypeAsTBD);
- }
- ilGenerator.Emit(OpCodes.Ldstr, cpi.Name);
- ilGenerator.Emit(OpCodes.Ldstr, cpi.Signature);
- ilGenerator.Emit(OpCodes.Ldstr, wrapper.Name);
- context.EmitCallerID(ilGenerator);
- switch(bytecode)
+ ClassFile.RefKind kind;
+ switch (instr.NormalizedOpCode)
{
case NormalizedByteCode.__dynamic_getfield:
Profiler.Count("EmitDynamicGetfield");
- ilGenerator.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicGetfield);
- EmitReturnTypeConversion(ilGenerator, fieldTypeWrapper);
+ kind = ClassFile.RefKind.getField;
break;
case NormalizedByteCode.__dynamic_putfield:
Profiler.Count("EmitDynamicPutfield");
- ilGenerator.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicPutfield);
+ kind = ClassFile.RefKind.putField;
break;
case NormalizedByteCode.__dynamic_getstatic:
Profiler.Count("EmitDynamicGetstatic");
- ilGenerator.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicGetstatic);
- EmitReturnTypeConversion(ilGenerator, fieldTypeWrapper);
+ kind = ClassFile.RefKind.getStatic;
break;
case NormalizedByteCode.__dynamic_putstatic:
Profiler.Count("EmitDynamicPutstatic");
- ilGenerator.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicPutstatic);
+ kind = ClassFile.RefKind.putStatic;
break;
default:
throw new InvalidOperationException();
}
+ ClassFile.ConstantPoolItemFieldref cpi = classFile.GetFieldref(instr.Arg1);
+ TypeWrapper fieldType = cpi.GetFieldType();
+ if (kind == ClassFile.RefKind.putField || kind == ClassFile.RefKind.putStatic)
+ {
+ fieldType.EmitConvStackTypeToSignatureType(ilGenerator, ma.GetStackTypeWrapper(i, 0));
+ if (strictfp)
+ {
+ // no need to convert
+ }
+ else if (fieldType == PrimitiveTypeWrapper.DOUBLE)
+ {
+ ilGenerator.Emit(OpCodes.Conv_R8);
+ }
+ }
+ context.GetValue<DynamicFieldBinder>(instr.Arg1 | ((byte)kind << 24)).Emit(this, cpi, kind);
+ if (kind == ClassFile.RefKind.getField || kind == ClassFile.RefKind.getStatic)
+ {
+ fieldType.EmitConvSignatureTypeToStackType(ilGenerator);
+ }
}
private static void EmitReturnTypeConversion(CodeEmitter ilgen, TypeWrapper typeWrapper)
@@ -3787,69 +3546,187 @@ sealed class Compiler
private readonly DynamicTypeWrapper.FinishContext context;
private readonly TypeWrapper wrapper;
private readonly ClassFile.ConstantPoolItemMI cpi;
- private readonly bool exact;
- internal MethodHandleMethodWrapper(DynamicTypeWrapper.FinishContext context, TypeWrapper wrapper, ClassFile.ConstantPoolItemMI cpi, bool exact)
+ internal MethodHandleMethodWrapper(DynamicTypeWrapper.FinishContext context, TypeWrapper wrapper, ClassFile.ConstantPoolItemMI cpi)
: base(wrapper, cpi.Name, cpi.Signature, null, cpi.GetRetType(), cpi.GetArgTypes(), Modifiers.Public, MemberFlags.None)
{
this.context = context;
this.wrapper = wrapper;
this.cpi = cpi;
- this.exact = exact;
+ }
+
+ private static void ToBasic(TypeWrapper tw, CodeEmitter ilgen)
+ {
+ if (tw.IsNonPrimitiveValueType)
+ {
+ tw.EmitBox(ilgen);
+ }
+ else if (tw.IsGhost)
+ {
+ tw.EmitConvSignatureTypeToStackType(ilgen);
+ }
+ }
+
+ private static void FromBasic(TypeWrapper tw, CodeEmitter ilgen)
+ {
+ if (tw.IsNonPrimitiveValueType)
+ {
+ tw.EmitUnbox(ilgen);
+ }
+ else if (tw.IsGhost)
+ {
+ tw.EmitConvStackTypeToSignatureType(ilgen, null);
+ }
+ else if (!tw.IsPrimitive && tw != CoreClasses.java.lang.Object.Wrapper)
+ {
+ tw.EmitCheckcast(ilgen);
+ }
}
internal override void EmitCall(CodeEmitter ilgen)
{
+#if !FIRST_PASS && !STATIC_COMPILER
+ Debug.Assert(cpi.Name == "linkToVirtual" || cpi.Name == "linkToStatic" || cpi.Name == "linkToSpecial" || cpi.Name == "linkToInterface");
+
+ TypeWrapper[] args = cpi.GetArgTypes();
+ CodeEmitterLocal[] temps = new CodeEmitterLocal[args.Length];
+ for (int i = args.Length - 1; i > 0; i--)
+ {
+ temps[i] = ilgen.DeclareLocal(MethodHandleUtil.AsBasicType(args[i]));
+ ToBasic(args[i], ilgen);
+ ilgen.Emit(OpCodes.Stloc, temps[i]);
+ }
+ temps[0] = ilgen.DeclareLocal(args[0].TypeAsSignatureType);
+ ilgen.Emit(OpCodes.Stloc, temps[0]);
+ Array.Resize(ref args, args.Length - 1);
+ Type delegateType = MethodHandleUtil.CreateMemberWrapperDelegateType(args, cpi.GetRetType());
+ ilgen.Emit(OpCodes.Ldloc, temps[args.Length]);
+ ilgen.Emit(OpCodes.Ldfld, typeof(java.lang.invoke.MemberName).GetField("vmtarget", BindingFlags.Instance | BindingFlags.NonPublic));
+ ilgen.Emit(OpCodes.Castclass, delegateType);
+ for (int i = 0; i < args.Length; i++)
+ {
+ ilgen.Emit(OpCodes.Ldloc, temps[i]);
+ }
+ MethodHandleUtil.EmitCallDelegateInvokeMethod(ilgen, delegateType);
+ FromBasic(ReturnType, ilgen);
+#else
throw new InvalidOperationException();
+#endif
}
- internal override void EmitCallvirt(CodeEmitter ilgen)
+ private void EmitInvokeExact(CodeEmitter ilgen)
{
- TypeWrapper[] args;
- CodeEmitterLocal[] temps;
- Type delegateType;
- if (exact)
+ TypeWrapper[] args = cpi.GetArgTypes();
+ CodeEmitterLocal[] temps = new CodeEmitterLocal[args.Length];
+ for (int i = args.Length - 1; i >= 0; i--)
{
- args = cpi.GetArgTypes();
- temps = new CodeEmitterLocal[args.Length];
- for (int i = args.Length - 1; i >= 0; i--)
- {
- temps[i] = ilgen.DeclareLocal(args[i].TypeAsSignatureType);
- ilgen.Emit(OpCodes.Stloc, temps[i]);
- }
- delegateType = MethodHandleUtil.CreateDelegateType(args, cpi.GetRetType());
- MethodInfo mi = ByteCodeHelperMethods.GetDelegateForInvokeExact.MakeGenericMethod(delegateType);
- ilgen.Emit(OpCodes.Call, mi);
+ temps[i] = ilgen.DeclareLocal(args[i].TypeAsSignatureType);
+ ilgen.Emit(OpCodes.Stloc, temps[i]);
}
- else
+ Type delegateType = MethodHandleUtil.CreateMethodHandleDelegateType(args, cpi.GetRetType());
+ MethodInfo mi = ByteCodeHelperMethods.GetDelegateForInvokeExact.MakeGenericMethod(delegateType);
+ ilgen.Emit(OpCodes.Call, mi);
+ for (int i = 0; i < args.Length; i++)
{
- args = new TypeWrapper[cpi.GetArgTypes().Length + 1];
- Array.Copy(cpi.GetArgTypes(), 0, args, 1, args.Length - 1);
- args[0] = CoreClasses.java.lang.invoke.MethodHandle.Wrapper;
- temps = new CodeEmitterLocal[args.Length];
- for (int i = args.Length - 1; i >= 0; i--)
- {
- temps[i] = ilgen.DeclareLocal(args[i].TypeAsSignatureType);
- ilgen.Emit(OpCodes.Stloc, temps[i]);
- }
- delegateType = MethodHandleUtil.CreateDelegateType(args, cpi.GetRetType());
- MethodInfo mi = ByteCodeHelperMethods.GetDelegateForInvoke.MakeGenericMethod(delegateType);
- Type typeofInvokeCache;
+ ilgen.Emit(OpCodes.Ldloc, temps[i]);
+ }
+ MethodHandleUtil.EmitCallDelegateInvokeMethod(ilgen, delegateType);
+ }
+
+ private void EmitInvokeMaxArity(CodeEmitter ilgen)
+ {
+ TypeWrapper[] args = cpi.GetArgTypes();
+ CodeEmitterLocal[] temps = new CodeEmitterLocal[args.Length];
+ for (int i = args.Length - 1; i >= 0; i--)
+ {
+ temps[i] = ilgen.DeclareLocal(args[i].TypeAsSignatureType);
+ ilgen.Emit(OpCodes.Stloc, temps[i]);
+ }
+ Type delegateType = MethodHandleUtil.CreateMethodHandleDelegateType(args, cpi.GetRetType());
+ ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.LoadMethodType.MakeGenericMethod(delegateType));
+ CoreClasses.java.lang.invoke.MethodHandle.Wrapper.GetMethodWrapper("asType", "(Ljava.lang.invoke.MethodType;)Ljava.lang.invoke.MethodHandle;", false).EmitCallvirt(ilgen);
+ MethodInfo mi = ByteCodeHelperMethods.GetDelegateForInvokeExact.MakeGenericMethod(delegateType);
+ ilgen.Emit(OpCodes.Call, mi);
+ for (int i = 0; i < args.Length; i++)
+ {
+ ilgen.Emit(OpCodes.Ldloc, temps[i]);
+ }
+ MethodHandleUtil.EmitCallDelegateInvokeMethod(ilgen, delegateType);
+ }
+
+ private void EmitInvoke(CodeEmitter ilgen)
+ {
+ if (cpi.GetArgTypes().Length >= 127 && MethodHandleUtil.SlotCount(cpi.GetArgTypes()) >= 254)
+ {
+ EmitInvokeMaxArity(ilgen);
+ return;
+ }
+ TypeWrapper[] args = ArrayUtil.Concat(CoreClasses.java.lang.invoke.MethodHandle.Wrapper, cpi.GetArgTypes());
+ CodeEmitterLocal[] temps = new CodeEmitterLocal[args.Length];
+ for (int i = args.Length - 1; i >= 0; i--)
+ {
+ temps[i] = ilgen.DeclareLocal(args[i].TypeAsSignatureType);
+ ilgen.Emit(OpCodes.Stloc, temps[i]);
+ }
+ Type delegateType = MethodHandleUtil.CreateMethodHandleDelegateType(args, cpi.GetRetType());
+ MethodInfo mi = ByteCodeHelperMethods.GetDelegateForInvoke.MakeGenericMethod(delegateType);
+ Type typeofInvokeCache;
#if STATIC_COMPILER
- typeofInvokeCache = StaticCompiler.GetRuntimeType("IKVM.Runtime.InvokeCache`1");
+ typeofInvokeCache = StaticCompiler.GetRuntimeType("IKVM.Runtime.InvokeCache`1");
#else
- typeofInvokeCache = typeof(IKVM.Runtime.InvokeCache<>);
+ typeofInvokeCache = typeof(IKVM.Runtime.InvokeCache<>);
#endif
- FieldBuilder fb = context.DefineMethodHandleInvokeCacheField(typeofInvokeCache.MakeGenericType(delegateType));
- ilgen.Emit(OpCodes.Ldloc, temps[0]);
- ilgen.Emit(OpCodes.Ldsflda, fb);
- ilgen.Emit(OpCodes.Call, mi);
+ FieldBuilder fb = context.DefineMethodHandleInvokeCacheField(typeofInvokeCache.MakeGenericType(delegateType));
+ ilgen.Emit(OpCodes.Ldloc, temps[0]);
+ ilgen.Emit(OpCodes.Ldsflda, fb);
+ ilgen.Emit(OpCodes.Call, mi);
+ for (int i = 0; i < args.Length; i++)
+ {
+ ilgen.Emit(OpCodes.Ldloc, temps[i]);
}
+ MethodHandleUtil.EmitCallDelegateInvokeMethod(ilgen, delegateType);
+ }
+
+ private void EmitInvokeBasic(CodeEmitter ilgen)
+ {
+ TypeWrapper[] args = ArrayUtil.Concat(CoreClasses.java.lang.invoke.MethodHandle.Wrapper, cpi.GetArgTypes());
+ CodeEmitterLocal[] temps = new CodeEmitterLocal[args.Length];
+ for (int i = args.Length - 1; i > 0; i--)
+ {
+ temps[i] = ilgen.DeclareLocal(MethodHandleUtil.AsBasicType(args[i]));
+ ToBasic(args[i], ilgen);
+ ilgen.Emit(OpCodes.Stloc, temps[i]);
+ }
+ temps[0] = ilgen.DeclareLocal(args[0].TypeAsSignatureType);
+ ilgen.Emit(OpCodes.Stloc, temps[0]);
+ Type delegateType = MethodHandleUtil.CreateMemberWrapperDelegateType(args, cpi.GetRetType());
+ MethodInfo mi = ByteCodeHelperMethods.GetDelegateForInvokeBasic.MakeGenericMethod(delegateType);
+ ilgen.Emit(OpCodes.Ldloc, temps[0]);
+ ilgen.Emit(OpCodes.Call, mi);
for (int i = 0; i < args.Length; i++)
{
ilgen.Emit(OpCodes.Ldloc, temps[i]);
}
MethodHandleUtil.EmitCallDelegateInvokeMethod(ilgen, delegateType);
+ FromBasic(ReturnType, ilgen);
+ }
+
+ internal override void EmitCallvirt(CodeEmitter ilgen)
+ {
+ switch (cpi.Name)
+ {
+ case "invokeExact":
+ EmitInvokeExact(ilgen);
+ break;
+ case "invoke":
+ EmitInvoke(ilgen);
+ break;
+ case "invokeBasic":
+ EmitInvokeBasic(ilgen);
+ break;
+ default:
+ throw new InvalidOperationException();
+ }
}
internal override void EmitNewobj(CodeEmitter ilgen)
@@ -3858,16 +3735,58 @@ sealed class Compiler
}
}
+ private sealed class DynamicFieldBinder
+ {
+ private MethodInfo method;
+
+ internal void Emit(Compiler compiler, ClassFile.ConstantPoolItemFieldref cpi, ClassFile.RefKind kind)
+ {
+ if (method == null)
+ {
+ method = CreateMethod(compiler, cpi, kind);
+ }
+ compiler.ilGenerator.Emit(OpCodes.Call, method);
+ }
+
+ private static MethodInfo CreateMethod(Compiler compiler, ClassFile.ConstantPoolItemFieldref cpi, ClassFile.RefKind kind)
+ {
+ TypeWrapper ret;
+ TypeWrapper[] args;
+ switch (kind)
+ {
+ case ClassFile.RefKind.getField:
+ ret = cpi.GetFieldType();
+ args = new TypeWrapper[] { cpi.GetClassType() };
+ break;
+ case ClassFile.RefKind.getStatic:
+ ret = cpi.GetFieldType();
+ args = TypeWrapper.EmptyArray;
+ break;
+ case ClassFile.RefKind.putField:
+ ret = PrimitiveTypeWrapper.VOID;
+ args = new TypeWrapper[] { cpi.GetClassType(), cpi.GetFieldType() };
+ break;
+ case ClassFile.RefKind.putStatic:
+ ret = PrimitiveTypeWrapper.VOID;
+ args = new TypeWrapper[] { cpi.GetFieldType() };
+ break;
+ default:
+ throw new InvalidOperationException();
+ }
+ return DynamicBinder.Emit(compiler, kind, cpi, ret, args, false);
+ }
+ }
+
private sealed class DynamicBinder
{
private MethodWrapper mw;
- internal MethodWrapper Get(DynamicTypeWrapper.FinishContext context, ClassFile.RefKind kind, ClassFile.ConstantPoolItemMI cpi)
+ internal MethodWrapper Get(Compiler compiler, ClassFile.RefKind kind, ClassFile.ConstantPoolItemMI cpi, bool privileged)
{
- return mw ?? (mw = new DynamicBinderMethodWrapper(cpi, Emit(context, kind, cpi), kind));
+ return mw ?? (mw = new DynamicBinderMethodWrapper(cpi, Emit(compiler, kind, cpi, privileged), kind));
}
- private static MethodInfo Emit(DynamicTypeWrapper.FinishContext context, ClassFile.RefKind kind, ClassFile.ConstantPoolItemMI cpi)
+ private static MethodInfo Emit(Compiler compiler, ClassFile.RefKind kind, ClassFile.ConstantPoolItemMI cpi, bool privileged)
{
TypeWrapper ret;
TypeWrapper[] args;
@@ -3884,18 +3803,26 @@ sealed class Compiler
else
{
ret = cpi.GetRetType();
- args = new TypeWrapper[cpi.GetArgTypes().Length + 1];
- Array.Copy(cpi.GetArgTypes(), 0, args, 1, args.Length - 1);
- args[0] = cpi.GetClassType();
+ args = ArrayUtil.Concat(cpi.GetClassType(), cpi.GetArgTypes());
}
- Type delegateType = MethodHandleUtil.CreateDelegateType(args, ret);
- FieldBuilder fb = context.DefineMethodHandleInvokeCacheField(delegateType);
+ return Emit(compiler, kind, cpi, ret, args, privileged);
+ }
+
+ internal static MethodInfo Emit(Compiler compiler, ClassFile.RefKind kind, ClassFile.ConstantPoolItemFMI cpi, TypeWrapper ret, TypeWrapper[] args, bool privileged)
+ {
+ bool ghostTarget = (kind == ClassFile.RefKind.invokeSpecial || kind == ClassFile.RefKind.invokeVirtual || kind == ClassFile.RefKind.invokeInterface) && args[0].IsGhost;
+ Type delegateType = MethodHandleUtil.CreateMethodHandleDelegateType(args, ret);
+ FieldBuilder fb = compiler.context.DefineMethodHandleInvokeCacheField(delegateType);
Type[] types = new Type[args.Length];
for (int i = 0; i < types.Length; i++)
{
types[i] = args[i].TypeAsSignatureType;
}
- MethodBuilder mb = context.DefineMethodHandleDispatchStub(ret.TypeAsSignatureType, types);
+ if (ghostTarget)
+ {
+ types[0] = types[0].MakeByRefType();
+ }
+ MethodBuilder mb = compiler.context.DefineMethodHandleDispatchStub(ret.TypeAsSignatureType, types);
CodeEmitter ilgen = CodeEmitter.Create(mb);
ilgen.Emit(OpCodes.Ldsfld, fb);
CodeEmitterLabel label = ilgen.DefineLabel();
@@ -3904,7 +3831,14 @@ sealed class Compiler
ilgen.Emit(OpCodes.Ldstr, cpi.Class);
ilgen.Emit(OpCodes.Ldstr, cpi.Name);
ilgen.Emit(OpCodes.Ldstr, cpi.Signature);
- context.EmitCallerID(ilgen);
+ if (privileged)
+ {
+ compiler.context.EmitHostCallerID(ilgen);
+ }
+ else
+ {
+ compiler.context.EmitCallerID(ilgen, compiler.m.IsLambdaFormCompiled);
+ }
ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicBinderMemberLookup.MakeGenericMethod(delegateType));
ilgen.Emit(OpCodes.Volatile);
ilgen.Emit(OpCodes.Stsfld, fb);
@@ -3913,6 +3847,10 @@ sealed class Compiler
for (int i = 0; i < args.Length; i++)
{
ilgen.EmitLdarg(i);
+ if (i == 0 && ghostTarget)
+ {
+ ilgen.Emit(OpCodes.Ldobj, args[0].TypeAsSignatureType);
+ }
}
MethodHandleUtil.EmitCallDelegateInvokeMethod(ilgen, delegateType);
ilgen.Emit(OpCodes.Ret);
@@ -3980,41 +3918,74 @@ sealed class Compiler
mw = cpi.GetMethod();
break;
case NormalizedByteCode.__dynamic_invokeinterface:
- return context.GetValue<DynamicBinder>(constantPoolIndex).Get(context, ClassFile.RefKind.invokeInterface, cpi);
case NormalizedByteCode.__dynamic_invokestatic:
- return context.GetValue<DynamicBinder>(constantPoolIndex).Get(context, ClassFile.RefKind.invokeStatic, cpi);
case NormalizedByteCode.__dynamic_invokevirtual:
- return context.GetValue<DynamicBinder>(constantPoolIndex).Get(context, ClassFile.RefKind.invokeVirtual, cpi);
case NormalizedByteCode.__dynamic_invokespecial:
- return context.GetValue<DynamicBinder>(constantPoolIndex).Get(context, ClassFile.RefKind.newInvokeSpecial, cpi);
+ case NormalizedByteCode.__privileged_invokestatic:
+ case NormalizedByteCode.__privileged_invokevirtual:
+ case NormalizedByteCode.__privileged_invokespecial:
+ return GetDynamicMethodWrapper(constantPoolIndex, invoke, cpi);
case NormalizedByteCode.__methodhandle_invoke:
- return new MethodHandleMethodWrapper(context, clazz, cpi, false);
- case NormalizedByteCode.__methodhandle_invokeexact:
- return new MethodHandleMethodWrapper(context, clazz, cpi, true);
+ case NormalizedByteCode.__methodhandle_link:
+ return new MethodHandleMethodWrapper(context, clazz, cpi);
default:
throw new InvalidOperationException();
}
if(mw.IsDynamicOnly)
{
- switch (invoke)
- {
- case NormalizedByteCode.__invokespecial:
- return context.GetValue<DynamicBinder>(constantPoolIndex).Get(context, ClassFile.RefKind.invokeSpecial, cpi);
- case NormalizedByteCode.__invokeinterface:
- return context.GetValue<DynamicBinder>(constantPoolIndex).Get(context, ClassFile.RefKind.invokeInterface, cpi);
- case NormalizedByteCode.__invokestatic:
- return context.GetValue<DynamicBinder>(constantPoolIndex).Get(context, ClassFile.RefKind.invokeStatic, cpi);
- case NormalizedByteCode.__invokevirtual:
- return context.GetValue<DynamicBinder>(constantPoolIndex).Get(context, ClassFile.RefKind.invokeVirtual, cpi);
- default:
- throw new InvalidOperationException();
- }
+ return GetDynamicMethodWrapper(constantPoolIndex, invoke, cpi);
}
return mw;
}
- // TODO this method should have a better name
- private TypeWrapper SigTypeToClassName(TypeWrapper type, TypeWrapper nullType)
+ private MethodWrapper GetDynamicMethodWrapper(int index, NormalizedByteCode invoke, ClassFile.ConstantPoolItemMI cpi)
+ {
+ ClassFile.RefKind kind;
+ switch (invoke)
+ {
+ case NormalizedByteCode.__invokeinterface:
+ case NormalizedByteCode.__dynamic_invokeinterface:
+ kind = ClassFile.RefKind.invokeInterface;
+ break;
+ case NormalizedByteCode.__invokestatic:
+ case NormalizedByteCode.__dynamic_invokestatic:
+ case NormalizedByteCode.__privileged_invokestatic:
+ kind = ClassFile.RefKind.invokeStatic;
+ break;
+ case NormalizedByteCode.__invokevirtual:
+ case NormalizedByteCode.__dynamic_invokevirtual:
+ case NormalizedByteCode.__privileged_invokevirtual:
+ kind = ClassFile.RefKind.invokeVirtual;
+ break;
+ case NormalizedByteCode.__invokespecial:
+ case NormalizedByteCode.__dynamic_invokespecial:
+ kind = ClassFile.RefKind.newInvokeSpecial;
+ break;
+ case NormalizedByteCode.__privileged_invokespecial:
+ // we don't support calling a base class constructor
+ kind = cpi.GetMethod().IsConstructor
+ ? ClassFile.RefKind.newInvokeSpecial
+ : ClassFile.RefKind.invokeSpecial;
+ break;
+ default:
+ throw new InvalidOperationException();
+ }
+ bool privileged;
+ switch (invoke)
+ {
+ case NormalizedByteCode.__privileged_invokestatic:
+ case NormalizedByteCode.__privileged_invokevirtual:
+ case NormalizedByteCode.__privileged_invokespecial:
+ privileged = true;
+ break;
+ default:
+ privileged = false;
+ break;
+ }
+ return context.GetValue<DynamicBinder>(index | ((byte)kind << 24)).Get(this, kind, cpi, privileged);
+ }
+
+ private TypeWrapper ComputeThisType(TypeWrapper type, MethodWrapper method, NormalizedByteCode invoke)
{
if(type == VerifierTypeWrapper.UninitializedThis
|| VerifierTypeWrapper.IsThis(type))
@@ -4027,7 +3998,11 @@ sealed class Compiler
}
else if(type == VerifierTypeWrapper.Null)
{
- return nullType;
+ return method.DeclaringType;
+ }
+ else if(invoke == NormalizedByteCode.__invokevirtual && method.IsProtected && type.IsUnloadable)
+ {
+ return clazz;
}
else
{