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]
This commit is contained in:
Aaron Patterson 2021-05-25 16:20:52 -07:00 коммит произвёл Aaron Patterson
Родитель 2a29a5311c
Коммит fc832ffbfa
2 изменённых файлов: 44 добавлений и 15 удалений

18
gc.c
Просмотреть файл

@ -9998,6 +9998,24 @@ heap_check_moved_i(void *vstart, void *vend, size_t stride, void *data)
static VALUE static VALUE
gc_compact(rb_execution_context_t *ec, VALUE self) gc_compact(rb_execution_context_t *ec, VALUE self)
{ {
#if defined(HAVE_SYSCONF) && defined(_SC_PAGE_SIZE)
/* If Ruby's heap pages are not a multiple of the system page size, we
* cannot use mprotect for the read barrier, so we must disable compaction. */
int pagesize;
pagesize = (int)sysconf(_SC_PAGE_SIZE);
if ((HEAP_PAGE_SIZE % pagesize) != 0) {
rb_raise(rb_eNotImpError, "Compaction isn't available on this platform");
}
#endif
/* If not MinGW, Windows, or does not have mmap, we cannot use mprotect for
* the read barrier, so we must disable compaction. */
#if !defined(__MINGW32__) && !defined(_WIN32)
if (!USE_MMAP_ALIGNED_ALLOC) {
rb_raise(rb_eNotImpError, "Compaction isn't available on this platform");
}
#endif
/* Run GC with compaction enabled */ /* Run GC with compaction enabled */
gc_start_internal(ec, self, Qtrue, Qtrue, Qtrue, Qtrue); gc_start_internal(ec, self, Qtrue, Qtrue, Qtrue, Qtrue);

Просмотреть файл

@ -4,12 +4,32 @@ require 'fiddle'
require 'etc' require 'etc'
class TestGCCompact < Test::Unit::TestCase class TestGCCompact < Test::Unit::TestCase
class AutoCompact < Test::Unit::TestCase module SupportsCompact
def setup def setup
skip "autocompact not supported on this platform" unless supports_auto_compact? skip "autocompact not supported on this platform" unless supports_auto_compact?
super super
end end
private
def supports_auto_compact?
return true unless defined?(Etc::SC_PAGE_SIZE)
begin
return GC::INTERNAL_CONSTANTS[:HEAP_PAGE_SIZE] % Etc.sysconf(Etc::SC_PAGE_SIZE) == 0
rescue NotImplementedError
rescue ArgumentError
end
true
end
end
include SupportsCompact
class AutoCompact < Test::Unit::TestCase
include SupportsCompact
def test_enable_autocompact def test_enable_autocompact
before = GC.auto_compact before = GC.auto_compact
GC.auto_compact = true GC.auto_compact = true
@ -59,26 +79,17 @@ class TestGCCompact < Test::Unit::TestCase
ensure ensure
GC.auto_compact = before GC.auto_compact = before
end end
private
def supports_auto_compact?
return true unless defined?(Etc::SC_PAGE_SIZE)
begin
return GC::INTERNAL_CONSTANTS[:HEAP_PAGE_SIZE] % Etc.sysconf(Etc::SC_PAGE_SIZE) == 0
rescue NotImplementedError
rescue ArgumentError
end
true
end
end end
def os_page_size def os_page_size
return true unless defined?(Etc::SC_PAGE_SIZE) return true unless defined?(Etc::SC_PAGE_SIZE)
end end
def setup
skip "autocompact not supported on this platform" unless supports_auto_compact?
super
end
def test_gc_compact_stats def test_gc_compact_stats
list = [] list = []