Skip to content

Commit 4f46d46

Browse files
committed
improve reflection
1 parent 9c6aae4 commit 4f46d46

File tree

3 files changed

+23
-19
lines changed

3 files changed

+23
-19
lines changed

src/sci/impl/analyzer.cljc

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,10 +1052,21 @@
10521052
args arg-count)
10531053
stack))))
10541054
(let [arg-count #?(:cljs nil :clj (count args))
1055-
args (object-array args)]
1055+
args (object-array args)
1056+
#?@(:clj [^"[Ljava.lang.Class;" arg-types (when (and (pos? arg-count))
1057+
(make-array Class arg-count))
1058+
has-types? (volatile! nil)])]
1059+
#?(:clj (when arg-types
1060+
(areduce args idx _ret nil
1061+
(when-let [t (:tag-class (meta (aget args idx)))]
1062+
(vreset! has-types? true)
1063+
(aset arg-types idx t)))))
10561064
(with-meta (sci.impl.types/->Node
10571065
(eval/eval-instance-method-invocation
1058-
ctx bindings instance-expr meth-name field-access args arg-count)
1066+
ctx bindings instance-expr meth-name field-access args arg-count
1067+
#?(:cljs nil
1068+
:clj (when @has-types?
1069+
arg-types)))
10591070
stack)
10601071
{::instance-expr instance-expr
10611072
::method-name method-name})))
@@ -1077,7 +1088,7 @@
10771088
(do
10781089
(sci.impl.types/->Node
10791090
(eval/eval-instance-method-invocation
1080-
ctx bindings instance-expr meth-name field-access args allowed? nil)
1091+
ctx bindings instance-expr meth-name field-access args allowed? nil nil)
10811092
stack)))
10821093
{::instance-expr instance-expr
10831094
::method-name method-name}))))]
@@ -1609,7 +1620,7 @@
16091620
(let [obj (sci.impl.types/eval obj ctx bindings)]
16101621
(interop/invoke-instance-method ctx bindings obj clazz
16111622
meth
1612-
children child-count))
1623+
children child-count nil))
16131624
stack))])
16141625
#?@(:clj [(and f-meta (:sci.impl.analyzer/invoke-constructor f-meta))
16151626
(invoke-constructor-node ctx (first f) (rest expr))])

src/sci/impl/evaluator.cljc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@
108108
#?(:cljs
109109
(defn allowed-instance-method-invocation [ctx bindings instance-expr method-str args arg-count]
110110
(let [instance-expr* (types/eval instance-expr ctx bindings)]
111-
(interop/invoke-instance-method ctx bindings instance-expr* nil method-str args arg-count))))
111+
(interop/invoke-instance-method ctx bindings instance-expr* nil method-str args arg-count nil))))
112112

113113
#?(:cljs
114114
(defn allowed-instance-field-invocation [ctx bindings instance-expr method-str]
@@ -127,7 +127,7 @@
127127
none-sentinel))
128128

129129
(defn eval-instance-method-invocation
130-
[ctx bindings instance-expr method-str field-access args #?(:cljs allowed) arg-count]
130+
[ctx bindings instance-expr method-str field-access args #?(:cljs allowed) arg-count arg-types]
131131
(let [instance-meta (meta instance-expr)
132132
tag-class (:tag-class instance-meta)
133133
instance-expr* (types/eval instance-expr ctx bindings)
@@ -154,7 +154,7 @@
154154
(throw-error-with-location (str "Method " method-str " on " instance-class " not allowed!") instance-expr))
155155
(if field-access
156156
(interop/invoke-instance-field instance-expr* target-class method-str)
157-
(interop/invoke-instance-method ctx bindings instance-expr* target-class method-str args arg-count))))))
157+
(interop/invoke-instance-method ctx bindings instance-expr* target-class method-str args arg-count arg-types))))))
158158

159159
;;;; End interop
160160

src/sci/impl/interop.cljc

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,33 +35,26 @@
3535
meths)))))
3636

3737
(defn invoke-instance-method
38-
#?@(:cljs [[ctx bindings obj _target-class method-name args _arg-count]
38+
#?@(:cljs [[ctx bindings obj _target-class method-name args _arg-count _arg-types]
3939
;; gobject/get didn't work here
4040
(if-some [method (aget obj method-name)]
4141
;; use Reflect rather than (.apply method ...), see https://github.com/babashka/nbb/issues/118
4242
(let [args (.map args #(sci.impl.types/eval % ctx bindings))]
4343
(js/Reflect.apply method obj args))
4444
(throw (js/Error. (str "Could not find instance method: " method-name))))]
4545
:clj
46-
[[ctx bindings obj ^Class target-class method ^objects args arg-count]
46+
[[ctx bindings obj ^Class target-class method ^objects args arg-count arg-types]
4747
(let [^java.util.List methods
4848
(meth-cache ctx target-class method arg-count #(Reflector/getMethods target-class arg-count method false) :instance-methods)
4949
zero-args? (zero? arg-count)]
5050
(if (and zero-args? (.isEmpty ^java.util.List methods))
5151
(invoke-instance-field obj target-class method)
52-
(do (let [args-array (object-array arg-count)
53-
;; TODO: this can all be done at analysis time
54-
^"[Ljava.lang.Class;" types-array (when (and (not zero-args?)
55-
(> (.size methods) 1))
56-
(make-array Class arg-count))]
52+
(do (let [args-array (object-array arg-count)]
5753
(areduce args idx _ret nil
58-
(do (aset args-array idx (sci.impl.types/eval (aget args idx) ctx bindings))
59-
(when types-array
60-
(when-let [t (:tag-class (meta (aget args idx)))]
61-
(aset types-array idx t)))))
54+
(aset args-array idx (sci.impl.types/eval (aget args idx) ctx bindings)))
6255
;; Note: I also tried caching the method that invokeMatchingMethod looks up, but retrieving it from the cache was actually more expensive than just doing the invocation!
6356
;; See getMatchingMethod in Reflector
64-
(Reflector/invokeMatchingMethod method methods target-class obj args-array types-array)))))]))
57+
(Reflector/invokeMatchingMethod method methods target-class obj args-array arg-types)))))]))
6558

6659
(defn get-static-field [^Class class field-name-sym]
6760
#?(:clj (Reflector/getStaticField class (str field-name-sym))

0 commit comments

Comments
 (0)