;; See microcode/cmpintmd/svm1.c for a description of the layout.
;; Offset of the first object in the closure from the address of the
-;; first closure entry point, in words.
+;; first closure entry point, in words. In order to make this work,
+;; we add padding to the closure-count field so that the first entry
+;; is aligned on an object boundary.
(define (closure-first-offset count entry)
entry
(if (= count 0)
1
- ;; This returns the offset in bytes, it isn't necessarily in words.
- (receive (entries entries-size padding-size) (make-closure-entries count)
- entries-size padding-size
- (+ 2 (car (car entries))))))
+ (+ (integer-ceiling (* count 3) address-units-per-object)
+ count)))
;; Offset of the first object in the closure from the address of the
;; manifest-closure header word, in words.
(define (closure-object-first-offset count)
(if (= count 0)
1
- (receive (entries entries-size padding-size) (make-closure-entries count)
- entries
- (quotient (+ 2 entries-size padding-size)
- address-units-per-object))))
+ (+ 2 (closure-first-offset count 0))))
;; Increment from one closure entry address to another, in bytes.
(define (closure-entry-distance count entry entry*)
- (* 10 (- entry* entry)))
+ (* 3 (- entry* entry)))
;; Increment from a given closure address to the first closure
;; address, in bytes. Usually negative.
(define (closure-environment-adjustment count entry)
- (closure-entry-distance count entry 0))
-
-
-;; This could get stuck toggling between two states. It's probably
-;; not worth running the ITERATION loop more than a couple of times.
-(define (make-closure-entries count)
- (let ((last (- count 1))
- (initial-padding (padding-size (* count 9))))
- (let ((entries
- (reverse!
- (make-initialized-list count
- (lambda (i)
- (cons (+ (* (- last i) 9)
- initial-padding
- (* i 4))
- 9))))))
- (let iteration ((padding initial-padding))
- (let loop ((entries entries))
- (if (pair? entries)
- (let ((entry (car entries))
- (entries (cdr entries)))
- (let ((size* (offset->entry-size (car entry)))
- (size (cdr entry)))
- (if (not (= size* size))
- (begin
- (set-cdr! entry size*)
- (adjust-entries! entries (- size size*)))))
- (loop entries))))
- (let ((entries-size (entries-size entries)))
- (let ((padding* (padding-size entries-size)))
- (if (not (= padding* padding))
- (begin
- (adjust-entries! entries (- padding padding*))
- (iteration padding*))
- (values (map car (reverse! entries))
- entries-size
- padding))))))))
-
-(define (entries-size entries)
- (reduce + 0 (map cdr entries)))
-
-(define (padding-size entries-size)
- (let ((entries-size (+ entries-size 2)))
- (- (* (integer-ceiling entries-size 4) 4) entries-size)))
-
-(define (offset->entry-size offset)
- (cond ((< offset #x100) 6)
- ((< offset #x10000) 7)
- (else 9)))
-
-(define (adjust-entries! entries delta)
- (for-each (lambda (entry)
- (set-car! entry (- (car entry) delta)))
- entries))
\ No newline at end of file
+ (closure-entry-distance count entry 0))
\ No newline at end of file
For example, on a 32-bit machine with count == 3 and 4 value cells:
- 0x00 TC_MANIFEST_CLOSURE | n_words == 11
+ 0x00 TC_MANIFEST_CLOSURE | n_words == 12
+
0x04 count == 3
+ 0x06 2 padding bytes (next address must be word-aligned)
- 0x06 SVM1_INST_ENTER_CLOSURE
- 0x07 index == 0
+ 0x08 SVM1_INST_ENTER_CLOSURE
+ 0x09 index == 0
- 0x09 SVM1_INST_ENTER_CLOSURE
- 0x0A index == 1
+ 0x0B SVM1_INST_ENTER_CLOSURE
+ 0x0C index == 1
- 0x0C SVM1_INST_ENTER_CLOSURE
- 0x0D index == 2
+ 0x0E SVM1_INST_ENTER_CLOSURE
+ 0x0F index == 2
- 0x0F 1 padding byte
+ 0x11 3 padding bytes (next address must be word-aligned)
- 0x10 target 0
- 0x14 target 1
- 0x18 target 2
+ 0x14 target 0
+ 0x18 target 1
+ 0x1C target 2
- 0x1C value cell 0
- 0x20 value cell 1
- 0x24 value cell 2
- 0x28 value cell 3
+ 0x20 value cell 0
+ 0x24 value cell 1
+ 0x28 value cell 2
+ 0x2C value cell 3
*/