transport.scm 9.9 KB

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