read-image-portable.scm 13 KB

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