memory.scm 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. ; Copyright (c) 1993-2008 by Richard Kelsey and Jonathan Rees. See file COPYING.
  2. ; An implementation of Pre-Scheme's memory interface that can detect some
  3. ; stray reads and writes. It has numerous limitiations:
  4. ; Allocations are always on page boundaries.
  5. ; No more than 16 megabytes can be allocated at once.
  6. ; More than 32 or 64 or so allocations result in addresses being
  7. ; bignums (dealloctions have no effect on this).
  8. ;
  9. ; Memory is represented as a vector of byte-vectors, with each byte-vector
  10. ; representing a 16-megabyte page. Allocations are always made on page
  11. ; boundaries, so the byte-vectors only need be as large as the allocated
  12. ; areas. Pages are never re-used.
  13. ;
  14. ; (Scheme 48 still calls byte-vectors code-vectors.)
  15. ; Addresses are distinct from integers.
  16. (define-record-type address :address
  17. (make-address index)
  18. address?
  19. (index address-index))
  20. (define-record-discloser :address
  21. (lambda (addr) (list 'address (address-index addr))))
  22. ; We add 100000000 to addresses to make them
  23. (define address-offset 100000000)
  24. (define (address->integer addr)
  25. (+ (address-index addr) address-offset))
  26. (define (integer->address int)
  27. (make-address (- int address-offset)))
  28. (define (address+ address integer)
  29. (make-address (+ (address-index address) integer)))
  30. (define (address- address integer)
  31. (make-address (- (address-index address) integer)))
  32. (define (address-binop op)
  33. (lambda (address1 address2)
  34. (op (address-index address1) (address-index address2))))
  35. (define address-difference (address-binop -))
  36. (define address= (address-binop =))
  37. (define address< (address-binop <))
  38. (define address<= (address-binop <=))
  39. (define address> (address-binop >))
  40. (define address>= (address-binop >=))
  41. (define null-address (make-address -1))
  42. (define (null-address? address)
  43. (address= address null-address))
  44. ; Memory
  45. (define *memory* (make-vector 16 #f)) ; vector of pages
  46. (define log-max-size 25) ; log of page size
  47. (define address-shift (- log-max-size)) ; turns addresses into page indices
  48. (define max-size (arithmetic-shift 1 log-max-size)) ; page size
  49. (define address-mask ; mask to get address within page
  50. (- (arithmetic-shift 1 log-max-size) 1))
  51. (define *next-index* 0) ; next available page
  52. (define (reinitialize-memory)
  53. (set! *memory* (make-vector 16 #f))
  54. (set! *next-index* 0))
  55. ; Extend the page vector if necessary, and then make a page of the
  56. ; appropriate size.
  57. (define (allocate-memory size)
  58. (cond ((> size max-size)
  59. null-address) ; error result
  60. (else
  61. (if (>= *next-index* (vector-length *memory*))
  62. (let ((new (make-vector (* 2 (vector-length *memory*)))))
  63. (do ((i 0 (+ i 1)))
  64. ((>= i (vector-length *memory*)))
  65. (vector-set! new i (vector-ref *memory* i)))
  66. (set! *memory* new)))
  67. (let ((index *next-index*))
  68. (set! *next-index* (+ *next-index* 1))
  69. (vector-set! *memory* index (make-code-vector size 0))
  70. (make-address (arithmetic-shift index log-max-size))))))
  71. ; Turning an address into a page or page index
  72. (define (address->vector address)
  73. (vector-ref *memory* (arithmetic-shift address address-shift)))
  74. (define (address->vector-index address)
  75. (bitwise-and address address-mask))
  76. ; Throw away the page containing ADDRESS, which must be the first address in
  77. ; that page,
  78. (define (deallocate-memory address)
  79. (let ((address (address-index address)))
  80. (let ((vector (address->vector address))
  81. (byte-address (address->vector-index address)))
  82. (if (and vector (= byte-address 0))
  83. (vector-set! *memory* (arithmetic-shift address address-shift) #f)
  84. (error "bad deallocation address" address)))))
  85. ; Various ways of accessing memory
  86. (define (unsigned-byte-ref address)
  87. (let ((address (address-index address)))
  88. (code-vector-ref (address->vector address)
  89. (address->vector-index address))))
  90. (define (signed-code-vector-ref bvec i)
  91. (let ((x (code-vector-ref bvec i)))
  92. (if (< x 128)
  93. x
  94. (bitwise-ior x -128))))
  95. (define (word-ref address)
  96. (let ((address (address-index address)))
  97. (let ((vector (address->vector address))
  98. (byte-address (address->vector-index address)))
  99. (if (not (= 0 (bitwise-and byte-address (- bytes-per-cell 1))))
  100. (error "unaligned address error" address)
  101. (do ((byte-offset 0 (+ byte-offset 1))
  102. (shift-offset (- bits-per-cell bits-per-byte)
  103. (- shift-offset bits-per-byte))
  104. (word 0
  105. (+ word
  106. (arithmetic-shift ((if (= 0 byte-offset)
  107. signed-code-vector-ref
  108. code-vector-ref)
  109. vector
  110. (+ byte-address byte-offset))
  111. shift-offset))))
  112. ((or (>= byte-offset bytes-per-cell) (< shift-offset 0))
  113. word))))))
  114. (define (unsigned-byte-set! address value)
  115. (let ((address (address-index address)))
  116. (code-vector-set! (address->vector address)
  117. (address->vector-index address)
  118. (bitwise-and 255 value))))
  119. (define (word-set! address value)
  120. (let ((address (address-index address)))
  121. (let ((vector (address->vector address))
  122. (byte-address (address->vector-index address)))
  123. (if (not (= 0 (bitwise-and byte-address 3)))
  124. (error "unaligned address error" address))
  125. (do ((byte-offset 0 (+ byte-offset 1))
  126. (shift-offset (- bits-per-cell bits-per-byte)
  127. (- shift-offset bits-per-byte)))
  128. ((or (>= byte-offset bytes-per-cell) (< shift-offset 0)))
  129. (code-vector-set! vector
  130. (+ byte-address byte-offset)
  131. (bitwise-and 255
  132. (arithmetic-shift value
  133. (- shift-offset))))))))
  134. ; With the right access to the flonum bits we could actually make these
  135. ; work. Something to do later.
  136. (define (flonum-ref address)
  137. (if #t ; work around type checker bug
  138. (error "call to FLONUM-REF" address)))
  139. (define (flonum-set! address value)
  140. (if #t ; work around type checker bug
  141. (error "call to FLONUM-SET!" address value)))
  142. ; Block I/O procedures.
  143. (define (write-block port address count)
  144. (let ((address (address-index address)))
  145. (let ((vector (address->vector address))
  146. (byte-address (address->vector-index address)))
  147. (do ((i 0 (+ i 1)))
  148. ((>= i count))
  149. (write-byte (code-vector-ref vector (+ i byte-address))
  150. port))
  151. (enum errors no-errors))))
  152. (define (read-block port address count)
  153. (let ((address (address-index address)))
  154. (cond ((not (byte-ready? port))
  155. (values 0 #f (enum errors no-errors)))
  156. ((eof-object? (peek-byte port))
  157. (values 0 #t (enum errors no-errors)))
  158. (else
  159. (let ((vector (address->vector address))
  160. (byte-address (address->vector-index address)))
  161. (let loop ((i 0))
  162. (if (or (= i count)
  163. (not (byte-ready? port)))
  164. (values i #f (enum errors no-errors))
  165. (let ((b (read-byte port)))
  166. (cond ((eof-object? b)
  167. (values i #f (enum errors no-errors)))
  168. (else
  169. (code-vector-set! vector
  170. (+ i byte-address)
  171. b)
  172. (loop (+ i 1))))))))))))
  173. (define (copy-memory! from to count)
  174. (let ((from (address-index from))
  175. (to (address-index to)))
  176. (let ((from-vector (address->vector from))
  177. (from-address (address->vector-index from))
  178. (to-vector (address->vector to))
  179. (to-address (address->vector-index to)))
  180. (if (>= from-address to-address)
  181. (do ((i 0 (+ i 1)))
  182. ((>= i count))
  183. (code-vector-set! to-vector
  184. (+ i to-address)
  185. (code-vector-ref from-vector
  186. (+ i from-address))))
  187. (do ((i (- count 1) (- i 1)))
  188. ((negative? i))
  189. (code-vector-set! to-vector
  190. (+ i to-address)
  191. (code-vector-ref from-vector
  192. (+ i from-address))))))))
  193. (define (memory-equal? from to count)
  194. (let ((from (address-index from))
  195. (to (address-index to)))
  196. (let ((from-vector (address->vector from))
  197. (from-address (address->vector-index from))
  198. (to-vector (address->vector to))
  199. (to-address (address->vector-index to)))
  200. (let loop ((i 0))
  201. (cond ((>= i count)
  202. #t)
  203. ((= (code-vector-ref to-vector (+ i to-address))
  204. (code-vector-ref from-vector (+ i from-address)))
  205. (loop (+ i 1)))
  206. (else
  207. #f))))))
  208. ; Turn the LENGTH bytes starting from ADDRESS into a string.
  209. (define (char-pointer->string address length)
  210. (let ((address (address-index address)))
  211. (let ((vector (address->vector address))
  212. (byte-address (address->vector-index address))
  213. (string (make-string length)))
  214. (do ((i 0 (+ i 1)))
  215. ((= i length))
  216. (string-set! string
  217. i
  218. (ascii->char (code-vector-ref vector (+ byte-address i)))))
  219. string)))
  220. ; Turn the bytes from ADDRESS to the next nul (byte equal to 0) into a
  221. ; string. This is a trivial operation in C.
  222. (define (char-pointer->nul-terminated-string address)
  223. (let ((index (address-index address)))
  224. (let ((vector (address->vector index))
  225. (byte-address (address->vector-index index)))
  226. (char-pointer->string address (index-of-first-nul vector byte-address)))))
  227. (define (index-of-first-nul vector address)
  228. (let loop ((i address))
  229. (cond ((= i (code-vector-length vector))
  230. (error "CHAR-POINTER->STRING called on pointer with no nul termination"))
  231. ((= 0 (code-vector-ref vector i))
  232. (- i address))
  233. (else
  234. (loop (+ i 1))))))