Skip to content

Commit 75eee35

Browse files
[debug] Use Java method for injecting breakpoint instrumentation
1 parent aa2859f commit 75eee35

File tree

3 files changed

+36
-1
lines changed

3 files changed

+36
-1
lines changed

project.clj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
:filespecs [{:type :bytes :path "cider/cider-nrepl/project.clj" :bytes ~(slurp "project.clj")}]
5353

5454
:source-paths ["src"]
55+
:java-source-paths ["src"]
5556
:resource-paths ["resources"]
5657
:test-paths ["test/clj" "test/cljs" "test/common"]
5758

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package cider.nrepl.middleware;
2+
3+
import clojure.lang.*;
4+
5+
/**
6+
* Contains instrumentation helpers for cider.nrepl.middleware.debug. The main
7+
* purpose of having these helpers in Java is reducing the instrumentation
8+
* footprint (measured in bytecode size). Invoking Java methods usually takes
9+
* fewer bytecode instructions than a corresponding Clojure function. Java also
10+
* allows us to have primitive overrides which further reduces overhead when
11+
* instrumenting code that contains primitives, but also preserves type hints
12+
* (so instrumented code behaves closer to original code).
13+
*
14+
* The reason we care about bytecode size is 65KB method limit that JVM imposes.
15+
*/
16+
public class DebugSupport {
17+
18+
private static volatile IFn breakFn = null;
19+
20+
public static Object doBreak(Object coor, Object val, Object locals, Object STATE__) {
21+
if (breakFn == null)
22+
breakFn = (IFn)RT.var("cider.nrepl.middleware.debug", "break");
23+
return breakFn.invoke(coor, val, locals, STATE__);
24+
}
25+
26+
public static long doBreak(Object coor, long val, Object locals, Object STATE__) {
27+
return (long)doBreak(coor, Numbers.num(val), locals, STATE__);
28+
}
29+
30+
public static double doBreak(Object coor, double val, Object locals, Object STATE__) {
31+
return (double)doBreak(coor, Numbers.num(val), locals, STATE__);
32+
}
33+
}

src/cider/nrepl/middleware/debug.clj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
[orchard.print]
1616
[orchard.stacktrace :as stacktrace])
1717
(:import
18+
(cider.nrepl.middleware DebugSupport)
1819
(clojure.lang Compiler$LocalBinding)
1920
(java.util UUID)))
2021

@@ -557,7 +558,7 @@ this map (identified by a key), and will `dissoc` it afterwards."}
557558
;; Keep original forms in a separate atom to save some code
558559
;; size. Unfortunately same trick wouldn't work for locals.
559560
(swap! *tmp-forms* assoc coor original-form)
560-
`(break ~coor ~val-form ~locals ~'STATE__)))
561+
`(DebugSupport/doBreak ~coor ~val-form ~locals ~'STATE__)))
561562

562563
(def irrelevant-return-value-forms
563564
"Set of special-forms whose return value we don't care about.

0 commit comments

Comments
 (0)