зеркало из https://github.com/github/ruby.git
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:
Родитель
2a29a5311c
Коммит
fc832ffbfa
18
gc.c
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 = []
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче