diff options
author | jfrijters <jfrijters> | 2015-06-23 10:24:39 +0300 |
---|---|---|
committer | jfrijters <jfrijters> | 2015-06-23 10:24:39 +0300 |
commit | 75b9e730c8697759745ff79584bed644e4f7e7a5 (patch) | |
tree | 2e287686c2ce07202eeca905c4602b98c208f9e3 | |
parent | e6322146dbaf32f9586401cd48e5df1abf40a521 (diff) |
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.
-rw-r--r-- | openjdk/map.xml | 38 | ||||
-rw-r--r-- | runtime/Dummy.OpenJDK.Core.cs | 19 | ||||
-rw-r--r-- | runtime/openjdk/java.lang.invoke.cs | 77 |
3 files changed, 69 insertions, 65 deletions
diff --git a/openjdk/map.xml b/openjdk/map.xml index 4bbb3412..0b50611d 100644 --- a/openjdk/map.xml +++ b/openjdk/map.xml @@ -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=""> diff --git a/runtime/Dummy.OpenJDK.Core.cs b/runtime/Dummy.OpenJDK.Core.cs index e9968b28..95fce5b2 100644 --- a/runtime/Dummy.OpenJDK.Core.cs +++ b/runtime/Dummy.OpenJDK.Core.cs @@ -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 { } +} diff --git a/runtime/openjdk/java.lang.invoke.cs b/runtime/openjdk/java.lang.invoke.cs index 6929b6c5..5c892eba 100644 --- a/runtime/openjdk/java.lang.invoke.cs +++ b/runtime/openjdk/java.lang.invoke.cs @@ -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) |