transport.scm 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: Richard Kelsey, Jonathan Rees, Mike Sperber, Marcus Crestani
  3. ; This is file transport.scm.
  4. ; System builder for bootstrapping and debugging.
  5. ; Things that have to be written out:
  6. ; Made by the compiler
  7. ; closures
  8. ; templates
  9. ; code-vectors
  10. ; locations
  11. ; Quoted data
  12. ; symbols
  13. ; pairs
  14. ; vectors
  15. ; strings
  16. ; booleans
  17. ; characters
  18. ; Convert THING to the Scheme 48 virtual machine's representation and
  19. ; return it. Locations and symbols may have multiple references in
  20. ; the image. Their transported addresses are kept in a table.
  21. (define (transport thing . stuff)
  22. (let transport ((thing thing))
  23. (cond ((immediate? thing)
  24. (transport-immediate thing))
  25. ((closure? thing)
  26. (transport-closure thing))
  27. ((code-vector? thing)
  28. (allocate-b-vector thing code-vector-length))
  29. ((location? thing)
  30. (let ((address (table-ref *locations* thing)))
  31. (cond (address address)
  32. (else
  33. (let ((desc (transport-location thing)))
  34. (table-set! *locations* thing desc)
  35. desc)))))
  36. ((symbol? thing)
  37. (let ((address (table-ref *symbols* thing)))
  38. (cond (address address)
  39. (else
  40. (let ((desc (transport-symbol thing)))
  41. (table-set! *symbols* thing desc)
  42. desc)))))
  43. ((pair? thing)
  44. (transport-pair thing))
  45. ((template? thing)
  46. (transport-template thing))
  47. ((vector? thing)
  48. (transport-vector thing))
  49. ((string? thing)
  50. (transport-string thing))
  51. (else
  52. (assertion-violation 'transport
  53. "cannot transport object" thing stuff))))) ; DELETEME stuff
  54. ; Transport the things that are not allocated from the heap.
  55. (define (transport-immediate thing)
  56. (cond ((integer? thing)
  57. (make-descriptor (enum tag fixnum) thing))
  58. ((char? thing)
  59. (make-immediate (enum imm char) (char->ascii thing)))
  60. ((eq? thing '())
  61. vm-null)
  62. ((eq? thing #f)
  63. vm-false)
  64. ((eq? thing #t)
  65. vm-true)
  66. ((eq? thing (unspecific))
  67. vm-unspecific)
  68. (else
  69. (assertion-violation 'transport-immediate "cannot transport literal" thing))))
  70. ;==============================================================================
  71. ; The heap is a list of transported stored objects, each of which is either a
  72. ; string, a code-vector, or a vector of length N+1 representing a stored object
  73. ; with N cells. The last slot of the vector is the object's header.
  74. (define *heap* '())
  75. (define *hp* 0) ; Current heap-pointer (in a-units)
  76. (define *symbols* #f) ; Table of already-transported symbols
  77. (define *locations* #f) ; Table of already-transported locations
  78. ; We need to preserve sharing of vectors because `syntax-rules' relies on it.
  79. (define *vector-alist* #f) ; Table of already-transported vectors
  80. (define (initialize-memory)
  81. (set! *hp* 0)
  82. (set! *heap* '())
  83. (set! *symbols* (make-table))
  84. (set! *locations* (make-table location-id))
  85. (set! *vector-alist* '()))
  86. ; Allocate a new stored object in the heap. DATA is whatever data is
  87. ; associated with the object, LEN is the length of the object (not
  88. ; including the header) in bytes. A pointer to the new object is
  89. ; returned.
  90. (define (allocate-stob data len)
  91. (let ((addr (+ *hp* (cells->a-units 1)))) ; move past header
  92. (set! *hp* (+ addr (bytes->a-units len)))
  93. (set! *heap* (cons data *heap*))
  94. (make-stob-descriptor addr)))
  95. ; Allocate a new stored object that contains descriptors. This
  96. ; creates a vector to hold the header and the object's tranported
  97. ; contents and allocates a stob in the heap. Returns a pair
  98. ; containing the stob-pointer and the vector.
  99. (define (allocate-d-vector type cells immutable?)
  100. (let* ((vec (make-vector (+ cells 1) 0))
  101. (ptr (allocate-stob vec (cells->bytes cells)))
  102. (hdr (make-header type (cells->bytes cells))))
  103. (vector-set! vec cells (if immutable? (make-header-immutable hdr) hdr))
  104. (cons ptr vec)))
  105. ; Allocate a new stored object that contains data. VEC is either a
  106. ; code-vector or a string.
  107. (define (allocate-b-vector vec length)
  108. (let ((len (cells->bytes (bytes->cells (length vec)))))
  109. (allocate-stob vec len)))
  110. ;==============================================================================
  111. ; Transport an object with two slots. ALLOCATE-D-VECTOR allocates the
  112. ; storage and then the two values are transported.
  113. (define (transport-two-slot type accessor1 offset1 accessor2 offset2
  114. immutable?)
  115. (lambda (thing)
  116. (let* ((data (allocate-d-vector type 2 immutable?))
  117. (descriptor (car data))
  118. (vector (cdr data)))
  119. (vector-set! vector offset1 (transport (accessor1 thing)))
  120. (vector-set! vector offset2 (transport (accessor2 thing)))
  121. descriptor)))
  122. ; Closures and pairs are transported using TRANSPORT-TWO-SLOT.
  123. (define transport-closure
  124. (transport-two-slot (enum stob closure)
  125. closure-template closure-template-offset
  126. closure-env closure-env-offset
  127. #f))
  128. (define transport-pair
  129. (transport-two-slot (enum stob pair)
  130. car car-offset
  131. cdr cdr-offset
  132. #t)) ; *** ?
  133. ; Transporting a location requires some care so as to avoid calling CONTENTS
  134. ; when the location is unbound.
  135. (define (transport-location loc)
  136. (let* ((data (allocate-d-vector (enum stob location) 2 #f))
  137. (descriptor (car data))
  138. (vector (cdr data)))
  139. (vector-set! vector
  140. location-contents-offset
  141. (if (location-defined? loc)
  142. (transport (contents loc))
  143. vm-unbound))
  144. (vector-set! vector
  145. location-id-offset
  146. (transport (location-id loc)))
  147. descriptor))
  148. ; The characters on the linker system may not be the same as those of Scheme 48
  149. (define (transport-string string)
  150. (allocate-b-vector string
  151. (lambda (x)
  152. (scalar-value-units->bytes (string-length x)))))
  153. ; Symbols have two slots, the string containing the symbol's name and a slot
  154. ; used in building the symbol table.
  155. ; Characters in the symbol name are made to be lower case.
  156. (define (transport-symbol symbol)
  157. (let* ((data (allocate-d-vector (enum stob symbol) 2 #t))
  158. (descriptor (car data))
  159. (vector (cdr data)))
  160. (vector-set! vector
  161. 0
  162. (transport-string (symbol-case-converter (symbol->string symbol))))
  163. (vector-set! vector
  164. 1
  165. (transport #f))
  166. descriptor))
  167. (define (string-case-converter string)
  168. (let ((new (make-string (string-length string) #\x)))
  169. (do ((i 0 (+ i 1)))
  170. ((>= i (string-length new))
  171. new)
  172. (string-set! new i (preferred-case (string-ref string i))))))
  173. ;(define preferred-case ;Copied from rts/read.scm
  174. ; (if (char=? (string-ref (symbol->string 't) 0) #\T)
  175. ; char-upcase
  176. ; char-downcase))
  177. (define preferred-case char-downcase)
  178. (define symbol-case-converter
  179. (if (char=? (string-ref (symbol->string 't) 0)
  180. (preferred-case #\t))
  181. (lambda (string) string)
  182. string-case-converter))
  183. ; Templates and vectors have an arbitrary number of slots but are otherwise
  184. ; the same as pairs and closures.
  185. (define (transport-template template)
  186. (transport-vector-like template
  187. (enum stob template)
  188. (template-length template)
  189. template-ref
  190. #f))
  191. (define (transport-vector vector)
  192. (transport-vector-like vector
  193. (enum stob vector)
  194. (vector-length vector)
  195. vector-ref
  196. #t)) ;***
  197. (define (transport-vector-like vector type length ref immutable?)
  198. (cond
  199. ((assq vector *vector-alist*)
  200. => cdr)
  201. (else
  202. (let* ((data (allocate-d-vector type length immutable?))
  203. (descriptor (car data))
  204. (new (cdr data)))
  205. (do ((i 0 (+ i 1)))
  206. ((>= i length))
  207. (vector-set! new i (transport (ref vector i) vector type)))
  208. (set! *vector-alist* (cons (cons vector descriptor) *vector-alist*))
  209. descriptor))))
  210. ;==============================================================================
  211. ; Writing the heap out to a port.
  212. (define (write-heap port)
  213. (do ((heap (reverse *heap*) (cdr heap)))
  214. ((null? heap))
  215. (write-heap-stob (car heap) port)))
  216. ; Dispatch on the type of THING and call WRITE-STOB.
  217. (define (write-heap-stob thing port)
  218. (cond ((string? thing)
  219. (let* ((len (string-length thing))
  220. (byte-len (scalar-value-units->bytes len)))
  221. (write-stob (make-header-immutable ; ***
  222. (make-header (enum stob string) byte-len))
  223. thing len string-ref write-char-scalar-value port)
  224. (align-port byte-len port)))
  225. ((code-vector? thing)
  226. (let ((len (code-vector-length thing)))
  227. (write-stob (make-header-immutable ; ***
  228. (make-header (enum stob byte-vector) len))
  229. thing len code-vector-ref write-byte port)
  230. (align-port len port)))
  231. ((vector? thing)
  232. (let ((len (vector-length thing)))
  233. (write-stob (vector-ref thing (- len 1))
  234. thing (- len 1) vector-ref write-descriptor port)))
  235. (else
  236. (assertion-violation 'write-heap-stob "do not know how to write stob" thing))))
  237. ; Write out a transported STOB to PORT. HEADER is the header, LENGTH is the
  238. ; number of objects the STOB contains, ACCESSOR and WRITER access the contents
  239. ; and write them to the heap.
  240. (define (write-stob header contents length accessor writer port)
  241. (write-descriptor header port)
  242. (do ((i 0 (+ i 1)))
  243. ((>= i length))
  244. (writer (accessor contents i) port)))
  245. (define (write-char-scalar-value char port)
  246. (write-scalar-value (char->ascii char) ; ASCII is a subset of Unicode code points
  247. port))
  248. ; Write out zeros to align the port on a four-byte boundary.
  249. (define (align-port len port)
  250. (let ((count (- (cells->bytes (bytes->cells len)) len)))
  251. (do ((count count (- count 1)))
  252. ((<= count 0))
  253. (write-byte 0 port))))