@@ -531,16 +531,11 @@ Value* value_tns_get_ptr(Value v, const size_t* idxs, size_t nidxs) {
531531
532532// Shallow copy semantics: increment refcount for MAP/TNS and return aliasing Value.
533533Value value_copy (Value v ) {
534- // New semantics: value_copy produces an atomic (de-referenced) copy for
535- // container types (TNS and MAP): the container object is duplicated so
536- // mutations to the returned value won't affect the original. Element
537- // values inside the container remain as aliases (not deep-copied).
538534 Value out = v ;
539535 if (v .type == VAL_STR && v .as .s ) {
540536 out .as .s = strdup (v .as .s );
541537 } else if (v .type == VAL_TNS && v .as .tns ) {
542538 Tensor * t = v .as .tns ;
543- // allocate new tensor structure and copy shape/strides
544539 Tensor * t2 = malloc (sizeof (Tensor ));
545540 if (!t2 ) { fprintf (stderr , "Out of memory\n" ); exit (1 ); }
546541 t2 -> elem_type = t -> elem_type ;
@@ -551,8 +546,6 @@ Value value_copy(Value v) {
551546 t2 -> length = t -> length ;
552547 t2 -> data = malloc (sizeof (Value ) * t2 -> length );
553548 for (size_t i = 0 ; i < t2 -> length ; i ++ ) {
554- // keep element references (shallow): use value_alias to preserve
555- // previous element-sharing semantics for nested containers
556549 extern Value value_alias (Value v );
557550 t2 -> data [i ] = value_alias (t -> data [i ]);
558551 }
@@ -566,20 +559,29 @@ Value value_copy(Value v) {
566559 m2 -> count = m -> count ;
567560 m2 -> capacity = m -> count ;
568561 m2 -> items = malloc (sizeof (MapEntry ) * (m2 -> capacity ? m2 -> capacity : 1 ));
562+ m2 -> buckets = NULL ;
563+ m2 -> bucket_count = 0 ;
564+ m2 -> refcount = 1 ;
565+ mtx_init (& m2 -> lock , 0 );
569566 for (size_t i = 0 ; i < m -> count ; i ++ ) {
570567 extern Value value_alias (Value v );
571568 m2 -> items [i ].key = value_alias (m -> items [i ].key );
572- m2 -> items [i ].value = value_alias (m -> items [i ].value );
569+ Value orig_val = m -> items [i ].value ;
570+ if (orig_val .type == VAL_MAP && orig_val .as .map == m ) {
571+ Value tmp ;
572+ tmp .type = VAL_MAP ;
573+ tmp .num_base = 2 ;
574+ tmp .num_base_nan = 0 ;
575+ tmp .as .map = m2 ;
576+ m2 -> items [i ].value = value_alias (tmp );
577+ } else {
578+ m2 -> items [i ].value = value_alias (m -> items [i ].value );
579+ }
573580 m2 -> items [i ].next_hash = -1 ;
574581 }
575- m2 -> buckets = NULL ;
576- m2 -> bucket_count = 0 ;
577582 if (m2 -> count > 0 ) map_rehash (m2 , map_recommended_bucket_count (m2 -> count ));
578- m2 -> refcount = 1 ;
579- mtx_init (& m2 -> lock , 0 );
580583 out .as .map = m2 ;
581584 } else if (v .type == VAL_THR && v .as .thr ) {
582- // threads remain shared handles
583585 Thr * th = v .as .thr ;
584586 mtx_lock (& th -> state_lock );
585587 th -> refcount ++ ;
0 commit comments