A JVM bytecode generator for ASTs compatible with tools.analyzer(.jvm)
Clojure HTML
Latest commit 24288e5 Dec 14, 2016 @puredanger puredanger committed on GitHub Update parent pom version
Permalink
Failed to load latest commit information.
src remove dead code Nov 30, 2015
.gitignore init Oct 4, 2013
CHANGELOG.md Update README, pom.xml, Changelog Aug 9, 2014
CONTRIBUTING.md add CONTRIBUGING.md Mar 31, 2014
README.md update README, project.clj Apr 28, 2015
epl.html init Oct 4, 2013
pom.xml Update parent pom version Dec 13, 2016
project.clj bump deps Mar 24, 2016

README.md

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>

Changelog

API Index

Developer Information

License

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

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