use local def for cljs inline cache. faster and enables bootstrap compatibility

This commit is contained in:
Nathan Marz 2016-05-28 20:01:10 -04:00
parent bb5fcbe7b3
commit e5db7252c3
2 changed files with 36 additions and 27 deletions

View file

@ -41,6 +41,8 @@
(defn do-macroexpand-all [form] (defn do-macroexpand-all [form]
(riddley/macroexpand-all form)) (riddley/macroexpand-all form))
;;this is not a secure way to generate uuids  the `path` implementation
;;for cljs uses an alternative strategy
#+cljs #+cljs
(defn gen-uuid-str [] (defn gen-uuid-str []
(apply str (repeatedly 50 #(rand-int 9))) (apply str (repeatedly 50 #(rand-int 9)))
@ -723,12 +725,8 @@
params-maker ; can be null params-maker ; can be null
]) ])
(defonce PATH-CACHE #+clj
#+clj (java.util.concurrent.ConcurrentHashMap.) (defonce PATH-CACHE (java.util.concurrent.ConcurrentHashMap.))
;;TODO: according to @dnolen, can forgo this for instead doing
;;inline defs at runtime
#+cljs (atom {})
)
(def MUST-CACHE-PATHS (mutable-cell false)) (def MUST-CACHE-PATHS (mutable-cell false))
@ -744,14 +742,6 @@
(defn get-path-cache [^String k] (defn get-path-cache [^String k]
(.get ^java.util.concurrent.ConcurrentHashMap PATH-CACHE k)) (.get ^java.util.concurrent.ConcurrentHashMap PATH-CACHE k))
#+cljs
(defn add-path-cache! [k v]
(swap! PATH-CACHE (fn [m] (assoc m k v))))
#+cljs
(defn get-path-cache [k]
(get @PATH-CACHE k))
(defn- extract-original-code [p] (defn- extract-original-code [p]
(cond (cond
(instance? LocalSym p) (:sym p) (instance? LocalSym p) (:sym p)

View file

@ -414,7 +414,12 @@
))) )))
;; still possible to mess this up with alter-var-root ;; still possible to mess this up with alter-var-root
(defmacro path [& path] ; "inline cache" (defmacro path
"Same as calling comp-paths, except it caches the composition of the static part
of the path for later re-use (when possible). For almost all idiomatic uses
of Specter provides huge speedup. This macro is automatically used by the
select/transform/setval/replace-in/etc. macros."
[& path]
(let [;;this is a hack, but the composition of &env is considered stable for cljs (let [;;this is a hack, but the composition of &env is considered stable for cljs
platform (if (contains? &env :locals) :cljs :clj) platform (if (contains? &env :locals) :cljs :clj)
local-syms (if (= platform :cljs) local-syms (if (= platform :cljs)
@ -439,7 +444,18 @@
;; - with invokedynamic here, could go directly to the code ;; - with invokedynamic here, could go directly to the code
;; to invoke and/or parameterize the precompiled path without ;; to invoke and/or parameterize the precompiled path without
;; a bunch of checks beforehand ;; a bunch of checks beforehand
cache-id (i/gen-uuid-str) cache-id (i/gen-uuid-str) ;; used for clj
cache-sym (gensym "pathcache") ;; used for cljs
info-sym (gensym "info")
get-cache-code (if (= platform :clj)
`(i/get-path-cache ~cache-id)
cache-sym
)
add-cache-code (if (= platform :clj)
`(i/add-path-cache! ~cache-id ~info-sym)
`(def ~cache-sym ~info-sym))
precompiled-sym (gensym "precompiled") precompiled-sym (gensym "precompiled")
params-maker-sym (gensym "params-maker") params-maker-sym (gensym "params-maker")
@ -453,20 +469,23 @@
~(mapv (fn [p] `(fn [] ~p)) possible-params) ~(mapv (fn [p] `(fn [] ~p)) possible-params)
)) ))
] ]
`(let [info# (i/get-path-cache ~cache-id) `(let [;;TODO: for cljs, use the dynamic def strategy + exists for a direct
;; inline cache
info# ~get-cache-code
^com.rpl.specter.impl.CachedPathInfo info# ^com.rpl.specter.impl.CachedPathInfo info#
(if (nil? info#) (if (nil? info#)
(let [info# (i/magic-precompilation (let [~info-sym (i/magic-precompilation
~prepared-path ~prepared-path
~(str *ns*) ~(str *ns*)
(quote ~used-locals) (quote ~used-locals)
;;possible-params is wrong atm ;;possible-params is wrong atm
;;as is used-locals in cljs... ;;as is used-locals in cljs...
(quote ~possible-params) (quote ~possible-params)
)] )]
(i/add-path-cache! ~cache-id info#) ~add-cache-code
info# ~info-sym
) )
info# info#
) )