external-call.scm 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. ; -*- Mode: Scheme; Syntax: Scheme; Package: Scheme; -*-
  2. ; Copyright (c) 1993-2008 by Richard Kelsey and Jonathan Rees. See file COPYING.
  3. ; Calling C procedures.
  4. ; The arguments have been pushed on the stack after the procedure.
  5. ; *stack* = procedure name arg1 ... argN rest-list N+1 total-nargs
  6. ;
  7. ; The procedure must be an external binding whose value is a pointer-sized
  8. ; code-vector. If it is, we actually do the call.
  9. ;
  10. ; The REMOVE-CURRENT-FRAME call pops all of our values off of the stack.
  11. ; In fact we still use them there for a moment (see s48_external_call() in
  12. ; external.c) but all of the values are fetched from the stack before
  13. ; anything new is pushed on.
  14. (define-primitive call-external-value ()
  15. (lambda ()
  16. (let* ((nargs (extract-fixnum (pop)))
  17. (stack-nargs (extract-fixnum (pop)))
  18. (rest-list (pop)))
  19. (if (< maximum-external-call-args
  20. (- nargs 2)) ; procedure & name
  21. (raise-exception too-many-arguments-to-external-procedure
  22. 0
  23. (stack-ref (- stack-nargs 1))
  24. nargs)
  25. (begin
  26. (do ((rest-list rest-list (vm-cdr rest-list)))
  27. ((vm-eq? rest-list null))
  28. (push (vm-car rest-list)))
  29. (let ((proc (stack-ref (- nargs 1)))
  30. (name (stack-ref (- nargs 2)))
  31. (args (pointer-to-stack-arguments)))
  32. (if (and (vm-string? name)
  33. (code-vector? proc)
  34. (= (code-vector-length proc)
  35. (cells->bytes 1)))
  36. (begin
  37. (remove-current-frame)
  38. (let ((result (external-call proc name (- nargs 2) args)))
  39. (cond (*external-exception?*
  40. (set! *external-exception?* #f)
  41. (goto raise *external-exception-nargs*))
  42. (else
  43. (goto continue-with-value result 0)))))
  44. (raise-exception wrong-type-argument 0 proc name))))))))
  45. ;----------------
  46. ; Raising exceptions from C.
  47. ; True if the C procedure is raising an exception instead of doing a normal
  48. ; return.
  49. (define *external-exception?* #f)
  50. ; The number of arguments being passed to the exception handler.
  51. (define *external-exception-nargs*)
  52. ; These are for exceptions raised by external code. They work pretty
  53. ; much in the same way as other VM instructions raise exceptions.
  54. ; Note that this doesn't actually perform the raise; it just sets
  55. ; *EXTERNAL-EXCEPTION?* to be true, so that the EXTERNAL-CALL procedure
  56. ; will do the raise.
  57. ;
  58. ; If you extend the maximum number of arguments, be sure to adjust the
  59. ; definition of STACK-SLACK in stack.scm. It needs to know the maximum
  60. ; number of values pushed by an exception handler, which is the number
  61. ; of arguments pushed here, plus the procedure.
  62. (define (s48-setup-external-exception why nargs)
  63. (push-exception-setup! why 1) ; 1 = one-byte instruction
  64. (if (< 10 nargs)
  65. (error "too many arguments from external exception"))
  66. (set! *external-exception-nargs* nargs)
  67. (set! *external-exception?* #t))
  68. ; The external code needs to piggyback an exception on top of one already
  69. ; being raised. We increase the argument count and return the old exception.
  70. (define (s48-resetup-external-exception new-why additional-nargs)
  71. (let* ((old-nargs *external-exception-nargs*)
  72. (old-why (stack-ref old-nargs)))
  73. (stack-set! old-nargs (enter-fixnum new-why))
  74. (set! *external-exception-nargs* (+ old-nargs additional-nargs))
  75. old-why))
  76. ; Shared bindings
  77. (define-primitive find-undefined-imported-bindings ()
  78. (lambda ()
  79. (let loop ((first? #t))
  80. (let ((vector (s48-gather-objects shared-binding-undefined?
  81. for-each-imported-binding)))
  82. (cond ((not (false? vector))
  83. (goto return vector))
  84. (first?
  85. ;; if the result vector couldn't be created force a
  86. ;; major collection and try again once.
  87. (s48-collect #t)
  88. (loop #f))
  89. (else
  90. (raise-exception heap-overflow 0)))))))
  91. (define-consing-primitive lookup-shared-binding (string-> boolean->)
  92. (lambda (ignore)
  93. shared-binding-size)
  94. (lambda (name is-import? key)
  95. (goto return
  96. (if is-import?
  97. (lookup-imported-binding name key)
  98. (lookup-exported-binding name key)))))
  99. (define-primitive undefine-shared-binding (string-> boolean->)
  100. (lambda (name is-import?)
  101. (undefine-shared-binding! (if is-import?
  102. (s48-imported-bindings)
  103. (s48-exported-bindings))
  104. name)
  105. (goto continue 0)))