From d103feb7f1d845eb70370ccc0fa5cd8d57c13eef Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Tue, 30 Sep 2025 13:42:18 +0200 Subject: [PATCH 1/3] 8368953 Hi all, please review this trivial change to document the reason for the dirty/clean card value selection. Testing: local compilation Thanks, Thomas --- src/hotspot/share/gc/shared/cardTable.hpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/hotspot/share/gc/shared/cardTable.hpp b/src/hotspot/share/gc/shared/cardTable.hpp index 63dcfe7aecb39..ccb8e8a5faba1 100644 --- a/src/hotspot/share/gc/shared/cardTable.hpp +++ b/src/hotspot/share/gc/shared/cardTable.hpp @@ -61,6 +61,19 @@ class CardTable: public CHeapObj { inline size_t compute_byte_map_size(size_t num_bytes); + // We use 0x00 (zero) as "dirty" and 0xff as "clean" because this reduces the + // barrier code by one instruction. Many architectures have a constant-zero + // register that can be used for the store, so the dirty value does not need + // to be explicitly loaded. + // + // E.g. see + // Urs Hölzle. A fast write barrier for generational garbage collectors. + // In Eliot Moss, Paul R. Wilson, and Benjamin Zorn, editors, OOPSLA/ECOOP '93 + // Workshop on Garbage Collection in Object-Oriented Systems, October 1993 + // + // that shows this for SPARC (but aarch32/aarch64/RISC-V are similar in this + // respect). + // enum CardValues { clean_card = (CardValue)-1, From 9ce7f816ce6ab9e162b52cd51196017f98a77178 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl <59967451+tschatzl@users.noreply.github.com> Date: Tue, 30 Sep 2025 15:08:58 +0200 Subject: [PATCH 2/3] Update src/hotspot/share/gc/shared/cardTable.hpp --- src/hotspot/share/gc/shared/cardTable.hpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/hotspot/share/gc/shared/cardTable.hpp b/src/hotspot/share/gc/shared/cardTable.hpp index ccb8e8a5faba1..c25303013c9a1 100644 --- a/src/hotspot/share/gc/shared/cardTable.hpp +++ b/src/hotspot/share/gc/shared/cardTable.hpp @@ -61,10 +61,11 @@ class CardTable: public CHeapObj { inline size_t compute_byte_map_size(size_t num_bytes); - // We use 0x00 (zero) as "dirty" and 0xff as "clean" because this reduces the - // barrier code by one instruction. Many architectures have a constant-zero - // register that can be used for the store, so the dirty value does not need - // to be explicitly loaded. + // We use 0x00 (zero) to represent dirty and 0xFF to represent clean because + // this choice reduces the barrier code by one instruction on architectures with + // a constant-zero register. On such architectures, the dirty value (0x00) is + // directly accessible through the zero register, eliminating the need to load + // the value explicitly and thereby saving one instruction // // E.g. see // Urs Hölzle. A fast write barrier for generational garbage collectors. From cef01833e3c11ce8bbd8462b5a700d004370c0e3 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl <59967451+tschatzl@users.noreply.github.com> Date: Tue, 30 Sep 2025 15:10:22 +0200 Subject: [PATCH 3/3] Update src/hotspot/share/gc/shared/cardTable.hpp --- src/hotspot/share/gc/shared/cardTable.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/gc/shared/cardTable.hpp b/src/hotspot/share/gc/shared/cardTable.hpp index c25303013c9a1..ab26055e522f1 100644 --- a/src/hotspot/share/gc/shared/cardTable.hpp +++ b/src/hotspot/share/gc/shared/cardTable.hpp @@ -61,9 +61,9 @@ class CardTable: public CHeapObj { inline size_t compute_byte_map_size(size_t num_bytes); - // We use 0x00 (zero) to represent dirty and 0xFF to represent clean because + // We use 0x00 (zero) to represent Dirty and 0xFF to represent Clean because // this choice reduces the barrier code by one instruction on architectures with - // a constant-zero register. On such architectures, the dirty value (0x00) is + // a constant-zero register. On such architectures, the Dirty value (0x00) is // directly accessible through the zero register, eliminating the need to load // the value explicitly and thereby saving one instruction //