Skip to content

Commit 6ab3e4c

Browse files
committed
Unify numeric semantics around longs, with throw on overflow. Allow numeric literals to be primitive initializers. Canonicalize boxing of integers, if it fits in int, is Integer, else Long, thus primitive coercions can't be used to get particular boxed types, use Long/valueOf etc. Ask for BigIntegers if you want arbitrary precision, new literal number format - append 'N' for BigInteger. BigIntegers do not reduce automatically, are contagious. New particular names for unchecked ops - unchecked-xxx-int or unchecked-xxx-long. You should need far fewer hints for primitive perf, and avoid int casts and any casting of numeric literals, see:
http://gist.github.com/440102
1 parent 8fbafa9 commit 6ab3e4c

File tree

9 files changed

+1075
-900
lines changed

9 files changed

+1075
-900
lines changed

src/clj/clojure/core.clj

Lines changed: 98 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -970,61 +970,117 @@
970970
:added "1.0"}
971971
[x] (. clojure.lang.Numbers (dec x)))
972972

973-
(defn unchecked-inc
974-
"Returns a number one greater than x, an int or long.
973+
(defn unchecked-inc-int
974+
"Returns a number one greater than x, an int.
975975
Note - uses a primitive operator subject to overflow."
976-
{:inline (fn [x] `(. clojure.lang.Numbers (unchecked_inc ~x)))
976+
{:inline (fn [x] `(. clojure.lang.Numbers (unchecked_int_inc ~x)))
977977
:added "1.0"}
978-
[x] (. clojure.lang.Numbers (unchecked_inc x)))
978+
[x] (. clojure.lang.Numbers (unchecked_int_inc x)))
979979

980-
(defn unchecked-dec
981-
"Returns a number one less than x, an int or long.
980+
(defn unchecked-inc-long
981+
"Returns a number one greater than x, a long.
982982
Note - uses a primitive operator subject to overflow."
983-
{:inline (fn [x] `(. clojure.lang.Numbers (unchecked_dec ~x)))
983+
{:inline (fn [x] `(. clojure.lang.Numbers (unchecked_long_inc ~x)))
984984
:added "1.0"}
985-
[x] (. clojure.lang.Numbers (unchecked_dec x)))
985+
[x] (. clojure.lang.Numbers (unchecked_long_inc x)))
986986

987-
(defn unchecked-negate
988-
"Returns the negation of x, an int or long.
987+
(defn unchecked-dec-int
988+
"Returns a number one less than x, an int.
989989
Note - uses a primitive operator subject to overflow."
990-
{:inline (fn [x] `(. clojure.lang.Numbers (unchecked_negate ~x)))
990+
{:inline (fn [x] `(. clojure.lang.Numbers (unchecked_int_dec ~x)))
991991
:added "1.0"}
992-
[x] (. clojure.lang.Numbers (unchecked_negate x)))
992+
[x] (. clojure.lang.Numbers (unchecked_int_dec x)))
993993

994-
(defn unchecked-add
995-
"Returns the sum of x and y, both int or long.
994+
(defn unchecked-dec-long
995+
"Returns a number one less than x, a long.
996996
Note - uses a primitive operator subject to overflow."
997-
{:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_add ~x ~y)))
997+
{:inline (fn [x] `(. clojure.lang.Numbers (unchecked_long_dec ~x)))
998998
:added "1.0"}
999-
[x y] (. clojure.lang.Numbers (unchecked_add x y)))
999+
[x] (. clojure.lang.Numbers (unchecked_long_dec x)))
10001000

1001-
(defn unchecked-subtract
1002-
"Returns the difference of x and y, both int or long.
1001+
(defn unchecked-negate-int
1002+
"Returns the negation of x, an int.
10031003
Note - uses a primitive operator subject to overflow."
1004-
{:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_subtract ~x ~y)))
1004+
{:inline (fn [x] `(. clojure.lang.Numbers (unchecked_int_negate ~x)))
10051005
:added "1.0"}
1006-
[x y] (. clojure.lang.Numbers (unchecked_subtract x y)))
1006+
[x] (. clojure.lang.Numbers (unchecked_int_negate x)))
10071007

