Eclipse crash on small heap during mature evacuation
wenyuzhao opened this issue · comments
RUST_BACKTRACE=1 MMTK_PLAN=LXR /usr/local/google/home/wenyuzhao/mmtk-dev/openjdk/build/linux-x86_64-normal-server-fastdebug/jdk/bin/java -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions -XX:-InlineObjectCopy -XX:-UseBiasedLocking -XX:-UseCompressedOops -XX:-UseCompressedClassPointers -XX:+UseThirdPartyHeap -Xms534M -Xmx534M --add-exports java.base/jdk.internal.ref=ALL-UNNAMED -cp ~/dacapo/dacapo-evaluation-git-b00bfa9.jar Harness -n 5 eclipse
MMTk Compressed Pointers: disabled
Enable 47-bit address space
VMLayoutConstants: 64bit
Workers: 24
-------------------- Immix Args --------------------
* barrier: "FieldBarrier"
* barrier_measurement: false
* instrumentation: false
* ix_block_only: false
* ix_no_defrag: false
* ix_ref_count: false
* lxr_evacuate_nursery_in_recycled_lines: false
* lxr_delayed_nursery_evacuation: false
* lxr_enable_initial_alloc_limit: false
* ignore_reusing_blocks: true
* log_block_size: 15
* log_line_size: 8
* log_bytes_per_rc_lock_bit: 9
* lxr_rc_only: false
* buffer_size: 1024
* nontemporal: false
* cm_large_array_optimization: false
* inc_max_copy_depth: false
* no_finalizer: false
* no_reference_types: false
RuntimeArgs {
incs_limit: None,
blocks_limit: None,
no_mutator_line_recycling: false,
lock_free_blocks: 24,
nursery_blocks: None,
nursery_ratio: None,
lower_concurrent_worker_priority: false,
concurrent_worker_ratio: 50,
max_mature_defrag_percent: 15,
max_pause_millis: None,
max_copy_size: 512,
concurrent_marking_stop_blocks: 128,
max_survival_mb: Some(
128,
),
survival_predictor_harmonic_mean: false,
survival_predictor_weighted: true,
trace_threshold: 20,
min_reuse_lines: 1,
no_recursive_dec: false,
}
----------------------------------------------------
start: 0x20000000000, end: 0x200000000000
FieldBarrier
ClassUnloading Enabled
--------------------------------------------------------------------------------
...
thread '<unnamed>' panicked at 'assertion failed: object.is_in_any_space()', /usr/local/google/home/wenyuzhao/mmtk-dev/./mmtk-core/src/plan/lxr/cm.rs:322:9
stack backtrace:
0: rust_begin_unwind
at /rustc/fe5b13d681f25ee6474be29d748c65adcd91f69e/library/std/src/panicking.rs:584:5
1: core::panicking::panic_fmt
at /rustc/fe5b13d681f25ee6474be29d748c65adcd91f69e/library/core/src/panicking.rs:143:14
2: core::panicking::panic
at /rustc/fe5b13d681f25ee6474be29d748c65adcd91f69e/library/core/src/panicking.rs:48:5
3: <mmtk::plan::lxr::cm::LXRStopTheWorldProcessEdges<VM,_> as mmtk::scheduler::gc_work::ProcessEdgesWork>::trace_object
at ./mmtk-core/src/plan/lxr/cm.rs:322:9
4: <mmtk::plan::lxr::cm::LXRStopTheWorldProcessEdges<VM,_> as mmtk::scheduler::gc_work::ProcessEdgesWork>::process_edge
at ./mmtk-core/src/plan/lxr/cm.rs:372:26
5: <mmtk::plan::lxr::cm::LXRStopTheWorldProcessEdges<VM,_> as mmtk::scheduler::gc_work::ProcessEdgesWork>::process_edges
at ./mmtk-core/src/plan/lxr/cm.rs:357:17
6: mmtk::scheduler::gc_work::<impl mmtk::scheduler::work::GCWork<<E as mmtk::scheduler::gc_work::ProcessEdgesWork>::VM> for E>::do_work
at ./mmtk-core/src/scheduler/gc_work.rs:583:13
7: mmtk::scheduler::work::GCWork::do_work_with_stat
at ./mmtk-core/src/scheduler/work.rs:55:9
8: mmtk::scheduler::worker::GCWorker<VM>::run
at ./mmtk-core/src/scheduler/worker.rs:242:13
9: mmtk::memory_manager::start_worker
at ./mmtk-core/src/memory_manager.rs:484:5
10: start_worker
at ./mmtk-openjdk/mmtk/src/api.rs:189:5
11: _ZN6Thread8call_runEv
at ./openjdk/src/hotspot/share/runtime/thread.cpp:402:12
12: thread_native_entry
at ./openjdk/src/hotspot/os/linux/os_linux.cpp:799:19
13: start_thread
at ./nptl/./nptl/pthread_create.c:442:8
14: __GI___clone3
at ./misc/../sysdeps/unix/sysv/linux/x86_64/clone3.S:81
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
Traceback (most recent call last):
File "/usr/local/google/home/wenyuzhao/mmtk-dev/run-jdk.py", line 267, in <module>
main()
File "/usr/local/google/home/wenyuzhao/mmtk-dev/run-jdk.py", line 261, in main
run(build_args, run_args)
File "/usr/local/google/home/wenyuzhao/mmtk-dev/run-jdk.py", line 221, in run
Looks like this happens at the second iteration, in final mark pause when LXR is doing mature evacuation.
LXR mature evacuation remset is a list of remembered field slots (or field locations / addresses). This remset is constructed during concurrent marking.
Multiple RC pauses can happen during CM. RC pauses can kill dead mature objects and reuse the memory during CM -- which makes the remset entry invalidated. Some remset entry can point to arbitrary data instead of a valid heap object.
LXR already has a pass to filter out invalid entries before mature evacuation.
However, during mature evacuation, the copy allocator can also reuse lines, and thus invalidate more entries.
The current solution is to filter out invalid remset entries again before forwarding.
Potential data race issue: One GC thread can invalidate an entry when another thread is updating the pointer after forwarding. The pointer update part should be atomic compare and swap, so that the store operation can be cancelled if the entry is already overwritten.
Note: The current solution relies on conservative reference validity check and is not sound