Skip to content
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

[JVM] Java limit for method code size can be hit by defining large hashes #727

Open
usev6 opened this issue Jun 12, 2021 · 1 comment
Open
Labels

Comments

@usev6
Copy link
Contributor

usev6 commented Jun 12, 2021

In rakudo/rakudo#4397 an unexpected error showed up: Java's limit of 65535 bytes for the code length of methods is hit, if a hash with many entries is defined.

The error can be provoked by just defining a hash with 2244 entries, like so:

$ ## define function that creates a nqp::hash with a given number of entries 
$ create_hash () { name=$1; elems=$2; echo "my \$$name := nqp::hash("; for ((i=0; i<$elems; i++)); do echo "'key$i',$i,"; done; echo ');'; }
$ { create_hash foo 2243; } > test.nqp; ./nqp-j test.nqp  ## 2243 entries are still ok
$ { create_hash foo 2244; } > test.nqp; ./nqp-j test.nqp  ## 2244 entries hit the limit
java.lang.ClassFormatError: Invalid method Code length 65536 in class file 826811A4E482E077B970F459C3BCF17E44B6DD8E
  in jvm (gen/jvm/stage2/NQPHLL.nqp:101)
  in execute_stage (gen/jvm/stage2/NQPHLL.nqp:1481)
  in run (gen/jvm/stage2/NQPHLL.nqp:1519)
  in <anon> (gen/jvm/stage2/NQPHLL.nqp:1522)
  in compile (gen/jvm/stage2/NQPHLL.nqp:1514)
  in eval (gen/jvm/stage2/NQPHLL.nqp:1186)
  in evalfiles (gen/jvm/stage2/NQPHLL.nqp:1460)
  in command_eval (gen/jvm/stage2/NQPHLL.nqp:1350)
  in command_line (gen/jvm/stage2/NQPHLL.nqp:1309)
  in MAIN (gen/jvm/stage2/NQP.nqp:4183)
  in <mainline> (gen/jvm/stage2/NQP.nqp:4179)
  in <anon> (gen/jvm/stage2/NQP.nqp)
$ { create_hash foo 2245; } > test.nqp; ./nqp-j test.nqp  ## even more entries give a different error (very likely a secondary problem)
java.lang.NoClassDefFoundError: org/objectweb/asm/tree/MethodNode
  in classfile (gen/jvm/stage2/NQPHLL.nqp:92)
  in execute_stage (gen/jvm/stage2/NQPHLL.nqp:1481)
  in run (gen/jvm/stage2/NQPHLL.nqp:1519)
  in <anon> (gen/jvm/stage2/NQPHLL.nqp:1522)
  in compile (gen/jvm/stage2/NQPHLL.nqp:1514)
  in eval (gen/jvm/stage2/NQPHLL.nqp:1186)
  in evalfiles (gen/jvm/stage2/NQPHLL.nqp:1460)
  in command_eval (gen/jvm/stage2/NQPHLL.nqp:1350)
  in command_line (gen/jvm/stage2/NQPHLL.nqp:1309)
  in MAIN (gen/jvm/stage2/NQP.nqp:4183)
  in <mainline> (gen/jvm/stage2/NQP.nqp:4179)
  in <anon> (gen/jvm/stage2/NQP.nqp)

Splitting the date into two smaller hashes does not help:

$ { create_hash foo 1122; create_hash bar 1122; } > test.nqp; ./nqp-j test.nqp
java.lang.NoClassDefFoundError: org/objectweb/asm/tree/MethodNode
  in classfile (gen/jvm/stage2/NQPHLL.nqp:92)
  in execute_stage (gen/jvm/stage2/NQPHLL.nqp:1481)
  in run (gen/jvm/stage2/NQPHLL.nqp:1519)
  in <anon> (gen/jvm/stage2/NQPHLL.nqp:1522)
  in compile (gen/jvm/stage2/NQPHLL.nqp:1514)
  in eval (gen/jvm/stage2/NQPHLL.nqp:1186)
  in evalfiles (gen/jvm/stage2/NQPHLL.nqp:1460)
  in command_eval (gen/jvm/stage2/NQPHLL.nqp:1350)
  in command_line (gen/jvm/stage2/NQPHLL.nqp:1309)
  in MAIN (gen/jvm/stage2/NQP.nqp:4183)
  in <mainline> (gen/jvm/stage2/NQP.nqp:4179)
  in <anon> (gen/jvm/stage2/NQP.nqp)
$ { create_hash foo 1121; create_hash bar 1121; } > test.nqp; ./nqp-j test.nqp  ## works fine
$

Actually, it's not just entries in the hashes, that leads to the error -- other code could contribute as well.
But since the error first showed up with a large hash, I sticked to that example.

This all makes sense, since we compile the code to java bytecode. I'm not sure of the details -- e.g. what exactly will be compiled as a Java method, though.

@usev6
Copy link
Contributor Author

usev6 commented Jun 12, 2021

Btw, rakudo-j doesn't seem to be affected:

$ { echo 'use nqp;'; create_hash foo 25000; } > test.nqp; ~/bin/rakudo.jvm/bin/rakudo-j test.nqp
$

It blows up with Class file too large! for larger values, though:

$ { echo 'use nqp;'; create_hash foo 50000; } > test.nqp; ~/bin/rakudo.jvm/bin/rakudo-j test.nqp
===SORRY!===
java.lang.RuntimeException: java.lang.RuntimeException: Class file too large!

@usev6 usev6 added the JVM label Jun 14, 2021
raydiak added a commit to raydiak/roast that referenced this issue Jun 23, 2021
This functionality could not be easily implemented for JVM due to
Raku/nqp#727
Altai-man pushed a commit to Raku/roast that referenced this issue Jul 24, 2021
This functionality could not be easily implemented for JVM due to
Raku/nqp#727
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant