Skip to content

Commit cf7879f

Browse files
authored
Fix reference processing crash (#309)
Fixed a bug that when enqueuing references, it swapped the reference pending list with the last node of the new linked list. It should swap with the *first* node instead. Worked around a fact that the list given by the method `ReferenceGlue::enqueue_references` may contain duplicated elements. This is because the reference processor in mmtk-core was designed to work with both of the two use patterns: (1) registering references when created, and (2) discovering references while tracing. Therefore, the reference processor kept the list of Reference instances discovered in the previous GC (in the from-space). But as the OpenJDK binding scans new Reference instances, it will add to-space addresses of the same Reference instances to the reference processor. After the references are processed, both pointers will be normalized to the two-space copy, but as two different entries. We work around this problem in the OpenJDK binding by simply skipping visited entries.
1 parent ad9a6fa commit cf7879f

File tree

2 files changed

+18
-54
lines changed

2 files changed

+18
-54
lines changed
Lines changed: 2 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,5 @@
11
set -xe
22

3-
. $(dirname "$0")/common.sh
4-
5-
unset JAVA_TOOL_OPTIONS
6-
cd $OPENJDK_PATH
7-
3+
# Just run everything in ci-test-only-normal.sh, but with reference processing enabled.
84
export MMTK_NO_REFERENCE_TYPES=false
9-
# Just test Immix and MarkCompact
10-
# Immix - normal weak ref impl
11-
# MarkCompact - with extra ref forwarding
12-
13-
run_all() {
14-
heap_multiplier=$1
15-
16-
runbms_dacapo2006_with_heap_multiplier antlr $heap_multiplier
17-
runbms_dacapo2006_with_heap_multiplier fop $heap_multiplier
18-
runbms_dacapo2006_with_heap_multiplier luindex $heap_multiplier
19-
runbms_dacapo2006_with_heap_multiplier pmd $heap_multiplier
20-
runbms_dacapo2006_with_heap_multiplier hsqldb $heap_multiplier
21-
# The test may fail. Skip it for now.
22-
#/home/runner/work/mmtk-openjdk/mmtk-openjdk/bundles/jdk/bin/java -XX:+UseThirdPartyHeap -server -XX:MetaspaceSize=100M -Xms92M -Xmx92M -jar /home/runner/work/mmtk-openjdk/mmtk-openjdk/dacapo/dacapo-2006-10-MR2.jar eclipse
23-
#[2024-01-15T04:42:55Z INFO mmtk::memory_manager] Initialized MMTk with Immix (FixedHeapSize(96468992))
24-
#===== DaCapo eclipse starting =====
25-
#[2024-01-15T04:42:58Z INFO mmtk::util::heap::gc_trigger] [POLL] immix: Triggering collection (23560/23552 pages)
26-
#[2024-01-15T04:42:58Z INFO mmtk::scheduler::gc_work] End of GC (5015/23552 pages, took 76 ms)
27-
#<setting up workspace...>
28-
#<creating projects..............................................................>
29-
#
30-
# A fatal error has been detected by the Java Runtime Environment:
31-
#
32-
# SIGSEGV (0xb) at pc=0x00007f7dd4627dff, pid=2923, tid=2924
33-
#
34-
# JRE version: OpenJDK Runtime Environment (11.0.19) (fastdebug build 11.0.19-internal+0-adhoc.runner.openjdk)
35-
# Java VM: OpenJDK 64-Bit Server VM (fastdebug 11.0.19-internal+0-adhoc.runner.openjdk, mixed mode, tiered, compressed oops, third-party gc, linux-amd64)
36-
# Problematic frame:
37-
# j java.lang.invoke.LambdaFormEditor.getInCache(Ljava/lang/invoke/LambdaFormEditor$Transform;)Ljava/lang/invoke/LambdaForm;+175 [email protected]
38-
#
39-
# runbms_dacapo2006_with_heap_multiplier eclipse $heap_multiplier
40-
}
41-
42-
# --- Immix ---
43-
export MMTK_PLAN=Immix
44-
45-
run_all 4
46-
47-
# --- MarkCompact ---
48-
export MMTK_PLAN=MarkCompact
49-
50-
run_all 4
5+
. $(dirname "$0")/ci-test-only-normal.sh

openjdk/mmtkUpcalls.cpp

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -304,17 +304,26 @@ static void mmtk_enqueue_references(void** objects, size_t len) {
304304

305305
MutexLocker x(Heap_lock);
306306

307-
oop prev = NULL;
308-
for (size_t i = 0; i < len; i++) {
307+
oop first = (oop) objects[0]; // This points to the first node of the linked list.
308+
oop last = first; // This points to the last node of the linked list.
309+
310+
for (size_t i = 1; i < len; i++) {
309311
oop reff = (oop) objects[i];
310-
if (prev != NULL) {
311-
HeapAccess<AS_NO_KEEPALIVE>::oop_store_at(prev, java_lang_ref_Reference::discovered_offset, reff);
312+
oop old_discovered = HeapAccess<AS_NO_KEEPALIVE>::oop_load_at(reff, java_lang_ref_Reference::discovered_offset);
313+
if (old_discovered != NULL || old_discovered == last) {
314+
// Note that `objects` may contain duplicated elements.
315+
// Because we gradually discover references during tracing,
316+
// the ReferenceProcessor in mmtk-core may contain both from-space and to-space references of the same object.
317+
// After processing references, they will be forwarded and become to-space references.
318+
// We skip references that already have the `discovered` field set because they have already been visited.
319+
continue;
312320
}
313-
prev = reff;
321+
HeapAccess<AS_NO_KEEPALIVE>::oop_store_at(last, java_lang_ref_Reference::discovered_offset, reff);
322+
last = reff;
314323
}
315324

316-
oop old = Universe::swap_reference_pending_list(prev);
317-
HeapAccess<AS_NO_KEEPALIVE>::oop_store_at(prev, java_lang_ref_Reference::discovered_offset, old);
325+
oop old_first = Universe::swap_reference_pending_list(first);
326+
HeapAccess<AS_NO_KEEPALIVE>::oop_store_at(last, java_lang_ref_Reference::discovered_offset, old_first);
318327
assert(Universe::has_reference_pending_list(), "Reference pending list is empty after swap");
319328
}
320329

0 commit comments

Comments
 (0)