read-image-portable.scm 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: David Frese, Mike Sperber, Norbert Freudemann
  3. ;; Image reader that works for both GCs
  4. ;; Local Values of the temporary heap-image-object (to read in the image)
  5. (define *heap-image-pointer*) ;; pointer to the image-object
  6. (define *symbol-address*)
  7. (define *heap-object-remaining-cells*)
  8. (define *heap-object-pointer*)
  9. (define *stob-table*) ;; Table for mapping the heap <-> image relation
  10. ; local initializations to read the image
  11. (define (init-locals!)
  12. (set! *heap-image-pointer* null-address)
  13. (set! *symbol-address* null-address) ;; Once for the type-checker
  14. (set! *symbol-address* (if (= false (get-symbols))
  15. (get-img-end-addr)
  16. (address-at-header (get-symbols))))
  17. (set! *heap-object-remaining-cells* 0)
  18. (set! *heap-object-pointer* null-address)
  19. (set! *stob-table* (make-table)))
  20. ; Using a heap-object and a *stob-table*
  21. (define (really-read-image-portable image-format reverse-byte-order? port)
  22. (init-locals!)
  23. (cond
  24. ((got-error? (image->heap image-format port))
  25. -1)
  26. (else
  27. (if reverse-byte-order?
  28. (reverse-image-byte-order! image-format))
  29. (allocate+parse+copy-objects! image-format)
  30. (read-tables image-format port)
  31. (deallocate-things)
  32. 0)))
  33. (define (reverse-image-byte-order! image-format)
  34. (reverse-byte-order! (old->new-addr (get-img-start-addr) image-format)
  35. (old->new-addr (get-img-end-addr) image-format)))
  36. (define (read-tables image-format port)
  37. (set-startup-procedure!
  38. (address->stob-descriptor
  39. (address+
  40. (address-table-ref (address-at-header (get-startup-procedure)))
  41. (cells->a-units stob-overhead))))
  42. (if (not (= false (get-symbols)))
  43. (begin
  44. (set-symbols! (allocate-table (get-symbols) image-format))
  45. (relocate-symbol-table-bibop! (get-symbols) *stob-table*)))
  46. (if (not (= false (get-imported-bindings)))
  47. (begin
  48. (set-imported-bindings! (allocate-table (get-imported-bindings) image-format))
  49. (relocate-binding-table-bibop! (get-imported-bindings) *stob-table*)))
  50. (if (not (= false (get-exported-bindings)))
  51. (begin
  52. (set-exported-bindings! (allocate-table (get-exported-bindings) image-format))
  53. (relocate-binding-table-bibop! (get-exported-bindings) *stob-table*)))
  54. (if (not (= false (get-resumer-records)))
  55. (begin
  56. (set-resumer-records! (allocate-table (get-resumer-records) image-format))
  57. (relocate-resumer-record! (get-resumer-records))))
  58. (unspecific))
  59. (define (deallocate-things)
  60. (deallocate-table *stob-table*)
  61. (deallocate-memory *heap-image-pointer*)
  62. 0)
  63. ; address table abstraction
  64. (define (address->non-zero-integer addr)
  65. (if (= 0 (address->integer addr))
  66. -1
  67. (address->integer addr)))
  68. (define (address-table-ref address)
  69. (integer->address
  70. (image-location-new-descriptor
  71. (table-ref *stob-table* (address->non-zero-integer address)))))
  72. (define (address-table-set! old-address new-address)
  73. (let ((val (make-image-location (address->integer new-address))))
  74. (table-set! *stob-table* (address->non-zero-integer old-address) val)))
  75. ; creates a new object of a given size in the heap, writes a
  76. ; new entry into *STOB-TABLE*, and returns a pointer to the object.
  77. (define (alloc-object current-address size-in-bytes)
  78. (let ((new-address (alloc-space size-in-bytes)))
  79. (address-table-set! current-address new-address)
  80. new-address))
  81. (define (allocate-table tab image-format)
  82. (let* ((addr (old->new-addr (address-at-header tab) image-format))
  83. (cell (fetch addr)))
  84. (if (header? cell)
  85. (let* ((size (header-length-in-cells cell))
  86. (pointer (alloc-space
  87. (cells->bytes
  88. (+ size stob-overhead)))))
  89. (copy-memory! addr pointer
  90. (cells->bytes
  91. (+ size stob-overhead)))
  92. (address->stob-descriptor
  93. (address+ pointer (cells->a-units stob-overhead))))
  94. (error "read-tables! no header"))))
  95. (define (relocate-resumer-record! resumer-records)
  96. (let ((cell (fetch (address-at-header resumer-records))))
  97. (if (header? cell)
  98. (let loop ((address (address-after-header resumer-records))
  99. (size (header-length-in-cells cell)))
  100. (if (= size 0)
  101. (unspecific)
  102. (let ((cell (fetch address)))
  103. (if (stob? cell)
  104. (let ((new-addr (address-table-ref (address-at-header cell))))
  105. (store! address
  106. (address->stob-descriptor
  107. (address+ new-addr
  108. (cells->a-units stob-overhead))))
  109. (loop (address+ address (cells->a-units 1))
  110. (- size 1)))
  111. (error "Could this happen?")))))
  112. (error "relocate-resumer-record! - no header"))))
  113. ; does the key *STOB-TABLE* have an associated value?
  114. (define (not-allocated? current-addr)
  115. (null-pointer? (table-ref *stob-table*
  116. (address->non-zero-integer current-addr))))
  117. ; writes a b-vector
  118. (define (write-b-vector current-addr size-in-cells image-format)
  119. (let ((new-address (alloc-object current-addr (cells->bytes size-in-cells))))
  120. (copy-memory! (old->new-addr current-addr image-format) new-address
  121. (cells->bytes size-in-cells))))
  122. ; writes a header for a new non-b-vector object
  123. ; The current heap object address is stored into *heap-object-pointer*
  124. (define (write-new-header current-addr size-in-cells cell)
  125. (let ((new-address (alloc-object current-addr (cells->bytes size-in-cells))))
  126. (if (not (header? cell))
  127. (error "cell was not a header"))
  128. (store! new-address cell)
  129. (set! *heap-object-pointer* new-address)
  130. (set! *heap-object-remaining-cells* (+ stob-overhead (header-length-in-cells cell)))
  131. (obj-address+)))
  132. ; writes a header for an existing non-b-vector object
  133. (define (write-header current-address cell)
  134. (let* ((new-address (address-table-ref current-address)))
  135. (if (not (header? cell))
  136. (error "cell was not a header"))
  137. (store! new-address cell)
  138. (set! *heap-object-pointer* new-address)
  139. (set! *heap-object-remaining-cells* (+ stob-overhead (header-length-in-cells cell)))
  140. (obj-address+)))
  141. ; This gets used when, going through the image, we hit a stob descriptor
  142. ; whose stob isn't in *STOB-TABLE* yet.
  143. ; For a b-vector, we write the complete object, for all others, we
  144. ; generate a dummy object.
  145. (define (write-pointed-object stob-cell image-format)
  146. (let* ((current-addr (address-at-header stob-cell))
  147. (header-cell (fetch (old->new-addr current-addr image-format)))
  148. (size-in-cells (+ stob-overhead (header-length-in-cells header-cell)))
  149. (size-in-bytes (cells->bytes size-in-cells)))
  150. (if (b-vector-header? header-cell)
  151. (write-b-vector current-addr size-in-cells image-format)
  152. (let ((new-address (alloc-object current-addr size-in-bytes)))
  153. (store! new-address (make-header (enum stob byte-vector)
  154. (- size-in-bytes
  155. (cells->bytes stob-overhead))))
  156. (let ((new-end (address+ new-address (bytes->a-units size-in-bytes))))
  157. (let lp ((index (address+ new-address (cells->a-units stob-overhead))))
  158. (if (not (address= index new-end))
  159. (begin (store! index 0)
  160. (lp (address1+ index))))))))))
  161. ; Writes a pointer to an existing object into the object currently being worked on.
  162. ; increments *HEAP-OBJECT-POINTER*
  163. (define (write-fixed-stob stob current-addr)
  164. (let* ((new-address (address-table-ref (address-at-header stob)))
  165. (fixed-stob (address->stob-descriptor
  166. (address+ new-address (cells->a-units stob-overhead )))))
  167. (store! *heap-object-pointer* fixed-stob)
  168. (obj-address+)))
  169. (define (allocate+parse+copy-objects! format)
  170. (enum-case image-format format
  171. ((two-space)
  172. (parse-reachable-objects (get-img-start-addr) *symbol-address* format))
  173. ((bibop)
  174. (parse-reachable-objects (get-small-img-start-addr) *symbol-address*
  175. format)
  176. (parse-reachable-objects (get-large-img-start-addr)
  177. (address+ (get-large-img-start-addr)
  178. (cells->a-units (get-large-img-heap-size)))
  179. format)
  180. (parse-reachable-objects (get-weaks-img-start-addr)
  181. (address+ (get-weaks-img-start-addr)
  182. (cells->a-units (get-weaks-img-heap-size)))
  183. format))
  184. (else (error "allocate+parse+copy-objects!: Unknown image format"))))
  185. (define (parse-reachable-objects from-addr to-addr image-format)
  186. (let loop ((current-addr from-addr))
  187. (if (address= current-addr to-addr)
  188. 0
  189. (begin
  190. (let* ((cell (fetch (old->new-addr current-addr image-format))))
  191. (if (header? cell)
  192. (let ((size-in-cells (header-length-in-cells cell)))
  193. (if (not (= 0 *heap-object-remaining-cells*))
  194. (error "Encountered an header within an d-vector."))
  195. (if (b-vector-header? cell)
  196. (begin
  197. (if (not-allocated? current-addr)
  198. (write-b-vector current-addr
  199. (+ stob-overhead size-in-cells)
  200. image-format))
  201. (loop (address+ current-addr
  202. (cells->a-units
  203. (+ stob-overhead size-in-cells)))))
  204. (begin
  205. (if (not-allocated? current-addr)
  206. (write-new-header current-addr
  207. (+ 1 size-in-cells) cell)
  208. (write-header current-addr cell))
  209. (loop (address+ current-addr (cells->a-units 1))))))
  210. ;; content of the object:
  211. (begin
  212. (if (stob? cell)
  213. (begin
  214. (if (not-allocated? (address-at-header cell))
  215. (write-pointed-object cell image-format))
  216. (write-fixed-stob cell current-addr))
  217. (begin
  218. (store! *heap-object-pointer* cell)
  219. (obj-address+)))
  220. (loop (address+ current-addr (cells->a-units 1))))))))))
  221. ;; address-conversion between heap and image-address:
  222. ;; type checker doesn't allow these variables as locals with let :-(
  223. (define *offset* 0)
  224. (define *area-start*)
  225. (define (old->new-addr addr format)
  226. (enum-case image-format format
  227. ((two-space)
  228. (address+ *heap-image-pointer*
  229. (address-difference addr (get-img-start-addr))))
  230. ((bibop)
  231. (cond ((and (address>= addr (get-small-img-start-addr))
  232. (address<= addr (get-small-img-hp-addr)))
  233. (set! *offset*
  234. (+ (address-difference (get-weaks-img-end-addr)
  235. (get-weaks-img-start-addr))
  236. (address-difference (get-large-img-end-addr)
  237. (get-large-img-start-addr))))
  238. (set! *area-start* (get-small-img-start-addr)))
  239. ((and (address>= addr (get-large-img-start-addr))
  240. (address<= addr (get-large-img-hp-addr)))
  241. (set! *offset*
  242. (address-difference (get-weaks-img-end-addr)
  243. (get-weaks-img-start-addr)))
  244. (set! *area-start* (get-large-img-start-addr)))
  245. ((and (address>= addr (get-weaks-img-start-addr))
  246. (address<= addr (get-weaks-img-hp-addr)))
  247. (set! *offset* 0)
  248. (set! *area-start* (get-weaks-img-start-addr)))
  249. (else (error "Unknown address area!")))
  250. (address+ *heap-image-pointer*
  251. (+ *offset*
  252. (address-difference addr *area-start*))))
  253. (else (error "old->new-addr: Unknown image format"))))
  254. (define (obj-address+)
  255. (set! *heap-object-remaining-cells* (- *heap-object-remaining-cells* 1))
  256. (set! *heap-object-pointer*
  257. (address+ *heap-object-pointer* (cells->a-units 1))))
  258. ; saves all reachable objects from the image file in a heap object
  259. (define (image->heap format port)
  260. (set! *heap-image-pointer*
  261. (allocate-memory (cells->a-units (get-img-heap-size))))
  262. (cond
  263. ((got-error?
  264. (enum-case image-format format
  265. ((two-space) ; with BIBOP GC
  266. (receive (okay? string)
  267. (image-read-block port *heap-image-pointer*
  268. (cells->a-units (get-img-heap-size)))
  269. (if okay?
  270. 0
  271. (read-lost string port))))
  272. ((bibop) ; with two-space copier
  273. (cond
  274. ((got-error? (really-read-weaks-image port))
  275. -1)
  276. ((got-error? (really-read-large-image port))
  277. -1)
  278. ((got-error? (really-read-small-image port))
  279. -1)
  280. (else
  281. 0)))
  282. (else
  283. (read-lost "this can't happen: invalid image format" port))))
  284. -1)
  285. (else
  286. (receive (ch eof? status)
  287. (read-char port)
  288. (cond
  289. ((error? status)
  290. (read-lost "Error reading from image file" port))
  291. ((not eof?)
  292. ;; debugging
  293. (read-lost "Image file has extraneous data after image" port))
  294. ((error? (close-input-port port))
  295. (read-lost "Error closing image file" port))
  296. (else
  297. 0))))))
  298. (define (table-relocator-bibop foo-next set-foo-next!)
  299. (lambda (table stob-table)
  300. (define (address->non-zero-integer addr)
  301. (if (= 0 (address->integer addr))
  302. -1
  303. (address->integer addr)))
  304. (define (address-table-ref address)
  305. (integer->address
  306. (image-location-new-descriptor
  307. (table-ref stob-table (address->non-zero-integer address)))))
  308. (relocate-table table
  309. (lambda (address)
  310. (address->stob-descriptor
  311. (address+ (address-table-ref (address-at-header address))
  312. (cells->a-units stob-overhead))))
  313. foo-next
  314. set-foo-next!)))
  315. (define relocate-symbol-table-bibop!
  316. (table-relocator-bibop vm-symbol-next
  317. vm-set-symbol-next!))
  318. (define relocate-binding-table-bibop!
  319. (table-relocator-bibop shared-binding-next
  320. set-shared-binding-next!))
  321. (define (really-read-image-area new-start-addr img-heap-size port)
  322. (receive (okay? string)
  323. (image-read-block port
  324. new-start-addr
  325. (cells->a-units img-heap-size))
  326. (cond ((not okay?)
  327. (read-lost string port))
  328. (else 0))))
  329. (define (really-read-small-image port)
  330. (really-read-image-area (get-small-start-addr *heap-image-pointer*)
  331. (get-small-img-heap-size)
  332. port))
  333. (define (really-read-large-image port)
  334. (really-read-image-area (get-large-start-addr *heap-image-pointer*)
  335. (get-large-img-heap-size)
  336. port))
  337. (define (really-read-weaks-image port)
  338. (really-read-image-area (get-weaks-start-addr *heap-image-pointer*)
  339. (get-weaks-img-heap-size)
  340. port))