mthmulders / brainfuck-jvm

This project provides a Brainfuck implementation on the JVM.
MIT License
8 stars 1 forks source link

Unable to run bf code on graalvm 11 #59

Open asm0dey opened 4 years ago

asm0dey commented 4 years ago

I'm trying to run following code https://gist.github.com/asm0dey/08268c4ef1ae172f82ad509be67e35a7 on graalvm with this interpreter.

First thing I hit is failing tests.

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.22.2:test (default-test) on project brainfuck-jvm: There are test failures.
[ERROR] 
[ERROR] Please refer to /tmp/brainfuck-jvm/language/target/surefire-reports for the individual test results.
[ERROR] Please refer to dump files (if any exist) [date].dump, [date]-jvmRun[N].dump and [date].dumpstream.
[ERROR] The forked VM terminated without properly saying goodbye. VM crash or System.exit called?
[ERROR] Command was /bin/sh -c cd /tmp/brainfuck-jvm/language && /usr/lib/jvm/java-14-openjdk/bin/java -Dgraalvm.locatorDisabled=true -XX:-UseJVMCIClassLoader -jar /tmp/brainfuck-jvm/language/target/surefire/surefirebooter15452760603575350292.jar /tmp/brainfuck-jvm/language/target/surefire 2020-06-12T14-31-08_181-jvmRun1 surefire6108423771394059595tmp surefire_05052993105705640796tmp
[ERROR] Error occurred in starting fork, check output in log
[ERROR] Process Exit Code: 1
[ERROR] org.apache.maven.surefire.booter.SurefireBooterForkException: The forked VM terminated without properly saying goodbye. VM crash or System.exit called?
[ERROR] Command was /bin/sh -c cd /tmp/brainfuck-jvm/language && /usr/lib/jvm/java-14-openjdk/bin/java -Dgraalvm.locatorDisabled=true -XX:-UseJVMCIClassLoader -jar /tmp/brainfuck-jvm/language/target/surefire/surefirebooter15452760603575350292.jar /tmp/brainfuck-jvm/language/target/surefire 2020-06-12T14-31-08_181-jvmRun1 surefire6108423771394059595tmp surefire_05052993105705640796tmp
[ERROR] Error occurred in starting fork, check output in log
[ERROR] Process Exit Code: 1
[ERROR]         at org.apache.maven.plugin.surefire.booterclient.ForkStarter.fork(ForkStarter.java:669)
[ERROR]         at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:282)
[ERROR]         at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:245)
[ERROR]         at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeProvider(AbstractSurefireMojo.java:1183)
[ERROR]         at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeAfterPreconditionsChecked(AbstractSurefireMojo.java:1011)
[ERROR]         at org.apache.maven.plugin.surefire.AbstractSurefireMojo.execute(AbstractSurefireMojo.java:857)
[ERROR]         at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:137)
[ERROR]         at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:210)
[ERROR]         at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:156)
[ERROR]         at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:148)
[ERROR]         at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:117)
[ERROR]         at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:81)
[ERROR]         at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:56)
[ERROR]         at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
[ERROR]         at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:305)
[ERROR]         at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:192)
[ERROR]         at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:105)
[ERROR]         at org.apache.maven.cli.MavenCli.execute(MavenCli.java:957)
[ERROR]         at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:289)
[ERROR]         at org.apache.maven.cli.MavenCli.main(MavenCli.java:193)
[ERROR]         at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[ERROR]         at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[ERROR]         at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[ERROR]         at java.base/java.lang.reflect.Method.invoke(Method.java:564)
[ERROR]         at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:282)
[ERROR]         at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:225)
[ERROR]         at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:406)
[ERROR]         at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:347)
[ERROR] 

