graalvm

Discuss GraalVM related topics. Use clojure 1.10.2 or newer for all new projects. Contribute to https://github.com/clj-easy/graal-docs and https://github.com/BrunoBonacci/graalvm-clojure. GraalVM slack: https://www.graalvm.org/slack-invitation/.
borkdude 2020-07-20T12:55:24.071900Z

I'm getting the locking issue while compiling a library (datalevin) with GraalVM native-image. Haven't dug deeply into this yet. Could be that some AOT-ed thing is left on the classpath that brings in the old locking stuff, but the source which occurs in the error output is not AOT-ed I believe: https://github.com/borkdude/datalevin-native

borkdude 2020-07-20T13:04:25.072400Z

Hmm, I believe this repros it:

(defprotocol IFoo
  (store [_]))

(deftype Foo [^:volatile-mutable ^long max-gt]
  IFoo
  (store [_]
    (locking max-gt
      (println "Stored!"))))

(defn -main [& _args]
  (let [foo (Foo. 10)]
    (store foo))

borkdude 2020-07-20T13:04:53.072600Z

Error: unbalanced monitors: mismatch at monitorexit, 7|Invoke#Numbers.num != 52|Invoke#Numbers.num
Detailed message:
Call path from entry point to borkdude.datalevin_native.main.Foo.store():
	at borkdude.datalevin_native.main.Foo.store(main.clj:14)

borkdude 2020-07-20T13:05:47.073300Z

I'll make a dedicated repro repo in a few hours, and I'll add some comment to CLJ-1472 (cc @alexmiller)

borkdude 2020-07-20T13:09:54.073800Z

Aha! When I remove the ^long type hint, then it compiles:

(defprotocol IFoo
  (store [_]))

(deftype Foo [^long max-gt]
  IFoo
  (store [_]
    (locking max-gt
      (println "Stored!"))))

(defn -main [& _args]
  (let [foo (Foo. 10)]
    (store foo)))

alexmiller 2020-07-20T13:11:16.074100Z

just file a new ticket

alexmiller 2020-07-20T13:11:24.074300Z

and link to CLJ-1472

alexmiller 2020-07-20T13:12:10.074600Z

wait, you can't lock on a primitive long - it has to be an object

alexmiller 2020-07-20T13:12:17.074800Z

that code doesn't make sense

borkdude 2020-07-20T13:12:43.075100Z

yeah, I figured the same. it comes from here: https://github.com/juji-io/datalevin/blob/0588dde496b18ced06fed036db3f969c35c69ef8/src/datalevin/storage.clj#L226

alexmiller 2020-07-20T13:13:09.075500Z

yeah, that's bad

borkdude 2020-07-20T13:14:07.075900Z

so it does not work, but it doesn't fail in the JVM either?

alexmiller 2020-07-20T13:25:40.077300Z

my guess would be that in some cases the primitive long is getting up cast. that's the only way it could work (but locking on a Long value is still a bad idea). this code is just wrong.

alexmiller 2020-07-20T13:27:09.078500Z

the Java numeric value objects can be cached around 0 and that means the scope of your Long sharing can escape your own code (similarly, you should never lock on a String instance which might be interned)

borkdude 2020-07-20T13:28:17.078900Z

:thumbsup: I'll make an issue with this conversation in their repo

alexmiller 2020-07-20T13:29:24.079200Z

it's best to make an explicit lock Object

borkdude 2020-07-20T13:31:53.079400Z

https://github.com/juji-io/datalevin/issues/5