duplicate and cycle detection for places_deserialize_worker

This commit is contained in:
Kevin Tew 2011-05-12 05:10:20 -06:00
parent 79778e0a1e
commit c9c02f3fb0
2 changed files with 57 additions and 12 deletions

View File

@ -236,7 +236,8 @@
(test-long (lambda (x) 3) "Listof ints") (test-long (lambda (x) 3) "Listof ints")
(test-long (lambda (x) #(1 2)) "Listof vectors") (test-long (lambda (x) #(1 2)) "Listof vectors")
(test-long (lambda (x) (intern-num-sym (modulo x 1000))) "Listof symbols") (test-long (lambda (x) (intern-num-sym (modulo x 1000))) "Listof symbols")
(test-long (lambda (x) #s(clown "Binky" "pie")) "Listof prefabs")) (test-long (lambda (x) #s(clown "Binky" "pie")) "Listof prefabs")
(test-long (lambda (x) (read (open-input-string "#0=(#0# . #0#)"))) "Listof cycles"))
;(report-errs) ;(report-errs)

View File

@ -1665,23 +1665,27 @@ Scheme_Object *scheme_places_deep_copy_to_master(Scheme_Object *so) {
} }
#ifdef DO_STACK_CHECK #ifdef DO_STACK_CHECK
static void places_deserialize_worker(Scheme_Object **pso); static void places_deserialize_worker(Scheme_Object **pso, Scheme_Hash_Table **ht);
static Scheme_Object *places_deserialize_worker_k(void) static Scheme_Object *places_deserialize_worker_k(void)
{ {
Scheme_Thread *p = scheme_current_thread; Scheme_Thread *p = scheme_current_thread;
Scheme_Object *pso = (Scheme_Object **)p->ku.k.p1; Scheme_Object *pso = (Scheme_Object *)p->ku.k.p1;
Scheme_Hash_Table*ht = (Scheme_Hash_Table *)p->ku.k.p2;
p->ku.k.p1 = NULL; p->ku.k.p1 = NULL;
p->ku.k.p2 = NULL;
places_deserialize_worker(&pso); places_deserialize_worker(&pso, &ht);
p = scheme_current_thread;
p->ku.k.p1 = ht;
return pso; return pso;
} }
#endif #endif
static void places_deserialize_worker(Scheme_Object **pso) static void places_deserialize_worker(Scheme_Object **pso, Scheme_Hash_Table **ht)
{ {
Scheme_Object *so; Scheme_Object *so;
Scheme_Object *tmp; Scheme_Object *tmp;
@ -1695,10 +1699,15 @@ static void places_deserialize_worker(Scheme_Object **pso)
{ {
# include "mzstkchk.h" # include "mzstkchk.h"
{ {
Scheme_Thread *p = scheme_current_thread; Scheme_Thread *p;
p = scheme_current_thread;
p->ku.k.p1 = *pso; p->ku.k.p1 = *pso;
p->ku.k.p2 = *ht;
tmp = scheme_handle_stack_overflow(places_deserialize_worker_k); tmp = scheme_handle_stack_overflow(places_deserialize_worker_k);
*pso = tmp; *pso = tmp;
p = scheme_current_thread;
*ht = p->ku.k.p1;
p->ku.k.p1 = NULL;
return; return;
} }
} }
@ -1736,35 +1745,69 @@ static void places_deserialize_worker(Scheme_Object **pso)
*pso = tmp; *pso = tmp;
break; break;
case scheme_pair_type: case scheme_pair_type:
if (*ht) {
if ((st = (Scheme_Structure *) scheme_hash_get(*ht, so)))
break;
else
scheme_hash_set(*ht, so, so);
}
else {
tmp = (Scheme_Object *) scheme_make_hash_table(SCHEME_hash_ptr);
*ht = (Scheme_Hash_Table *) tmp;
scheme_hash_set(*ht, so, so);
}
tmp = SCHEME_CAR(so); tmp = SCHEME_CAR(so);
places_deserialize_worker(&tmp); places_deserialize_worker(&tmp, ht);
SCHEME_CAR(so) = tmp; SCHEME_CAR(so) = tmp;
tmp = SCHEME_CDR(so); tmp = SCHEME_CDR(so);
places_deserialize_worker(&tmp); places_deserialize_worker(&tmp, ht);
SCHEME_CDR(so) = tmp; SCHEME_CDR(so) = tmp;
break; break;
case scheme_vector_type: case scheme_vector_type:
if (*ht) {
if ((st = (Scheme_Structure *) scheme_hash_get(*ht, so)))
break;
else
scheme_hash_set(*ht, so, so);
}
else {
tmp = (Scheme_Object *) scheme_make_hash_table(SCHEME_hash_ptr);
*ht = (Scheme_Hash_Table *) tmp;
scheme_hash_set(*ht, so, so);
}
size = SCHEME_VEC_SIZE(so); size = SCHEME_VEC_SIZE(so);
for (i = 0; i <size ; i++) { for (i = 0; i <size ; i++) {
tmp = SCHEME_VEC_ELS(so)[i]; tmp = SCHEME_VEC_ELS(so)[i];
places_deserialize_worker(&tmp); places_deserialize_worker(&tmp, ht);
SCHEME_VEC_ELS(so)[i] = tmp; SCHEME_VEC_ELS(so)[i] = tmp;
} }
break; break;
case scheme_structure_type: case scheme_structure_type:
break; break;
case scheme_serialized_structure_type: case scheme_serialized_structure_type:
if (*ht) {
if ((st = (Scheme_Structure *) scheme_hash_get(*ht, so))) {
*pso = (Scheme_Object *) st;
break;
}
}
else {
tmp = (Scheme_Object *) scheme_make_hash_table(SCHEME_hash_ptr);
*ht = (Scheme_Hash_Table *) tmp;
}
sst = (Scheme_Serialized_Structure*)so; sst = (Scheme_Serialized_Structure*)so;
size = sst->num_slots; size = sst->num_slots;
tmp = sst->prefab_key; tmp = sst->prefab_key;
places_deserialize_worker(&tmp); places_deserialize_worker(&tmp, ht);
sst->prefab_key = tmp; sst->prefab_key = tmp;
stype = scheme_lookup_prefab_type(sst->prefab_key, size); stype = scheme_lookup_prefab_type(sst->prefab_key, size);
st = (Scheme_Structure *) scheme_make_blank_prefab_struct_instance(stype); st = (Scheme_Structure *) scheme_make_blank_prefab_struct_instance(stype);
scheme_hash_set(*ht, so, (Scheme_Object *) st);
for (i = 0; i <size ; i++) { for (i = 0; i <size ; i++) {
tmp = sst->slots[i]; tmp = sst->slots[i];
places_deserialize_worker(&tmp); places_deserialize_worker(&tmp, ht);
st->slots[i] = tmp; st->slots[i] = tmp;
} }
*pso = (Scheme_Object *) st; *pso = (Scheme_Object *) st;
@ -1808,10 +1851,11 @@ Scheme_Object *scheme_places_deserialize(Scheme_Object *so, void *msg_memory) {
GC_dispose_short_message_allocator(msg_memory); GC_dispose_short_message_allocator(msg_memory);
} }
else { else {
Scheme_Object *ht = NULL;
GC_adopt_message_allocator(msg_memory); GC_adopt_message_allocator(msg_memory);
#if !defined(SHARED_TABLES) #if !defined(SHARED_TABLES)
new_so = so; new_so = so;
places_deserialize_worker(&new_so); places_deserialize_worker(&new_so, (Scheme_Hash_Table **) &ht);
#endif #endif
} }
return new_so; return new_so;