OK, let's run it with graalvm as JAVA

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.22.2:test (default-test) on project brainfuck-jvm: There are test failures.
[ERROR] 
[ERROR] Please refer to /tmp/brainfuck-jvm/language/target/surefire-reports for the individual test results.
[ERROR] Please refer to dump files (if any exist) [date].dump, [date]-jvmRun[N].dump and [date].dumpstream.
[ERROR] The forked VM terminated without properly saying goodbye. VM crash or System.exit called?
[ERROR] Command was /bin/sh -c cd /tmp/brainfuck-jvm/language && /usr/lib/jvm/java-11-graalvm/bin/java -Dgraalvm.locatorDisabled=true -XX:-UseJVMCIClassLoader -jar /tmp/brainfuck-jvm/language/target/surefire/surefirebooter6235115657144580644.jar /tmp/brainfuck-jvm/language/target/surefire 2020-06-12T14-31-58_330-jvmRun1 surefire1521407697740814466tmp surefire_016313578713563542937tmp
[ERROR] Error occurred in starting fork, check output in log
[ERROR] Process Exit Code: 1
[ERROR] org.apache.maven.surefire.booter.SurefireBooterForkException: The forked VM terminated without properly saying goodbye. VM crash or System.exit called?
[ERROR] Command was /bin/sh -c cd /tmp/brainfuck-jvm/language && /usr/lib/jvm/java-11-graalvm/bin/java -Dgraalvm.locatorDisabled=true -XX:-UseJVMCIClassLoader -jar /tmp/brainfuck-jvm/language/target/surefire/surefirebooter6235115657144580644.jar /tmp/brainfuck-jvm/language/target/surefire 2020-06-12T14-31-58_330-jvmRun1 surefire1521407697740814466tmp surefire_016313578713563542937tmp
[ERROR] Error occurred in starting fork, check output in log
[ERROR] Process Exit Code: 1
[ERROR]         at org.apache.maven.plugin.surefire.booterclient.ForkStarter.fork(ForkStarter.java:669)
[ERROR]         at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:282)
[ERROR]         at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:245)
[ERROR]         at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeProvider(AbstractSurefireMojo.java:1183)
[ERROR]         at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeAfterPreconditionsChecked(AbstractSurefireMojo.java:1011)
[ERROR]         at org.apache.maven.plugin.surefire.AbstractSurefireMojo.execute(AbstractSurefireMojo.java:857)
[ERROR]         at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:137)
[ERROR]         at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:210)
[ERROR]         at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:156)
[ERROR]         at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:148)
[ERROR]         at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:117)
[ERROR]         at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:81)
[ERROR]         at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:56)
[ERROR]         at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
[ERROR]         at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:305)
[ERROR]         at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:192)
[ERROR]         at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:105)
[ERROR]         at org.apache.maven.cli.MavenCli.execute(MavenCli.java:957)
[ERROR]         at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:289)
[ERROR]         at org.apache.maven.cli.MavenCli.main(MavenCli.java:193)
[ERROR]         at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[ERROR]         at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[ERROR]         at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[ERROR]         at java.base/java.lang.reflect.Method.invoke(Method.java:566)
[ERROR]         at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:282)
[ERROR]         at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:225)
[ERROR]         at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:406)
[ERROR]         at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:347)

OK, let's skip tests. Build finished, nice! Installing package goes fine with small notice:

Processing Component archive: component/target/brainfuck-0.1-SNAPSHOT-component.jar
Installing new component: Brainfuck (it.mulders.brainfuck-jvm, version 0.1-SNAPSHOT)

IMPORTANT NOTE:
---------------
Set of GraalVM components that provide language implementations have changed. The Polyglot native image and polyglot native C library may be out of sync: 
- new languages may not be accessible
- removed languages may cause the native binary to fail on missing resources or libraries.
To rebuild and refresh the native binaries, use the following command:
        /usr/lib/jvm/java-11-graalvm/bin/gu rebuild-images

Now let's run our application:

❯ sudo /usr/lib/jvm/java-11-graalvm/bin/bf ../c2bf/nqueens.bf
Installed in wrong version of GraalVM. Expected: 19.0.0, found "20.1.0"

OK, it's easy to fix right in bf file, replacing "19.0.0" with "\"20.1.0\""

And now we've got this nive exception:

