Bytecoder icon indicating copy to clipboard operation
Bytecoder copied to clipboard

Full Locale support

Open mirkosertic opened this issue 4 years ago • 5 comments

mirkosertic avatar Oct 17 '19 14:10 mirkosertic

Noticing that if I try to use the java.desktop, that I get "Cannot link static field JAPAN in java.util.Locale" when compiling to WebAssembly. I tried dropping use of java.desktop, and directly assigning java.util.Locale to a variable, and I was able to replicate the issue that way. (And then I tried java.util.Locale.CHINA, and got a similar error relating to that. java.util.Locale.US gave me no issue.) Presumably this is related to the fact that these constants aren't defined in de.mirkosertic.bytecoder.classlib.java.util.TLocale. (But some of the code in the java.desktop module implementation directly references a few Locale constants. eg. sun.awt.im.ExecutableInputMethodManager, and though I don't understand the architecture here very well. I would suspect that's the issue.)

Then again, maybe I'm doing things completely wrong.

Here's the full stack trace in case you want it. (Probably don't. It's not terribly informative.) Exception in thread "main" java.lang.reflect.InvocationTargetException at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:564) at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48) at org.springframework.boot.loader.Launcher.launch(Launcher.java:87) at org.springframework.boot.loader.Launcher.launch(Launcher.java:51) at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:52) Caused by: java.lang.IllegalStateException: Cannot link static field JAPAN in java.util.Locale at de.mirkosertic.bytecoder.core.BytecodeInstructionGETSTATIC.performLinking(BytecodeInstructionGETSTATIC.java:41) at de.mirkosertic.bytecoder.core.BytecodeLinkedClass.resolveMethodSignatureAndBody(BytecodeLinkedClass.java:410) at de.mirkosertic.bytecoder.core.BytecodeLinkedClass.resolveVirtualMethod(BytecodeLinkedClass.java:299) at de.mirkosertic.bytecoder.core.BytecodeInstructionINVOKEVIRTUAL.performLinking(BytecodeInstructionINVOKEVIRTUAL.java:54) at de.mirkosertic.bytecoder.core.BytecodeLinkedClass.resolveMethodSignatureAndBody(BytecodeLinkedClass.java:410) at de.mirkosertic.bytecoder.core.BytecodeLinkedClass.resolveVirtualMethod(BytecodeLinkedClass.java:299) at de.mirkosertic.bytecoder.core.BytecodeInstructionINVOKEVIRTUAL.performLinking(BytecodeInstructionINVOKEVIRTUAL.java:54) at de.mirkosertic.bytecoder.core.BytecodeLinkedClass.resolveMethodSignatureAndBody(BytecodeLinkedClass.java:410) at de.mirkosertic.bytecoder.core.BytecodeLinkedClass.resolveVirtualMethod(BytecodeLinkedClass.java:299) at de.mirkosertic.bytecoder.core.BytecodeLinkedClass.resolveInheritedOverriddenMethods(BytecodeLinkedClass.java:467) at de.mirkosertic.bytecoder.core.BytecodeLinkerContext.resolveAbstractMethodsInSubclasses(BytecodeLinkerContext.java:148) at de.mirkosertic.bytecoder.core.BytecodeLinkerContext.resolveAbstractMethodsInSubclasses(BytecodeLinkerContext.java:152) at de.mirkosertic.bytecoder.backend.CompileTarget.compile(CompileTarget.java:122) at de.mirkosertic.bytecoder.cli.BytecoderCLI.main(BytecoderCLI.java:124) ... 8 more

seanmcox avatar Dec 26 '19 23:12 seanmcox

I added the missing fields in de.mirkosertic.bytecoder.classlib.java.util.TLocale and recompiled/repackaged. I had to fill in a lot of missing pieces, (read: ugly hacks) but I finally got rid of all the obvious "Cannot link" errors related to TLocale.

