Skip to content

Commit fc832ff

Browse files
committed
Disable compaction on platforms that can't support it
Manual compaction also requires a read barrier, so we need to disable even manual compaction on platforms that don't support mprotect. [Bug #17871]
1 parent 2a29a53 commit fc832ff

File tree

2 files changed

+44
-15
lines changed

2 files changed

+44
-15
lines changed

gc.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9998,6 +9998,24 @@ heap_check_moved_i(void *vstart, void *vend, size_t stride, void *data)
99989998
static VALUE
99999999
gc_compact(rb_execution_context_t *ec, VALUE self)
1000010000
{
10001+
#if defined(HAVE_SYSCONF) && defined(_SC_PAGE_SIZE)
10002+
/* If Ruby's heap pages are not a multiple of the system page size, we
10003+
* cannot use mprotect for the read barrier, so we must disable compaction. */
10004+
int pagesize;
10005+
pagesize = (int)sysconf(_SC_PAGE_SIZE);
10006+
if ((HEAP_PAGE_SIZE % pagesize) != 0) {
10007+
rb_raise(rb_eNotImpError, "Compaction isn't available on this platform");
10008+
}
10009+
#endif
10010+
10011+
/* If not MinGW, Windows, or does not have mmap, we cannot use mprotect for
10012+
* the read barrier, so we must disable compaction. */
10013+
#if !defined(__MINGW32__) && !defined(_WIN32)
10014+
if (!USE_MMAP_ALIGNED_ALLOC) {
10015+
rb_raise(rb_eNotImpError, "Compaction isn't available on this platform");
10016+
}
10017+
#endif
10018+
1000110019
/* Run GC with compaction enabled */
1000210020
gc_start_internal(ec, self, Qtrue, Qtrue, Qtrue, Qtrue);
1000310021

test/ruby/test_gc_compact.rb

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,32 @@
44
require 'etc'
55

66
class TestGCCompact < Test::Unit::TestCase
7-
class AutoCompact < Test::Unit::TestCase
7+
module SupportsCompact
88
def setup
99
skip "autocompact not supported on this platform" unless supports_auto_compact?
1010
super
1111
end
1212

13+
private
14+
15+
def supports_auto_compact?
16+
return true unless defined?(Etc::SC_PAGE_SIZE)
17+
18+
begin
19+
return GC::INTERNAL_CONSTANTS[:HEAP_PAGE_SIZE] % Etc.sysconf(Etc::SC_PAGE_SIZE) == 0
20+
rescue NotImplementedError
21+
rescue ArgumentError
22+
end
23+
24+
true
25+
end
26+
end
27+
28+
include SupportsCompact
29+
30+
class AutoCompact < Test::Unit::TestCase
31+
include SupportsCompact
32+
1333
def test_enable_autocompact
1434
before = GC.auto_compact
1535
GC.auto_compact = true
@@ -59,26 +79,17 @@ def test_implicit_compaction_does_something
5979
ensure
6080
GC.auto_compact = before
6181
end
62-
63-
private
64-
65-
def supports_auto_compact?
66-
return true unless defined?(Etc::SC_PAGE_SIZE)
67-
68-
begin
69-
return GC::INTERNAL_CONSTANTS[:HEAP_PAGE_SIZE] % Etc.sysconf(Etc::SC_PAGE_SIZE) == 0
70-
rescue NotImplementedError
71-
rescue ArgumentError
72-
end
73-
74-
true
75-
end
7682
end
7783

7884
def os_page_size
7985
return true unless defined?(Etc::SC_PAGE_SIZE)
8086
end
8187

88+
def setup
89+
skip "autocompact not supported on this platform" unless supports_auto_compact?
90+
super
91+
end
92+
8293
def test_gc_compact_stats
8394
list = []
8495

0 commit comments

Comments
 (0)