cs: cache foriegn call and callable wrappers
Generating the code for a `_fun` type takes hundreds ot thousands of times as long as in the traditional Racket VM, to cache results to reduce the cost.
This commit is contained in:
parent
a1098bdb46
commit
eea40a6350
|
@ -471,12 +471,12 @@
|
||||||
[(types abi alignment)
|
[(types abi alignment)
|
||||||
(let ([make-decls
|
(let ([make-decls
|
||||||
(escapes-ok
|
(escapes-ok
|
||||||
(lambda (id)
|
(lambda (id next!-id)
|
||||||
(let-values ([(reps decls) (types->reps types)])
|
(let-values ([(reps decls) (types->reps types next!-id)])
|
||||||
(append decls
|
(append decls
|
||||||
`((define-ftype ,id
|
`((define-ftype ,id
|
||||||
(struct ,@(map (lambda (rep)
|
(struct ,@(map (lambda (rep)
|
||||||
`[,(gensym) ,rep])
|
`[,(next!-id) ,rep])
|
||||||
reps))))))))])
|
reps))))))))])
|
||||||
(let-values ([(size alignment) (ctypes-sizeof+alignof types alignment)])
|
(let-values ([(size alignment) (ctypes-sizeof+alignof types alignment)])
|
||||||
(create-compound-ctype 'struct
|
(create-compound-ctype 'struct
|
||||||
|
@ -493,12 +493,12 @@
|
||||||
types)
|
types)
|
||||||
(let ([make-decls
|
(let ([make-decls
|
||||||
(escapes-ok
|
(escapes-ok
|
||||||
(lambda (id)
|
(lambda (id next!-id)
|
||||||
(let-values ([(reps decls) (types->reps types)])
|
(let-values ([(reps decls) (types->reps types next!-id)])
|
||||||
(append decls
|
(append decls
|
||||||
`((define-ftype ,id
|
`((define-ftype ,id
|
||||||
(union ,@(map (lambda (rep)
|
(union ,@(map (lambda (rep)
|
||||||
`[,(gensym) ,rep])
|
`[,(next!-id) ,rep])
|
||||||
reps))))))))]
|
reps))))))))]
|
||||||
[size (apply max (map ctype-sizeof types))]
|
[size (apply max (map ctype-sizeof types))]
|
||||||
[alignment (apply max (map ctype-alignof types))])
|
[alignment (apply max (map ctype-alignof types))])
|
||||||
|
@ -516,8 +516,8 @@
|
||||||
(check who exact-nonnegative-integer? count)
|
(check who exact-nonnegative-integer? count)
|
||||||
(let ([make-decls
|
(let ([make-decls
|
||||||
(escapes-ok
|
(escapes-ok
|
||||||
(lambda (id)
|
(lambda (id next!-id)
|
||||||
(let-values ([(reps decls) (types->reps (list type))])
|
(let-values ([(reps decls) (types->reps (list type) next!-id)])
|
||||||
(append decls
|
(append decls
|
||||||
`((define-ftype ,id
|
`((define-ftype ,id
|
||||||
(array ,count ,(car reps))))))))]
|
(array ,count ,(car reps))))))))]
|
||||||
|
@ -1286,6 +1286,10 @@
|
||||||
(define (set-foreign-eval! proc)
|
(define (set-foreign-eval! proc)
|
||||||
(set! eval/foreign proc))
|
(set! eval/foreign proc))
|
||||||
|
|
||||||
|
;; Cache generated code for an underlying foreign call or callable shape:
|
||||||
|
(define ffi-expr->code (make-weak-hash)) ; expr to weak cell of code
|
||||||
|
(define ffi-code->expr (make-weak-eq-hashtable)) ; keep exprs alive as long as code lives
|
||||||
|
|
||||||
(define/who ffi-call
|
(define/who ffi-call
|
||||||
(case-lambda
|
(case-lambda
|
||||||
[(p in-types out-type)
|
[(p in-types out-type)
|
||||||
|
@ -1343,22 +1347,29 @@
|
||||||
(if (eq? host-rep 'array)
|
(if (eq? host-rep 'array)
|
||||||
'void*
|
'void*
|
||||||
host-rep))]
|
host-rep))]
|
||||||
|
[next!-id (let ([counter 0])
|
||||||
|
;; Like `gensym`, but deterministic --- and doesn't
|
||||||
|
;; have to be totally unique, as long as it doesn't
|
||||||
|
;; collide with other code that we generate
|
||||||
|
(lambda ()
|
||||||
|
(set! counter (add1 counter))
|
||||||
|
(string->symbol (string-append "type_" (number->string counter)))))]
|
||||||
[ids (map (lambda (in-type)
|
[ids (map (lambda (in-type)
|
||||||
(and (by-value? in-type)
|
(and (by-value? in-type)
|
||||||
(gensym)))
|
(next!-id)))
|
||||||
in-types)]
|
in-types)]
|
||||||
[ret-id (and (by-value? out-type)
|
[ret-id (and (by-value? out-type)
|
||||||
(gensym))]
|
(next!-id))]
|
||||||
[decls (let loop ([in-types in-types] [ids ids] [decls '()])
|
[decls (let loop ([in-types in-types] [ids ids] [decls '()])
|
||||||
(cond
|
(cond
|
||||||
[(null? in-types) decls]
|
[(null? in-types) decls]
|
||||||
[(car ids)
|
[(car ids)
|
||||||
(let ([id-decls ((compound-ctype-get-decls (car in-types)) (car ids))])
|
(let ([id-decls ((compound-ctype-get-decls (car in-types)) (car ids) next!-id)])
|
||||||
(loop (cdr in-types) (cdr ids) (append decls id-decls)))]
|
(loop (cdr in-types) (cdr ids) (append decls id-decls)))]
|
||||||
[else
|
[else
|
||||||
(loop (cdr in-types) (cdr ids) decls)]))]
|
(loop (cdr in-types) (cdr ids) decls)]))]
|
||||||
[ret-decls (if ret-id
|
[ret-decls (if ret-id
|
||||||
((compound-ctype-get-decls out-type) ret-id)
|
((compound-ctype-get-decls out-type) ret-id next!-id)
|
||||||
'())]
|
'())]
|
||||||
[ret-size (and ret-id (ctype-sizeof out-type))]
|
[ret-size (and ret-id (ctype-sizeof out-type))]
|
||||||
[gen-proc+ret-maker+arg-makers
|
[gen-proc+ret-maker+arg-makers
|
||||||
|
@ -1392,7 +1403,16 @@
|
||||||
(make-ftype-pointer ,id p))))
|
(make-ftype-pointer ,id p))))
|
||||||
ids)
|
ids)
|
||||||
'())))])
|
'())))])
|
||||||
(eval/foreign expr (if call? 'comp-ffi 'comp-ffi-back)))]
|
(let* ([wb (with-interrupts-disabled
|
||||||
|
(weak-hash-ref ffi-expr->code expr #f))]
|
||||||
|
[code (if wb (car wb) #!bwp)])
|
||||||
|
(if (eq? code #!bwp)
|
||||||
|
(let ([code (eval/foreign expr (if call? 'comp-ffi 'comp-ffi-back))])
|
||||||
|
(hashtable-set! ffi-code->expr (car code) expr)
|
||||||
|
(with-interrupts-disabled
|
||||||
|
(weak-hash-set! ffi-expr->code expr (weak-cons code #f)))
|
||||||
|
code)
|
||||||
|
code)))]
|
||||||
[gen-proc (car gen-proc+ret-maker+arg-makers)]
|
[gen-proc (car gen-proc+ret-maker+arg-makers)]
|
||||||
[ret-maker (cadr gen-proc+ret-maker+arg-makers)]
|
[ret-maker (cadr gen-proc+ret-maker+arg-makers)]
|
||||||
[arg-makers (cddr gen-proc+ret-maker+arg-makers)]
|
[arg-makers (cddr gen-proc+ret-maker+arg-makers)]
|
||||||
|
@ -1480,15 +1500,15 @@
|
||||||
[(void*) (cpointer-address v)]
|
[(void*) (cpointer-address v)]
|
||||||
[else v]))))))])))
|
[else v]))))))])))
|
||||||
|
|
||||||
(define (types->reps types)
|
(define (types->reps types next!-id)
|
||||||
(let loop ([types types] [reps '()] [decls '()])
|
(let loop ([types types] [reps '()] [decls '()])
|
||||||
(cond
|
(cond
|
||||||
[(null? types) (values (reverse reps) decls)]
|
[(null? types) (values (reverse reps) decls)]
|
||||||
[else
|
[else
|
||||||
(let ([type (car types)])
|
(let ([type (car types)])
|
||||||
(if (compound-ctype? type)
|
(if (compound-ctype? type)
|
||||||
(let* ([id (gensym)]
|
(let* ([id (next!-id)]
|
||||||
[id-decls ((compound-ctype-get-decls type) id)])
|
[id-decls ((compound-ctype-get-decls type) id next!-id)])
|
||||||
(loop (cdr types) (cons id reps) (append id-decls decls)))
|
(loop (cdr types) (cons id reps) (append id-decls decls)))
|
||||||
(loop (cdr types) (cons (ctype-host-rep type) reps) decls)))])))
|
(loop (cdr types) (cons (ctype-host-rep type) reps) decls)))])))
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user