Now, I'm stuck with "No such method : jlClass_jlClassgetSuperclass". I don't think I'm ready to think about this yet. Here's the stack trace:

    [exec] Exception in thread "main" java.lang.reflect.InvocationTargetException
    [exec] 	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    [exec] 	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    [exec] 	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    [exec] 	at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    [exec] 	at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48)
    [exec] 	at org.springframework.boot.loader.Launcher.launch(Launcher.java:87)
    [exec] 	at org.springframework.boot.loader.Launcher.launch(Launcher.java:51)
    [exec] 	at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:52)
    [exec] Caused by: java.lang.IllegalStateException: Error relooping cfg for java/awt/Component.isCoalesceEventsOverriden BOOLEAN(java.lang.Class)
    [exec] 	at de.mirkosertic.bytecoder.backend.wasm.WASMSSAASTCompilerBackend.lambda$null$11(WASMSSAASTCompilerBackend.java:861)
    [exec] 	at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1492)
    [exec] 	at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:658)
    [exec] 	at de.mirkosertic.bytecoder.backend.wasm.WASMSSAASTCompilerBackend.lambda$generateCodeFor$12(WASMSSAASTCompilerBackend.java:642)
    [exec] 	at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1492)
    [exec] 	at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:658)
    [exec] 	at de.mirkosertic.bytecoder.backend.wasm.WASMSSAASTCompilerBackend.generateCodeFor(WASMSSAASTCompilerBackend.java:516)
    [exec] 	at de.mirkosertic.bytecoder.backend.wasm.WASMSSAASTCompilerBackend.generateCodeFor(WASMSSAASTCompilerBackend.java:112)
    [exec] 	at de.mirkosertic.bytecoder.backend.CompileTarget.compile(CompileTarget.java:158)
    [exec] 	at de.mirkosertic.bytecoder.cli.BytecoderCLI.main(BytecoderCLI.java:124)
    [exec] 	... 8 more
    [exec] Caused by: java.lang.IllegalArgumentException: No such method : jlClass_jlClassgetSuperclass
    [exec] 	at de.mirkosertic.bytecoder.backend.wasm.ast.FunctionIndex.firstByLabel(FunctionIndex.java:56)
    [exec] 	at de.mirkosertic.bytecoder.backend.wasm.WASMSSAASTWriter.directMethodInvokeValue(WASMSSAASTWriter.java:1416)
    [exec] 	at de.mirkosertic.bytecoder.backend.wasm.WASMSSAASTWriter.toValue(WASMSSAASTWriter.java:682)
    [exec] 	at de.mirkosertic.bytecoder.backend.wasm.WASMSSAASTWriter.generateInitVariableExpression(WASMSSAASTWriter.java:656)
    [exec] 	at de.mirkosertic.bytecoder.backend.wasm.WASMSSAASTWriter.generateExpressions(WASMSSAASTWriter.java:330)
    [exec] 	at de.mirkosertic.bytecoder.backend.wasm.WASMSSAASTWriter.writeExpressionList(WASMSSAASTWriter.java:317)
    [exec] 	at de.mirkosertic.bytecoder.backend.wasm.WASMSSAASTWriter.writeSimpleBlock(WASMSSAASTWriter.java:1713)
    [exec] 	at de.mirkosertic.bytecoder.backend.wasm.WASMSSAASTWriter.writeReloopedInternal(WASMSSAASTWriter.java:1684)
    [exec] 	at de.mirkosertic.bytecoder.backend.wasm.WASMSSAASTWriter.writeMultipleBlock(WASMSSAASTWriter.java:1769)
    [exec] 	at de.mirkosertic.bytecoder.backend.wasm.WASMSSAASTWriter.writeReloopedInternal(WASMSSAASTWriter.java:1692)
    [exec] 	at de.mirkosertic.bytecoder.backend.wasm.WASMSSAASTWriter.writeSimpleBlock(WASMSSAASTWriter.java:1715)
    [exec] 	at de.mirkosertic.bytecoder.backend.wasm.WASMSSAASTWriter.writeReloopedInternal(WASMSSAASTWriter.java:1684)
    [exec] 	at de.mirkosertic.bytecoder.backend.wasm.WASMSSAASTWriter.writeRelooped(WASMSSAASTWriter.java:1663)
    [exec] 	at de.mirkosertic.bytecoder.backend.wasm.WASMSSAASTCompilerBackend.lambda$null$11(WASMSSAASTCompilerBackend.java:858)
    [exec] 	... 17 more

seanmcox avatar Dec 28 '19 04:12 seanmcox

@seanmcox thank you for testing the java.desktop module. Bytecoder currently does not support the whole Java Reflection API. Some of the AWT/Swing code relies heavily on the reflection API, raising compile errors like the one above indicating that Class.getSuperclass is not supported.

If you have added some code the the Locale class, maybe you want to submit a PR for this? Help is always welcome! And there is no ugly hack, so please submit your changes!

mirkosertic avatar Dec 30 '19 08:12 mirkosertic

@mirkosertic Sure, will do. I did manage to address the issue above. I figured out how to add the jlClass_jlClassgetSuperclass definition. I couldn't figure out how return the pointer to a class object (not sure that there is such a thing in the compiled webassembly), so I just implemented it with an unreachable code, based on what I'd seen done elsewhere, and spent a little time trying to grock how the objects were getting modeled in webassembly. (Didn't get very far, but one of my goals is to learn more about the nuts and bolts of webassembly, so I consider it time well spent.)

That left me with: No such method : jlClass_jlrMethodgetDeclaredMethodjlStringA1jlClass

That's a somewhat more complex case. I couldn't immediately make sense of how I might define the parameter with the ellipses. (Couldn't find examples of it. Thinking about it now, I imagine this would be equivalent to passing an array, so probably just another I32 pointer.)

Anyhow, I'll create a branch and submit my changes.

seanmcox avatar Dec 30 '19 17:12 seanmcox

@mirkosertic I can't create a pull request directly. Presumably the right thing to do is create a fork, so that's what I'm doing. (I haven't collaborated much on Github, so, sorry if this was obvious, or if I'm missing something.)

seanmcox avatar Dec 30 '19 18:12 seanmcox