❯ sudo /usr/lib/jvm/java-11-graalvm/bin/bf ../c2bf/nqueens.bf
Exception in thread "main" java.lang.IllegalArgumentException: A language with id 'bf' is not installed. Installed languages are: [js, llvm].
        at org.graalvm.truffle/com.oracle.truffle.polyglot.PolyglotEngineException.illegalArgument(PolyglotEngineException.java:122)
        at org.graalvm.truffle/com.oracle.truffle.polyglot.PolyglotEngineImpl.requirePublicLanguage(PolyglotEngineImpl.java:871)
        at org.graalvm.truffle/com.oracle.truffle.polyglot.PolyglotContextImpl.requirePublicLanguage(PolyglotContextImpl.java:874)
        at org.graalvm.truffle/com.oracle.truffle.polyglot.PolyglotContextImpl.eval(PolyglotContextImpl.java:843)
        at org.graalvm.sdk/org.graalvm.polyglot.Context.eval(Context.java:345)
        at it.mulders.brainfuckjvm.launcher.Launcher.executeSourceFile(Launcher.java:80)
        at it.mulders.brainfuckjvm.launcher.Launcher.run(Launcher.java:49)
        at it.mulders.brainfuckjvm.launcher.Launcher.main(Launcher.java:21)
mthmulders commented 4 years ago

Thanks for reporting this, @asm0dey.

Your first attempt failed (as you figured yourself) because you were running it without GraalVM. It's not clearly stated in the instructions, so I'll update them to explicitly mention that.

Your second attempt failed because you're the first one to use it with a Java 11 build of GraalVM. I'm adding support for that in #60 as we speak, so stay tuned on that part.

The warning about the "wrong version of GraalVM" is a bit of tricky one. Unfortunately, it's not possible to build a component that targets more than one version of GraalVM. I've tried before to use a version range in the manifest, but installing it would fail with

Unsupported operation in filter. Only = is supported.

So, unfortunately, you can only run it with the version that you've built it for - 20.1.0 in my case, or if you patch it yourself 19.0.0.

asm0dey commented 4 years ago

Still it may be interesting experience to launch this piece of code :)

mthmulders commented 4 years ago

After the work in #60, I am able to run the launcher like this:

$ /Library/Java/JavaVirtualMachines/graalvm-ce-java11-20.1.0/Contents/Home/bin/bf language/src/test/resources/hello.bf
Hello World!

So that seems about right. I guess it should now be possible for you to run nqueens.bf.

Please let me know if you still run into any problems.

asm0dey commented 4 years ago

I'm already waiting for more than an hour on 8th version.

Stack looks like this:

   java.lang.Thread.State: RUNNABLE
        at com.oracle.truffle.api.nodes.NodeUtil.adoptChildrenHelper(NodeUtil.java:297)
        at com.oracle.truffle.api.nodes.Node.adoptChildren(Node.java:262)
        at it.mulders.brainfuckjvm.simpleparser.parser.BrainfuckParser.buildNodes(BrainfuckParser.java:121)
        at it.mulders.brainfuckjvm.simpleparser.parser.BrainfuckParser.parse(BrainfuckParser.java:77)
        at it.mulders.brainfuckjvm.simpleparser.SimpleParser.parseSource(SimpleParser.java:36)
        at it.mulders.brainfuckjvm.BrainfuckLanguage.parse(BrainfuckLanguage.java:37)
        at com.oracle.truffle.api.TruffleLanguage$ParsingRequest.parse(TruffleLanguage.java:833)
        at com.oracle.truffle.api.TruffleLanguage.parse(TruffleLanguage.java:1420)
        at com.oracle.truffle.api.LanguageAccessor$LanguageImpl.parse(LanguageAccessor.java:241)
        at com.oracle.truffle.polyglot.PolyglotSourceCache.parseImpl(PolyglotSourceCache.java:92)
        at com.oracle.truffle.polyglot.PolyglotSourceCache.parseCached(PolyglotSourceCache.java:73)
        at com.oracle.truffle.polyglot.PolyglotLanguageContext.parseCached(PolyglotLanguageContext.java:323)
        at com.oracle.truffle.polyglot.PolyglotContextImpl.eval(PolyglotContextImpl.java:851)
        at org.graalvm.polyglot.Context.eval(Context.java:345)
        at HelloPolyglot.main(HelloPolyglot.java:12)

Maybe 14kk vertexes is a little bit too much :)

asm0dey commented 4 years ago

And it failed!

