Arc Forumnew | comments | leaders | submitlogin
3 points by almkglor 5719 days ago | link | parent

We can actually implement hash tables as hidden classes on Arc-on-mzscheme.

Basically calls on the arc side are compiled thusly:

  (fn (bar)
    (foo bar))
   =>
  (lambda (bar)
    (ar-funcall1 __foo bar)) ; the 1 here means there is one argument
Now we only need to perform some kind of let-lifting:

  (let ((callsite1 (ar-funcaller1)))
    (lambda (bar)
      (callsite1 __foo bar)))
where ar-funcaller1 would be:

  ; scheme!!
  (define (ar-funcaller1)
    (lambda (f arg1)
      ;dispatch based on f, argument types, etc.
      ...))
(I've actually already implemented this experimentally, but the performance didn't increase much - however this was before I implemented serious multimethods (which I haven't actually completed implementing anyway...), so I suppose I can bring this back to amortize multimethod lookup.)

By using a callsite lambda object, we can keep track of previous multimethod etc. lookups.

And then we can make the compiler emit code especially for (foo 'bar) forms:

  (fn (foo) foo!bar)
    =>
  (let ((callsite1 (ar-quotecaller1 'bar)))
    (lambda (foo)
      (callsite1 foo)))
callsite1 can then cache lookups on hidden classes.

  (define (always-false . rest) #f)
  (define (ar-quotecaller1 quoted)
    ; use only a single variable to prevent
    ; race conditions in multi-threaded code
    ; (might not always work if using true
    ; threads instead of green ones though)
    (let ((checker-and-dispatch (cons always-false #f)))
      (lambda (ob)
        ; copy to our own local variable to
        ; prevent race conditions (assuming
        ; the read is atomic anyway)
        (let* ((my-checker-and-dispatch checker-and-dispatch)
               (checker (car my-checker-and-dispatch)))
          (if (not (checker ob))
              (begin
                (set! my-checker-and-dispatch
                      (patch-quotecaller1 ob quoted))
                (set! checker-and-dispatch my-checker-and-dispatch)))
          ((cdr my-checker-and-dispatch) ob quoted)))))
  (define (patch-quotecaller1 ob quoted)
    (cond
      ((table-with-hidden-class? ob) ; implemented however you will
        (let* ((hidden-class (hidden-class-get ob))
               (hidden-class-index (hidden-class-index-lookup hidden-class quoted)))
          (cons
            ; checker
            (lambda (ob _)
              (and (table-with-hidden-class? ob)
                   (eq? hidden-class (hidden-class-get ob))))
            ; dispatcher
            (lambda (ob _)
              (hidden-class-ref ob hidden-class-index)))))
      (... ;other conditions: functions, methods, other data types...
        )))

I was actually going to implement this, but then I thought that using arc hash tables as objects - and in particular the (tb 'key) form - wasn't actually that common enough (at least in Arc) to justify optimizing for it. Hmm.