;; lib/jit.sx — SX-level convenience wrappers over the JIT cache control
;; primitives (jit-stats, jit-set-threshold!, jit-set-budget!, jit-reset-cache!,
;; jit-reset-counters!). Host-specific implementations live in
;; hosts/<host>/lib/sx_*.ml; the API surface is portable across hosts.

;; with-jit-threshold — temporarily set the JIT call-count threshold for
;; the duration of body, restoring the previous value on exit. Useful for
;; sections that want eager compilation (threshold=1) or want to skip JIT
;; entirely (threshold=999999) for diagnostic comparison.
(defmacro
  with-jit-threshold
  (n &rest body)
  `(let
     ((__old (get (jit-stats) "threshold")))
     (jit-set-threshold! ,n)
     (let
       ((__r (do ,@body)))
       (jit-set-threshold! __old)
       __r)))

;; with-jit-budget — temporarily set the LRU cache budget. Setting to 0
;; disables JIT entirely (everything falls through to the interpreter);
;; large values are effectively unbounded.
(defmacro
  with-jit-budget
  (n &rest body)
  `(let
     ((__old (get (jit-stats) "budget")))
     (jit-set-budget! ,n)
     (let
       ((__r (do ,@body)))
       (jit-set-budget! __old)
       __r)))

;; with-fresh-jit — clear the cache before body, run body, clear again
;; after. Use between sessions / request batches / test suites where you
;; want deterministic timing free of carryover.
(defmacro
  with-fresh-jit
  (&rest body)
  `(let
     ((__r (do (jit-reset-cache!) ,@body)))
     (jit-reset-cache!)
     __r))

;; jit-report — human-readable summary of current JIT state. Returns a
;; string suitable for logging.
(define
  jit-report
  (fn
    ()
    (let
      ((s (jit-stats)))
      (let
        ((compiled (get s "compiled"))
          (skipped (get s "below-threshold"))
          (failed (get s "compile-failed"))
          (evicted (get s "evicted"))
          (cache-size (get s "cache-size"))
          (budget (get s "budget"))
          (threshold (get s "threshold")))
        (let
          ((total (+ compiled skipped failed)))
          (str
            "jit: " cache-size "/" budget " cached "
            "(thr=" threshold ") · "
            compiled " compiled, "
            skipped " below-thr, "
            failed " failed, "
            evicted " evicted "
            "(" (if (> total 0) (* 100 (/ compiled total)) 0) "% compile rate)"))))))

;; jit-disable! / jit-enable! — convenience helpers. Disabling sets budget
;; to 0 which causes the VM to skip JIT entirely on the next call. Enable
;; restores the budget to its previous value (or 5000 if no previous).
(define _jit-saved-budget (list 5000))

(define
  jit-disable!
  (fn
    ()
    (set! _jit-saved-budget (list (get (jit-stats) "budget")))
    (jit-set-budget! 0)))

(define
  jit-enable!
  (fn
    ()
    (jit-set-budget! (first _jit-saved-budget))))
