|
1 | 1 | #include "gc-common.h"
|
2 | 2 | #include "gc-tls-mmtk.h"
|
| 3 | +#include "gc-wb-mmtk.h" |
3 | 4 | #include "mmtkMutator.h"
|
4 | 5 | #include "threading.h"
|
5 | 6 |
|
@@ -861,10 +862,22 @@ STATIC_INLINE void* mmtk_immortal_alloc_fast(MMTkMutatorContext* mutator, size_t
|
861 | 862 | return bump_alloc_fast(mutator, (uintptr_t*)&allocator->cursor, (uintptr_t)allocator->limit, size, align, offset, 1);
|
862 | 863 | }
|
863 | 864 |
|
| 865 | +inline void mmtk_set_side_metadata(const void* side_metadata_base, void* obj) { |
| 866 | + intptr_t addr = (intptr_t) obj; |
| 867 | + uint8_t* meta_addr = (uint8_t*) side_metadata_base + (addr >> 6); |
| 868 | + intptr_t shift = (addr >> 3) & 0b111; |
| 869 | + while(1) { |
| 870 | + uint8_t old_val = *meta_addr; |
| 871 | + uint8_t new_val = old_val | (1 << shift); |
| 872 | + if (jl_atomic_cmpswap((_Atomic(uint8_t)*)meta_addr, &old_val, new_val)) { |
| 873 | + break; |
| 874 | + } |
| 875 | + } |
| 876 | +} |
| 877 | + |
864 | 878 | STATIC_INLINE void mmtk_immortal_post_alloc_fast(MMTkMutatorContext* mutator, void* obj, size_t size) {
|
865 |
| - // FIXME: Similarly, for now, we do nothing |
866 |
| - // but when supporting moving, this is where we set the valid object (VO) bit |
867 |
| - // and log (old gen) bit |
| 879 | + if (MMTK_NEEDS_WRITE_BARRIER == MMTK_OBJECT_BARRIER) { |
| 880 | + mmtk_set_side_metadata(MMTK_SIDE_LOG_BIT_BASE_ADDRESS, obj); |
868 | 881 | }
|
869 | 882 |
|
870 | 883 | JL_DLLEXPORT jl_value_t *jl_mmtk_gc_alloc_default(jl_ptls_t ptls, int osize, size_t align, void *ty)
|
@@ -1128,7 +1141,9 @@ _Atomic(int) gc_stack_free_idx = 0;
|
1128 | 1141 |
|
1129 | 1142 | JL_DLLEXPORT void jl_gc_queue_root(const struct _jl_value_t *ptr) JL_NOTSAFEPOINT
|
1130 | 1143 | {
|
1131 |
| - mmtk_unreachable(); |
| 1144 | + jl_task_t *ct = jl_current_task; |
| 1145 | + jl_ptls_t ptls = ct->ptls; |
| 1146 | + mmtk_object_reference_write_slow(&ptls->gc_tls.mmtk_mutator, parent, (const void*) 0); |
1132 | 1147 | }
|
1133 | 1148 |
|
1134 | 1149 | JL_DLLEXPORT void jl_gc_queue_multiroot(const struct _jl_value_t *root, const void *stored,
|
@@ -1210,6 +1225,82 @@ JL_DLLEXPORT jl_value_t *jl_gc_internal_obj_base_ptr(void *p)
|
1210 | 1225 | return NULL;
|
1211 | 1226 | }
|
1212 | 1227 |
|
| 1228 | +JL_DLLEXPORT void jl_genericmemory_copyto(jl_genericmemory_t *dest, char* destdata, |
| 1229 | + jl_genericmemory_t *src, char* srcdata, |
| 1230 | + size_t n) JL_NOTSAFEPOINT |
| 1231 | +{ |
| 1232 | + jl_datatype_t *dt = (jl_datatype_t*)jl_typetagof(dest); |
| 1233 | + if (dt != (jl_datatype_t*)jl_typetagof(src)) |
| 1234 | + jl_exceptionf(jl_argumenterror_type, "jl_genericmemory_copyto requires source and dest to have same type"); |
| 1235 | + const jl_datatype_layout_t *layout = dt->layout; |
| 1236 | + if (layout->flags.arrayelem_isboxed) { |
| 1237 | + _Atomic(void*) * dest_p = (_Atomic(void*)*)destdata; |
| 1238 | + _Atomic(void*) * src_p = (_Atomic(void*)*)srcdata; |
| 1239 | + jl_value_t *owner = jl_genericmemory_owner(dest); |
| 1240 | + jl_gc_wb(owner, NULL); |
| 1241 | + if (__unlikely(jl_astaggedvalue(owner)->bits.gc == GC_OLD_MARKED)) { |
| 1242 | + jl_value_t *src_owner = jl_genericmemory_owner(src); |
| 1243 | + ssize_t done = 0; |
| 1244 | + if (jl_astaggedvalue(src_owner)->bits.gc != GC_OLD_MARKED) { |
| 1245 | + if (dest_p < src_p || dest_p > src_p + n) { |
| 1246 | + for (; done < n; done++) { // copy forwards |
| 1247 | + void *val = jl_atomic_load_relaxed(src_p + done); |
| 1248 | + jl_atomic_store_release(dest_p + done, val); |
| 1249 | + // `val` is young or old-unmarked |
| 1250 | + if (val && !(jl_astaggedvalue(val)->bits.gc & GC_MARKED)) { |
| 1251 | + jl_gc_queue_root(owner); |
| 1252 | + break; |
| 1253 | + } |
| 1254 | + } |
| 1255 | + src_p += done; |
| 1256 | + dest_p += done; |
| 1257 | + } else { |
| 1258 | + for (; done < n; done++) { // copy backwards |
| 1259 | + void *val = jl_atomic_load_relaxed(src_p + n - done - 1); |
| 1260 | + jl_atomic_store_release(dest_p + n - done - 1, val); |
| 1261 | + // `val` is young or old-unmarked |
| 1262 | + if (val && !(jl_astaggedvalue(val)->bits.gc & GC_MARKED)) { |
| 1263 | + jl_gc_queue_root(owner); |
| 1264 | + break; |
| 1265 | + } |
| 1266 | + } |
| 1267 | + } |
| 1268 | + n -= done; |
| 1269 | + } |
| 1270 | + } |
| 1271 | + return memmove_refs(dest_p, src_p, n); |
| 1272 | + } |
| 1273 | + size_t elsz = layout->size; |
| 1274 | + char *src_p = srcdata; |
| 1275 | + int isbitsunion = layout->flags.arrayelem_isunion; |
| 1276 | + if (isbitsunion) { |
| 1277 | + char *sourcetypetagdata = jl_genericmemory_typetagdata(src); |
| 1278 | + char *desttypetagdata = jl_genericmemory_typetagdata(dest); |
| 1279 | + memmove(desttypetagdata+(size_t)destdata, sourcetypetagdata+(size_t)srcdata, n); |
| 1280 | + srcdata = (char*)src->ptr + elsz*(size_t)srcdata; |
| 1281 | + destdata = (char*)dest->ptr + elsz*(size_t)destdata; |
| 1282 | + } |
| 1283 | + if (layout->first_ptr != -1) { |
| 1284 | + memmove_refs((_Atomic(void*)*)destdata, (_Atomic(void*)*)srcdata, n * elsz / sizeof(void*)); |
| 1285 | + jl_value_t *owner = jl_genericmemory_owner(dest); |
| 1286 | + if (__unlikely(jl_astaggedvalue(owner)->bits.gc == GC_OLD_MARKED)) { |
| 1287 | + jl_value_t *src_owner = jl_genericmemory_owner(src); |
| 1288 | + if (jl_astaggedvalue(src_owner)->bits.gc != GC_OLD_MARKED) { |
| 1289 | + dt = (jl_datatype_t*)jl_tparam1(dt); |
| 1290 | + for (size_t done = 0; done < n; done++) { // copy forwards |
| 1291 | + char* s = (char*)src_p+done*elsz; |
| 1292 | + if (*((jl_value_t**)s+layout->first_ptr) != NULL) |
| 1293 | + jl_gc_queue_multiroot(owner, s, dt); |
| 1294 | + } |
| 1295 | + } |
| 1296 | + } |
| 1297 | + } |
| 1298 | + else { |
| 1299 | + memmove(destdata, srcdata, n * elsz); |
| 1300 | + } |
| 1301 | +} |
| 1302 | + |
| 1303 | + |
1213 | 1304 | #ifdef __cplusplus
|
1214 | 1305 | }
|
1215 | 1306 | #endif
|
0 commit comments