Exception in thread "main" org.graalvm.polyglot.PolyglotException: java.lang.ArrayIndexOutOfBoundsException: 200777
        at it.mulders.brainfuckjvm.ast.BFCommandNode.getSlot(BFCommandNode.java:132)
        at it.mulders.brainfuckjvm.ast.BFCommandNode.getCurrentByte(BFCommandNode.java:136)
        at it.mulders.brainfuckjvm.ast.BFIncrementByteNode.execute(BFIncrementByteNode.java:16)
        at it.mulders.brainfuckjvm.ast.BFJumpNode.executeChildren(BFJumpNode.java:57)
        at it.mulders.brainfuckjvm.ast.BFJumpNode.execute(BFJumpNode.java:39)
        at it.mulders.brainfuckjvm.ast.BFJumpNode.executeChildren(BFJumpNode.java:57)
        at it.mulders.brainfuckjvm.ast.BFJumpNode.execute(BFJumpNode.java:39)
        at it.mulders.brainfuckjvm.ast.BFJumpNode.executeChildren(BFJumpNode.java:57)
        at it.mulders.brainfuckjvm.ast.BFJumpNode.execute(BFJumpNode.java:39)
        at it.mulders.brainfuckjvm.ast.BFJumpNode.executeChildren(BFJumpNode.java:57)
        at it.mulders.brainfuckjvm.ast.BFJumpNode.execute(BFJumpNode.java:39)
        at it.mulders.brainfuckjvm.ast.BFJumpNode.executeChildren(BFJumpNode.java:57)
        at it.mulders.brainfuckjvm.ast.BFJumpNode.execute(BFJumpNode.java:39)
        at it.mulders.brainfuckjvm.ast.BFRootNode.execute(BFRootNode.java:57)
        at <bf> null(Unknown)
        at org.graalvm.polyglot.Context.eval(Context.java:345)
        at HelloPolyglot.main(HelloPolyglot.java:12)
Original Internal Error: 
java.lang.ArrayIndexOutOfBoundsException: 200777
        at it.mulders.brainfuckjvm.ast.BFCommandNode.getSlot(BFCommandNode.java:132)
        at it.mulders.brainfuckjvm.ast.BFCommandNode.getCurrentByte(BFCommandNode.java:136)
        at it.mulders.brainfuckjvm.ast.BFIncrementByteNode.execute(BFIncrementByteNode.java:16)
        at it.mulders.brainfuckjvm.ast.BFJumpNode.executeChildren(BFJumpNode.java:57)
        at it.mulders.brainfuckjvm.ast.BFJumpNode.execute(BFJumpNode.java:39)
        at it.mulders.brainfuckjvm.ast.BFJumpNode.executeChildren(BFJumpNode.java:57)
        at it.mulders.brainfuckjvm.ast.BFJumpNode.execute(BFJumpNode.java:39)
        at it.mulders.brainfuckjvm.ast.BFJumpNode.executeChildren(BFJumpNode.java:57)
        at it.mulders.brainfuckjvm.ast.BFJumpNode.execute(BFJumpNode.java:39)
        at it.mulders.brainfuckjvm.ast.BFJumpNode.executeChildren(BFJumpNode.java:57)
        at it.mulders.brainfuckjvm.ast.BFJumpNode.execute(BFJumpNode.java:39)
        at it.mulders.brainfuckjvm.ast.BFJumpNode.executeChildren(BFJumpNode.java:57)
        at it.mulders.brainfuckjvm.ast.BFJumpNode.execute(BFJumpNode.java:39)
        at it.mulders.brainfuckjvm.ast.BFRootNode.execute(BFRootNode.java:57)
        at org.graalvm.compiler.truffle.runtime.OptimizedCallTarget.executeRootNode(OptimizedCallTarget.java:505)
        at org.graalvm.compiler.truffle.runtime.OptimizedCallTarget.profiledPERoot(OptimizedCallTarget.java:482)
        at org.graalvm.compiler.truffle.runtime.OptimizedCallTarget.callBoundary(OptimizedCallTarget.java:448)
        at org.graalvm.compiler.truffle.runtime.OptimizedCallTarget.doInvoke(OptimizedCallTarget.java:432)
        at org.graalvm.compiler.truffle.runtime.OptimizedCallTarget.callIndirect(OptimizedCallTarget.java:360)
        at org.graalvm.compiler.truffle.runtime.OptimizedCallTarget.call(OptimizedCallTarget.java:350)
        at com.oracle.truffle.polyglot.PolyglotContextImpl.eval(PolyglotContextImpl.java:852)
        at org.graalvm.polyglot.Context.eval(Context.java:345)
        at HelloPolyglot.main(HelloPolyglot.java:12)
