Skip to content

Instantly share code, notes, and snippets.

@morj
Last active September 19, 2019 19:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save morj/53516068abd49e14a2ed7874df20bc3e to your computer and use it in GitHub Desktop.
Save morj/53516068abd49e14a2ed7874df20bc3e to your computer and use it in GitHub Desktop.
(def bootstrap-invoke
'(fn
[^java.lang.invoke.MethodHandles$Lookup caller
^String methodName
^java.lang.invoke.MethodType methodType
^String varName]
(do
(when (nil? huj.SampleNS/var_x_var)
(set! huj.SampleNS/var_x_var
(clojure.lang.Var. huj.SampleNS/ns (clojure.lang.Symbol/intern varName))))
(when (nil? huj.SampleNS/var_x_invoke_fallback_mh)
(set! huj.SampleNS/var_x_invoke_fallback_mh
(.findVirtual caller clojure.lang.Var "invoke" methodType)))
(cond
huj.SampleNS/var_x_invalid
(java.lang.invoke.ConstantCallSite. huj.SampleNS/var_x_invoke_fallback_mh)
(identical? huj.SampleNS/var_x_value huj.SampleNS/UNBOUND)
(java.lang.invoke.ConstantCallSite. huj.SampleNS/var_x_invoke_fallback_mh)
(some? huj.SampleNS/var_x_invoke_mh)
(java.lang.invoke.ConstantCallSite. huj.SampleNS/var_x_invoke_mh)
:else
(do
(when (nil? huj.SampleNS/var_x_switchPoint)
(set! huj.SampleNS/var_x_switchPoint
(java.lang.invoke.SwitchPoint.)))
(if (identical? huj.SampleNS/var_x_value huj.SampleNS/UNINITIALIZED_FN)
(java.lang.invoke.ConstantCallSite.
(.guardWithTest huj.SampleNS/var_x_switchPoint
(.findStatic caller huj.MyLambda "invokeStatic" methodType)
huj.SampleNS/var_x_invoke_fallback_mh))
(java.lang.invoke.ConstantCallSite.
(.guardWithTest huj.SampleNS/var_x_switchPoint
(.bindTo
(.findVirtual caller clojure.lang.IFn "invoke" methodType) huj.SampleNS/var_x_value)
huj.SampleNS/var_x_invoke_fallback_mh))))))))
(def loader-test
(res (list clojure.tools.emitter.temp/bootstrap-invoke) cl))
(def class-name (:class-name (first (:bytecode loader-test))))
; bytecode for "dispatch" method
(def boot-up {:op :method,
:attr #{:public :static},
:method [:bootstrap-dispatch
[java.lang.invoke.MethodHandles$Lookup
java.lang.String
java.lang.invoke.MethodType
java.lang.String]
java.lang.invoke.CallSite],
:code
[[:start-method]
[:load-arg 0]
[:load-arg 1]
[:load-arg 2]
[:load-arg 3]
[:push "x"]
; start repeat
[:jump-insn :IF_ACMPEQ :after-x-label]
[:invoke-static
"class-name/bootstrap-invoke-x"
[java.lang.invoke.MethodHandles$Lookup
java.lang.String
java.lang.invoke.MethodType
java.lang.String]
java.lang.invoke.CallSite]
[:mark :after-x-label]
; end repeat
[:new-instance "java.lang.IllegalArgumentException"]
[:dup]
[:invoke-constructor
[:java.lang.IllegalArgumentException/<init>]
:void]
[:check-cast java.lang.Throwable]
[:throw-exception]
[:insn :ACONST_NULL]
[:mark :label__8230]
[:mark :label__8227]
[:return-value]
[:end-method]]})
(clojure.pprint/pprint
(map
(fn [m]
(let [[[method-name & other] return] (:method m)]
(cond
(= :invoke method-name)
(conj
(update m :code
(fn [code]
(map
(fn [instruction]
(replace
{class-name "class-name",
"x" "var-name",
huj.SampleNS "class-name"
"huj.MyLambda" "lambda-name"}
instruction))
code)))
{:method [:bootstrap-invoke ; add x to method name
[java.lang.invoke.MethodHandles$Lookup
java.lang.String
java.lang.invoke.MethodType
java.lang.String]
java.lang.invoke.CallSite]})
(= :<clinit> method-name)
(update m :code
(fn [code]
(map
(fn [instruction]
(replace
{class-name "class-name",
huj.SampleNS "class-name"
"huj.MyLambda" "lambda-name"}
instruction))
code))))))
(:methods (first (:bytecode loader-test)))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment