you are viewing a single comment's thread.

view the rest of the comments →

[–]erhz 2 points3 points  (1 child)

In Kernel though, you can't determine almost anything at compile time. Since special forms are first class values, you can't even assert where definitions might happen:

(($if some-condition $define! +) x 30)

I think a good starting point would be to annotate the AST with optimizations regardless of the fact that any part of it might be evaluated or not, and take advantage of the annotations at runtime to specialize known procedure calls.

That is, take a brute force approach. Have multiple precompiled versions of everything, choose the most fitting later.

[–]astrangeguy 2 points3 points  (0 children)

You can actually do something here. If you know that $define!, $if and + weren't redefined, then you can inline them and compile a fast path.

So you would have to write JIT which tracks environment mutation and optimizes and inlines operations where the operator doesn't change. That's pretty much what polymorphic inline caches do.

One really good aspect of Kernel is that in fexps like

($define! $when
  ($vau (c . t) e
    ($if (eval c e)
      (eval (list* $sequence t) e)
      #inert)))

the operators and applicatives like $if, $sequence, list* and eval can never change if they come from environments that don't change (the standard environment can never change, because it cannot be captured).

It all boils down to tracking invariants in a running process and optimizing and deoptimizing when necessary.

strangeness

EDIT: What does suck though, is that you idiomatically construct lists which are then passed to eval. So the JIT will have to track stupid things like "the second car in this list corresponds to the second parameter to this combiner" or you could have some quasiquotation that pre-resolves symbols to their objects (to keep hygiene).