Caused by: Attached Guest Language Frames (1)
mthmulders commented 4 years ago

Wow, how much memory does your program need? From the stacktrace, it seems your program is trying to access position 200777...

If you don't configure it, the default memory size will be 30.000 but you can override it with -Dbf.mem.size=250000 (or any value of your choice). Unfortunately, the wrapper script doesn't (yet) accept it from the command line.

asm0dey commented 4 years ago

It's my first day of programming in bf so I'm not sure about memory requirements :)

BTW dotfile takes more then 700M :)

mthmulders commented 4 years ago

It's my first day of programming in bf so I'm not sure about memory requirements :)

There is no formal memory requirement. According to Wikipedia, implementations typically have an array of at least 30,000 byte cells initialized to zero. That's why I chose that value - but after #61 you should be able to pass that value as a command line argument:

$ bf -Dbf.mem.size=10 language/src/test/resources/hello.bf
#  Works

$ bf -Dbf.mem.size=1 language/src/test/resources/hello.bf
# fails because the Hello World program needs more than one byte of memory to work

BTW dotfile takes more then 700M :)

That's really impressive... I'm hesitant to run your program since I simply can't tell what it does and/or whether it'll blow up my machine ;-)

asm0dey commented 4 years ago

It's n-queens for N=4 :) I've generated it with ELVM from

#include <stdio.h>
#define MAXN 31

int nqueens(int n)
{
  int q0,q1;
  int cols[MAXN], diagl[MAXN], diagr[MAXN], posibs[MAXN]; // Our backtracking 'stack' 
  int num=0;
  //
  // The top level is two fors, to save one bit of symmetry in the enumeration by forcing second queen to
  // be AFTER the first queen.
  //
  for (q0=0; q0<n-2; q0++) {
    for (q1=q0+2; q1<n; q1++){
      int bit0 = 1<<q0;
      int bit1 = 1<<q1;
      int d=0; // d is our depth in the backtrack stack 
      cols[0] = bit0 | bit1 | (-1<<n); // The -1 here is used to fill all 'coloumn' bits after n ...
      diagl[0]= (bit0<<1 | bit1)<<1;
      diagr[0]= (bit0>>1 | bit1)>>1;

      //  The variable posib contains the bitmask of possibilities we still have to try in a given row ...
      int posib = ~(cols[0] | diagl[0] | diagr[0]);

      while (d >= 0) {
        while(posib) {
          int bit = posib & -posib; // The standard trick for getting the rightmost bit in the mask
          int ncols= cols[d] | bit;
          int ndiagl = (diagl[d] | bit) << 1;
          int ndiagr = (diagr[d] | bit) >> 1;
          int nposib = ~(ncols | ndiagl | ndiagr);
          posib^=bit; // Eliminate the tried possibility.

          // The following is the main additional trick here, as recognizing solution can not be done using stack level (d),
          // since we save the depth+backtrack time at the end of the enumeration loop. However by noticing all coloumns are
          // filled (comparison to -1) we know a solution was reached ...
          // Notice also that avoiding an if on the ncols==-1 comparison is more efficient!
          num += ncols==-1; 

          if (nposib) {
            if (posib) { // This if saves stack depth + backtrack operations when we passed the last possibility in a row.
              posibs[d++] = posib; // Go lower in stack ..
            }
            cols[d] = ncols;
            diagl[d] = ndiagl;
            diagr[d] = ndiagr;
            posib = nposib;
          }
        }
        posib = posibs[--d]; // backtrack ...
      }
    }
  }
  return num*2;
}

main(int ac , char **av) 
{

  int n = 4;

  printf("Number of solution for %d is %d\n",n,nqueens(n));
}