Skip to content

A JVM bytecode generator for ASTs compatible with tools.analyzer(.jvm)

License

Notifications You must be signed in to change notification settings

clojure/tools.emitter.jvm

Repository files navigation

tools.emitter.jvm

A JVM bytecode generator for ASTs compatible with tools.analyzer[.jvm].

When trying out tools.emitter.jvm be careful not to include in your project.clj's :dependencies a different version of tools.analyzer.jvm or tools.analyzer than the one required by tools.emitter.jvm otherwise the library probably won't work and trying to evaluate clojure forms with it will likely produce errors.

Example Usage

user=> (require '[clojure.tools.emitter.jvm :as e])
nil
user=> (e/eval '(+ 1 2))
3
user=> (e/eval '(+ 1 2) {:debug? true})
// class version 50.0 (50)
// access flags 0x31
public final class user$fn__6242 extends clojure/lang/AFunction  implements clojure/lang/IFn$L  {

  // compiled from: user$fn__6242

  // access flags 0x9
  public static <clinit>()V
    RETURN
    MAXSTACK = 0
    MAXLOCALS = 0

  // access flags 0x1
  public <init>()V
    ALOAD 0
    INVOKESPECIAL clojure/lang/AFunction.<init> ()V
    RETURN
    MAXSTACK = 1
    MAXLOCALS = 1

  // access flags 0x1
  public invokePrim()J
   L0
    LINENUMBER 1 L0
    LCONST_1
    LDC 2
    ACONST_NULL
    ASTORE 0
    INVOKESTATIC clojure/lang/Numbers.add (JJ)J
    LRETURN
    LOCALVARIABLE this Lclojure/lang/AFunction; L0 L0 0
    MAXSTACK = 5
    MAXLOCALS = 1

  // access flags 0x1
  public invoke()Ljava/lang/Object;
    ALOAD 0
    INVOKEVIRTUAL user$fn__6242.invokePrim ()J
    INVOKESTATIC clojure/lang/RT.box (J)Ljava/lang/Number;
    ARETURN
    MAXSTACK = 2
    MAXLOCALS = 1
}
3
user=> (e/load "clojure.pprint")
nil
user=> (clojure.pprint/pprint 1)
1

Differences From Clojure

While the bytecode produced by tools.emitter.jvm is similar to the one produces by Clojure itself, there are some differences:

  • tools.emitter.jvm is capable of clearing locals closed over by loops, in the loop exit path
  • tools.emitter.jvm clears the "this" local before the last tail call in a method, see CLJ-1250
  • tools.emitter.jvm clears unused locals after their creation
  • tools.emitter.jvm hoists loop and try bodies into separate methods rather than wrapping them in a fn, see CLJ-701
  • tools.emitter.jvm emits keyword invoke callsites only when the keyword is not namespaces, see CLJ-1469
  • tools.emitter.jvm emits typed bytecode, enforcing any explicit tag, this breaks some functions in clojure.core like ns-interns. This behaviour might be reconsidered in the future.
  • tools.emitter.jvm handles CLJ-1330

Performances

clojure.tools.emitter.jvm/eval is currently between 5x and 8x slower than clojure.core/eval

SPONSORSHIP

YourKit

YourKit has given an open source license for their profiler, greatly simplifying the profiling of tools.emitter.jvm performance.

YourKit is kindly supporting open source projects with its full-featured Java Profiler. YourKit, LLC is the creator of innovative and intelligent tools for profiling Java and .NET applications. Take a look at YourKit's leading software products:

Releases and Dependency Information

Latest stable release: 0.1.0-beta5

Leiningen dependency information:

[org.clojure/tools.emitter.jvm "0.1.0-beta5"]

Maven dependency information:

<dependency>
  <groupId>org.clojure</groupId>
  <artifactId>tools.emitter.jvm</artifactId>
  <version>0.1.0-beta5</version>
</dependency>

API Index

Developer Information

License

Copyright © 2013-2023 Nicola Mometto, Rich Hickey & contributors.

Distributed under the Eclipse Public License, the same as Clojure.

About

A JVM bytecode generator for ASTs compatible with tools.analyzer(.jvm)

Resources

License

Stars

Watchers

Forks

Packages

No packages published