1008-
(defn unchecked-multiply
1009-
"Returns the product of x and y, both int or long.
1008+
(defn unchecked-negate-long
1009+
"Returns the negation of x, a long.
10101010
Note - uses a primitive operator subject to overflow."
1011-
{:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_multiply ~x ~y)))
1011+
{:inline (fn [x] `(. clojure.lang.Numbers (unchecked_long_negate ~x)))
10121012
:added "1.0"}
1013-
[x y] (. clojure.lang.Numbers (unchecked_multiply x y)))
1013+
[x] (. clojure.lang.Numbers (unchecked_long_negate x)))
10141014

1015-
(defn unchecked-divide
1016-
"Returns the division of x by y, both int or long.
1015+
(defn unchecked-add-int
1016+
"Returns the sum of x and y, both int.
1017+
Note - uses a primitive operator subject to overflow."
1018+
{:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_int_add ~x ~y)))
1019+
:added "1.0"}
1020+
[x y] (. clojure.lang.Numbers (unchecked_int_add x y)))
1021+
1022+
(defn unchecked-add-long
1023+
"Returns the sum of x and y, both long.
1024+
Note - uses a primitive operator subject to overflow."
1025+
{:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_long_add ~x ~y)))
1026+
:added "1.0"}
1027+
[x y] (. clojure.lang.Numbers (unchecked_long_add x y)))
1028+
1029+
(defn unchecked-subtract-int
1030+
"Returns the difference of x and y, both int.
1031+
Note - uses a primitive operator subject to overflow."
1032+
{:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_int_subtract ~x ~y)))
1033+
:added "1.0"}
1034+
[x y] (. clojure.lang.Numbers (unchecked_int_subtract x y)))
1035+
1036+
(defn unchecked-subtract-long
1037+
"Returns the difference of x and y, both long.
1038+
Note - uses a primitive operator subject to overflow."
1039+
{:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_long_subtract ~x ~y)))
1040+
:added "1.0"}
1041+
[x y] (. clojure.lang.Numbers (unchecked_long_subtract x y)))
1042+
1043+
(defn unchecked-multiply-int
1044+
"Returns the product of x and y, both int.
1045+
Note - uses a primitive operator subject to overflow."
1046+
{:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_int_multiply ~x ~y)))
1047+
:added "1.0"}
1048+
[x y] (. clojure.lang.Numbers (unchecked_int_multiply x y)))
1049+
1050+
(defn unchecked-multiply-long
1051+
"Returns the product of x and y, both long.
1052+
Note - uses a primitive operator subject to overflow."
1053+
{:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_long_multiply ~x ~y)))
1054+
:added "1.0"}
1055+
[x y] (. clojure.lang.Numbers (unchecked_long_multiply x y)))
1056+
1057+
(defn unchecked-divide-int
1058+
"Returns the division of x by y, both int.
1059+
Note - uses a primitive operator subject to truncation."
1060+
{:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_int_divide ~x ~y)))
1061+
:added "1.0"}
1062+
[x y] (. clojure.lang.Numbers (unchecked_int_divide x y)))
1063+
1064+
(defn unchecked-divide-long
1065+
"Returns the division of x by y, both long.
1066+
Note - uses a primitive operator subject to truncation."
1067+
{:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_long_divide ~x ~y)))
1068+
:added "1.0"}
1069+
[x y] (. clojure.lang.Numbers (unchecked_long_divide x y)))
1070+
1071+
(defn unchecked-remainder-int
1072+
"Returns the remainder of division of x by y, both int.
10171073
Note - uses a primitive operator subject to truncation."
1018-
{:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_divide ~x ~y)))
1074+
{:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_int_remainder ~x ~y)))
10191075
:added "1.0"}
1020-
[x y] (. clojure.lang.Numbers (unchecked_divide x y)))
1076+
[x y] (. clojure.lang.Numbers (unchecked_int_remainder x y)))
10211077

1022-
(defn unchecked-remainder
1023-
"Returns the remainder of division of x by y, both int or long.
1078+
(defn unchecked-remainder-long
1079+
"Returns the remainder of division of x by y, both long.
10241080
Note - uses a primitive operator subject to truncation."
1025-
{:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_remainder ~x ~y)))
1081+
{:inline (fn [x y] `(. clojure.lang.Numbers (unchecked_long_remainder ~x ~y)))
10261082
:added "1.0"}
1027-
[x y] (. clojure.lang.Numbers (unchecked_remainder x y)))
1083+
[x y] (. clojure.lang.Numbers (unchecked_long_remainder x y)))
10281084

10291085
(defn pos?
10301086
"Returns true if num is greater than zero, else false"
@@ -2183,11 +2239,11 @@
21832239
[bindings & body]
21842240
(let [i (first bindings)
21852241
n (second bindings)]
2186-
`(let [n# (int ~n)]
2242+
`(let [n# ~n]
21872243
(loop [~i (int 0)]
21882244
(when (< ~i n#)
21892245
~@body
2190-
(recur (inc ~i)))))))
2246+
(recur (unchecked-inc-long ~i)))))))
21912247

