Skip to content

Commit

Permalink
implementors of IFn now get direct invoke implementations, add (vector
Browse files Browse the repository at this point in the history
0) benchmark, ~2X faster under V8.
  • Loading branch information
swannodette committed Oct 18, 2013
1 parent a191acc commit 95447d1
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 9 deletions.
1 change: 1 addition & 0 deletions benchmark/cljs/benchmark_runner.cljs
Expand Up @@ -56,6 +56,7 @@
(simple-benchmark [coll [1 2 3]] (nth coll 0) 1000000)
(simple-benchmark [coll [1 2 3]] (-nth coll 0) 1000000)
(simple-benchmark [coll [1 2 3]] (-nth ^not-native coll 0) 1000000)
(simple-benchmark [coll [1 2 3]] (coll 0) 1000000)
(simple-benchmark [coll [1 2 3]] (conj coll 4) 1000000)
(simple-benchmark [coll [1 2 3]] (-conj coll 4) 1000000)
(simple-benchmark [coll [1 2 3]] (seq coll) 1000000)
Expand Down
36 changes: 27 additions & 9 deletions src/clj/cljs/core.clj
Expand Up @@ -658,6 +658,12 @@
(let [~this ~self-sym]
~@body)))))

;; for IFn invoke implementations, we need to drop first arg
(defn adapt-ifn-invoke-params [type [[this & args :as sig] & body]]
`(~(vec args)
(this-as ~(vary-meta this assoc :tag type)
~@body)))

(defn adapt-proto-params [type [[this & args :as sig] & body]]
`(~(vec (cons (vary-meta this assoc :tag type) args))
(this-as ~this
Expand All @@ -669,18 +675,30 @@
~(with-meta `(fn ~@(map #(adapt-obj-params type %) meths)) (meta form))))
sigs))

(defn ifn-invoke-methods [type-sym meths]
(map
(fn [meth]
(let [arity (count (first meth))]
`(set! ~(prototype-prefix type-sym
(symbol (core/str "cljs$core$IFn$_invoke$arity$" arity)))
(fn ~meth))))
meths))

(defn add-ifn-methods [type type-sym [f & meths :as form]]
(let [meths (map #(adapt-ifn-params type %) meths)
(let [meths' (map #(adapt-ifn-params type %) meths)
this-sym (with-meta 'self__ {:tag type})
argsym (gensym "args")]
[`(set! ~(prototype-prefix type-sym 'call) ~(with-meta `(fn ~@meths) (meta form)))
`(set! ~(prototype-prefix type-sym 'apply)
~(with-meta
`(fn ~[this-sym argsym]
(this-as ~this-sym
(.apply (.-call ~this-sym) ~this-sym
(.concat (array ~this-sym) (aclone ~argsym)))))
(meta form)))]))
(concat
[`(set! ~(prototype-prefix type-sym 'call) ~(with-meta `(fn ~@meths') (meta form)))
`(set! ~(prototype-prefix type-sym 'apply)
~(with-meta
`(fn ~[this-sym argsym]
(this-as ~this-sym
(.apply (.-call ~this-sym) ~this-sym
(.concat (array ~this-sym) (aclone ~argsym)))))
(meta form)))]
(ifn-invoke-methods type-sym
(map #(adapt-ifn-invoke-params type %) meths)))))

(defn add-proto-methods* [pprefix type type-sym [f & meths :as form]]
(let [pf (core/str pprefix f)]
Expand Down

0 comments on commit 95447d1

Please sign in to comment.