-
-
Notifications
You must be signed in to change notification settings - Fork 925
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow JRuby 9K to run on Ruboto #4589
base: master
Are you sure you want to change the base?
Conversation
Return ObjectIdentityInvalidator if indy disabled. See #4004. Everything java.lang.invoke related is not available on android, so for now revert to the old behavior here. This still makes some tests fail, but might suffice to run on android. Use jruby's ClassValue. Instead of java.lang.ClassValue which ist not available on android. See #4004. Remove seemingly unused constant. Could not find a usage for this. And since MethodHandles is not available on android, I simply removed it for the time being. See #4004. Revert to old behavior, when indy disabled. Just like in 8db25932200fb3ed7160066b184e6db2e29f1921 Do not init JITCompiler if it is not used. See #4004. Use jruby's ClassValue. Instead of java.lang.ClassValue which ist not available on android. See #4004. Move idTest to where it is actually needed. This of course destroys any gains of caching the idTest, but gets rid of MethodHandle et al in RubyModule which is important to run on android. See #4004. Remove unused Method. Since this will not run on android is not being used currently anyway, just comment it out for now. See #4004. Revert "relax seek-channel type requirement from FileChannel to SeekableByteChannel" This reverts commit dc48f34. No SeekableByteChannel on android. See #4004. Work around missing java.nio libs on android. See #4004. Replace ClassValue with internal implementation. Because java.lang.ClassValue is not available on android. See #4004. Add minimal MethodHandle implementation. java.lang.invoke.Method* classes are not available on android. See #4004. Add code generation for android. See #4004. Move nullToNil out of the way. To not have MethodHandles in Ruby.java as this is not available on android. See #4004. Guard against missing JITCompiler. Necessry as JITCompiler will not get instantiated on android. See #4004. Remove unused methods getIdTest + newIdTest Move Android logic to the Ruboto project Removed extra white space Remove the maven repository for dexmaker
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall it's a good approach. We need to address the loss of cached MethodHandle for non-Android, and there's a few questions to be addressed.
return ctime(context); | ||
} | ||
|
||
public static final FileTime getBirthtimeWithNIO(String pathString) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mild concern here about removing a public method, but I don't know how long it has been around.
@@ -299,18 +300,6 @@ public void addIncludingHierarchy(IncludedModule hierarchy) { | |||
} | |||
} | |||
|
|||
public MethodHandle getIdTest() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here but it was probably wrong of me to expose it in the first place.
import org.jruby.runtime.DynamicScope; | ||
import org.jruby.runtime.Frame; | ||
import org.jruby.runtime.ThreadContext; | ||
import org.jruby.runtime.*; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We prefer not to do * except in the most extreme cases. This isn't one of them.
@@ -39,6 +34,7 @@ | |||
import org.objectweb.asm.Opcodes; | |||
|
|||
import java.lang.invoke.*; | |||
import java.lang.invoke.CallSite; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This * is my fault. We should just expand it.
@@ -657,7 +653,10 @@ public static IRubyObject ivarGet(VariableSite site, IRubyObject self) throws Th | |||
VariableAccessor accessor = realClass.getVariableAccessorForRead(site.name()); | |||
|
|||
// produce nil if the variable has not been initialize | |||
MethodHandle nullToNil = self.getRuntime().getNullToNilHandle(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The purpose of getNullToNilHandle was to have a single place to cache the handle and reuse it everywhere. This is going to recreate handles every time. I agree we need a better place than on Ruby, but we still need these one-time handles.
@@ -657,7 +653,10 @@ public static IRubyObject ivarGet(VariableSite site, IRubyObject self) throws Th | |||
VariableAccessor accessor = realClass.getVariableAccessorForRead(site.name()); | |||
|
|||
// produce nil if the variable has not been initialize | |||
MethodHandle nullToNil = self.getRuntime().getNullToNilHandle(); | |||
IRubyObject nilObject = self.getRuntime().getNil(); | |||
MethodHandle nullToNil = lookup().findStatic(Helpers.class, "nullToNil", methodType(IRubyObject.class, IRubyObject.class, IRubyObject.class)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same issue here with excessive handle creation.
MethodHandles.Lookup lookup = MethodHandles.lookup(); | ||
MethodHandle testModuleMatch = null; | ||
try { | ||
testModuleMatch = lookup.findStatic(Bootstrap.class, "testModuleMatch", MethodType.methodType(boolean.class, ThreadContext.class, IRubyObject.class, int.class)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same issue here with excessive module creation. I'm sure we can find a way/place to save these handles without polluting things so much that Android doesn't work.
@@ -50,7 +50,7 @@ | |||
public abstract class BlockBody { | |||
|
|||
protected final Signature signature; | |||
protected volatile MethodHandle testBlockBody; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not used but might be later. It is also to avoid recreating the same handle over and over again. It could be made Object and casted elsewhere to avoid the hard reference of MethodHandle.
import java.lang.reflect.InvocationTargetException; | ||
import java.lang.reflect.Method; | ||
|
||
public class MethodHandle { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This part is pretty nice, and I almost wonder if we should pull it out into its own library, for others to use.
@@ -131,7 +130,7 @@ private void initChannelTypes() { | |||
else chRead = null; | |||
if (ch instanceof WritableByteChannel) chWrite = (WritableByteChannel)ch; | |||
else chWrite = null; | |||
if (ch instanceof SeekableByteChannel) chSeek = (SeekableByteChannel)ch; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the reason for this? SeekableByteChannel is not a new class, is it? I suppose on current Java the only SeekableByteChannel is FileChannel, but I prefer to use the more generic interface if possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason for this is that SeekableByteChannel was added to Android 7.0 API level 24 ref.:
https://developer.android.com/reference/java/nio/channels/SeekableByteChannel.html
FileChannel has been in Android since the initial release.
I agree that using the interface is the better option, and we can do a patch in Ruboto if necessary, although better if we don't have to 😄 .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ugh. I'd really rather not use FileChannel everywhere, even though I don't know of any SeekableByteChannel offhand (even jnr-enxio channels don't implement the interface). And changing chSeek to be a FileChannel makes it essentially just a duplicate of chFile.
I hate to make more work here but this is a pretty icky change to have to make. I wish Google's incorporation of Java 7 APIs weren't so arbitrary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll do a patch in Ruboto, then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, reinstated the use of SeekableByteChannel and put a copy of the ChannelFD source in Ruboto.
Thanks for the review! I can fix the import expansions. Do you prefer I force-push those changes, or add a new commit? |
@donv I don't care if you do it as a separate commit or not. The original set of commits was long and has already been squashed, so we don't really have much history left in this PR anyway. |
OK, I fixed the '*' imports. Which of the other comments need to be done before merging? |
@@ -0,0 +1,53 @@ | |||
package org.jruby.util.invoke; | |||
|
|||
import org.jruby.javasupport.ext.JavaLangReflect; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✂️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed.
OK, reinstated SeekableByteChannel. What more needs to be done? I am on it in a flash! ⚡️ |
@donv The places where we removed MethodHandle from e.g. Ruby, RubyModule, etc, should be reinstated, but signatures changed to something Android supports (maybe just Object) and the creation of the handles indirected through e.g. OptoFactory. We need to still be able to cache those handles rather than recreating them every time. nullToNil, for example. |
@donv It occurs to me we could use generics to fix those methods; when called with a MethodHandle factory, they'd return MethodHandle, so type-safety on non-Android would still be restored. I may try to prototype that this evening. |
Cool! Looking forward to it 😄 |
Ok...obviously I didn't get back to it before my trip. I'll review what we have now. |
@donv Sorry for the long delay but I made my changes. Since there were only two places where we had removed handle caches, I just restored them as all Object signatures. Unless used (by JIT+indy) they shouldn't get called and shouldn't trigger load of Java 7+ indy classes. Review my changes please! I think this could go into 9.2. @enebo? |
So I realized that the travis build has not been green. It appears that it's failing because the JIT is still running and using invokedynamic for globals and constants, but indy defaults to false which disables the SwitchPoint-based invalidators for constants and globals. I'll see what I can figure out. |
Problem stems from this change, which provided a non-indy way to create a constant invalidator: 1f31168 We'll need to modify the JIT to have non-indy global and const logic. |
This is not a straight reversion of the caching commit below, since there were modifications to how constants bound after that change. Note that we still need to restore constant caching for non-indy paths, or otherwise make it easier to say that Java 7+ JRuby will use indy for some things without compile.invokedynamic, but disable those features on platforms that don't support indy. Revert "Always use invokeynamic to lookup and cache constants." This reverts commit e03c4f1.
This is a completely unoptimized path, and can't be shipped, but it should continue to allow things to work on Android without breaking the non-indy JIT for JRuby proper.
I have pushed a few more commits that get things further along:
We can't really ship this for JRuby proper without providing some non-indy caching for constants and globals, since that would represent a fairly bad regression. At the very least we need a better way to pick and choose features based on profile: for example, on desktop Java 7 we may use a few indy features even if full indy is not turned on, but on Android we must avoid all indy features but may be able to use some other 7 features. Rake still seems to be having trouble starting up, now due to an NPE in the IR interpreter. @enebo |
Tests appear to be going green now, yay. We'll see how it looks and then see about optimizing these non-indy compiler changes. |
I'm confused by the MRI failures. A handful of tests that attempt to run in a subprocess seem to be timing out, in this and other builds (see also the spec:ruby:fast timeout). I'll poke at things today and try to figure it out. |
@headius This is looking great! Seems we are getting close! |
@donv Whatever's causing those two failures seems to be affecting all branches, so we may actually be good to go with the branch as-is. |
Woohoo! |
@headius Good news! I used the jruby-jars from this branch and upgraded one of our production apps today. And it is now operational! Sure, it is a simple app with very few in-house users, but it works well 😄 I encountered some problems I had to work around, but I'd like to get this PR merged before I report those. You mentioned we may be ready to merge this PR? Doable? Yes? |
@headius Can we merge this issue now? I have a problem with subclassing a Java class on Android, but it would be good to work off JRuby master with this PR merged. |
Hi @headius ! Master has moved on a bit. I can try to resolve the conflicts unless you want to do it. |
See #4004 and ruboto/ruboto/issues/737.
Everything java.lang.invoke related is not
available on android, so for now revert to the old
behavior here.
This still makes some tests fail, but might suffice
to run on android.
Use jruby's ClassValue.
Instead of java.lang.ClassValue which ist not available on
android. See #4004.
Remove seemingly unused constant.
Could not find a usage for this. And since MethodHandles
is not available on android, I simply removed it for the time
being. See #4004.
Revert to old behavior, when indy disabled.
Just like in 8db25932200fb3ed7160066b184e6db2e29f1921
Do not init JITCompiler if it is not used.
See #4004.
Use jruby's ClassValue.
Instead of java.lang.ClassValue which ist not available on
android. See #4004.
Move idTest to where it is actually needed.
This of course destroys any gains of caching the idTest, but
gets rid of MethodHandle et al in RubyModule which is
important to run on android. See #4004.
Remove unused Method.
Since this will not run on android is not being used
currently anyway, just comment it out for now. See #4004.
Revert "relax seek-channel type requirement from FileChannel to SeekableByteChannel"
This reverts commit dc48f34.
No SeekableByteChannel on android. See #4004.
Work around missing java.nio libs on android.
See #4004.
Replace ClassValue with internal implementation.
Because java.lang.ClassValue is not available on android.
See #4004.
Add minimal MethodHandle implementation.
java.lang.invoke.Method* classes are not available on
android. See #4004.
Add code generation for android.
See #4004.
Move nullToNil out of the way.
To not have MethodHandles in Ruby.java as this
is not available on android. See #4004.
Guard against missing JITCompiler.
Necessry as JITCompiler will not get instantiated on android.
See #4004.
Remove unused methods getIdTest + newIdTest
Move Android logic to the Ruboto project
Removed extra white space
Remove the maven repository for dexmaker