21922248
(defn map
21932249
"Returns a lazy sequence consisting of the result of applying f to the
@@ -2553,17 +2609,17 @@
25532609
{:tag 'clojure.lang.IChunk})
25542610
count- (gensym "count_")
25552611
i- (gensym "i_")
2556-
recform `(recur (next ~seq-) nil (int 0) (int 0))
2612+
recform `(recur (next ~seq-) nil 0 0)
25572613
steppair (step recform (nnext exprs))
25582614
needrec (steppair 0)
25592615
subform (steppair 1)
25602616
recform-chunk
2561-
`(recur ~seq- ~chunk- ~count- (unchecked-inc ~i-))
2617+
`(recur ~seq- ~chunk- ~count- (unchecked-inc-long ~i-))
25622618
steppair-chunk (step recform-chunk (nnext exprs))
25632619
subform-chunk (steppair-chunk 1)]
25642620
[true
25652621
`(loop [~seq- (seq ~v), ~chunk- nil,
2566-
~count- (int 0), ~i- (int 0)]
2622+
~count- 0, ~i- 0]
25672623
(if (< ~i- ~count-)
25682624
(let [~k (.nth ~chunk- ~i-)]
25692625
~subform-chunk
@@ -2660,11 +2716,11 @@
26602716
(= 2 (count bindings)) "exactly 2 forms in binding vector")
26612717
(let [i (first bindings)
26622718
n (second bindings)]
2663-
`(let [n# (int ~n)]
2664-
(loop [~i (int 0)]
2719+
`(let [n# ~n]
2720+
(loop [~i 0]
26652721
(when (< ~i n#)
26662722
~@body
2667-
(recur (unchecked-inc ~i)))))))
2723+
(recur (unchecked-inc-long ~i)))))))
26682724

26692725
#_(defn into
26702726
"Returns a new coll consisting of to-coll with all of the items of
@@ -3849,12 +3905,12 @@
38493905
(= k :when) `(if ~v
38503906
~(do-cmod etc)
38513907
(recur
3852-
(unchecked-inc ~gi)))
3908+
(unchecked-inc-long ~gi)))
38533909
(keyword? k)
38543910
(err "Invalid 'for' keyword " k)
38553911
:else
38563912
`(do (chunk-append ~gb ~body-expr)
3857-
(recur (unchecked-inc ~gi)))))]
3913+
(recur (unchecked-inc-long ~gi)))))]
38583914
`(fn ~giter [~gxs]
38593915
(lazy-seq
38603916
(loop [~gxs ~gxs]

src/clj/clojure/genclass.clj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -299,22 +299,22 @@
299299
(arg-types (count ptypes)))))
300300
;expecting [[super-ctor-args] state] returned
301301
(. gen dup)
302-
(. gen push 0)
302+
(. gen push (int 0))
303303
(. gen (invokeStatic rt-type nth-method))
304304
(. gen storeLocal local)
305305

306306
(. gen (loadThis))
307307
(. gen dupX1)
308308
(dotimes [i (count super-pclasses)]
309309
(. gen loadLocal local)
310-
(. gen push i)
310+
(. gen push (int i))
311311
(. gen (invokeStatic rt-type nth-method))
312312
(. clojure.lang.Compiler$HostExpr (emitUnboxArg nil gen (nth super-pclasses i))))
313313
(. gen (invokeConstructor super-type super-m))
314314

315315
(if state
316316
(do
317-
(. gen push 1)
317+
(. gen push (int 1))
318318
(. gen (invokeStatic rt-type nth-method))
319319
(. gen (putField ctype state-name obj-type)))
320320
(. gen pop))

src/clj/clojure/gvec.clj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,11 @@
6262
(if (< aidx (count vec))
6363
(let [node (.arrayFor vec aidx)
6464
result (loop [result result
65-
node-idx (bit-and (int 0x1f) aidx)]
65+
node-idx (bit-and 0x1f aidx)]
6666
(if (< node-idx (.alength am node))
6767
(recur (f result (.aget am node node-idx)) (inc node-idx))
6868
result))]
69-
(recur result (bit-and (int 0xffe0) (+ aidx (int 32)))))
69+
(recur result (bit-and 0xffe0 (+ aidx 32))))
7070
result)))
7171

7272
clojure.lang.ISeq
@@ -141,7 +141,7 @@
141141
(if (= i cnt)
142142
hash
143143
(let [val (.nth this i)]
144-
(recur (unchecked-add (unchecked-multiply (int 31) hash)
144+
(recur (unchecked-add-int (unchecked-multiply-int 31 hash)
145145
(clojure.lang.Util/hash val))
146146
(inc i))))))
147147

0 commit comments

Comments
 (0)