stob.scm 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. ; Copyright (c) 1993-2008 by Richard Kelsey and Jonathan Rees. See file COPYING.
  2. ; Pre-Allocation
  3. ;
  4. ; Preallocation and keys are used to ensure that for every call to MAKE-STOB
  5. ; there is a corresponding call to ENSURE-SPACE to see if there is sufficient
  6. ; heap space. ENSURE-SPACE returns a key and MAKE-STOB checks that the
  7. ; key it is passed is the most recently allocated key and that the space
  8. ; needed is no greater than the argument to ENSURE-SPACE.
  9. ;
  10. ; Another solution would be to make ENSURE-SPACE and MAKE-STOB a single
  11. ; procedure. The difficulty is that ENSURE-SPACE may trigger a garbage
  12. ; collection, which in turn requires that all live data be reachable
  13. ; from the VM's registers. The VM solves this by only calling ENSURE-SPACE
  14. ; at the beginning of an instruction, before any values have been removed
  15. ; from the stack or any of the registers. Once the key has been obtained
  16. ; the instruction is free to make any number of calls to MAKE-STOB, as long
  17. ; as the total heap space required is no more than what was checked for.
  18. ;
  19. ; There is a flag, CHECK-PREALLOCATION?, that determines whether MAKE-STOB
  20. ; actually checks the keys. In the VM as seen by the Pre-Scheme compiler
  21. ; this flag is defined to be #f and never set, so all of the key code is
  22. ; constant-folded into oblivion.
  23. ;
  24. ; The main virtue of the keys is not that they can be checked but
  25. ; that they exist at all. MAKE-STOB requires a key argument, and
  26. ; if there is none available you know that you forgot an ENSURE-SPACE.
  27. ; Occasionally I run the VM in Scheme with checking enabled, just
  28. ; to see if it all still works.
  29. (define check-preallocation? #f)
  30. (define (checking-preallocation?)
  31. check-preallocation?)
  32. (define *heap-key* 0)
  33. (define *okayed-space* 0)
  34. (define (ensure-space cells)
  35. (s48-make-available+gc (cells->bytes cells))
  36. (cond (check-preallocation?
  37. (set! *heap-key* (+ *heap-key* 1))
  38. (set! *okayed-space* cells)
  39. *heap-key*)
  40. (else
  41. 0)))
  42. (define (allocate-space len key) ;len is in bytes
  43. (if check-preallocation?
  44. (let ((cells (bytes->cells len)))
  45. (if (not (and (= key *heap-key*)
  46. (>= *okayed-space* cells)))
  47. (error "invalid heap key" key cells))
  48. (set! *okayed-space* (- *okayed-space* cells))))
  49. (s48-allocate-small len))
  50. ;----------------
  51. (define max-stob-size-in-cells
  52. (+ max-stob-contents-size-in-cells
  53. stob-overhead))
  54. (define (make-stob type len key)
  55. (let ((addr (allocate-space (+ len
  56. (cells->bytes stob-overhead))
  57. key)))
  58. (initialize-stob addr type len)))
  59. (define (make-d-vector type len key)
  60. (make-stob type (cells->bytes len) key))
  61. (define make-b-vector make-stob)
  62. ; Versions of the above two procedures that can be used to allocate large
  63. ; objects. These may trigger a GC and will return false if insufficient
  64. ; space is available after the GC.
  65. (define (maybe-make-b-vector+gc type len)
  66. (let ((addr (s48-allocate-untraced+gc (+ len
  67. (cells->bytes stob-overhead)))))
  68. (if (null-address? addr)
  69. false
  70. (initialize-stob addr type len))))
  71. (define (maybe-make-d-vector+gc type len)
  72. (let* ((len (cells->bytes len))
  73. (addr (s48-allocate-traced+gc (+ len
  74. (cells->bytes stob-overhead)))))
  75. (if (null-address? addr)
  76. false
  77. (initialize-stob addr type len))))
  78. (define (make-weak-pointer init weak-pointer-size)
  79. (let* ((addr (s48-allocate-weak+gc (cells->bytes weak-pointer-size)))
  80. (weak-pointer (initialize-stob addr
  81. (enum stob weak-pointer)
  82. (cells->bytes (- weak-pointer-size 1)))))
  83. (d-vector-init! weak-pointer 0 init)
  84. weak-pointer))
  85. ; Add the header to a stob and add the tag to the address.
  86. (define (initialize-stob addr type len)
  87. (store! addr (make-header type len))
  88. (address->stob-descriptor (address+ addr
  89. (cells->bytes stob-overhead))))
  90. ; Used to copy stuff from the stack to the heap.
  91. (define (header+contents->stob header contents key)
  92. (let* ((addr (allocate-space (+ (header-length-in-bytes header)
  93. (cells->bytes stob-overhead))
  94. key))
  95. (data-addr (address+ addr (cells->bytes stob-overhead))))
  96. (store! addr header)
  97. (copy-memory! contents data-addr (header-length-in-bytes header))
  98. (address->stob-descriptor data-addr)))
  99. ;----------------
  100. (define (stob-type obj)
  101. (header-type (stob-header obj)))
  102. (define (stob-of-type? obj type)
  103. (and (stob? obj)
  104. (= (stob-type obj) type)))
  105. ;----------------
  106. ; Immutability
  107. (define (immutable? thing)
  108. (or (not (stob? thing))
  109. (immutable-header? (stob-header thing))))
  110. (define (make-immutable! thing)
  111. (if (not (immutable? thing))
  112. (stob-header-set! thing (make-header-immutable (stob-header thing)))))
  113. ;----------------
  114. ; D-vectors (vectors of descriptors)
  115. (define (d-vector? obj)
  116. (and (stob? obj)
  117. (< (header-type (stob-header obj)) least-b-vector-type)))
  118. ; The type in these routines is used only for internal error checking.
  119. (define (d-vector-length x)
  120. (assert (d-vector? x))
  121. (header-length-in-cells (stob-header x)))
  122. (define (d-vector-ref x index)
  123. (assert (valid-index? index (d-vector-length x)))
  124. (fetch (address+ (address-after-header x) (cells->a-units index))))
  125. (define (d-vector-set! x index value)
  126. (assert (valid-index? index (d-vector-length x)))
  127. (let ((addr (address+ (address-after-header x) (cells->a-units index))))
  128. (s48-write-barrier x addr value)
  129. (store! addr value)))
  130. (define (d-vector-init! x index value)
  131. (assert (valid-index? index (d-vector-length x)))
  132. (store! (address+ (address-after-header x) (cells->a-units index))
  133. value))
  134. ;----------------
  135. ; B-vector = vector of bytes.
  136. (define (b-vector? obj)
  137. (and (stob? obj)
  138. (>= (header-type (stob-header obj))
  139. least-b-vector-type)))
  140. (define (b-vector-length x)
  141. (assert (b-vector? x))
  142. (header-length-in-bytes (stob-header x)))
  143. (define (b-vector-ref b-vector index)
  144. (assert (valid-index? index (b-vector-length b-vector)))
  145. (fetch-byte (address+ (address-after-header b-vector) index)))
  146. (define (b-vector-set! b-vector index value)
  147. (assert (valid-index? index (b-vector-length b-vector)))
  148. (store-byte! (address+ (address-after-header b-vector) index) value))
  149. ; Various utilities
  150. (define (valid-index? index len)
  151. (and (>= index 0) (< index len)))