Skip to content

Commit

Permalink
ensure write barrier in last step of vector-sort! (#784)
Browse files Browse the repository at this point in the history
The old `$vector-copy!` could use `$ptr-copy!`, which doesn't have an
associated write barrier. As a result, using `$vector-copy!` at the
end of `vector-sort!` is incorrect.

The new test is arranges for one half of a vector to have generation-0
objects and the other to have immediate objects; the two halves are
already sorted, so they end up being swapped via a temporary vector
and `$vector-copy!`. As a result, a collection afterward can fail to
scan the half of the original vector that it should scan.

The solution here is to rename the internal `$vector-copy!` function
to `$vector-fill-copy!` (by analogy to `$stencil-vector-fill-set!`)
and use keep using it for things like `vector-copy`. But the new
`$vector-copy!` as used by `vector-sort!` avoids `$ptr-copy!`.
  • Loading branch information
mflatt authored Dec 21, 2023
1 parent 33db037 commit 056efe1
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 8 deletions.
40 changes: 40 additions & 0 deletions mats/5_6.ms
Original file line number Diff line number Diff line change
Expand Up @@ -1340,6 +1340,46 @@
(fprintf (console-output-port) "\n~s\n" ls)
(errorf #f "failed")))))))
(make-string 200 #\.))

(let ([Ns '(10 100 1024 2048 4096)])
(with-interrupts-disabled
(andmap
(lambda (N)
(define vec (make-vector (* 2 N)))
;; make the vector gen-1:
(collect 0 1)
;; fill first half with immediates and second half with gen-0 objects,
;; where both halves are already in order
(let loop ([i 0])
(unless (fx= i N)
(vector-set! vec i i)
(vector-set! vec (fx+ i N) (number->string i))
(loop (fx+ i 1))))
;; sort, moving objects in second half to first
(vector-sort! (lambda (a b)
(cond
[(string? a)
(if (string? b)
(< (string->number a) (string->number b))
#t)]
[(string? b) #f]
[else (< a b)]))
vec)
;; check whether dirty words got recorded correctly...
;; collect all gen-0 into gen-1
(collect 0 1)
;; make sure the right values are in the still in vector,
;; which suggests that gen-0 references were updated correctly
(let loop ([i 0])
(unless (fx= i N)
(unless (equal? (vector-ref vec (fx+ i N)) i)
(errorf 'oops "at ~s ~s" i (vector-ref vec (fx+ i N))))
(unless (equal? (vector-ref vec i) (number->string i))
(errorf 'oops "at ~s ~s" i (vector-ref vec i)))
(loop (fx+ i 1))))
;; passes
#t)
Ns)))
)

(mat vector->immutable-vector
Expand Down
20 changes: 12 additions & 8 deletions s/5_6.ss
Original file line number Diff line number Diff line change
Expand Up @@ -36,20 +36,24 @@
v))

(define ($vector-copy! v1 v2 n)
(let loop ([i (fx- n 1)])
(cond
[(fx> i 0)
(vector-set! v2 i (vector-ref v1 i))
(let ([i (fx- i 1)]) (vector-set! v2 i (vector-ref v1 i)))
(loop (fx- i 2))]
[(fx= i 0) (vector-set! v2 i (vector-ref v1 i))])))

;; assumes that `v2` is newer than values to copy
(define ($vector-fill-copy! v1 v2 n)
(if (fx<= n 10)
(let loop ([i (fx- n 1)])
(cond
[(fx> i 0)
(vector-set! v2 i (vector-ref v1 i))
(let ([i (fx- i 1)]) (vector-set! v2 i (vector-ref v1 i)))
(loop (fx- i 2))]
[(fx= i 0) (vector-set! v2 i (vector-ref v1 i))]))
($vector-copy! v1 v2 n)
($ptr-copy! v1 (constant vector-data-disp) v2
(constant vector-data-disp) n)))

(define ($vector-copy v1 n)
(let ([v2 (make-vector n)])
($vector-copy! v1 v2 n)
($vector-fill-copy! v1 v2 n)
v2))

(set! vector->list
Expand Down

0 comments on commit 056efe1

Please sign in to comment.