зеркало из https://github.com/mono/ikvm-fork.git
Fixed regression introduced with pairwise convert optimization. MethodHandle String construction is now handled much more cleanly by hooking DirectMethodHandle.makeAllocator() instead of fiddling with the MemberName.
This commit is contained in:
Родитель
e6322146db
Коммит
75b9e730c8
|
@ -2888,6 +2888,15 @@
|
|||
<ret />
|
||||
</body>
|
||||
</method>
|
||||
<method name="_type" sig="(Ljava.lang.invoke.MethodType;)V" modifiers="final">
|
||||
<attribute type="IKVM.Attributes.HideFromJavaAttribute" sig="()V" />
|
||||
<body>
|
||||
<ldarg_0 />
|
||||
<ldarg_1 />
|
||||
<stfld class="java.lang.invoke.MemberName" name="type" sig="Ljava.lang.Object;" />
|
||||
<ret />
|
||||
</body>
|
||||
</method>
|
||||
<method name="_flags" sig="()I" modifiers="final">
|
||||
<attribute type="IKVM.Attributes.HideFromJavaAttribute" sig="()V" />
|
||||
<body>
|
||||
|
@ -2969,20 +2978,29 @@
|
|||
</replace-method-call>
|
||||
</method>
|
||||
</class>
|
||||
<class name="java.lang.invoke.MethodHandles$Lookup">
|
||||
<!-- We hook this to undo the fiddling we do to support string constructors -->
|
||||
<method name="revealDirect" sig="(Ljava.lang.invoke.MethodHandle;)Ljava.lang.invoke.MethodHandleInfo;">
|
||||
<replace-method-call class="java.lang.invoke.MethodHandle" name="internalMemberName" sig="()Ljava.lang.invoke.MemberName;">
|
||||
<code>
|
||||
<call type="Java_java_lang_invoke_MethodHandleNatives" name="internalMemberName" sig="(Ljava.lang.invoke.MethodHandle;)Ljava.lang.invoke.MemberName;" />
|
||||
</code>
|
||||
</replace-method-call>
|
||||
</method>
|
||||
</class>
|
||||
<class name="java.lang.invoke.DirectMethodHandle">
|
||||
<method name="_preparedLambdaForm" sig="(Ljava.lang.invoke.MethodType;I)Ljava.lang.invoke.LambdaForm;" modifiers="static">
|
||||
<body>
|
||||
<ldarg_0 />
|
||||
<ldarg_1 />
|
||||
<call class="java.lang.invoke.DirectMethodHandle" name="preparedLambdaForm" sig="(Ljava.lang.invoke.MethodType;I)Ljava.lang.invoke.LambdaForm;" />
|
||||
<ret />
|
||||
</body>
|
||||
</method>
|
||||
<method name="allocateInstance" sig="(Ljava.lang.Object;)Ljava.lang.Object;">
|
||||
<attribute type="System.Security.SecuritySafeCriticalAttribute" sig="()V" />
|
||||
</method>
|
||||
<method name="makeAllocator" sig="(Ljava.lang.invoke.MemberName;)Ljava.lang.invoke.DirectMethodHandle;">
|
||||
<prologue>
|
||||
<ldarg_0 />
|
||||
<call type="Java_java_lang_invoke_DirectMethodHandle" name="makeStringAllocator" sig="(Ljava.lang.invoke.MemberName;)Ljava.lang.invoke.DirectMethodHandle;" />
|
||||
<dup />
|
||||
<brfalse name="continue" />
|
||||
<ret />
|
||||
<label name="continue" />
|
||||
<pop />
|
||||
</prologue>
|
||||
</method>
|
||||
</class>
|
||||
<class name="java.lang.invoke.MethodType">
|
||||
<field name="voidAdapter" sig="Ljava.lang.Object;" modifiers="">
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (C) 2010 Jeroen Frijters
|
||||
Copyright (C) 2010-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
|
||||
|
@ -53,10 +53,8 @@ namespace java
|
|||
|
||||
namespace invoke
|
||||
{
|
||||
public class MemberName { }
|
||||
public class AdapterMethodHandle { }
|
||||
public class BoundMethodHandle { }
|
||||
public class DirectMethodHandle { }
|
||||
public class MemberName { }
|
||||
public class MethodType { }
|
||||
public class MethodHandle { }
|
||||
public class CallSite { }
|
||||
|
@ -64,8 +62,10 @@ namespace java
|
|||
|
||||
namespace reflect
|
||||
{
|
||||
public class Constructor { }
|
||||
public class Method { }
|
||||
public class Constructor : Executable { }
|
||||
public class Executable { }
|
||||
public class Field { }
|
||||
public class Method : Executable { }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,3 +92,10 @@ namespace java
|
|||
public class Vector { }
|
||||
}
|
||||
}
|
||||
|
||||
namespace sun.reflect
|
||||
{
|
||||
public interface ConstructorAccessor { }
|
||||
public interface FieldAccessor { }
|
||||
public interface MethodAccessor { }
|
||||
}
|
||||
|
|
|
@ -31,6 +31,26 @@ using IKVM.Internal;
|
|||
using java.lang.invoke;
|
||||
using jlClass = java.lang.Class;
|
||||
|
||||
static class Java_java_lang_invoke_DirectMethodHandle
|
||||
{
|
||||
// this is called from DirectMethodHandle.makeAllocator() via a map.xml prologue patch
|
||||
public static DirectMethodHandle makeStringAllocator(MemberName member)
|
||||
{
|
||||
#if FIRST_PASS
|
||||
return null;
|
||||
#else
|
||||
// we cannot construct strings via the standard two-pass approach (allocateObject followed by constructor invocation),
|
||||
// so we special case string construction here (to call our static factory method instead)
|
||||
if (member.getDeclaringClass() == CoreClasses.java.lang.String.Wrapper.ClassObject)
|
||||
{
|
||||
MethodType mt = member.getMethodType().changeReturnType(CoreClasses.java.lang.String.Wrapper.ClassObject);
|
||||
return new DirectMethodHandle(mt, DirectMethodHandle._preparedLambdaForm(mt, MethodTypeForm.LF_INVSTATIC), member, null);
|
||||
}
|
||||
return null;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static class Java_java_lang_invoke_MethodHandle
|
||||
{
|
||||
public static object invokeExact(MethodHandle thisObject, object[] args)
|
||||
|
@ -136,35 +156,6 @@ static class Java_java_lang_invoke_MethodHandleNatives
|
|||
return tw.IsInstance(obj) || (tw == CoreClasses.cli.System.Object.Wrapper && obj is Array);
|
||||
}
|
||||
|
||||
// called from Lookup.revealDirect() (instead of MethodHandle.internalMemberName()) via map.xml replace-method-call
|
||||
public static MemberName internalMemberName(MethodHandle mh)
|
||||
{
|
||||
#if FIRST_PASS
|
||||
return null;
|
||||
#else
|
||||
MemberName mn = mh.internalMemberName();
|
||||
if (mn.isStatic() && mn.getName() == "<init>")
|
||||
{
|
||||
// HACK since we convert String constructors into static methods, we have to undo that here
|
||||
// Note that the MemberName we return is only used for a security check and by InfoFromMemberName (a MethodHandleInfo implementation),
|
||||
// so we don't need to make it actually invokable.
|
||||
MemberName alt = new MemberName();
|
||||
typeof(MemberName).GetField("clazz", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(alt, mn.getDeclaringClass());
|
||||
typeof(MemberName).GetField("name", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(alt, mn.getName());
|
||||
typeof(MemberName).GetField("type", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(alt, mn.getMethodType().changeReturnType(typeof(void)));
|
||||
int flags = mn._flags();
|
||||
flags -= MethodHandleNatives.Constants.MN_IS_METHOD;
|
||||
flags += MethodHandleNatives.Constants.MN_IS_CONSTRUCTOR;
|
||||
flags &= ~(MethodHandleNatives.Constants.MN_REFERENCE_KIND_MASK << MethodHandleNatives.Constants.MN_REFERENCE_KIND_SHIFT);
|
||||
flags |= MethodHandleNatives.Constants.REF_newInvokeSpecial << MethodHandleNatives.Constants.MN_REFERENCE_KIND_SHIFT;
|
||||
flags &= ~MethodHandleNatives.Constants.ACC_STATIC;
|
||||
alt._flags(flags);
|
||||
return alt;
|
||||
}
|
||||
return mn;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void init(MemberName self, object refObj)
|
||||
{
|
||||
init(self, refObj, false);
|
||||
|
@ -209,6 +200,10 @@ static class Java_java_lang_invoke_MethodHandleNatives
|
|||
{
|
||||
flags |= MethodHandleNatives.Constants.REF_invokeStatic << MethodHandleNatives.Constants.MN_REFERENCE_KIND_SHIFT;
|
||||
}
|
||||
else if (mw.IsConstructor && !wantSpecial)
|
||||
{
|
||||
flags |= MethodHandleNatives.Constants.REF_newInvokeSpecial << MethodHandleNatives.Constants.MN_REFERENCE_KIND_SHIFT;
|
||||
}
|
||||
else if (mw.IsPrivate || mw.IsFinal || mw.IsConstructor || wantSpecial)
|
||||
{
|
||||
flags |= MethodHandleNatives.Constants.REF_invokeSpecial << MethodHandleNatives.Constants.MN_REFERENCE_KIND_SHIFT;
|
||||
|
@ -232,16 +227,11 @@ static class Java_java_lang_invoke_MethodHandleNatives
|
|||
{
|
||||
parameters1[i] = mw.GetParameters()[i].ClassObject;
|
||||
}
|
||||
MethodType mt = MethodType.methodType(typeof(string), parameters1);
|
||||
typeof(MemberName).GetField("type", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(self, mt);
|
||||
self.vmtarget = CreateMemberNameDelegate(mw, null, false, mt);
|
||||
flags -= MethodHandleNatives.Constants.REF_invokeSpecial << MethodHandleNatives.Constants.MN_REFERENCE_KIND_SHIFT;
|
||||
flags += MethodHandleNatives.Constants.REF_invokeStatic << MethodHandleNatives.Constants.MN_REFERENCE_KIND_SHIFT;
|
||||
flags -= MethodHandleNatives.Constants.MN_IS_CONSTRUCTOR;
|
||||
flags += MethodHandleNatives.Constants.MN_IS_METHOD;
|
||||
flags += MethodHandleNatives.Constants.ACC_STATIC;
|
||||
MethodType mt = MethodType.methodType(PrimitiveTypeWrapper.VOID.ClassObject, parameters1);
|
||||
self._type(mt);
|
||||
self._flags(flags);
|
||||
self._clazz(mw.DeclaringType.ClassObject);
|
||||
self.vmtarget = CreateMemberNameDelegate(mw, null, false, self.getMethodType().changeReturnType(CoreClasses.java.lang.String.Wrapper.ClassObject));
|
||||
return;
|
||||
}
|
||||
self._flags(flags);
|
||||
|
@ -369,8 +359,7 @@ static class Java_java_lang_invoke_MethodHandleNatives
|
|||
}
|
||||
if (mw.IsConstructor && mw.DeclaringType == CoreClasses.java.lang.String.Wrapper)
|
||||
{
|
||||
typeof(MemberName).GetField("type", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(self, self.getMethodType().changeReturnType(typeof(string)));
|
||||
self.vmtarget = CreateMemberNameDelegate(mw, caller, false, self.getMethodType());
|
||||
self.vmtarget = CreateMemberNameDelegate(mw, caller, false, self.getMethodType().changeReturnType(CoreClasses.java.lang.String.Wrapper.ClassObject));
|
||||
}
|
||||
else if (!mw.IsConstructor || invokeSpecial || newInvokeSpecial)
|
||||
{
|
||||
|
@ -398,16 +387,6 @@ static class Java_java_lang_invoke_MethodHandleNatives
|
|||
{
|
||||
self._flags(self._flags() | MemberName.CALLER_SENSITIVE);
|
||||
}
|
||||
if (mw.IsConstructor && mw.DeclaringType == CoreClasses.java.lang.String.Wrapper)
|
||||
{
|
||||
int flags = self._flags();
|
||||
flags -= MethodHandleNatives.Constants.REF_invokeSpecial << MethodHandleNatives.Constants.MN_REFERENCE_KIND_SHIFT;
|
||||
flags += MethodHandleNatives.Constants.REF_invokeStatic << MethodHandleNatives.Constants.MN_REFERENCE_KIND_SHIFT;
|
||||
flags -= MethodHandleNatives.Constants.MN_IS_CONSTRUCTOR;
|
||||
flags += MethodHandleNatives.Constants.MN_IS_METHOD;
|
||||
flags += MethodHandleNatives.Constants.ACC_STATIC;
|
||||
self._flags(flags);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ResolveField(MemberName self)
|
||||
|
|
Загрузка…
Ссылка в новой задаче