fix GC-cooperation bug in vector->values

The `vector->values` function set up multiple return values
badly in the case that the given vector is chaperoned.
The problem could lead to NULL as results for `vector->values`.

Merge to v6.1
This commit is contained in:
Matthew Flatt 2014-07-11 13:23:30 +01:00
parent 94bd5369b5
commit f57c1c8e2a
2 changed files with 21 additions and 10 deletions

View File

@ -199,6 +199,14 @@
(test #f vector-ref b 0) (test #f vector-ref b 0)
(test #f vector-ref b2 0))) (test #f vector-ref b2 0)))
;; check interaction of chaperones and vector->values:
(let ([b (vector 1 2 3)])
(let ([b2 (impersonate-vector b
(lambda (b i v) (collect-garbage) v)
(lambda (b i v) #f))])
(define-values (a b c) (vector->values b2))
(test '(1 2 3) list a b c)))
;; ---------------------------------------- ;; ----------------------------------------
(test #t chaperone?/impersonator (chaperone-procedure (lambda (x) x) (lambda (y) y))) (test #t chaperone?/impersonator (chaperone-procedure (lambda (x) x) (lambda (y) y)))

View File

@ -771,7 +771,7 @@ static Scheme_Object *vector_to_immutable (int argc, Scheme_Object *argv[])
static Scheme_Object *vector_to_values (int argc, Scheme_Object *argv[]) static Scheme_Object *vector_to_values (int argc, Scheme_Object *argv[])
{ {
Scheme_Thread *p; Scheme_Thread *p;
Scheme_Object *vec, **a; Scheme_Object *vec, **a, *plain_vec;
intptr_t len, start, finish, i; intptr_t len, start, finish, i;
vec = argv[0]; vec = argv[0];
@ -807,6 +807,16 @@ static Scheme_Object *vector_to_values (int argc, Scheme_Object *argv[])
return SCHEME_VEC_ELS(vec)[start]; return SCHEME_VEC_ELS(vec)[start];
} }
if (!SAME_OBJ(vec, argv[0])) {
plain_vec = scheme_make_vector(len, NULL);
for (i = 0; i < len; i++) {
vec = scheme_chaperone_vector_ref(argv[0], start + i);
SCHEME_VEC_ELS(plain_vec)[i] = vec;
}
vec = plain_vec;
start = 0;
}
p = scheme_current_thread; p = scheme_current_thread;
if (p->values_buffer && (p->values_buffer_size >= len)) if (p->values_buffer && (p->values_buffer_size >= len))
a = p->values_buffer; a = p->values_buffer;
@ -819,15 +829,8 @@ static Scheme_Object *vector_to_values (int argc, Scheme_Object *argv[])
p->ku.multiple.array = a; p->ku.multiple.array = a;
p->ku.multiple.count = len; p->ku.multiple.count = len;
if (!SAME_OBJ(vec, argv[0])) { for (i = 0; i < len; i++) {
for (i = 0; i < len; i++) { a[i] = SCHEME_VEC_ELS(vec)[start + i];
vec = scheme_chaperone_vector_ref(argv[0], start + i);
a[i] = vec;
}
} else {
for (i = 0; i < len; i++) {
a[i] = SCHEME_VEC_ELS(vec)[start + i];
}
} }
return SCHEME_MULTIPLE_VALUES; return SCHEME_MULTIPLE_VALUES;