2000-05-01 13:42:38 +04:00
/**********************************************************************
1998-01-16 15:13:05 +03:00
gc . c -
$ Author $
created at : Tue Oct 5 09 : 44 : 46 JST 1993
* encoding.c: provide basic features for M17N.
* parse.y: encoding aware parsing.
* parse.y (pragma_encoding): encoding specification pragma.
* parse.y (rb_intern3): encoding specified symbols.
* string.c (rb_str_length): length based on characters.
for older behavior, bytesize method added.
* string.c (rb_str_index_m): index based on characters. rindex as
well.
* string.c (succ_char): encoding aware succeeding string.
* string.c (rb_str_reverse): reverse based on characters.
* string.c (rb_str_inspect): encoding aware string description.
* string.c (rb_str_upcase_bang): encoding aware case conversion.
downcase, capitalize, swapcase as well.
* string.c (rb_str_tr_bang): tr based on characters. delete,
squeeze, tr_s, count as well.
* string.c (rb_str_split_m): split based on characters.
* string.c (rb_str_each_line): encoding aware each_line.
* string.c (rb_str_each_char): added. iteration based on
characters.
* string.c (rb_str_strip_bang): encoding aware whitespace
stripping. lstrip, rstrip as well.
* string.c (rb_str_justify): encoding aware justifying (ljust,
rjust, center).
* string.c (str_encoding): get encoding attribute from a string.
* re.c (rb_reg_initialize): encoding aware regular expression
* sprintf.c (rb_str_format): formatting (i.e. length count) based
on characters.
* io.c (rb_io_getc): getc to return one-character string.
for older behavior, getbyte method added.
* ext/stringio/stringio.c (strio_getc): ditto.
* io.c (rb_io_ungetc): allow pushing arbitrary string at the
current reading point.
* ext/stringio/stringio.c (strio_ungetc): ditto.
* ext/strscan/strscan.c: encoding support.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13261 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-08-25 07:29:39 +04:00
Copyright ( C ) 1993 - 2007 Yukihiro Matsumoto
2000-05-01 13:42:38 +04:00
Copyright ( C ) 2000 Network Applied Communication Laboratory , Inc .
2000-05-09 08:53:16 +04:00
Copyright ( C ) 2000 Information - technology Promotion Agency , Japan
1998-01-16 15:13:05 +03:00
2000-05-01 13:42:38 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-01-16 15:13:05 +03:00
2007-06-10 07:06:15 +04:00
# include "ruby/ruby.h"
# include "ruby/st.h"
# include "ruby/re.h"
2007-11-20 06:16:53 +03:00
# include "ruby/io.h"
2012-07-10 17:57:11 +04:00
# include "ruby/thread.h"
2008-03-03 11:27:43 +03:00
# include "ruby/util.h"
2013-05-27 01:30:44 +04:00
# include "ruby/debug.h"
2008-03-12 08:47:10 +03:00
# include "eval_intern.h"
* blockinlining.c: remove "yarv" prefix.
* array.c, numeric.c: ditto.
* insnhelper.ci, insns.def, vm_evalbody.ci: ditto.
* yarvcore.c: removed.
* yarvcore.h: renamed to core.h.
* cont.c, debug.c, error.c, process.c, signal.c : ditto.
* ext/probeprofiler/probeprofiler.c: ditto.
* id.c, id.h: added.
* inits.c: ditto.
* compile.c: rename internal functions.
* compile.h: fix debug flag.
* eval.c, object.c, vm.c: remove ruby_top_self.
use rb_vm_top_self() instead.
* eval_intern.h, eval_load: ditto.
* gc.c: rename yarv_machine_stack_mark() to
rb_gc_mark_machine_stack().
* insnhelper.h: remove unused macros.
* iseq.c: add iseq_compile() to create iseq object
from source string.
* proc.c: rename a internal function.
* template/insns.inc.tmpl: remove YARV prefix.
* thread.c:
* vm.c (rb_iseq_eval): added.
* vm.c: move some functions from yarvcore.c.
* vm_dump.c: fix to remove compiler warning.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12741 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-07-12 08:25:46 +04:00
# include "vm_core.h"
2011-05-18 17:41:54 +04:00
# include "internal.h"
2007-05-29 19:49:30 +04:00
# include "gc.h"
2010-10-26 21:27:32 +04:00
# include "constant.h"
2012-11-09 20:05:07 +04:00
# include "ruby_atomic.h"
* probes.d: add DTrace probe declarations. [ruby-core:27448]
* array.c (empty_ary_alloc, ary_new): added array create DTrace probe.
* compile.c (rb_insns_name): allowing DTrace probes to access
instruction sequence name.
* Makefile.in: translate probes.d file to appropriate header file.
* common.mk: declare dependencies on the DTrace header.
* configure.in: add a test for existence of DTrace.
* eval.c (setup_exception): add a probe for when an exception is
raised.
* gc.c: Add DTrace probes for mark begin and end, and sweep begin and
end.
* hash.c (empty_hash_alloc): Add a probe for hash allocation.
* insns.def: Add probes for function entry and return.
* internal.h: function declaration for compile.c change.
* load.c (rb_f_load): add probes for `load` entry and exit, require
entry and exit, and wrapping search_required for load path search.
* object.c (rb_obj_alloc): added a probe for general object creation.
* parse.y (yycompile0): added a probe around parse and compile phase.
* string.c (empty_str_alloc, str_new): DTrace probes for string
allocation.
* test/dtrace/*: tests for DTrace probes.
* vm.c (vm_invoke_proc): add probes for function return on exception
raise, hash create, and instruction sequence execution.
* vm_core.h: add probe declarations for function entry and exit.
* vm_dump.c: add probes header file.
* vm_eval.c (vm_call0_cfunc, vm_call0_cfunc_with_frame): add probe on
function entry and return.
* vm_exec.c: expose instruction number to instruction name function.
* vm_insnshelper.c: add function entry and exit probes for cfunc
methods.
* vm_insnhelper.h: vm usage information is always collected, so
uncomment the functions.
12 19:14:50 2012 Akinori MUSHA <knu@iDaemons.org>
* configure.in (isinf, isnan): isinf() and isnan() are macros on
DragonFly which cannot be found by AC_REPLACE_FUNCS(). This
workaround enforces the fact that they exist on DragonFly.
12 15:59:38 2012 Shugo Maeda <shugo@ruby-lang.org>
* vm_core.h (rb_call_info_t::refinements), compile.c (new_callinfo),
vm_insnhelper.c (vm_search_method): revert r37616 because it's too
slow. [ruby-dev:46477]
* test/ruby/test_refinement.rb (test_inline_method_cache): skip
the test until the bug is fixed efficiently.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37631 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-11-13 01:52:12 +04:00
# include "probes.h"
1998-01-16 15:13:05 +03:00
# include <stdio.h>
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
# include <stdarg.h>
1998-01-16 15:13:05 +03:00
# include <setjmp.h>
2001-11-19 17:42:45 +03:00
# include <sys/types.h>
2012-01-07 18:02:23 +04:00
# include <assert.h>
2001-11-19 17:42:45 +03:00
2013-09-26 10:06:19 +04:00
# ifndef __has_feature
# define __has_feature(x) 0
# endif
2013-11-21 13:52:09 +04:00
# ifndef HAVE_MALLOC_USABLE_SIZE
# ifdef _WIN32
2013-11-25 05:13:31 +04:00
# define HAVE_MALLOC_USABLE_SIZE
2013-11-21 13:52:09 +04:00
# define malloc_usable_size(a) _msize(a)
2013-12-03 18:48:20 +04:00
# elif defined HAVE_MALLOC_SIZE
# define HAVE_MALLOC_USABLE_SIZE
# define malloc_usable_size(a) malloc_size(a)
2013-11-21 13:52:09 +04:00
# endif
2013-12-03 18:48:20 +04:00
# endif
# ifdef HAVE_MALLOC_USABLE_SIZE
2013-11-22 04:05:34 +04:00
# ifdef HAVE_MALLOC_H
# include <malloc.h>
# elif defined(HAVE_MALLOC_NP_H)
# include <malloc_np.h>
2013-12-03 18:48:20 +04:00
# elif defined(HAVE_MALLOC_MALLOC_H)
# include <malloc / malloc.h>
2013-11-22 04:05:34 +04:00
# endif
2013-11-21 13:52:09 +04:00
# endif
2013-09-26 10:06:19 +04:00
# if /* is ASAN enabled? */ \
__has_feature ( address_sanitizer ) /* Clang */ | | \
2013-09-26 09:46:52 +04:00
defined ( __SANITIZE_ADDRESS__ ) /* GCC 4.8.x */
# define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS \
__attribute__ ( ( no_address_safety_analysis ) ) \
__attribute__ ( ( noinline ) )
# else
# define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS
# endif
2001-11-19 17:42:45 +03:00
# ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
# endif
1998-01-16 15:13:05 +03:00
2001-11-19 08:03:03 +03:00
# ifdef HAVE_SYS_RESOURCE_H
# include <sys/resource.h>
2012-05-17 06:48:59 +04:00
# endif
# if defined(__native_client__) && defined(NACL_NEWLIB)
# include "nacl / resource.h"
# undef HAVE_POSIX_MEMALIGN
# undef HAVE_MEMALIGN
2001-11-19 08:03:03 +03:00
# endif
2004-07-08 14:27:23 +04:00
# if defined _WIN32 || defined __CYGWIN__
# include <windows.h>
2012-01-09 02:50:59 +04:00
# elif defined(HAVE_POSIX_MEMALIGN)
# elif defined(HAVE_MEMALIGN)
2012-01-07 19:13:37 +04:00
# include <malloc.h>
# endif
2008-03-31 21:58:41 +04:00
# define rb_setjmp(env) RUBY_SETJMP(env)
# define rb_jmp_buf rb_jmpbuf_t
1998-01-16 15:13:05 +03:00
2013-05-17 12:35:26 +04:00
# if defined(HAVE_RB_GC_GUARDED_PTR) && HAVE_RB_GC_GUARDED_PTR
volatile VALUE *
rb_gc_guarded_ptr ( volatile VALUE * ptr )
{
return ptr ;
}
# endif
2013-11-23 07:33:10 +04:00
# ifndef GC_HEAP_FREE_SLOTS
# define GC_HEAP_FREE_SLOTS 4096
2013-09-27 12:01:14 +04:00
# endif
2013-11-23 07:33:10 +04:00
# ifndef GC_HEAP_INIT_SLOTS
# define GC_HEAP_INIT_SLOTS 10000
2013-09-27 12:01:14 +04:00
# endif
# ifndef GC_HEAP_GROWTH_FACTOR
# define GC_HEAP_GROWTH_FACTOR 1.8
# endif
2013-11-23 07:33:10 +04:00
# ifndef GC_HEAP_GROWTH_MAX_SLOTS
# define GC_HEAP_GROWTH_MAX_SLOTS 0 /* 0 is disable */
2013-10-24 02:47:29 +04:00
# endif
2014-02-17 07:27:13 +04:00
# ifndef GC_HEAP_OLDOBJECT_LIMIT_FACTOR
# define GC_HEAP_OLDOBJECT_LIMIT_FACTOR 2.0
# endif
2013-11-05 08:51:01 +04:00
2013-11-21 12:20:34 +04:00
# ifndef GC_MALLOC_LIMIT_MIN
# define GC_MALLOC_LIMIT_MIN (16 * 1024 * 1024 /* 16MB */ )
2002-10-10 19:26:58 +04:00
# endif
2013-09-27 12:01:14 +04:00
# ifndef GC_MALLOC_LIMIT_MAX
2013-11-07 14:45:01 +04:00
# define GC_MALLOC_LIMIT_MAX (32 * 1024 * 1024 /* 32MB */ )
2013-09-27 12:01:14 +04:00
# endif
2013-09-27 13:36:48 +04:00
# ifndef GC_MALLOC_LIMIT_GROWTH_FACTOR
2013-11-07 14:45:01 +04:00
# define GC_MALLOC_LIMIT_GROWTH_FACTOR 1.4
2013-09-27 12:01:14 +04:00
# endif
2011-03-07 11:39:39 +03:00
2013-11-24 22:13:48 +04:00
# ifndef GC_OLDMALLOC_LIMIT_MIN
# define GC_OLDMALLOC_LIMIT_MIN (16 * 1024 * 1024 /* 16MB */ )
2013-11-05 08:51:01 +04:00
# endif
2013-11-24 22:13:48 +04:00
# ifndef GC_OLDMALLOC_LIMIT_GROWTH_FACTOR
# define GC_OLDMALLOC_LIMIT_GROWTH_FACTOR 1.2
2013-11-05 08:51:01 +04:00
# endif
2013-11-24 22:13:48 +04:00
# ifndef GC_OLDMALLOC_LIMIT_MAX
# define GC_OLDMALLOC_LIMIT_MAX (128 * 1024 * 1024 /* 128MB */ )
2013-11-05 08:51:01 +04:00
# endif
2011-10-21 17:02:19 +04:00
typedef struct {
2014-02-07 05:54:26 +04:00
size_t heap_init_slots ;
size_t heap_free_slots ;
2013-11-21 12:50:40 +04:00
double growth_factor ;
2014-02-07 05:54:26 +04:00
size_t growth_max_slots ;
2014-02-17 07:27:13 +04:00
double oldobject_limit_factor ;
2014-02-07 05:54:26 +04:00
size_t malloc_limit_min ;
size_t malloc_limit_max ;
2013-11-21 12:50:40 +04:00
double malloc_limit_growth_factor ;
2014-02-07 05:54:26 +04:00
size_t oldmalloc_limit_min ;
size_t oldmalloc_limit_max ;
2013-11-24 22:13:48 +04:00
double oldmalloc_limit_growth_factor ;
2011-06-12 04:32:32 +04:00
# if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
2013-06-19 02:45:41 +04:00
VALUE gc_stress ;
2011-06-12 04:32:32 +04:00
# endif
2011-10-21 17:02:19 +04:00
} ruby_gc_params_t ;
2013-11-21 12:50:40 +04:00
static ruby_gc_params_t gc_params = {
2013-11-23 07:33:10 +04:00
GC_HEAP_FREE_SLOTS ,
GC_HEAP_INIT_SLOTS ,
2013-09-27 12:01:14 +04:00
GC_HEAP_GROWTH_FACTOR ,
2013-11-23 07:33:10 +04:00
GC_HEAP_GROWTH_MAX_SLOTS ,
2014-02-17 07:27:13 +04:00
GC_HEAP_OLDOBJECT_LIMIT_FACTOR ,
2013-11-21 12:20:34 +04:00
GC_MALLOC_LIMIT_MIN ,
2013-09-27 12:01:14 +04:00
GC_MALLOC_LIMIT_MAX ,
2013-09-27 13:36:48 +04:00
GC_MALLOC_LIMIT_GROWTH_FACTOR ,
2013-11-24 22:13:48 +04:00
GC_OLDMALLOC_LIMIT_MIN ,
GC_OLDMALLOC_LIMIT_MAX ,
GC_OLDMALLOC_LIMIT_GROWTH_FACTOR ,
2011-10-21 17:02:19 +04:00
# if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
FALSE ,
# endif
} ;
2011-03-07 11:39:39 +03:00
2013-08-19 16:00:51 +04:00
/* GC_DEBUG:
* enable to embed GC debugging information .
*/
# ifndef GC_DEBUG
# define GC_DEBUG 0
# endif
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
# if USE_RGENGC
/* RGENGC_DEBUG:
2013-05-22 03:09:22 +04:00
* 1 : basic information
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
* 2 : remember set operation
* 3 : mark
2013-05-14 05:54:48 +04:00
* 4 :
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
* 5 : sweep
*/
# ifndef RGENGC_DEBUG
# define RGENGC_DEBUG 0
# endif
/* RGENGC_CHECK_MODE
2013-05-15 12:07:30 +04:00
* 0 : disable all assertions
* 1 : enable assertions ( to debug RGenGC )
2013-12-10 10:44:35 +04:00
* 2 : enable generational bits check ( for debugging )
* 3 : enable livness check
* 4 : show all references
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
*/
# ifndef RGENGC_CHECK_MODE
2013-11-21 17:34:38 +04:00
# define RGENGC_CHECK_MODE 0
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
# endif
2013-05-15 12:07:30 +04:00
/* RGENGC_PROFILE
* 0 : disable RGenGC profiling
* 1 : enable profiling for basic information
* 2 : enable profiling for each types
*/
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
# ifndef RGENGC_PROFILE
2013-06-21 10:04:29 +04:00
# define RGENGC_PROFILE 0
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
# endif
2013-11-04 22:59:33 +04:00
/* RGENGC_THREEGEN
* Enable / disable three gen GC .
* 0 : Infant gen - > Old gen
* 1 : Infant gen - > Young - > Old gen
*/
# ifndef RGENGC_THREEGEN
# define RGENGC_THREEGEN 0
# endif
2013-11-24 23:49:02 +04:00
/* RGENGC_ESTIMATE_OLDMALLOC
* Enable / disable to estimate increase size of malloc ' ed size by old objects .
2014-01-19 09:43:28 +04:00
* If estimation exceeds threshold , then will invoke full GC .
2013-11-05 08:51:01 +04:00
* 0 : disable estimation .
* 1 : enable estimation .
*/
2013-11-24 23:49:02 +04:00
# ifndef RGENGC_ESTIMATE_OLDMALLOC
# define RGENGC_ESTIMATE_OLDMALLOC 1
2013-11-05 08:51:01 +04:00
# endif
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
# else /* USE_RGENGC */
2013-11-06 04:14:26 +04:00
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
# define RGENGC_DEBUG 0
# define RGENGC_CHECK_MODE 0
# define RGENGC_PROFILE 0
2013-11-04 22:59:33 +04:00
# define RGENGC_THREEGEN 0
2013-11-24 23:49:02 +04:00
# define RGENGC_ESTIMATE_OLDMALLOC 0
2013-11-06 04:14:26 +04:00
# endif /* USE_RGENGC */
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
2011-09-10 03:34:05 +04:00
# ifndef GC_PROFILE_MORE_DETAIL
2013-06-21 10:04:29 +04:00
# define GC_PROFILE_MORE_DETAIL 0
2011-09-10 03:34:05 +04:00
# endif
2013-11-09 03:59:20 +04:00
# ifndef GC_PROFILE_DETAIL_MEMORY
# define GC_PROFILE_DETAIL_MEMORY 0
# endif
2013-03-24 08:53:44 +04:00
# ifndef GC_ENABLE_LAZY_SWEEP
2013-06-21 10:08:07 +04:00
# define GC_ENABLE_LAZY_SWEEP 1
2013-03-24 08:53:44 +04:00
# endif
2013-06-16 00:18:11 +04:00
# ifndef CALC_EXACT_MALLOC_SIZE
# define CALC_EXACT_MALLOC_SIZE 0
# endif
2013-12-05 08:54:20 +04:00
# if defined(HAVE_MALLOC_USABLE_SIZE) || CALC_EXACT_MALLOC_SIZE > 0
# ifndef MALLOC_ALLOCATED_SIZE
# define MALLOC_ALLOCATED_SIZE 0
# endif
# else
# define MALLOC_ALLOCATED_SIZE 0
# endif
# ifndef MALLOC_ALLOCATED_SIZE_CHECK
# define MALLOC_ALLOCATED_SIZE_CHECK 0
2013-10-17 13:51:41 +04:00
# endif
2011-09-10 03:34:05 +04:00
2013-05-21 12:19:07 +04:00
typedef enum {
2013-11-24 23:49:02 +04:00
GPR_FLAG_NONE = 0x000 ,
2013-06-21 16:31:13 +04:00
/* major reason */
2013-11-24 23:49:02 +04:00
GPR_FLAG_MAJOR_BY_NOFREE = 0x001 ,
GPR_FLAG_MAJOR_BY_OLDGEN = 0x002 ,
GPR_FLAG_MAJOR_BY_SHADY = 0x004 ,
GPR_FLAG_MAJOR_BY_RESCAN = 0x008 ,
GPR_FLAG_MAJOR_BY_STRESS = 0x010 ,
# if RGENGC_ESTIMATE_OLDMALLOC
GPR_FLAG_MAJOR_BY_OLDMALLOC = 0x020 ,
# endif
GPR_FLAG_MAJOR_MASK = 0x0ff ,
2013-06-21 16:31:13 +04:00
/* gc reason */
2013-11-24 23:49:02 +04:00
GPR_FLAG_NEWOBJ = 0x100 ,
GPR_FLAG_MALLOC = 0x200 ,
GPR_FLAG_METHOD = 0x400 ,
GPR_FLAG_CAPI = 0x800 ,
GPR_FLAG_STRESS = 0x1000 ,
2013-06-21 16:31:13 +04:00
/* others */
2013-11-24 23:49:02 +04:00
GPR_FLAG_IMMEDIATE_SWEEP = 0x2000 ,
GPR_FLAG_HAVE_FINALIZE = 0x4000
2013-05-21 12:19:07 +04:00
} gc_profile_record_flag ;
2008-08-11 13:36:57 +04:00
typedef struct gc_profile_record {
2013-05-21 12:19:07 +04:00
int flags ;
2008-08-11 13:36:57 +04:00
double gc_time ;
2012-10-31 13:22:37 +04:00
double gc_invoke_time ;
size_t heap_total_objects ;
size_t heap_use_size ;
size_t heap_total_size ;
# if GC_PROFILE_MORE_DETAIL
2008-08-11 13:36:57 +04:00
double gc_mark_time ;
double gc_sweep_time ;
2009-05-13 18:08:26 +04:00
2013-10-18 10:33:36 +04:00
size_t heap_use_pages ;
2008-08-11 13:36:57 +04:00
size_t heap_live_objects ;
size_t heap_free_objects ;
2009-05-13 18:08:26 +04:00
2008-08-11 13:36:57 +04:00
size_t allocate_increase ;
size_t allocate_limit ;
2013-06-16 00:18:11 +04:00
double prepare_time ;
size_t removing_objects ;
size_t empty_objects ;
2013-11-09 03:59:20 +04:00
# if GC_PROFILE_DETAIL_MEMORY
long maxrss ;
long minflt ;
long majflt ;
# endif
2012-10-31 13:22:37 +04:00
# endif
2013-12-05 08:54:20 +04:00
# if MALLOC_ALLOCATED_SIZE
2013-10-03 13:03:06 +04:00
size_t allocated_size ;
# endif
2013-06-20 16:20:27 +04:00
# if RGENGC_PROFILE > 0
2013-11-04 22:59:33 +04:00
size_t old_objects ;
2013-06-20 16:20:27 +04:00
size_t remembered_normal_objects ;
size_t remembered_shady_objects ;
# endif
2008-08-11 13:36:57 +04:00
} gc_profile_record ;
2006-12-31 18:02:22 +03:00
# if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__)
# pragma pack(push, 1) /* magic for reducing sizeof(RVALUE): 24 -> 20 */
# endif
typedef struct RVALUE {
union {
struct {
2007-06-25 15:20:45 +04:00
VALUE flags ; /* always 0 for freed obj */
2006-12-31 18:02:22 +03:00
struct RVALUE * next ;
} free ;
struct RBasic basic ;
struct RObject object ;
struct RClass klass ;
struct RFloat flonum ;
struct RString string ;
struct RArray array ;
struct RRegexp regexp ;
struct RHash hash ;
struct RData data ;
2009-06-17 01:36:50 +04:00
struct RTypedData typeddata ;
2006-12-31 18:02:22 +03:00
struct RStruct rstruct ;
struct RBignum bignum ;
struct RFile file ;
struct RNode node ;
struct RMatch match ;
2008-03-16 03:23:43 +03:00
struct RRational rational ;
struct RComplex complex ;
2013-05-15 14:26:22 +04:00
struct {
struct RBasic basic ;
VALUE v1 ;
VALUE v2 ;
VALUE v3 ;
} values ;
2006-12-31 18:02:22 +03:00
} as ;
2013-08-19 16:00:51 +04:00
# if GC_DEBUG
2009-06-15 13:06:16 +04:00
const char * file ;
2013-08-19 16:00:51 +04:00
VALUE line ;
2006-12-31 18:02:22 +03:00
# endif
} RVALUE ;
# if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__)
# pragma pack(pop)
# endif
2013-06-21 03:15:18 +04:00
typedef uintptr_t bits_t ;
enum {
BITS_SIZE = sizeof ( bits_t ) ,
BITS_BITLENGTH = ( BITS_SIZE * CHAR_BIT )
} ;
2013-10-18 10:33:36 +04:00
struct heap_page_header {
struct heap_page * page ;
2013-07-17 09:55:39 +04:00
} ;
2013-10-18 10:33:36 +04:00
struct heap_page_body {
struct heap_page_header header ;
2013-07-17 09:55:39 +04:00
/* char gap[]; */
/* RVALUE values[]; */
2008-04-14 07:47:04 +04:00
} ;
2006-12-31 18:02:22 +03:00
2008-04-14 07:47:04 +04:00
struct gc_list {
VALUE * varptr ;
struct gc_list * next ;
} ;
2012-10-03 16:30:21 +04:00
# define STACK_CHUNK_SIZE 500
typedef struct stack_chunk {
VALUE data [ STACK_CHUNK_SIZE ] ;
struct stack_chunk * next ;
} stack_chunk_t ;
typedef struct mark_stack {
stack_chunk_t * chunk ;
stack_chunk_t * cache ;
size_t index ;
size_t limit ;
size_t cache_size ;
size_t unused_cache_size ;
} mark_stack_t ;
2013-10-22 14:28:31 +04:00
typedef struct rb_heap_struct {
2013-10-19 03:33:55 +04:00
struct heap_page * pages ;
struct heap_page * free_pages ;
struct heap_page * using_page ;
struct heap_page * sweep_pages ;
2013-10-22 14:28:31 +04:00
RVALUE * freelist ;
2013-11-27 05:42:25 +04:00
size_t page_length ; /* total page count in a heap */
size_t total_slots ; /* total slot count (page_length * HEAP_OBJ_LIMIT) */
2013-10-22 14:28:31 +04:00
} rb_heap_t ;
2013-10-19 03:33:55 +04:00
2008-04-27 07:20:35 +04:00
typedef struct rb_objspace {
2008-04-14 07:47:04 +04:00
struct {
2008-05-12 10:28:43 +04:00
size_t limit ;
size_t increase ;
2013-12-05 08:54:20 +04:00
# if MALLOC_ALLOCATED_SIZE
2008-06-08 14:27:06 +04:00
size_t allocated_size ;
size_t allocations ;
# endif
} malloc_params ;
2013-10-19 03:33:55 +04:00
2013-10-22 14:28:31 +04:00
rb_heap_t eden_heap ;
2013-10-23 12:48:54 +04:00
rb_heap_t tomb_heap ; /* heap for zombies and ghosts */
2013-10-22 14:28:31 +04:00
struct {
struct heap_page * * sorted ;
size_t used ;
size_t length ;
RVALUE * range [ 2 ] ;
size_t limit ;
2013-10-23 14:16:01 +04:00
size_t increment ;
2013-10-23 12:48:54 +04:00
2013-11-23 03:50:08 +04:00
size_t swept_slots ;
2013-10-23 19:05:22 +04:00
size_t min_free_slots ;
size_t max_free_slots ;
2013-10-22 14:28:31 +04:00
/* final */
2013-11-24 23:18:53 +04:00
size_t final_slots ;
2013-10-22 14:28:31 +04:00
RVALUE * deferred_final ;
} heap_pages ;
2013-10-19 03:33:55 +04:00
2008-04-14 07:47:04 +04:00
struct {
int dont_gc ;
2010-10-21 08:18:09 +04:00
int dont_lazy_sweep ;
2008-04-14 07:47:04 +04:00
int during_gc ;
2011-09-29 20:54:14 +04:00
rb_atomic_t finalizing ;
2008-04-14 07:47:04 +04:00
} flags ;
2013-10-22 14:28:31 +04:00
st_table * finalizer_table ;
2012-10-03 16:30:21 +04:00
mark_stack_t mark_stack ;
2008-08-11 13:36:57 +04:00
struct {
int run ;
2013-06-22 01:51:41 +04:00
gc_profile_record * records ;
gc_profile_record * current_record ;
2013-05-13 20:34:25 +04:00
size_t next_index ;
2008-08-11 13:36:57 +04:00
size_t size ;
2013-05-21 12:19:07 +04:00
2013-06-16 00:18:11 +04:00
# if GC_PROFILE_MORE_DETAIL
double prepare_time ;
# endif
2008-08-11 13:36:57 +04:00
double invoke_time ;
2013-05-13 20:34:25 +04:00
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
# if USE_RGENGC
size_t minor_gc_count ;
size_t major_gc_count ;
2013-11-04 22:59:33 +04:00
# if RGENGC_PROFILE > 0
2013-06-07 05:17:19 +04:00
size_t generated_normal_object_count ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
size_t generated_shady_object_count ;
size_t shade_operation_count ;
2013-11-04 22:59:33 +04:00
size_t promote_infant_count ;
# if RGENGC_THREEGEN
size_t promote_young_count ;
# endif
2013-06-07 05:17:19 +04:00
size_t remembered_normal_object_count ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
size_t remembered_shady_object_count ;
2013-06-20 16:20:27 +04:00
2013-05-15 12:07:30 +04:00
# if RGENGC_PROFILE >= 2
2013-06-18 06:27:37 +04:00
size_t generated_normal_object_count_types [ RUBY_T_MASK ] ;
2013-05-15 12:07:30 +04:00
size_t generated_shady_object_count_types [ RUBY_T_MASK ] ;
2013-05-26 20:43:21 +04:00
size_t shade_operation_count_types [ RUBY_T_MASK ] ;
2013-11-04 22:59:33 +04:00
size_t promote_infant_types [ RUBY_T_MASK ] ;
# if RGENGC_THREEGEN
size_t promote_young_types [ RUBY_T_MASK ] ;
# endif
2013-06-07 05:17:19 +04:00
size_t remembered_normal_object_count_types [ RUBY_T_MASK ] ;
2013-05-26 20:43:21 +04:00
size_t remembered_shady_object_count_types [ RUBY_T_MASK ] ;
2013-05-15 12:07:30 +04:00
# endif
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
# endif /* RGENGC_PROFILE */
# endif /* USE_RGENGC */
2013-06-20 00:49:28 +04:00
/* temporary profiling space */
double gc_sweep_start_time ;
2013-06-21 09:17:40 +04:00
size_t total_allocated_object_num_at_gc_start ;
2013-07-17 09:55:39 +04:00
size_t heap_used_at_gc_start ;
2013-11-01 16:49:49 +04:00
/* basic statistics */
size_t count ;
size_t total_allocated_object_num ;
size_t total_freed_object_num ;
2013-12-05 14:30:38 +04:00
int latest_gc_info ;
2008-08-11 13:36:57 +04:00
} profile ;
2008-04-14 07:47:04 +04:00
struct gc_list * global_list ;
2013-05-27 04:21:02 +04:00
rb_event_flag_t hook_events ; /* this place may be affinity with memory cache */
2013-06-19 02:45:41 +04:00
VALUE gc_stress ;
2012-10-05 12:14:09 +04:00
struct mark_func_data_struct {
2012-10-24 04:04:56 +04:00
void * data ;
void ( * mark_func ) ( VALUE v , void * data ) ;
2012-10-05 12:14:09 +04:00
} * mark_func_data ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
2013-06-21 03:10:34 +04:00
# if USE_RGENGC
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
struct {
int during_minor_gc ;
2013-11-04 22:59:33 +04:00
int parent_object_is_old ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
2013-05-24 14:21:04 +04:00
int need_major_gc ;
size_t remembered_shady_object_count ;
size_t remembered_shady_object_limit ;
2013-11-04 22:59:33 +04:00
size_t old_object_count ;
size_t old_object_limit ;
# if RGENGC_THREEGEN
size_t young_object_count ;
# endif
2013-11-24 23:49:02 +04:00
# if RGENGC_ESTIMATE_OLDMALLOC
size_t oldmalloc_increase ;
size_t oldmalloc_increase_limit ;
2013-11-05 08:51:01 +04:00
# endif
2013-06-22 10:43:30 +04:00
# if RGENGC_CHECK_MODE >= 2
2013-11-21 08:57:37 +04:00
struct st_table * allrefs_table ;
size_t error_count ;
2013-06-22 10:43:30 +04:00
# endif
2013-05-24 14:21:04 +04:00
} rgengc ;
2013-06-21 03:10:34 +04:00
# endif /* USE_RGENGC */
2008-04-14 07:47:04 +04:00
} rb_objspace_t ;
2013-06-21 03:15:18 +04:00
# ifndef HEAP_ALIGN_LOG
/* default tiny heap size: 16KB */
# define HEAP_ALIGN_LOG 14
# endif
# define CEILDIV(i, mod) (((i) + (mod) - 1) / (mod))
enum {
HEAP_ALIGN = ( 1UL < < HEAP_ALIGN_LOG ) ,
HEAP_ALIGN_MASK = ( ~ ( ~ 0UL < < HEAP_ALIGN_LOG ) ) ,
REQUIRED_SIZE_BY_MALLOC = ( sizeof ( size_t ) * 5 ) ,
HEAP_SIZE = ( HEAP_ALIGN - REQUIRED_SIZE_BY_MALLOC ) ,
2013-10-18 10:33:36 +04:00
HEAP_OBJ_LIMIT = ( unsigned int ) ( ( HEAP_SIZE - sizeof ( struct heap_page_header ) ) / sizeof ( struct RVALUE ) ) ,
2013-06-21 03:15:18 +04:00
HEAP_BITMAP_LIMIT = CEILDIV ( CEILDIV ( HEAP_SIZE , sizeof ( struct RVALUE ) ) , BITS_BITLENGTH ) ,
HEAP_BITMAP_SIZE = ( BITS_SIZE * HEAP_BITMAP_LIMIT ) ,
HEAP_BITMAP_PLANES = USE_RGENGC ? 3 : 1 /* RGENGC: mark bits, rememberset bits and oldgen bits */
} ;
2013-10-18 10:33:36 +04:00
struct heap_page {
struct heap_page_body * body ;
2013-10-23 12:48:54 +04:00
RVALUE * freelist ;
2013-07-17 08:34:57 +04:00
RVALUE * start ;
2013-11-24 23:18:53 +04:00
size_t final_slots ;
2013-07-17 08:34:57 +04:00
size_t limit ;
2013-10-18 10:33:36 +04:00
struct heap_page * next ;
struct heap_page * prev ;
struct heap_page * free_next ;
2013-10-23 12:48:54 +04:00
rb_heap_t * heap ;
2013-11-01 17:47:39 +04:00
int before_sweep ;
2013-06-21 05:26:50 +04:00
bits_t mark_bits [ HEAP_BITMAP_LIMIT ] ;
# if USE_RGENGC
bits_t rememberset_bits [ HEAP_BITMAP_LIMIT ] ;
bits_t oldgen_bits [ HEAP_BITMAP_LIMIT ] ;
# endif
} ;
2013-10-18 10:33:36 +04:00
# define GET_PAGE_BODY(x) ((struct heap_page_body *)((bits_t)(x) & ~(HEAP_ALIGN_MASK)))
# define GET_PAGE_HEADER(x) (&GET_PAGE_BODY(x)->header)
# define GET_HEAP_PAGE(x) (GET_PAGE_HEADER(x)->page)
# define GET_HEAP_MARK_BITS(x) (&GET_HEAP_PAGE(x)->mark_bits[0])
# define GET_HEAP_REMEMBERSET_BITS(x) (&GET_HEAP_PAGE(x)->rememberset_bits[0])
# define GET_HEAP_OLDGEN_BITS(x) (&GET_HEAP_PAGE(x)->oldgen_bits[0])
# define NUM_IN_PAGE(p) (((bits_t)(p) & HEAP_ALIGN_MASK) / sizeof(RVALUE))
# define BITMAP_INDEX(p) (NUM_IN_PAGE(p) / BITS_BITLENGTH )
# define BITMAP_OFFSET(p) (NUM_IN_PAGE(p) & (BITS_BITLENGTH-1))
2013-06-21 05:26:50 +04:00
# define BITMAP_BIT(p) ((bits_t)1 << BITMAP_OFFSET(p))
2013-06-21 03:15:18 +04:00
/* Bitmap Operations */
2013-06-21 05:26:50 +04:00
# define MARKED_IN_BITMAP(bits, p) ((bits)[BITMAP_INDEX(p)] & BITMAP_BIT(p))
# define MARK_IN_BITMAP(bits, p) ((bits)[BITMAP_INDEX(p)] = (bits)[BITMAP_INDEX(p)] | BITMAP_BIT(p))
# define CLEAR_IN_BITMAP(bits, p) ((bits)[BITMAP_INDEX(p)] = (bits)[BITMAP_INDEX(p)] & ~BITMAP_BIT(p))
2013-06-21 03:15:18 +04:00
/* Aliases */
2008-04-27 07:20:35 +04:00
# if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
# define rb_objspace (*GET_VM()->objspace)
2013-11-21 12:50:40 +04:00
# define ruby_initial_gc_stress gc_params.gc_stress
2013-06-19 02:45:41 +04:00
VALUE * ruby_initial_gc_stress_ptr = & ruby_initial_gc_stress ;
2008-04-27 07:20:35 +04:00
# else
2013-11-21 12:20:34 +04:00
static rb_objspace_t rb_objspace = { { GC_MALLOC_LIMIT_MIN } } ;
2013-06-19 20:01:16 +04:00
VALUE * ruby_initial_gc_stress_ptr = & rb_objspace . gc_stress ;
2008-04-27 07:20:35 +04:00
# endif
2013-07-18 03:19:38 +04:00
2008-06-08 14:27:06 +04:00
# define malloc_limit objspace->malloc_params.limit
# define malloc_increase objspace->malloc_params.increase
2013-06-16 00:18:11 +04:00
# define malloc_allocated_size objspace->malloc_params.allocated_size
2013-10-22 14:28:31 +04:00
# define heap_pages_sorted objspace->heap_pages.sorted
# define heap_pages_used objspace->heap_pages.used
# define heap_pages_length objspace->heap_pages.length
# define heap_pages_lomem objspace->heap_pages.range[0]
# define heap_pages_himem objspace->heap_pages.range[1]
2013-11-23 03:50:08 +04:00
# define heap_pages_swept_slots objspace->heap_pages.swept_slots
2013-10-23 14:16:01 +04:00
# define heap_pages_increment objspace->heap_pages.increment
2013-10-23 19:05:22 +04:00
# define heap_pages_min_free_slots objspace->heap_pages.min_free_slots
# define heap_pages_max_free_slots objspace->heap_pages.max_free_slots
2013-11-24 23:18:53 +04:00
# define heap_pages_final_slots objspace->heap_pages.final_slots
2013-10-22 14:28:31 +04:00
# define heap_pages_deferred_final objspace->heap_pages.deferred_final
# define heap_eden (&objspace->eden_heap)
2013-10-23 12:48:54 +04:00
# define heap_tomb (&objspace->tomb_heap)
2008-04-14 07:47:04 +04:00
# define dont_gc objspace->flags.dont_gc
# define during_gc objspace->flags.during_gc
2011-09-29 20:54:14 +04:00
# define finalizing objspace->flags.finalizing
2013-10-22 14:28:31 +04:00
# define finalizer_table objspace->finalizer_table
2008-04-14 07:47:04 +04:00
# define global_List objspace->global_list
2008-06-13 19:09:22 +04:00
# define ruby_gc_stress objspace->gc_stress
2013-06-24 19:57:16 +04:00
# define monitor_level objspace->rgengc.monitor_level
# define monitored_object_table objspace->rgengc.monitored_object_table
2008-04-14 07:47:04 +04:00
2013-10-22 14:28:31 +04:00
# define is_lazy_sweeping(heap) ((heap)->sweep_pages != 0)
2012-12-20 11:43:54 +04:00
# if SIZEOF_LONG == SIZEOF_VOIDP
# define nonspecial_obj_id(obj) (VALUE)((SIGNED_VALUE)(obj)|FIXNUM_FLAG)
2012-12-22 08:25:18 +04:00
# define obj_id_to_ref(objid) ((objid) ^ FIXNUM_FLAG) /* unset FIXNUM_FLAG */
2012-12-20 11:43:54 +04:00
# elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
# define nonspecial_obj_id(obj) LL2NUM((SIGNED_VALUE)(obj) / 2)
2012-12-22 08:25:18 +04:00
# define obj_id_to_ref(objid) (FIXNUM_P(objid) ? \
( ( objid ) ^ FIXNUM_FLAG ) : ( NUM2PTR ( objid ) < < 1 ) )
2012-12-20 11:43:54 +04:00
# else
# error not supported
# endif
2011-09-29 15:09:48 +04:00
2012-08-05 14:39:37 +04:00
# define RANY(o) ((RVALUE*)(o))
2013-07-18 03:19:38 +04:00
# define nomem_error GET_VM()->special_exceptions[ruby_error_nomemory]
2012-08-05 14:39:37 +04:00
int ruby_gc_debug_indent = 0 ;
VALUE rb_mGC ;
int ruby_disable_gc_stress = 0 ;
2012-01-07 18:02:23 +04:00
2013-07-18 03:19:38 +04:00
void rb_gcdebug_print_obj_condition ( VALUE obj ) ;
2009-09-18 11:29:17 +04:00
static void rb_objspace_call_finalizer ( rb_objspace_t * objspace ) ;
2012-03-13 07:37:06 +04:00
static VALUE define_final0 ( VALUE obj , VALUE block ) ;
2012-08-05 14:39:37 +04:00
static void negative_size_allocation_error ( const char * ) ;
static void * aligned_malloc ( size_t , size_t ) ;
static void aligned_free ( void * ) ;
2012-10-03 16:30:21 +04:00
static void init_mark_stack ( mark_stack_t * stack ) ;
2012-08-05 14:39:37 +04:00
static VALUE lazy_sweep_enable ( void ) ;
2013-07-18 03:19:38 +04:00
static int ready_to_gc ( rb_objspace_t * objspace ) ;
2013-10-22 14:28:31 +04:00
static int heap_ready_to_gc ( rb_objspace_t * objspace , rb_heap_t * heap ) ;
2013-05-22 03:09:22 +04:00
static int garbage_collect ( rb_objspace_t * , int full_mark , int immediate_sweep , int reason ) ;
static int garbage_collect_body ( rb_objspace_t * , int full_mark , int immediate_sweep , int reason ) ;
2013-10-22 14:28:31 +04:00
static int gc_heap_lazy_sweep ( rb_objspace_t * objspace , rb_heap_t * heap ) ;
2013-07-18 03:19:38 +04:00
static void gc_rest_sweep ( rb_objspace_t * objspace ) ;
2013-10-22 14:28:31 +04:00
static void gc_heap_rest_sweep ( rb_objspace_t * objspace , rb_heap_t * heap ) ;
2012-08-05 14:39:37 +04:00
2013-07-18 03:19:38 +04:00
static void gc_mark_stacked_objects ( rb_objspace_t * ) ;
2013-06-17 06:54:25 +04:00
static void gc_mark ( rb_objspace_t * objspace , VALUE ptr ) ;
static void gc_mark_maybe ( rb_objspace_t * objspace , VALUE ptr ) ;
static void gc_mark_children ( rb_objspace_t * objspace , VALUE ptr ) ;
2013-11-05 08:51:01 +04:00
static size_t obj_memsize_of ( VALUE obj , int use_tdata ) ;
2012-08-05 14:39:37 +04:00
static double getrusage_time ( void ) ;
2013-06-24 02:58:01 +04:00
static inline void gc_prof_setup_new_record ( rb_objspace_t * objspace , int reason ) ;
static inline void gc_prof_timer_start ( rb_objspace_t * ) ;
2013-05-21 12:21:59 +04:00
static inline void gc_prof_timer_stop ( rb_objspace_t * ) ;
2012-08-05 14:39:37 +04:00
static inline void gc_prof_mark_timer_start ( rb_objspace_t * ) ;
static inline void gc_prof_mark_timer_stop ( rb_objspace_t * ) ;
2013-06-20 00:43:33 +04:00
static inline void gc_prof_sweep_timer_start ( rb_objspace_t * ) ;
static inline void gc_prof_sweep_timer_stop ( rb_objspace_t * ) ;
2012-08-05 14:39:37 +04:00
static inline void gc_prof_set_malloc_info ( rb_objspace_t * ) ;
2013-06-22 02:29:09 +04:00
static inline void gc_prof_set_heap_info ( rb_objspace_t * ) ;
2013-06-22 01:51:41 +04:00
# define gc_prof_record(objspace) (objspace)->profile.current_record
2013-12-18 11:58:04 +04:00
# define gc_prof_enabled(objspace) ((objspace)->profile.run && (objspace)->profile.current_record)
2012-08-05 14:39:37 +04:00
2013-07-18 03:19:38 +04:00
# define rgengc_report if (RGENGC_DEBUG) rgengc_report_body
static void rgengc_report_body ( int level , rb_objspace_t * objspace , const char * fmt , . . . ) ;
2013-07-19 17:00:23 +04:00
static const char * type_name ( int type , VALUE obj ) ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
static const char * obj_type_name ( VALUE obj ) ;
# if USE_RGENGC
static int rgengc_remembered ( rb_objspace_t * objspace , VALUE obj ) ;
2013-06-25 07:24:07 +04:00
static int rgengc_remember ( rb_objspace_t * objspace , VALUE obj ) ;
2013-10-22 14:28:31 +04:00
static void rgengc_mark_and_rememberset_clear ( rb_objspace_t * objspace , rb_heap_t * heap ) ;
static void rgengc_rememberset_mark ( rb_objspace_t * objspace , rb_heap_t * heap ) ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
2013-06-19 20:07:41 +04:00
# define FL_TEST2(x,f) ((RGENGC_CHECK_MODE && SPECIAL_CONST_P(x)) ? (rb_bug("FL_TEST2: SPECIAL_CONST"), 0) : FL_TEST_RAW((x),(f)) != 0)
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
# define FL_SET2(x,f) do {if (RGENGC_CHECK_MODE && SPECIAL_CONST_P(x)) rb_bug("FL_SET2: SPECIAL_CONST"); RBASIC(x)->flags |= (f);} while (0)
# define FL_UNSET2(x,f) do {if (RGENGC_CHECK_MODE && SPECIAL_CONST_P(x)) rb_bug("FL_UNSET2: SPECIAL_CONST"); RBASIC(x)->flags &= ~(f);} while (0)
2013-12-13 06:38:05 +04:00
# define RVALUE_WB_PROTECTED_RAW(obj) FL_TEST2((obj), FL_WB_PROTECTED)
# define RVALUE_WB_PROTECTED(obj) RVALUE_WB_PROTECTED_RAW(check_gen_consistency((VALUE)obj))
2013-06-21 23:36:48 +04:00
2013-12-12 08:43:14 +04:00
# define RVALUE_OLDGEN_BITMAP(obj) MARKED_IN_BITMAP(GET_HEAP_OLDGEN_BITS(obj), (obj))
2013-11-04 22:59:33 +04:00
static inline int is_pointer_to_heap ( rb_objspace_t * objspace , void * ptr ) ;
static inline int gc_marked ( rb_objspace_t * objspace , VALUE ptr ) ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
2013-06-21 23:36:48 +04:00
static inline VALUE
2013-11-04 22:59:33 +04:00
check_gen_consistency ( VALUE obj )
2013-06-19 18:34:11 +04:00
{
2013-11-04 22:59:33 +04:00
if ( RGENGC_CHECK_MODE > 0 ) {
2013-12-12 08:43:14 +04:00
int old_flag = RVALUE_OLDGEN_BITMAP ( obj ) ! = 0 ;
2013-11-04 22:59:33 +04:00
int promoted_flag = FL_TEST2 ( obj , FL_PROMOTED ) ;
rb_objspace_t * objspace = & rb_objspace ;
2013-06-19 18:34:11 +04:00
2013-11-05 08:51:01 +04:00
obj_memsize_of ( ( VALUE ) obj , FALSE ) ;
2013-11-04 22:59:33 +04:00
if ( ! is_pointer_to_heap ( objspace , ( void * ) obj ) ) {
rb_bug ( " check_gen_consistency: %p (%s) is not Ruby object. " , ( void * ) obj , obj_type_name ( obj ) ) ;
2013-06-21 23:36:48 +04:00
}
2013-11-04 22:59:33 +04:00
if ( promoted_flag ) {
2013-12-13 06:38:05 +04:00
if ( ! RVALUE_WB_PROTECTED_RAW ( obj ) ) {
2013-11-04 22:59:33 +04:00
const char * type = old_flag ? " old " : " young " ;
2013-12-13 06:38:05 +04:00
rb_bug ( " check_gen_consistency: %p (%s) is not WB protected, but %s object. " , ( void * ) obj , obj_type_name ( obj ) , type ) ;
2013-11-04 22:59:33 +04:00
}
# if !RGENGC_THREEGEN
if ( ! old_flag ) {
rb_bug ( " check_gen_consistency: %p (%s) is not infant, but is not old (on 2gen). " , ( void * ) obj , obj_type_name ( obj ) ) ;
}
2013-06-21 23:36:48 +04:00
# endif
2013-11-04 22:59:33 +04:00
if ( old_flag & & objspace - > rgengc . during_minor_gc & & ! gc_marked ( objspace , obj ) ) {
rb_bug ( " check_gen_consistency: %p (%s) is old, but is not marked while minor marking. " , ( void * ) obj , obj_type_name ( obj ) ) ;
}
}
else {
if ( old_flag ) {
rb_bug ( " check_gen_consistency: %p (%s) is not infant, but is old. " , ( void * ) obj , obj_type_name ( obj ) ) ;
}
}
}
2013-06-21 23:36:48 +04:00
return obj ;
2013-06-19 18:34:11 +04:00
}
2013-11-04 22:59:33 +04:00
static inline VALUE
RVALUE_INFANT_P ( VALUE obj )
{
check_gen_consistency ( obj ) ;
return ! FL_TEST2 ( obj , FL_PROMOTED ) ;
}
static inline VALUE
RVALUE_OLD_BITMAP_P ( VALUE obj )
{
check_gen_consistency ( obj ) ;
2013-12-12 08:43:14 +04:00
return ( RVALUE_OLDGEN_BITMAP ( obj ) ! = 0 ) ;
2013-11-04 22:59:33 +04:00
}
static inline VALUE
RVALUE_OLD_P ( VALUE obj )
{
check_gen_consistency ( obj ) ;
# if RGENGC_THREEGEN
return FL_TEST2 ( obj , FL_PROMOTED ) & & RVALUE_OLD_BITMAP_P ( obj ) ;
# else
return FL_TEST2 ( obj , FL_PROMOTED ) ;
# endif
}
static inline VALUE
RVALUE_PROMOTED_P ( VALUE obj )
{
check_gen_consistency ( obj ) ;
return FL_TEST2 ( obj , FL_PROMOTED ) ;
}
2013-05-26 21:27:42 +04:00
static inline void
2013-11-04 22:59:33 +04:00
RVALUE_PROMOTE_INFANT ( VALUE obj )
2013-05-26 21:27:42 +04:00
{
2013-11-04 22:59:33 +04:00
check_gen_consistency ( obj ) ;
if ( RGENGC_CHECK_MODE & & ! RVALUE_INFANT_P ( obj ) ) rb_bug ( " RVALUE_PROMOTE_INFANT: %p (%s) is not infant object. " , ( void * ) obj , obj_type_name ( obj ) ) ;
2013-11-04 19:04:10 +04:00
FL_SET2 ( obj , FL_PROMOTED ) ;
2013-11-04 22:59:33 +04:00
# if !RGENGC_THREEGEN
MARK_IN_BITMAP ( GET_HEAP_OLDGEN_BITS ( obj ) , obj ) ;
# endif
check_gen_consistency ( obj ) ;
# if RGENGC_PROFILE >= 1
{
rb_objspace_t * objspace = & rb_objspace ;
objspace - > profile . promote_infant_count + + ;
# if RGENGC_PROFILE >= 2
objspace - > profile . promote_infant_types [ BUILTIN_TYPE ( obj ) ] + + ;
# endif
}
# endif
}
# if RGENGC_THREEGEN
/*
* Two gen : Infant - > Old .
* Three gen : Infant - > Young - > Old .
*/
static inline VALUE
RVALUE_YOUNG_P ( VALUE obj )
{
check_gen_consistency ( obj ) ;
2013-12-12 08:43:14 +04:00
return FL_TEST2 ( obj , FL_PROMOTED ) & & ( RVALUE_OLDGEN_BITMAP ( obj ) = = 0 ) ;
2013-11-04 22:59:33 +04:00
}
static inline void
RVALUE_PROMOTE_YOUNG ( VALUE obj )
2013-11-05 11:48:31 +04:00
{
2013-11-04 22:59:33 +04:00
check_gen_consistency ( obj ) ;
if ( RGENGC_CHECK_MODE & & ! RVALUE_YOUNG_P ( obj ) ) rb_bug ( " RVALUE_PROMOTE_YOUNG: %p (%s) is not young object. " , ( void * ) obj , obj_type_name ( obj ) ) ;
MARK_IN_BITMAP ( GET_HEAP_OLDGEN_BITS ( obj ) , obj ) ;
check_gen_consistency ( obj ) ;
2013-05-26 21:27:42 +04:00
# if RGENGC_PROFILE >= 1
{
rb_objspace_t * objspace = & rb_objspace ;
2013-11-04 22:59:33 +04:00
objspace - > profile . promote_young_count + + ;
2013-05-26 21:27:42 +04:00
# if RGENGC_PROFILE >= 2
2013-11-04 22:59:33 +04:00
objspace - > profile . promote_young_types [ BUILTIN_TYPE ( obj ) ] + + ;
2013-05-26 21:27:42 +04:00
# endif
}
# endif
}
2013-06-07 06:28:03 +04:00
2013-06-10 12:15:31 +04:00
static inline void
2013-11-04 22:59:33 +04:00
RVALUE_DEMOTE_FROM_YOUNG ( VALUE obj )
2013-06-10 12:15:31 +04:00
{
2013-11-04 22:59:33 +04:00
if ( RGENGC_CHECK_MODE & & ! RVALUE_YOUNG_P ( obj ) )
rb_bug ( " RVALUE_DEMOTE_FROM_YOUNG: %p (%s) is not young object. " , ( void * ) obj , obj_type_name ( obj ) ) ;
check_gen_consistency ( obj ) ;
2013-11-04 19:04:10 +04:00
FL_UNSET2 ( obj , FL_PROMOTED ) ;
2013-11-04 22:59:33 +04:00
check_gen_consistency ( obj ) ;
2013-06-10 12:15:31 +04:00
}
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
# endif
2013-11-04 22:59:33 +04:00
static inline void
RVALUE_DEMOTE_FROM_OLD ( VALUE obj )
{
if ( RGENGC_CHECK_MODE & & ! RVALUE_OLD_P ( obj ) )
rb_bug ( " RVALUE_DEMOTE_FROM_OLD: %p (%s) is not old object. " , ( void * ) obj , obj_type_name ( obj ) ) ;
check_gen_consistency ( obj ) ;
FL_UNSET2 ( obj , FL_PROMOTED ) ;
CLEAR_IN_BITMAP ( GET_HEAP_OLDGEN_BITS ( obj ) , obj ) ;
check_gen_consistency ( obj ) ;
}
# endif /* USE_RGENGC */
2012-08-05 14:39:37 +04:00
/*
- - - - - - - - - - - - - - - - - - - - - - - - - - - ObjectSpace - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
2009-09-18 11:29:17 +04:00
2008-06-05 18:41:41 +04:00
# if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
2008-04-14 07:47:04 +04:00
rb_objspace_t *
rb_objspace_alloc ( void )
{
2008-04-27 07:20:35 +04:00
rb_objspace_t * objspace = malloc ( sizeof ( rb_objspace_t ) ) ;
2008-04-14 07:47:04 +04:00
memset ( objspace , 0 , sizeof ( * objspace ) ) ;
2008-06-14 02:57:41 +04:00
ruby_gc_stress = ruby_initial_gc_stress ;
2008-04-25 13:03:32 +04:00
2013-11-21 12:50:40 +04:00
malloc_limit = gc_params . malloc_limit_min ;
2013-11-05 08:51:01 +04:00
2008-04-14 07:47:04 +04:00
return objspace ;
}
2011-10-21 17:01:37 +04:00
# endif
2009-09-18 11:29:17 +04:00
2011-10-21 17:01:37 +04:00
# if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
2012-10-03 17:23:30 +04:00
static void free_stack_chunks ( mark_stack_t * ) ;
2013-10-23 12:48:54 +04:00
static void heap_page_free ( rb_objspace_t * objspace , struct heap_page * page ) ;
2010-12-03 06:53:21 +03:00
2009-09-18 11:29:17 +04:00
void
rb_objspace_free ( rb_objspace_t * objspace )
{
2013-07-18 03:19:38 +04:00
gc_rest_sweep ( objspace ) ;
2013-05-22 09:21:06 +04:00
2013-06-22 01:51:41 +04:00
if ( objspace - > profile . records ) {
free ( objspace - > profile . records ) ;
objspace - > profile . records = 0 ;
2009-09-18 11:29:17 +04:00
}
2013-10-22 14:28:31 +04:00
2009-09-18 11:29:17 +04:00
if ( global_List ) {
struct gc_list * list , * next ;
for ( list = global_List ; list ; list = next ) {
next = list - > next ;
2012-01-09 01:02:08 +04:00
xfree ( list ) ;
2009-09-18 11:29:17 +04:00
}
}
2013-10-22 14:28:31 +04:00
if ( heap_pages_sorted ) {
* compile.c, cont.c, gc.c, insns.def, iseq.c, iseq.h, process.c,
thread.c, vm.c, vm_core.h, vm_dump.c, vm_eval.c,
vm_insnhelper.c, vm_method.c, template/insns_info.inc.tmpl,
tool/instruction.rb: fixed types.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@25030 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-09-22 00:58:26 +04:00
size_t i ;
2013-10-22 14:28:31 +04:00
for ( i = 0 ; i < heap_pages_used ; + + i ) {
2013-10-23 12:48:54 +04:00
heap_page_free ( objspace , heap_pages_sorted [ i ] ) ;
2009-09-18 11:29:17 +04:00
}
2013-10-22 14:28:31 +04:00
free ( heap_pages_sorted ) ;
heap_pages_used = 0 ;
heap_pages_length = 0 ;
heap_pages_lomem = 0 ;
heap_pages_himem = 0 ;
2013-11-27 05:42:25 +04:00
objspace - > eden_heap . page_length = 0 ;
objspace - > eden_heap . total_slots = 0 ;
2013-10-23 12:48:54 +04:00
objspace - > eden_heap . pages = NULL ;
2009-09-18 11:29:17 +04:00
}
2012-10-03 16:30:21 +04:00
free_stack_chunks ( & objspace - > mark_stack ) ;
2009-09-18 11:29:17 +04:00
free ( objspace ) ;
}
2008-06-05 18:41:41 +04:00
# endif
2008-04-14 07:47:04 +04:00
2009-01-12 06:41:20 +03:00
static void
2013-10-23 12:48:54 +04:00
heap_pages_expand_sorted ( rb_objspace_t * objspace )
2009-01-12 06:41:20 +03:00
{
2013-10-23 14:16:01 +04:00
size_t next_length = heap_pages_increment ;
2013-11-27 05:42:25 +04:00
next_length + = heap_eden - > page_length ;
next_length + = heap_tomb - > page_length ;
2013-10-23 12:48:54 +04:00
if ( next_length > heap_pages_length ) {
2013-10-22 14:28:31 +04:00
struct heap_page * * sorted ;
2013-10-23 12:48:54 +04:00
size_t size = next_length * sizeof ( struct heap_page * ) ;
2012-08-05 14:39:37 +04:00
2013-10-23 12:48:54 +04:00
rgengc_report ( 3 , objspace , " heap_pages_expand_sorted: next_length: %d, size: %d \n " , ( int ) next_length , ( int ) size ) ;
2012-08-05 14:39:37 +04:00
2013-10-22 14:28:31 +04:00
if ( heap_pages_length > 0 ) {
sorted = ( struct heap_page * * ) realloc ( heap_pages_sorted , size ) ;
if ( sorted ) heap_pages_sorted = sorted ;
}
else {
sorted = heap_pages_sorted = ( struct heap_page * * ) malloc ( size ) ;
}
2009-01-12 06:41:20 +03:00
2013-10-22 14:28:31 +04:00
if ( sorted = = 0 ) {
during_gc = 0 ;
rb_memerror ( ) ;
}
2013-10-23 12:48:54 +04:00
heap_pages_length = next_length ;
1999-12-14 09:50:43 +03:00
}
}
1999-08-13 09:45:20 +04:00
2013-07-16 12:32:32 +04:00
static inline void
2013-10-18 10:33:36 +04:00
heap_page_add_freeobj ( rb_objspace_t * objspace , struct heap_page * page , VALUE obj )
2013-07-16 12:32:32 +04:00
{
RVALUE * p = ( RVALUE * ) obj ;
p - > as . free . flags = 0 ;
2013-10-18 10:33:36 +04:00
p - > as . free . next = page - > freelist ;
page - > freelist = p ;
rgengc_report ( 3 , objspace , " heap_page_add_freeobj: %p (%s) is added to freelist \n " , p , obj_type_name ( obj ) ) ;
2013-07-16 12:32:32 +04:00
}
static inline void
2013-10-22 14:28:31 +04:00
heap_add_freepage ( rb_objspace_t * objspace , rb_heap_t * heap , struct heap_page * page )
2013-07-16 12:32:32 +04:00
{
2013-10-18 10:33:36 +04:00
if ( page - > freelist ) {
2013-10-22 14:28:31 +04:00
page - > free_next = heap - > free_pages ;
heap - > free_pages = page ;
2013-07-16 12:32:32 +04:00
}
}
2013-10-23 12:48:54 +04:00
static void
heap_unlink_page ( rb_objspace_t * objspace , rb_heap_t * heap , struct heap_page * page )
{
if ( page - > prev ) page - > prev - > next = page - > next ;
if ( page - > next ) page - > next - > prev = page - > prev ;
if ( heap - > pages = = page ) heap - > pages = page - > next ;
page - > prev = NULL ;
page - > next = NULL ;
page - > heap = NULL ;
2013-11-27 05:42:25 +04:00
heap - > page_length - - ;
heap - > total_slots - = page - > limit ;
2013-10-23 12:48:54 +04:00
}
static void
heap_page_free ( rb_objspace_t * objspace , struct heap_page * page )
{
heap_pages_used - - ;
aligned_free ( page - > body ) ;
free ( page ) ;
}
static void
heap_pages_free_unused_pages ( rb_objspace_t * objspace )
{
size_t i , j ;
for ( i = j = 1 ; j < heap_pages_used ; i + + ) {
struct heap_page * page = heap_pages_sorted [ i ] ;
2013-11-24 23:18:53 +04:00
if ( page - > heap = = heap_tomb & & page - > final_slots = = 0 ) {
2013-11-23 03:50:08 +04:00
if ( heap_pages_swept_slots - page - > limit > heap_pages_max_free_slots ) {
if ( 0 ) fprintf ( stderr , " heap_pages_free_unused_pages: %d free page %p, heap_pages_swept_slots: %d, heap_pages_max_free_slots: %d \n " ,
( int ) i , page , ( int ) heap_pages_swept_slots , ( int ) heap_pages_max_free_slots ) ;
heap_pages_swept_slots - = page - > limit ;
2013-10-23 12:48:54 +04:00
heap_unlink_page ( objspace , heap_tomb , page ) ;
heap_page_free ( objspace , page ) ;
continue ;
}
else {
/* fprintf(stderr, "heap_pages_free_unused_pages: remain!!\n"); */
}
}
if ( i ! = j ) {
heap_pages_sorted [ j ] = page ;
}
j + + ;
}
assert ( j = = heap_pages_used ) ;
}
2013-10-22 14:28:31 +04:00
static struct heap_page *
heap_page_allocate ( rb_objspace_t * objspace )
2008-08-11 13:36:57 +04:00
{
2013-10-22 14:28:31 +04:00
RVALUE * start , * end , * p ;
2013-10-23 12:48:54 +04:00
struct heap_page * page ;
2013-10-18 10:33:36 +04:00
struct heap_page_body * page_body = 0 ;
2012-08-05 14:39:37 +04:00
size_t hi , lo , mid ;
2013-07-16 12:32:32 +04:00
size_t limit = HEAP_OBJ_LIMIT ;
2013-06-21 05:26:50 +04:00
2013-10-18 10:33:36 +04:00
/* assign heap_page body (contains heap_page_header and RVALUEs) */
page_body = ( struct heap_page_body * ) aligned_malloc ( HEAP_ALIGN , HEAP_SIZE ) ;
if ( page_body = = 0 ) {
2012-08-05 14:39:37 +04:00
during_gc = 0 ;
rb_memerror ( ) ;
2009-01-12 06:41:20 +03:00
}
2013-06-21 05:26:50 +04:00
2013-10-18 10:33:36 +04:00
/* assign heap_page entry */
page = ( struct heap_page * ) malloc ( sizeof ( struct heap_page ) ) ;
if ( page = = 0 ) {
aligned_free ( page_body ) ;
2013-07-16 12:32:32 +04:00
during_gc = 0 ;
rb_memerror ( ) ;
2009-01-12 06:41:20 +03:00
}
2013-10-18 10:33:36 +04:00
MEMZERO ( ( void * ) page , struct heap_page , 1 ) ;
2009-01-12 06:41:20 +03:00
2013-10-18 10:33:36 +04:00
page - > body = page_body ;
2013-07-16 12:32:32 +04:00
2013-10-22 14:28:31 +04:00
/* setup heap_pages_sorted */
2012-08-05 14:39:37 +04:00
lo = 0 ;
2013-10-22 14:28:31 +04:00
hi = heap_pages_used ;
2012-08-05 14:39:37 +04:00
while ( lo < hi ) {
2013-10-18 10:33:36 +04:00
struct heap_page * mid_page ;
2013-07-16 12:32:32 +04:00
2012-08-05 14:39:37 +04:00
mid = ( lo + hi ) / 2 ;
2013-10-22 14:28:31 +04:00
mid_page = heap_pages_sorted [ mid ] ;
2013-10-18 10:33:36 +04:00
if ( mid_page - > body < page_body ) {
2012-08-05 14:39:37 +04:00
lo = mid + 1 ;
}
2013-10-18 10:33:36 +04:00
else if ( mid_page - > body > page_body ) {
2012-08-05 14:39:37 +04:00
hi = mid ;
2009-01-12 06:41:20 +03:00
}
else {
2013-10-18 10:33:36 +04:00
rb_bug ( " same heap page is allocated: %p at % " PRIuVALUE , ( void * ) page_body , ( VALUE ) mid ) ;
2009-01-12 06:41:20 +03:00
}
}
2013-10-22 14:28:31 +04:00
if ( hi < heap_pages_used ) {
MEMMOVE ( & heap_pages_sorted [ hi + 1 ] , & heap_pages_sorted [ hi ] , struct heap_page_header * , heap_pages_used - hi ) ;
2012-11-10 19:04:27 +04:00
}
2013-10-22 14:28:31 +04:00
2013-10-23 12:48:54 +04:00
heap_pages_sorted [ hi ] = page ;
2013-10-22 14:28:31 +04:00
heap_pages_used + + ;
assert ( heap_pages_used < = heap_pages_length ) ;
2013-06-21 05:26:50 +04:00
2013-10-23 12:48:54 +04:00
/* adjust obj_limit (object number available in this page) */
start = ( RVALUE * ) ( ( VALUE ) page_body + sizeof ( struct heap_page_header ) ) ;
if ( ( VALUE ) start % sizeof ( RVALUE ) ! = 0 ) {
int delta = ( int ) ( sizeof ( RVALUE ) - ( ( VALUE ) start % sizeof ( RVALUE ) ) ) ;
start = ( RVALUE * ) ( ( VALUE ) start + delta ) ;
limit = ( HEAP_SIZE - ( size_t ) ( ( VALUE ) start - ( VALUE ) page_body ) ) / sizeof ( RVALUE ) ;
}
end = start + limit ;
if ( heap_pages_lomem = = 0 | | heap_pages_lomem > start ) heap_pages_lomem = start ;
if ( heap_pages_himem < end ) heap_pages_himem = end ;
2013-10-18 10:33:36 +04:00
page - > start = start ;
page - > limit = limit ;
2013-10-23 12:48:54 +04:00
page_body - > header . page = page ;
2009-01-12 06:41:20 +03:00
2013-07-16 12:32:32 +04:00
for ( p = start ; p ! = end ; p + + ) {
2013-10-18 10:33:36 +04:00
rgengc_report ( 3 , objspace , " assign_heap_page: %p is added to freelist \n " ) ;
heap_page_add_freeobj ( objspace , page , ( VALUE ) p ) ;
2012-08-05 14:39:37 +04:00
}
2013-06-21 05:26:50 +04:00
2013-10-22 14:28:31 +04:00
return page ;
2012-08-05 14:39:37 +04:00
}
2009-09-17 13:34:20 +04:00
2013-10-23 12:48:54 +04:00
static struct heap_page *
heap_page_resurrect ( rb_objspace_t * objspace )
1998-01-16 15:13:05 +03:00
{
2013-10-23 12:48:54 +04:00
struct heap_page * page ;
2000-09-25 21:51:29 +04:00
2013-10-29 11:25:45 +04:00
if ( ( page = heap_tomb - > pages ) ! = NULL ) {
heap_unlink_page ( objspace , heap_tomb , page ) ;
return page ;
2013-10-23 12:48:54 +04:00
}
2013-10-29 11:25:45 +04:00
return NULL ;
2013-10-23 12:48:54 +04:00
}
static struct heap_page *
heap_page_create ( rb_objspace_t * objspace )
{
struct heap_page * page = heap_page_resurrect ( objspace ) ;
const char * method = " recycle " ;
if ( page = = NULL ) {
page = heap_page_allocate ( objspace ) ;
method = " allocate " ;
}
2013-11-27 05:42:25 +04:00
if ( 0 ) fprintf ( stderr , " heap_page_create: %s - %p, heap_pages_used: %d, heap_pages_used: %d, tomb->page_length: %d \n " ,
method , page , ( int ) heap_pages_length , ( int ) heap_pages_used , ( int ) heap_tomb - > page_length ) ;
2013-10-23 12:48:54 +04:00
return page ;
}
static void
heap_add_page ( rb_objspace_t * objspace , rb_heap_t * heap , struct heap_page * page )
{
page - > heap = heap ;
2013-10-22 14:28:31 +04:00
page - > next = heap - > pages ;
if ( heap - > pages ) heap - > pages - > prev = page ;
heap - > pages = page ;
2013-11-27 05:42:25 +04:00
heap - > page_length + + ;
heap - > total_slots + = page - > limit ;
2013-10-23 12:48:54 +04:00
}
2008-06-08 14:27:06 +04:00
2013-10-23 12:48:54 +04:00
static void
heap_assign_page ( rb_objspace_t * objspace , rb_heap_t * heap )
{
struct heap_page * page = heap_page_create ( objspace ) ;
heap_add_page ( objspace , heap , page ) ;
2013-10-22 14:28:31 +04:00
heap_add_freepage ( objspace , heap , page ) ;
}
static void
heap_add_pages ( rb_objspace_t * objspace , rb_heap_t * heap , size_t add )
{
size_t i ;
2013-10-23 14:16:01 +04:00
heap_pages_increment = add ;
2013-10-23 12:48:54 +04:00
heap_pages_expand_sorted ( objspace ) ;
2012-08-05 14:39:37 +04:00
for ( i = 0 ; i < add ; i + + ) {
2013-10-22 14:28:31 +04:00
heap_assign_page ( objspace , heap ) ;
2012-08-05 14:39:37 +04:00
}
2013-10-23 14:16:01 +04:00
heap_pages_increment = 0 ;
2011-05-22 13:26:46 +04:00
}
2012-08-05 14:39:37 +04:00
static void
2013-11-22 11:40:27 +04:00
heap_set_increment ( rb_objspace_t * objspace , size_t minimum_limit )
1998-01-16 15:13:05 +03:00
{
2013-11-27 05:42:25 +04:00
size_t used = heap_pages_used - heap_tomb - > page_length ;
2013-11-21 12:50:40 +04:00
size_t next_used_limit = ( size_t ) ( used * gc_params . growth_factor ) ;
2013-11-23 07:33:10 +04:00
if ( gc_params . growth_max_slots > 0 ) {
size_t max_used_limit = ( size_t ) ( used + gc_params . growth_max_slots / HEAP_OBJ_LIMIT ) ;
2013-10-24 02:47:29 +04:00
if ( next_used_limit > max_used_limit ) next_used_limit = max_used_limit ;
}
2013-10-23 14:16:01 +04:00
if ( next_used_limit = = heap_pages_used ) next_used_limit + + ;
2013-11-22 11:40:27 +04:00
if ( next_used_limit < minimum_limit ) {
next_used_limit = minimum_limit ;
}
2013-10-23 14:16:01 +04:00
heap_pages_increment = next_used_limit - used ;
2013-10-23 12:48:54 +04:00
heap_pages_expand_sorted ( objspace ) ;
2008-07-05 11:15:41 +04:00
2013-10-23 14:16:01 +04:00
if ( 0 ) fprintf ( stderr , " heap_set_increment: heap_pages_length: %d, heap_pages_used: %d, heap_pages_increment: %d, next_used_limit: %d \n " ,
( int ) heap_pages_length , ( int ) heap_pages_used , ( int ) heap_pages_increment , ( int ) next_used_limit ) ;
1998-01-16 15:13:05 +03:00
}
2012-08-05 14:39:37 +04:00
static int
2013-10-23 14:16:01 +04:00
heap_increment ( rb_objspace_t * objspace , rb_heap_t * heap )
2008-06-08 14:27:06 +04:00
{
2013-11-27 05:42:25 +04:00
rgengc_report ( 5 , objspace , " heap_increment: heap_pages_length: %d, heap_pages_inc: %d, heap->page_length: %d \n " ,
( int ) heap_pages_length , ( int ) heap_pages_increment , ( int ) heap - > page_length ) ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
2013-10-23 14:16:01 +04:00
if ( heap_pages_increment > 0 ) {
heap_pages_increment - - ;
2013-10-22 14:28:31 +04:00
heap_assign_page ( objspace , heap ) ;
2012-08-05 14:39:37 +04:00
return TRUE ;
2012-01-11 18:09:10 +04:00
}
2012-08-05 14:39:37 +04:00
return FALSE ;
}
2008-06-08 14:27:06 +04:00
2013-10-18 10:33:36 +04:00
static struct heap_page *
2013-10-22 14:28:31 +04:00
heap_prepare_freepage ( rb_objspace_t * objspace , rb_heap_t * heap )
2013-07-16 14:29:31 +04:00
{
if ( ! GC_ENABLE_LAZY_SWEEP & & objspace - > flags . dont_lazy_sweep ) {
2013-10-23 14:16:01 +04:00
if ( heap_increment ( objspace , heap ) = = 0 & &
2013-07-16 14:29:31 +04:00
garbage_collect ( objspace , FALSE , TRUE , GPR_FLAG_NEWOBJ ) = = 0 ) {
goto err ;
}
goto ok ;
}
2013-10-22 14:28:31 +04:00
if ( ! heap_ready_to_gc ( objspace , heap ) ) return heap - > free_pages ;
2013-07-16 14:29:31 +04:00
during_gc + + ;
2013-10-23 14:16:01 +04:00
if ( ( is_lazy_sweeping ( heap ) & & gc_heap_lazy_sweep ( objspace , heap ) ) | | heap_increment ( objspace , heap ) ) {
2013-07-16 14:29:31 +04:00
goto ok ;
}
# if GC_PROFILE_MORE_DETAIL
objspace - > profile . prepare_time = 0 ;
# endif
if ( garbage_collect_body ( objspace , 0 , 0 , GPR_FLAG_NEWOBJ ) = = 0 ) {
err :
during_gc = 0 ;
rb_memerror ( ) ;
}
ok :
during_gc = 0 ;
2013-10-22 14:28:31 +04:00
return heap - > free_pages ;
2013-07-16 14:29:31 +04:00
}
2013-12-19 09:04:55 +04:00
static RVALUE *
heap_get_freeobj_from_next_freepage ( rb_objspace_t * objspace , rb_heap_t * heap )
2013-07-16 14:29:31 +04:00
{
2013-10-18 10:33:36 +04:00
struct heap_page * page ;
2013-12-19 09:04:55 +04:00
RVALUE * p ;
2013-07-16 14:29:31 +04:00
2013-10-22 14:28:31 +04:00
page = heap - > free_pages ;
2013-10-18 10:33:36 +04:00
while ( page = = NULL ) {
2013-10-22 14:28:31 +04:00
page = heap_prepare_freepage ( objspace , heap ) ;
2013-07-16 14:29:31 +04:00
}
2013-10-22 14:28:31 +04:00
heap - > free_pages = page - > free_next ;
2013-12-19 09:04:55 +04:00
heap - > using_page = page ;
2013-07-16 14:29:31 +04:00
2013-12-19 09:04:55 +04:00
p = page - > freelist ;
page - > freelist = NULL ;
return p ;
2013-07-16 14:29:31 +04:00
}
static inline VALUE
2013-10-22 14:28:31 +04:00
heap_get_freeobj ( rb_objspace_t * objspace , rb_heap_t * heap )
2013-07-16 14:29:31 +04:00
{
2013-10-22 14:28:31 +04:00
RVALUE * p = heap - > freelist ;
2013-07-16 14:29:31 +04:00
2013-12-19 09:04:55 +04:00
while ( 1 ) {
if ( p ) {
heap - > freelist = p - > as . free . next ;
return ( VALUE ) p ;
}
else {
p = heap_get_freeobj_from_next_freepage ( objspace , heap ) ;
}
2013-07-16 14:29:31 +04:00
}
}
2013-05-27 04:21:02 +04:00
void
rb_objspace_set_event_hook ( const rb_event_flag_t event )
{
rb_objspace_t * objspace = & rb_objspace ;
objspace - > hook_events = event & RUBY_INTERNAL_EVENT_OBJSPACE_MASK ;
}
static void
gc_event_hook_body ( rb_objspace_t * objspace , const rb_event_flag_t event , VALUE data )
{
rb_thread_t * th = GET_THREAD ( ) ;
EXEC_EVENT_HOOK ( th , event , th - > cfp - > self , 0 , 0 , data ) ;
}
# define gc_event_hook(objspace, event, data) do { \
if ( UNLIKELY ( ( objspace ) - > hook_events & ( event ) ) ) { \
gc_event_hook_body ( ( objspace ) , ( event ) , ( data ) ) ; \
} \
} while ( 0 )
2012-10-20 10:57:51 +04:00
static VALUE
2013-05-15 14:26:22 +04:00
newobj_of ( VALUE klass , VALUE flags , VALUE v1 , VALUE v2 , VALUE v3 )
2008-04-27 07:20:35 +04:00
{
2012-08-05 14:39:37 +04:00
rb_objspace_t * objspace = & rb_objspace ;
VALUE obj ;
2008-04-27 07:20:35 +04:00
2012-08-05 14:39:37 +04:00
if ( UNLIKELY ( during_gc ) ) {
dont_gc = 1 ;
during_gc = 0 ;
rb_bug ( " object allocation during garbage collection phase " ) ;
2005-10-05 20:15:16 +04:00
}
2008-06-08 14:27:06 +04:00
2012-08-05 14:39:37 +04:00
if ( UNLIKELY ( ruby_gc_stress & & ! ruby_disable_gc_stress ) ) {
2013-05-22 03:09:22 +04:00
if ( ! garbage_collect ( objspace , FALSE , FALSE , GPR_FLAG_NEWOBJ ) ) {
2012-08-05 14:39:37 +04:00
during_gc = 0 ;
rb_memerror ( ) ;
}
}
2013-10-22 14:28:31 +04:00
obj = heap_get_freeobj ( objspace , heap_eden ) ;
2012-08-05 14:39:37 +04:00
2013-05-15 14:26:22 +04:00
/* OBJSETUP */
RBASIC ( obj ) - > flags = flags ;
2013-12-19 05:51:16 +04:00
RBASIC_SET_CLASS_RAW ( obj , klass ) ;
* safe.c (rb_set_safe_level, safe_setter): raise an ArgumentError
when $SAFE is set to 4. $SAFE=4 is now obsolete.
[ruby-core:55222] [Feature #8468]
* object.c (rb_obj_untrusted, rb_obj_untrust, rb_obj_trust):
Kernel#untrusted?, untrust, and trust are now deprecated.
Their behavior is same as tainted?, taint, and untaint,
respectively.
* include/ruby/ruby.h (OBJ_UNTRUSTED, OBJ_UNTRUST): OBJ_UNTRUSTED()
and OBJ_UNTRUST() are aliases of OBJ_TAINTED() and OBJ_TAINT(),
respectively.
* array.c, class.c, debug.c, dir.c, encoding.c, error.c, eval.c,
ext/curses/curses.c, ext/dbm/dbm.c, ext/dl/cfunc.c,
ext/dl/cptr.c, ext/dl/dl.c, ext/etc/etc.c, ext/fiddle/fiddle.c,
ext/fiddle/pointer.c, ext/gdbm/gdbm.c, ext/readline/readline.c,
ext/sdbm/init.c, ext/socket/ancdata.c, ext/socket/basicsocket.c,
ext/socket/socket.c, ext/socket/udpsocket.c,
ext/stringio/stringio.c, ext/syslog/syslog.c, ext/tk/tcltklib.c,
ext/win32ole/win32ole.c, file.c, gc.c, hash.c, io.c, iseq.c,
load.c, marshal.c, object.c, proc.c, process.c, random.c, re.c,
safe.c, string.c, thread.c, transcode.c, variable.c,
vm_insnhelper.c, vm_method.c, vm_trace.c: remove code for
$SAFE=4.
* test/dl/test_dl2.rb, test/erb/test_erb.rb,
test/readline/test_readline.rb,
test/readline/test_readline_history.rb, test/ruby/test_alias.rb,
test/ruby/test_array.rb, test/ruby/test_dir.rb,
test/ruby/test_encoding.rb, test/ruby/test_env.rb,
test/ruby/test_eval.rb, test/ruby/test_exception.rb,
test/ruby/test_file_exhaustive.rb, test/ruby/test_hash.rb,
test/ruby/test_io.rb, test/ruby/test_method.rb,
test/ruby/test_module.rb, test/ruby/test_object.rb,
test/ruby/test_pack.rb, test/ruby/test_rand.rb,
test/ruby/test_regexp.rb, test/ruby/test_settracefunc.rb,
test/ruby/test_struct.rb, test/ruby/test_thread.rb,
test/ruby/test_time.rb: remove tests for $SAFE=4.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@41259 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-06-12 18:20:51 +04:00
if ( rb_safe_level ( ) > = 3 ) FL_SET ( ( obj ) , FL_TAINT ) ;
2013-05-15 14:26:22 +04:00
RANY ( obj ) - > as . values . v1 = v1 ;
RANY ( obj ) - > as . values . v2 = v2 ;
RANY ( obj ) - > as . values . v3 = v3 ;
2013-08-19 16:00:51 +04:00
# if GC_DEBUG
2013-05-15 14:26:22 +04:00
RANY ( obj ) - > file = rb_sourcefile ( ) ;
RANY ( obj ) - > line = rb_sourceline ( ) ;
2013-08-19 16:00:51 +04:00
assert ( ! SPECIAL_CONST_P ( obj ) ) ; /* check alignment */
2013-05-15 14:26:22 +04:00
# endif
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
# if RGENGC_PROFILE
2013-06-18 06:27:37 +04:00
if ( flags & FL_WB_PROTECTED ) {
objspace - > profile . generated_normal_object_count + + ;
# if RGENGC_PROFILE >= 2
objspace - > profile . generated_normal_object_count_types [ BUILTIN_TYPE ( obj ) ] + + ;
# endif
}
2013-05-15 12:07:30 +04:00
else {
objspace - > profile . generated_shady_object_count + + ;
# if RGENGC_PROFILE >= 2
objspace - > profile . generated_shady_object_count_types [ BUILTIN_TYPE ( obj ) ] + + ;
# endif
}
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
# endif
rgengc_report ( 5 , objspace , " newobj: %p (%s) \n " , ( void * ) obj , obj_type_name ( obj ) ) ;
# if USE_RGENGC && RGENGC_CHECK_MODE
2013-11-04 22:59:33 +04:00
if ( RVALUE_PROMOTED_P ( obj ) ) rb_bug ( " newobj: %p (%s) is promoted. \n " , ( void * ) obj , obj_type_name ( obj ) ) ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
if ( rgengc_remembered ( objspace , ( VALUE ) obj ) ) rb_bug ( " newobj: %p (%s) is remembered. \n " , ( void * ) obj , obj_type_name ( obj ) ) ;
# endif
2013-11-01 16:49:49 +04:00
objspace - > profile . total_allocated_object_num + + ;
2013-05-27 04:21:02 +04:00
gc_event_hook ( objspace , RUBY_INTERNAL_EVENT_NEWOBJ , obj ) ;
2012-08-05 14:39:37 +04:00
return obj ;
2011-05-22 13:26:46 +04:00
}
2008-06-08 14:27:06 +04:00
2012-10-20 10:57:51 +04:00
VALUE
rb_newobj ( void )
{
2013-05-15 14:26:22 +04:00
return newobj_of ( 0 , T_NONE , 0 , 0 , 0 ) ;
2012-10-20 10:57:51 +04:00
}
VALUE
rb_newobj_of ( VALUE klass , VALUE flags )
{
2013-05-15 14:26:22 +04:00
return newobj_of ( klass , flags , 0 , 0 , 0 ) ;
2012-10-20 10:57:51 +04:00
}
2012-08-05 14:39:37 +04:00
NODE *
rb_node_newnode ( enum node_type type , VALUE a0 , VALUE a1 , VALUE a2 )
2011-05-22 13:26:46 +04:00
{
2013-12-08 06:28:04 +04:00
VALUE flags = ( RGENGC_WB_PROTECTED_NODE_CREF & & type = = NODE_CREF ? FL_WB_PROTECTED : 0 ) ;
NODE * n = ( NODE * ) newobj_of ( 0 , T_NODE | flags , a0 , a1 , a2 ) ;
2012-08-05 14:39:37 +04:00
nd_set_type ( n , type ) ;
return n ;
2011-05-22 13:26:46 +04:00
}
2012-08-05 14:39:37 +04:00
VALUE
rb_data_object_alloc ( VALUE klass , void * datap , RUBY_DATA_FUNC dmark , RUBY_DATA_FUNC dfree )
2011-05-22 13:26:46 +04:00
{
2013-05-13 10:25:33 +04:00
if ( klass ) Check_Type ( klass , T_CLASS ) ;
2013-05-15 14:26:22 +04:00
return newobj_of ( klass , T_DATA , ( VALUE ) dmark , ( VALUE ) dfree , ( VALUE ) datap ) ;
2008-06-08 14:27:06 +04:00
}
2012-08-05 14:39:37 +04:00
VALUE
rb_data_typed_object_alloc ( VALUE klass , void * datap , const rb_data_type_t * type )
2008-06-08 14:27:06 +04:00
{
2012-08-05 14:39:37 +04:00
if ( klass ) Check_Type ( klass , T_CLASS ) ;
2013-10-29 13:42:45 +04:00
return newobj_of ( klass , T_DATA | ( type - > flags & ~ T_MASK ) , ( VALUE ) type , ( VALUE ) 1 , ( VALUE ) datap ) ;
2008-04-27 07:20:35 +04:00
}
2012-08-05 14:39:37 +04:00
size_t
rb_objspace_data_type_memsize ( VALUE obj )
2008-04-27 07:20:35 +04:00
{
2012-08-05 14:39:37 +04:00
if ( RTYPEDDATA_P ( obj ) & & RTYPEDDATA_TYPE ( obj ) - > function . dsize ) {
return RTYPEDDATA_TYPE ( obj ) - > function . dsize ( RTYPEDDATA_DATA ( obj ) ) ;
}
else {
return 0 ;
2008-06-08 14:27:06 +04:00
}
2005-10-05 20:15:16 +04:00
}
2012-08-05 14:39:37 +04:00
const char *
rb_objspace_data_type_name ( VALUE obj )
1999-08-13 09:45:20 +04:00
{
2012-08-05 14:39:37 +04:00
if ( RTYPEDDATA_P ( obj ) ) {
return RTYPEDDATA_TYPE ( obj ) - > wrap_struct_name ;
}
else {
return 0 ;
}
1999-08-13 09:45:20 +04:00
}
2012-08-05 14:39:37 +04:00
static inline int
is_pointer_to_heap ( rb_objspace_t * objspace , void * ptr )
2012-01-10 07:49:10 +04:00
{
2012-08-05 14:39:37 +04:00
register RVALUE * p = RANY ( ptr ) ;
2013-10-18 10:33:36 +04:00
register struct heap_page * page ;
2012-08-05 14:39:37 +04:00
register size_t hi , lo , mid ;
2003-12-22 09:20:14 +03:00
2013-10-22 14:28:31 +04:00
if ( p < heap_pages_lomem | | p > heap_pages_himem ) return FALSE ;
2012-08-05 14:39:37 +04:00
if ( ( VALUE ) p % sizeof ( RVALUE ) ! = 0 ) return FALSE ;
1998-01-16 15:13:05 +03:00
2012-08-05 14:39:37 +04:00
/* check if p looks like a pointer using bsearch*/
lo = 0 ;
2013-10-22 14:28:31 +04:00
hi = heap_pages_used ;
2012-08-05 14:39:37 +04:00
while ( lo < hi ) {
mid = ( lo + hi ) / 2 ;
2013-10-22 14:28:31 +04:00
page = heap_pages_sorted [ mid ] ;
2013-10-18 10:33:36 +04:00
if ( page - > start < = p ) {
if ( p < page - > start + page - > limit ) {
2012-08-05 14:39:37 +04:00
return TRUE ;
2013-07-17 09:55:39 +04:00
}
2012-08-05 14:39:37 +04:00
lo = mid + 1 ;
}
else {
hi = mid ;
}
}
return FALSE ;
1998-01-16 15:13:05 +03:00
}
2012-08-05 14:39:37 +04:00
static int
free_method_entry_i ( ID key , rb_method_entry_t * me , st_data_t data )
1998-01-16 15:13:05 +03:00
{
2012-08-05 14:39:37 +04:00
if ( ! me - > mark ) {
rb_free_method_entry ( me ) ;
}
return ST_CONTINUE ;
1998-01-16 15:13:05 +03:00
}
* array.c, bignum.c, cont.c, dir.c, dln.c, encoding.c, enumerator.c,
enumerator.c (enumerator_allocate), eval_jump.c, file.c, hash.c,
io.c, load.c, pack.c, proc.c, random.c, re.c, ruby.c, st.c,
string.c, thread.c, thread_pthread.c, time.c, util.c, variable.c,
vm.c, gc.c:
allocated memory objects by xmalloc (ruby_xmalloc) should be
freed by xfree (ruby_xfree).
* ext/curses/curses.c, ext/dbm/dbm.c, ext/digest/digest.c,
ext/gdbm/gdbm.c, ext/json/ext/parser/parser.c,
ext/json/ext/parser/unicode.c, ext/openssl/ossl_cipher.c,
ext/openssl/ossl_hmac.c, ext/openssl/ossl_pkey_ec.c,
ext/sdbm/init.c, ext/strscan/strscan.c, ext/zlib/zlib.c:
ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@17017 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-06-08 14:01:40 +04:00
void
2013-12-03 12:11:07 +04:00
rb_free_m_tbl ( st_table * tbl )
* array.c, bignum.c, cont.c, dir.c, dln.c, encoding.c, enumerator.c,
enumerator.c (enumerator_allocate), eval_jump.c, file.c, hash.c,
io.c, load.c, pack.c, proc.c, random.c, re.c, ruby.c, st.c,
string.c, thread.c, thread_pthread.c, time.c, util.c, variable.c,
vm.c, gc.c:
allocated memory objects by xmalloc (ruby_xmalloc) should be
freed by xfree (ruby_xfree).
* ext/curses/curses.c, ext/dbm/dbm.c, ext/digest/digest.c,
ext/gdbm/gdbm.c, ext/json/ext/parser/parser.c,
ext/json/ext/parser/unicode.c, ext/openssl/ossl_cipher.c,
ext/openssl/ossl_hmac.c, ext/openssl/ossl_pkey_ec.c,
ext/sdbm/init.c, ext/strscan/strscan.c, ext/zlib/zlib.c:
ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@17017 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-06-08 14:01:40 +04:00
{
2012-08-05 14:39:37 +04:00
st_foreach ( tbl , free_method_entry_i , 0 ) ;
* class.c, compile.c, eval.c, gc.h, insns.def, internal.h, method.h,
variable.c, vm.c, vm_core.c, vm_insnhelper.c, vm_insnhelper.h,
vm_method.c: Implement class hierarchy method cache invalidation.
[ruby-core:55053] [Feature #8426] [GH-387]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42822 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-09-04 09:25:06 +04:00
st_free_table ( tbl ) ;
}
2013-12-03 12:11:07 +04:00
void
rb_free_m_tbl_wrapper ( struct method_table_wrapper * wrapper )
{
if ( wrapper - > tbl ) {
rb_free_m_tbl ( wrapper - > tbl ) ;
}
xfree ( wrapper ) ;
}
2012-08-05 14:39:37 +04:00
static int
free_const_entry_i ( ID key , rb_const_entry_t * ce , st_data_t data )
1998-01-16 15:13:05 +03:00
{
2012-08-05 14:39:37 +04:00
xfree ( ce ) ;
return ST_CONTINUE ;
1998-01-16 15:13:05 +03:00
}
2000-02-08 11:54:01 +03:00
void
2012-08-05 14:39:37 +04:00
rb_free_const_table ( st_table * tbl )
2000-02-08 11:54:01 +03:00
{
2012-08-05 14:39:37 +04:00
st_foreach ( tbl , free_const_entry_i , 0 ) ;
st_free_table ( tbl ) ;
}
2000-02-08 11:54:01 +03:00
2012-08-05 14:39:37 +04:00
static inline void
2013-11-01 17:22:54 +04:00
make_deferred ( rb_objspace_t * objspace , RVALUE * p )
2008-04-25 13:03:32 +04:00
{
2013-06-19 02:26:57 +04:00
p - > as . basic . flags = T_ZOMBIE ;
2013-11-01 17:22:54 +04:00
p - > as . free . next = heap_pages_deferred_final ;
heap_pages_deferred_final = p ;
2011-06-11 14:51:51 +04:00
}
2012-08-05 14:39:37 +04:00
static inline void
2013-11-01 17:22:54 +04:00
make_io_deferred ( rb_objspace_t * objspace , RVALUE * p )
2011-06-11 14:51:51 +04:00
{
2012-08-05 14:39:37 +04:00
rb_io_t * fptr = p - > as . file . fptr ;
2013-11-01 17:22:54 +04:00
make_deferred ( objspace , p ) ;
2012-08-05 14:39:37 +04:00
p - > as . data . dfree = ( void ( * ) ( void * ) ) rb_io_fptr_finalize ;
p - > as . data . data = fptr ;
2008-04-25 13:03:32 +04:00
}
2012-08-05 14:39:37 +04:00
static int
obj_free ( rb_objspace_t * objspace , VALUE obj )
2011-06-11 14:51:51 +04:00
{
2013-05-27 14:28:25 +04:00
gc_event_hook ( objspace , RUBY_INTERNAL_EVENT_FREEOBJ , obj ) ;
2013-05-27 04:21:02 +04:00
2012-08-05 14:39:37 +04:00
switch ( BUILTIN_TYPE ( obj ) ) {
case T_NIL :
case T_FIXNUM :
case T_TRUE :
case T_FALSE :
rb_bug ( " obj_free() called for broken object " ) ;
break ;
}
2011-06-11 14:51:51 +04:00
2012-08-05 14:39:37 +04:00
if ( FL_TEST ( obj , FL_EXIVAR ) ) {
rb_free_generic_ivar ( ( VALUE ) obj ) ;
FL_UNSET ( obj , FL_EXIVAR ) ;
2011-06-11 14:51:51 +04:00
}
2013-06-07 06:28:03 +04:00
# if USE_RGENGC
if ( MARKED_IN_BITMAP ( GET_HEAP_OLDGEN_BITS ( obj ) , obj ) )
CLEAR_IN_BITMAP ( GET_HEAP_OLDGEN_BITS ( obj ) , obj ) ;
# endif
2012-08-05 14:39:37 +04:00
switch ( BUILTIN_TYPE ( obj ) ) {
case T_OBJECT :
if ( ! ( RANY ( obj ) - > as . basic . flags & ROBJECT_EMBED ) & &
RANY ( obj ) - > as . object . as . heap . ivptr ) {
xfree ( RANY ( obj ) - > as . object . as . heap . ivptr ) ;
}
break ;
case T_MODULE :
case T_CLASS :
2013-12-03 12:11:07 +04:00
if ( RCLASS_M_TBL_WRAPPER ( obj ) ) {
rb_free_m_tbl_wrapper ( RCLASS_M_TBL_WRAPPER ( obj ) ) ;
2012-08-05 14:39:37 +04:00
}
if ( RCLASS_IV_TBL ( obj ) ) {
st_free_table ( RCLASS_IV_TBL ( obj ) ) ;
}
if ( RCLASS_CONST_TBL ( obj ) ) {
rb_free_const_table ( RCLASS_CONST_TBL ( obj ) ) ;
}
if ( RCLASS_IV_INDEX_TBL ( obj ) ) {
st_free_table ( RCLASS_IV_INDEX_TBL ( obj ) ) ;
}
* class.c, compile.c, eval.c, gc.h, insns.def, internal.h, method.h,
variable.c, vm.c, vm_core.c, vm_insnhelper.c, vm_insnhelper.h,
vm_method.c: Implement class hierarchy method cache invalidation.
[ruby-core:55053] [Feature #8426] [GH-387]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42822 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-09-04 09:25:06 +04:00
if ( RCLASS_EXT ( obj ) - > subclasses ) {
if ( BUILTIN_TYPE ( obj ) = = T_MODULE ) {
rb_class_detach_module_subclasses ( obj ) ;
2013-09-04 11:18:24 +04:00
}
else {
* class.c, compile.c, eval.c, gc.h, insns.def, internal.h, method.h,
variable.c, vm.c, vm_core.c, vm_insnhelper.c, vm_insnhelper.h,
vm_method.c: Implement class hierarchy method cache invalidation.
[ruby-core:55053] [Feature #8426] [GH-387]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42822 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-09-04 09:25:06 +04:00
rb_class_detach_subclasses ( obj ) ;
}
RCLASS_EXT ( obj ) - > subclasses = NULL ;
}
rb_class_remove_from_module_subclasses ( obj ) ;
rb_class_remove_from_super_subclasses ( obj ) ;
if ( RANY ( obj ) - > as . klass . ptr )
xfree ( RANY ( obj ) - > as . klass . ptr ) ;
RANY ( obj ) - > as . klass . ptr = NULL ;
2012-08-05 14:39:37 +04:00
break ;
case T_STRING :
rb_str_free ( obj ) ;
break ;
case T_ARRAY :
rb_ary_free ( obj ) ;
break ;
case T_HASH :
if ( RANY ( obj ) - > as . hash . ntbl ) {
st_free_table ( RANY ( obj ) - > as . hash . ntbl ) ;
}
break ;
case T_REGEXP :
if ( RANY ( obj ) - > as . regexp . ptr ) {
onig_free ( RANY ( obj ) - > as . regexp . ptr ) ;
}
break ;
case T_DATA :
if ( DATA_PTR ( obj ) ) {
2013-11-03 16:40:29 +04:00
int free_immediately = FALSE ;
2013-10-29 13:42:45 +04:00
2012-08-05 14:39:37 +04:00
if ( RTYPEDDATA_P ( obj ) ) {
2013-11-03 16:40:29 +04:00
free_immediately = ( RANY ( obj ) - > as . typeddata . type - > flags & RUBY_TYPED_FREE_IMMEDIATELY ) ! = 0 ;
2012-08-05 14:39:37 +04:00
RDATA ( obj ) - > dfree = RANY ( obj ) - > as . typeddata . type - > function . dfree ;
2013-10-29 15:16:54 +04:00
if ( 0 & & free_immediately = = 0 ) /* to expose non-free-immediate T_DATA */
2013-11-03 16:40:29 +04:00
fprintf ( stderr , " not immediate -> %s \n " , RANY ( obj ) - > as . typeddata . type - > wrap_struct_name ) ;
2012-08-05 14:39:37 +04:00
}
2013-10-29 13:42:45 +04:00
if ( RANY ( obj ) - > as . data . dfree = = RUBY_DEFAULT_FREE ) {
2012-08-05 14:39:37 +04:00
xfree ( DATA_PTR ( obj ) ) ;
}
else if ( RANY ( obj ) - > as . data . dfree ) {
2013-10-29 13:42:45 +04:00
if ( free_immediately ) {
( RDATA ( obj ) - > dfree ) ( DATA_PTR ( obj ) ) ;
}
else {
2013-11-01 17:22:54 +04:00
make_deferred ( objspace , RANY ( obj ) ) ;
2013-10-29 13:42:45 +04:00
return 1 ;
}
2012-08-05 14:39:37 +04:00
}
}
break ;
case T_MATCH :
if ( RANY ( obj ) - > as . match . rmatch ) {
struct rmatch * rm = RANY ( obj ) - > as . match . rmatch ;
onig_region_free ( & rm - > regs , 0 ) ;
if ( rm - > char_offset )
xfree ( rm - > char_offset ) ;
xfree ( rm ) ;
}
break ;
case T_FILE :
if ( RANY ( obj ) - > as . file . fptr ) {
2013-11-01 17:22:54 +04:00
make_io_deferred ( objspace , RANY ( obj ) ) ;
2012-08-05 14:39:37 +04:00
return 1 ;
}
break ;
case T_RATIONAL :
case T_COMPLEX :
break ;
case T_ICLASS :
/* iClass shares table with the module */
* class.c, compile.c, eval.c, gc.h, insns.def, internal.h, method.h,
variable.c, vm.c, vm_core.c, vm_insnhelper.c, vm_insnhelper.h,
vm_method.c: Implement class hierarchy method cache invalidation.
[ruby-core:55053] [Feature #8426] [GH-387]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42822 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-09-04 09:25:06 +04:00
if ( RCLASS_EXT ( obj ) - > subclasses ) {
rb_class_detach_subclasses ( obj ) ;
RCLASS_EXT ( obj ) - > subclasses = NULL ;
}
rb_class_remove_from_module_subclasses ( obj ) ;
rb_class_remove_from_super_subclasses ( obj ) ;
2012-08-05 14:39:37 +04:00
xfree ( RANY ( obj ) - > as . klass . ptr ) ;
* class.c, compile.c, eval.c, gc.h, insns.def, internal.h, method.h,
variable.c, vm.c, vm_core.c, vm_insnhelper.c, vm_insnhelper.h,
vm_method.c: Implement class hierarchy method cache invalidation.
[ruby-core:55053] [Feature #8426] [GH-387]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42822 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-09-04 09:25:06 +04:00
RANY ( obj ) - > as . klass . ptr = NULL ;
2012-08-05 14:39:37 +04:00
break ;
2009-03-23 08:58:15 +03:00
2012-08-05 14:39:37 +04:00
case T_FLOAT :
break ;
2009-03-23 08:58:15 +03:00
2012-08-05 14:39:37 +04:00
case T_BIGNUM :
2014-02-16 01:17:34 +04:00
if ( ! ( RBASIC ( obj ) - > flags & BIGNUM_EMBED_FLAG ) & & BIGNUM_DIGITS ( obj ) ) {
xfree ( BIGNUM_DIGITS ( obj ) ) ;
2012-08-05 14:39:37 +04:00
}
break ;
case T_NODE :
switch ( nd_type ( obj ) ) {
case NODE_SCOPE :
if ( RANY ( obj ) - > as . node . u1 . tbl ) {
xfree ( RANY ( obj ) - > as . node . u1 . tbl ) ;
}
break ;
case NODE_ARGS :
if ( RANY ( obj ) - > as . node . u3 . args ) {
xfree ( RANY ( obj ) - > as . node . u3 . args ) ;
}
break ;
case NODE_ALLOCA :
xfree ( RANY ( obj ) - > as . node . u1 . node ) ;
break ;
}
break ; /* no need to free iv_tbl */
2008-04-25 13:03:32 +04:00
2012-08-05 14:39:37 +04:00
case T_STRUCT :
if ( ( RBASIC ( obj ) - > flags & RSTRUCT_EMBED_LEN_MASK ) = = 0 & &
RANY ( obj ) - > as . rstruct . as . heap . ptr ) {
2013-06-21 15:22:18 +04:00
xfree ( ( void * ) RANY ( obj ) - > as . rstruct . as . heap . ptr ) ;
2012-08-05 14:39:37 +04:00
}
break ;
2008-04-25 13:03:32 +04:00
2012-08-05 14:39:37 +04:00
default :
rb_bug ( " gc_sweep(): unknown data type 0x%x(%p) 0x% " PRIxVALUE ,
BUILTIN_TYPE ( obj ) , ( void * ) obj , RBASIC ( obj ) - > flags ) ;
2008-04-25 13:03:32 +04:00
}
2012-08-05 14:39:37 +04:00
return 0 ;
2008-04-25 13:03:32 +04:00
}
2012-08-05 14:39:37 +04:00
void
Init_heap ( void )
2010-11-03 04:01:12 +03:00
{
2013-10-22 14:54:44 +04:00
rb_objspace_t * objspace = & rb_objspace ;
2013-12-06 13:38:22 +04:00
# if RGENGC_ESTIMATE_OLDMALLOC
objspace - > rgengc . oldmalloc_increase_limit = gc_params . oldmalloc_limit_min ;
# endif
2013-11-23 07:33:10 +04:00
heap_add_pages ( objspace , heap_eden , gc_params . heap_init_slots / HEAP_OBJ_LIMIT ) ;
2013-10-22 14:54:44 +04:00
init_mark_stack ( & objspace - > mark_stack ) ;
# ifdef USE_SIGALTSTACK
{
/* altstack of another threads are allocated in another place */
rb_thread_t * th = GET_THREAD ( ) ;
void * tmp = th - > altstack ;
th - > altstack = malloc ( rb_sigaltstack_size ( ) ) ;
free ( tmp ) ; /* free previously allocated area */
}
# endif
objspace - > profile . invoke_time = getrusage_time ( ) ;
finalizer_table = st_init_numtable ( ) ;
2010-11-03 04:01:12 +03:00
}
2012-08-05 14:39:37 +04:00
typedef int each_obj_callback ( void * , void * , size_t , void * ) ;
2008-07-05 11:15:41 +04:00
2012-08-05 14:39:37 +04:00
struct each_obj_args {
each_obj_callback * callback ;
void * data ;
} ;
static VALUE
objspace_each_objects ( VALUE arg )
1998-01-16 15:13:05 +03:00
{
2012-08-05 14:39:37 +04:00
size_t i ;
2013-10-18 10:33:36 +04:00
struct heap_page_body * last_body = 0 ;
struct heap_page * page ;
2012-08-05 14:39:37 +04:00
RVALUE * pstart , * pend ;
2010-11-04 15:06:08 +03:00
rb_objspace_t * objspace = & rb_objspace ;
2012-08-05 14:39:37 +04:00
struct each_obj_args * args = ( struct each_obj_args * ) arg ;
2009-02-22 17:23:33 +03:00
2012-08-05 14:39:37 +04:00
i = 0 ;
2013-10-22 14:28:31 +04:00
while ( i < heap_pages_used ) {
while ( 0 < i & & last_body < heap_pages_sorted [ i - 1 ] - > body ) i - - ;
while ( i < heap_pages_used & & heap_pages_sorted [ i ] - > body < = last_body ) i + + ;
if ( heap_pages_used < = i ) break ;
2010-11-04 15:06:08 +03:00
2013-10-22 14:28:31 +04:00
page = heap_pages_sorted [ i ] ;
2013-10-18 10:33:36 +04:00
last_body = page - > body ;
2013-07-17 10:52:13 +04:00
2013-10-18 10:33:36 +04:00
pstart = page - > start ;
pend = pstart + page - > limit ;
2010-11-04 15:06:08 +03:00
2013-10-17 00:41:49 +04:00
if ( ( * args - > callback ) ( pstart , pend , sizeof ( RVALUE ) , args - > data ) ) {
break ;
2006-12-31 18:02:22 +03:00
}
}
1998-01-16 15:13:05 +03:00
2012-08-05 14:39:37 +04:00
return Qnil ;
1998-01-16 15:13:05 +03:00
}
2012-08-05 14:39:37 +04:00
/*
* rb_objspace_each_objects ( ) is special C API to walk through
* Ruby object space . This C API is too difficult to use it .
* To be frank , you should not use it . Or you need to read the
* source code of this function and understand what this function does .
*
2013-10-18 10:33:36 +04:00
* ' callback ' will be called several times ( the number of heap page ,
2012-08-05 14:39:37 +04:00
* at current implementation ) with :
2013-10-18 10:33:36 +04:00
* vstart : a pointer to the first living object of the heap_page .
* vend : a pointer to next to the valid heap_page area .
2012-08-05 14:39:37 +04:00
* stride : a distance to next VALUE .
*
* If callback ( ) returns non - zero , the iteration will be stopped .
*
* This is a sample callback code to iterate liveness objects :
*
* int
* sample_callback ( void * vstart , void * vend , int stride , void * data ) {
* VALUE v = ( VALUE ) vstart ;
* for ( ; v ! = ( VALUE ) vend ; v + = stride ) {
* if ( RBASIC ( v ) - > flags ) { // liveness check
* // do something with live object 'v'
* }
* return 0 ; // continue to iteration
* }
*
2013-10-18 10:33:36 +04:00
* Note : ' vstart ' is not a top of heap_page . This point the first
2012-08-05 14:39:37 +04:00
* living object to grasp at least one object to avoid GC issue .
2013-10-18 10:33:36 +04:00
* This means that you can not walk through all Ruby object page
* including freed object page .
2012-08-05 14:39:37 +04:00
*
* Note : On this implementation , ' stride ' is same as sizeof ( RVALUE ) .
* However , there are possibilities to pass variable values with
* ' stride ' with some reasons . You must use stride instead of
* use some constant value in the iteration .
*/
void
rb_objspace_each_objects ( each_obj_callback * callback , void * data )
{
struct each_obj_args args ;
rb_objspace_t * objspace = & rb_objspace ;
2013-12-16 13:01:49 +04:00
int prev_dont_lazy_sweep = objspace - > flags . dont_lazy_sweep ;
2009-06-17 01:36:50 +04:00
2013-07-18 03:19:38 +04:00
gc_rest_sweep ( objspace ) ;
2012-08-05 14:39:37 +04:00
objspace - > flags . dont_lazy_sweep = TRUE ;
2009-06-17 01:36:50 +04:00
2012-08-05 14:39:37 +04:00
args . callback = callback ;
args . data = data ;
2013-12-16 13:01:49 +04:00
if ( prev_dont_lazy_sweep ) {
objspace_each_objects ( ( VALUE ) & args ) ;
}
else {
rb_ensure ( objspace_each_objects , ( VALUE ) & args , lazy_sweep_enable , Qnil ) ;
}
2009-06-17 01:36:50 +04:00
}
2012-08-05 14:39:37 +04:00
struct os_each_struct {
size_t num ;
VALUE of ;
} ;
2009-06-17 01:36:50 +04:00
2012-10-05 12:14:09 +04:00
static int
internal_object_p ( VALUE obj )
{
RVALUE * p = ( RVALUE * ) obj ;
if ( p - > as . basic . flags ) {
switch ( BUILTIN_TYPE ( p ) ) {
case T_NONE :
case T_ICLASS :
case T_NODE :
case T_ZOMBIE :
break ;
case T_CLASS :
if ( FL_TEST ( p , FL_SINGLETON ) )
break ;
default :
if ( ! p - > as . basic . klass ) break ;
return 0 ;
}
}
return 1 ;
}
2012-10-24 04:04:56 +04:00
int
rb_objspace_internal_object_p ( VALUE obj )
{
return internal_object_p ( obj ) ;
}
2012-08-05 14:39:37 +04:00
static int
os_obj_of_i ( void * vstart , void * vend , size_t stride , void * data )
2009-06-17 01:36:50 +04:00
{
2012-08-05 14:39:37 +04:00
struct os_each_struct * oes = ( struct os_each_struct * ) data ;
RVALUE * p = ( RVALUE * ) vstart , * pend = ( RVALUE * ) vend ;
2009-06-17 01:36:50 +04:00
2012-08-05 14:39:37 +04:00
for ( ; p ! = pend ; p + + ) {
2012-10-05 12:14:09 +04:00
volatile VALUE v = ( VALUE ) p ;
if ( ! internal_object_p ( v ) ) {
if ( ! oes - > of | | rb_obj_is_kind_of ( v , oes - > of ) ) {
rb_yield ( v ) ;
oes - > num + + ;
2012-08-05 14:39:37 +04:00
}
}
}
2007-06-14 12:35:20 +04:00
2012-08-05 14:39:37 +04:00
return 0 ;
}
2004-12-13 12:57:41 +03:00
2012-08-05 14:39:37 +04:00
static VALUE
os_obj_of ( VALUE of )
2003-06-28 07:29:00 +04:00
{
2012-08-05 14:39:37 +04:00
struct os_each_struct oes ;
2003-06-28 07:29:00 +04:00
2012-08-05 14:39:37 +04:00
oes . num = 0 ;
oes . of = of ;
rb_objspace_each_objects ( os_obj_of_i , & oes ) ;
return SIZET2NUM ( oes . num ) ;
2003-06-28 07:29:00 +04:00
}
2001-11-19 08:03:03 +03:00
2012-08-05 14:39:37 +04:00
/*
* call - seq :
* ObjectSpace . each_object ( [ module ] ) { | obj | . . . } - > fixnum
* ObjectSpace . each_object ( [ module ] ) - > an_enumerator
*
* Calls the block once for each living , nonimmediate object in this
* Ruby process . If < i > module < / i > is specified , calls the block
* for only those classes or modules that match ( or are a subclass of )
* < i > module < / i > . Returns the number of objects found . Immediate
* objects ( < code > Fixnum < / code > s , < code > Symbol < / code > s
* < code > true < / code > , < code > false < / code > , and < code > nil < / code > ) are
* never returned . In the example below , < code > each_object < / code >
* returns both the numbers we defined and several constants defined in
* the < code > Math < / code > module .
*
* If no block is given , an enumerator is returned instead .
*
* a = 102.7
* b = 95 # Won ' t be returned
* c = 12345678987654321
* count = ObjectSpace . each_object ( Numeric ) { | x | p x }
* puts " Total count: #{count} "
*
* < em > produces : < / em >
*
* 12345678987654321
* 102.7
* 2.71828182845905
* 3.14159265358979
* 2.22044604925031e-16
* 1.7976931348623157e+308
* 2.2250738585072e-308
* Total count : 7
*
*/
2003-04-09 10:44:34 +04:00
2012-08-05 14:39:37 +04:00
static VALUE
os_each_obj ( int argc , VALUE * argv , VALUE os )
2001-11-19 08:03:03 +03:00
{
2012-08-05 14:39:37 +04:00
VALUE of ;
2001-11-19 08:03:03 +03:00
2012-08-05 14:39:37 +04:00
if ( argc = = 0 ) {
of = 0 ;
2007-12-15 07:09:24 +03:00
}
2012-08-05 14:39:37 +04:00
else {
rb_scan_args ( argc , argv , " 01 " , & of ) ;
}
RETURN_ENUMERATOR ( os , 1 , & of ) ;
return os_obj_of ( of ) ;
2008-11-27 17:55:45 +03:00
}
2012-08-05 14:39:37 +04:00
/*
* call - seq :
* ObjectSpace . undefine_finalizer ( obj )
*
* Removes all finalizers for < i > obj < / i > .
*
*/
2011-07-07 18:59:09 +04:00
2012-08-05 14:39:37 +04:00
static VALUE
undefine_final ( VALUE os , VALUE obj )
2008-11-27 17:55:45 +03:00
{
2013-11-10 03:03:11 +04:00
return rb_undefine_finalizer ( obj ) ;
2001-11-19 08:03:03 +03:00
}
2001-11-13 11:19:52 +03:00
2012-08-05 14:39:37 +04:00
VALUE
2013-11-10 03:03:11 +04:00
rb_undefine_finalizer ( VALUE obj )
2001-11-13 11:19:52 +03:00
{
2012-08-05 14:39:37 +04:00
rb_objspace_t * objspace = & rb_objspace ;
st_data_t data = obj ;
rb_check_frozen ( obj ) ;
st_delete ( finalizer_table , & data , 0 ) ;
FL_UNSET ( obj , FL_FINALIZE ) ;
return obj ;
2001-11-13 11:19:52 +03:00
}
2013-11-09 19:34:30 +04:00
static void
should_be_callable ( VALUE block )
{
2013-11-09 19:36:46 +04:00
if ( ! rb_obj_respond_to ( block , rb_intern ( " call " ) , TRUE ) ) {
2013-11-09 19:34:30 +04:00
rb_raise ( rb_eArgError , " wrong type argument %s (should be callable) " ,
rb_obj_classname ( block ) ) ;
}
}
2013-12-10 09:17:19 +04:00
static void
should_be_finalizable ( VALUE obj )
{
rb_check_frozen ( obj ) ;
if ( ! FL_ABLE ( obj ) ) {
rb_raise ( rb_eArgError , " cannot define finalizer for %s " ,
rb_obj_classname ( obj ) ) ;
}
}
2013-11-09 19:34:30 +04:00
2012-08-05 14:39:37 +04:00
/*
* call - seq :
* ObjectSpace . define_finalizer ( obj , aProc = proc ( ) )
*
* Adds < i > aProc < / i > as a finalizer , to be called after < i > obj < / i >
* was destroyed .
*
*/
2003-04-09 10:44:34 +04:00
2012-08-05 14:39:37 +04:00
static VALUE
define_final ( int argc , VALUE * argv , VALUE os )
2001-11-13 11:19:52 +03:00
{
2012-08-05 14:39:37 +04:00
VALUE obj , block ;
2001-11-27 13:00:35 +03:00
2012-08-05 14:39:37 +04:00
rb_scan_args ( argc , argv , " 11 " , & obj , & block ) ;
2013-12-10 09:17:19 +04:00
should_be_finalizable ( obj ) ;
2012-08-05 14:39:37 +04:00
if ( argc = = 1 ) {
block = rb_block_proc ( ) ;
}
2013-11-09 19:34:30 +04:00
else {
should_be_callable ( block ) ;
2001-11-13 11:19:52 +03:00
}
* probes.d: add DTrace probe declarations. [ruby-core:27448]
* array.c (empty_ary_alloc, ary_new): added array create DTrace probe.
* compile.c (rb_insns_name): allowing DTrace probes to access
instruction sequence name.
* Makefile.in: translate probes.d file to appropriate header file.
* common.mk: declare dependencies on the DTrace header.
* configure.in: add a test for existence of DTrace.
* eval.c (setup_exception): add a probe for when an exception is
raised.
* gc.c: Add DTrace probes for mark begin and end, and sweep begin and
end.
* hash.c (empty_hash_alloc): Add a probe for hash allocation.
* insns.def: Add probes for function entry and return.
* internal.h: function declaration for compile.c change.
* load.c (rb_f_load): add probes for `load` entry and exit, require
entry and exit, and wrapping search_required for load path search.
* object.c (rb_obj_alloc): added a probe for general object creation.
* parse.y (yycompile0): added a probe around parse and compile phase.
* string.c (empty_str_alloc, str_new): DTrace probes for string
allocation.
* test/dtrace/*: tests for DTrace probes.
* vm.c (vm_invoke_proc): add probes for function return on exception
raise, hash create, and instruction sequence execution.
* vm_core.h: add probe declarations for function entry and exit.
* vm_dump.c: add probes header file.
* vm_eval.c (vm_call0_cfunc, vm_call0_cfunc_with_frame): add probe on
function entry and return.
* vm_exec.c: expose instruction number to instruction name function.
* vm_insnshelper.c: add function entry and exit probes for cfunc
methods.
* vm_insnhelper.h: vm usage information is always collected, so
uncomment the functions.
12 19:14:50 2012 Akinori MUSHA <knu@iDaemons.org>
* configure.in (isinf, isnan): isinf() and isnan() are macros on
DragonFly which cannot be found by AC_REPLACE_FUNCS(). This
workaround enforces the fact that they exist on DragonFly.
12 15:59:38 2012 Shugo Maeda <shugo@ruby-lang.org>
* vm_core.h (rb_call_info_t::refinements), compile.c (new_callinfo),
vm_insnhelper.c (vm_search_method): revert r37616 because it's too
slow. [ruby-dev:46477]
* test/ruby/test_refinement.rb (test_inline_method_cache): skip
the test until the bug is fixed efficiently.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37631 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-11-13 01:52:12 +04:00
2012-08-05 14:39:37 +04:00
return define_final0 ( obj , block ) ;
2001-11-13 11:19:52 +03:00
}
2012-08-05 14:39:37 +04:00
static VALUE
define_final0 ( VALUE obj , VALUE block )
2003-04-09 12:27:01 +04:00
{
2012-08-05 14:39:37 +04:00
rb_objspace_t * objspace = & rb_objspace ;
VALUE table ;
st_data_t data ;
2003-04-09 12:27:01 +04:00
2012-08-05 14:39:37 +04:00
RBASIC ( obj ) - > flags | = FL_FINALIZE ;
1998-01-16 15:13:05 +03:00
2012-08-05 14:39:37 +04:00
block = rb_ary_new3 ( 2 , INT2FIX ( rb_safe_level ( ) ) , block ) ;
OBJ_FREEZE ( block ) ;
1998-01-16 15:13:05 +03:00
2012-08-05 14:39:37 +04:00
if ( st_lookup ( finalizer_table , obj , & data ) ) {
table = ( VALUE ) data ;
rb_ary_push ( table , block ) ;
1998-01-16 15:13:05 +03:00
}
2012-08-05 14:39:37 +04:00
else {
table = rb_ary_new3 ( 1 , block ) ;
* include/ruby/ruby.h: constify RBasic::klass and add
RBASIC_CLASS(obj) macro which returns a class of `obj'.
This change is a part of RGENGC branch [ruby-trunk - Feature #8339].
* object.c: add new function rb_obj_reveal().
This function reveal interal (hidden) object by rb_obj_hide().
Note that do not change class before and after hiding.
Only permitted example is:
klass = RBASIC_CLASS(obj);
rb_obj_hide(obj);
....
rb_obj_reveal(obj, klass);
TODO: API design. rb_obj_reveal() should be replaced with others.
TODO: modify constified variables using cast may be harmful for
compiler's analysis and optimizaton.
Any idea to prohibt inserting RBasic::klass directly?
If rename RBasic::klass and force to use RBASIC_CLASS(obj),
then all codes such as `RBASIC(obj)->klass' will be
compilation error. Is it acceptable? (We have similar
experience at Ruby 1.9,
for example "RARRAY(ary)->ptr" to "RARRAY_PTR(ary)".
* internal.h: add some macros.
* RBASIC_CLEAR_CLASS(obj) clear RBasic::klass to make it internal
object.
* RBASIC_SET_CLASS(obj, cls) set RBasic::klass.
* RBASIC_SET_CLASS_RAW(obj, cls) same as RBASIC_SET_CLASS
without write barrier (planned).
* RCLASS_SET_SUPER(a, b) set super class of a.
* array.c, class.c, compile.c, encoding.c, enum.c, error.c, eval.c,
file.c, gc.c, hash.c, io.c, iseq.c, marshal.c, object.c,
parse.y, proc.c, process.c, random.c, ruby.c, sprintf.c,
string.c, thread.c, transcode.c, vm.c, vm_eval.c, win32/file.c:
Use above macros and functions to access RBasic::klass.
* ext/coverage/coverage.c, ext/readline/readline.c,
ext/socket/ancdata.c, ext/socket/init.c,
* ext/zlib/zlib.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40691 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 14:49:11 +04:00
RBASIC_CLEAR_CLASS ( table ) ;
2012-08-05 14:39:37 +04:00
st_add_direct ( finalizer_table , obj , table ) ;
}
return block ;
1998-01-16 15:13:05 +03:00
}
2012-08-05 14:39:37 +04:00
VALUE
2013-11-10 03:03:11 +04:00
rb_define_finalizer ( VALUE obj , VALUE block )
1998-01-16 15:13:05 +03:00
{
2013-12-10 09:17:19 +04:00
should_be_finalizable ( obj ) ;
2013-11-09 19:34:30 +04:00
should_be_callable ( block ) ;
2012-08-05 14:39:37 +04:00
return define_final0 ( obj , block ) ;
1998-01-16 15:13:05 +03:00
}
2012-08-05 14:39:37 +04:00
void
rb_gc_copy_finalizer ( VALUE dest , VALUE obj )
1998-01-16 15:13:05 +03:00
{
2012-08-05 14:39:37 +04:00
rb_objspace_t * objspace = & rb_objspace ;
VALUE table ;
st_data_t data ;
1998-01-16 15:13:05 +03:00
2012-08-05 14:39:37 +04:00
if ( ! FL_TEST ( obj , FL_FINALIZE ) ) return ;
if ( st_lookup ( finalizer_table , obj , & data ) ) {
table = ( VALUE ) data ;
st_insert ( finalizer_table , dest , table ) ;
}
FL_SET ( dest , FL_FINALIZE ) ;
2008-04-27 07:20:35 +04:00
}
2012-08-05 14:39:37 +04:00
static VALUE
run_single_final ( VALUE arg )
2008-04-27 07:20:35 +04:00
{
2012-08-05 14:39:37 +04:00
VALUE * args = ( VALUE * ) arg ;
rb_eval_cmd ( args [ 0 ] , args [ 1 ] , ( int ) args [ 2 ] ) ;
return Qnil ;
1998-01-16 15:13:05 +03:00
}
2012-08-05 14:39:37 +04:00
static void
run_finalizer ( rb_objspace_t * objspace , VALUE obj , VALUE table )
{
long i ;
int status ;
VALUE args [ 3 ] ;
VALUE objid = nonspecial_obj_id ( obj ) ;
2008-04-27 07:20:35 +04:00
2012-08-05 14:39:37 +04:00
if ( RARRAY_LEN ( table ) > 0 ) {
args [ 1 ] = rb_obj_freeze ( rb_ary_new3 ( 1 , objid ) ) ;
}
else {
args [ 1 ] = 0 ;
}
2008-04-27 07:20:35 +04:00
2012-08-05 14:39:37 +04:00
args [ 2 ] = ( VALUE ) rb_safe_level ( ) ;
for ( i = 0 ; i < RARRAY_LEN ( table ) ; i + + ) {
2013-05-13 13:56:22 +04:00
VALUE final = RARRAY_AREF ( table , i ) ;
args [ 0 ] = RARRAY_AREF ( final , 1 ) ;
args [ 2 ] = FIX2INT ( RARRAY_AREF ( final , 0 ) ) ;
2012-08-05 14:39:37 +04:00
status = 0 ;
rb_protect ( run_single_final , ( VALUE ) args , & status ) ;
if ( status )
rb_set_errinfo ( Qnil ) ;
}
1998-01-16 15:13:05 +03:00
}
2005-10-18 21:35:18 +04:00
static void
2012-08-05 14:39:37 +04:00
run_final ( rb_objspace_t * objspace , VALUE obj )
1998-01-16 15:13:05 +03:00
{
2012-08-05 14:39:37 +04:00
RUBY_DATA_FUNC free_func = 0 ;
st_data_t key , table ;
2013-11-24 23:18:53 +04:00
heap_pages_final_slots - - ;
2012-08-05 14:39:37 +04:00
* include/ruby/ruby.h: constify RBasic::klass and add
RBASIC_CLASS(obj) macro which returns a class of `obj'.
This change is a part of RGENGC branch [ruby-trunk - Feature #8339].
* object.c: add new function rb_obj_reveal().
This function reveal interal (hidden) object by rb_obj_hide().
Note that do not change class before and after hiding.
Only permitted example is:
klass = RBASIC_CLASS(obj);
rb_obj_hide(obj);
....
rb_obj_reveal(obj, klass);
TODO: API design. rb_obj_reveal() should be replaced with others.
TODO: modify constified variables using cast may be harmful for
compiler's analysis and optimizaton.
Any idea to prohibt inserting RBasic::klass directly?
If rename RBasic::klass and force to use RBASIC_CLASS(obj),
then all codes such as `RBASIC(obj)->klass' will be
compilation error. Is it acceptable? (We have similar
experience at Ruby 1.9,
for example "RARRAY(ary)->ptr" to "RARRAY_PTR(ary)".
* internal.h: add some macros.
* RBASIC_CLEAR_CLASS(obj) clear RBasic::klass to make it internal
object.
* RBASIC_SET_CLASS(obj, cls) set RBasic::klass.
* RBASIC_SET_CLASS_RAW(obj, cls) same as RBASIC_SET_CLASS
without write barrier (planned).
* RCLASS_SET_SUPER(a, b) set super class of a.
* array.c, class.c, compile.c, encoding.c, enum.c, error.c, eval.c,
file.c, gc.c, hash.c, io.c, iseq.c, marshal.c, object.c,
parse.y, proc.c, process.c, random.c, ruby.c, sprintf.c,
string.c, thread.c, transcode.c, vm.c, vm_eval.c, win32/file.c:
Use above macros and functions to access RBasic::klass.
* ext/coverage/coverage.c, ext/readline/readline.c,
ext/socket/ancdata.c, ext/socket/init.c,
* ext/zlib/zlib.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40691 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 14:49:11 +04:00
RBASIC_CLEAR_CLASS ( obj ) ;
2012-08-05 14:39:37 +04:00
if ( RTYPEDDATA_P ( obj ) ) {
free_func = RTYPEDDATA_TYPE ( obj ) - > function . dfree ;
}
else {
free_func = RDATA ( obj ) - > dfree ;
}
if ( free_func ) {
( * free_func ) ( DATA_PTR ( obj ) ) ;
}
key = ( st_data_t ) obj ;
if ( st_delete ( finalizer_table , & key , & table ) ) {
run_finalizer ( objspace , obj , ( VALUE ) table ) ;
}
2003-11-28 17:23:33 +03:00
}
2012-08-05 14:39:37 +04:00
static void
finalize_list ( rb_objspace_t * objspace , RVALUE * p )
2007-09-26 23:40:49 +04:00
{
2012-08-05 14:39:37 +04:00
while ( p ) {
RVALUE * tmp = p - > as . free . next ;
2013-10-23 12:48:54 +04:00
struct heap_page * page = GET_HEAP_PAGE ( p ) ;
2012-08-05 14:39:37 +04:00
run_final ( objspace , ( VALUE ) p ) ;
2013-11-01 16:49:49 +04:00
objspace - > profile . total_freed_object_num + + ;
2013-10-23 12:48:54 +04:00
2013-11-24 23:18:53 +04:00
page - > final_slots - - ;
2013-10-23 12:48:54 +04:00
heap_page_add_freeobj ( objspace , GET_HEAP_PAGE ( p ) , ( VALUE ) p ) ;
2013-11-23 03:50:08 +04:00
heap_pages_swept_slots + + ;
2013-10-23 12:48:54 +04:00
2012-08-05 14:39:37 +04:00
p = tmp ;
}
2007-09-26 23:40:49 +04:00
}
static void
2012-08-05 14:39:37 +04:00
finalize_deferred ( rb_objspace_t * objspace )
2007-09-26 23:40:49 +04:00
{
2013-12-05 05:47:12 +04:00
RVALUE * p ;
2012-08-05 14:39:37 +04:00
2013-12-05 05:47:12 +04:00
while ( ( p = ATOMIC_PTR_EXCHANGE ( heap_pages_deferred_final , 0 ) ) ! = 0 ) {
2012-08-05 14:39:37 +04:00
finalize_list ( objspace , p ) ;
}
2007-09-26 23:40:49 +04:00
}
2013-05-27 01:30:44 +04:00
static void
gc_finalize_deferred ( void * dmy )
2007-09-26 23:40:49 +04:00
{
2012-08-05 14:39:37 +04:00
rb_objspace_t * objspace = & rb_objspace ;
if ( ATOMIC_EXCHANGE ( finalizing , 1 ) ) return ;
finalize_deferred ( objspace ) ;
ATOMIC_SET ( finalizing , 0 ) ;
2007-09-26 23:40:49 +04:00
}
2013-05-27 01:30:44 +04:00
/* TODO: to keep compatibility, maybe unused. */
void
rb_gc_finalize_deferred ( void )
{
gc_finalize_deferred ( 0 ) ;
}
static void
2013-12-17 09:29:14 +04:00
gc_finalize_deferred_register ( void )
2013-05-27 01:30:44 +04:00
{
2013-10-22 10:24:54 +04:00
if ( rb_postponed_job_register_one ( 0 , gc_finalize_deferred , 0 ) = = 0 ) {
rb_bug ( " gc_finalize_deferred_register: can't register finalizer. " ) ;
}
2013-05-27 01:30:44 +04:00
}
2012-08-05 14:39:37 +04:00
struct force_finalize_list {
VALUE obj ;
VALUE table ;
struct force_finalize_list * next ;
} ;
static int
force_chain_object ( st_data_t key , st_data_t val , st_data_t arg )
1998-01-16 15:13:05 +03:00
{
2012-08-05 14:39:37 +04:00
struct force_finalize_list * * prev = ( struct force_finalize_list * * ) arg ;
struct force_finalize_list * curr = ALLOC ( struct force_finalize_list ) ;
curr - > obj = key ;
curr - > table = val ;
curr - > next = * prev ;
* prev = curr ;
return ST_CONTINUE ;
2003-11-28 17:23:33 +03:00
}
void
2012-08-05 14:39:37 +04:00
rb_gc_call_finalizer_at_exit ( void )
2003-11-28 17:23:33 +03:00
{
2012-08-05 14:39:37 +04:00
rb_objspace_call_finalizer ( & rb_objspace ) ;
1998-01-16 15:13:05 +03:00
}
2009-07-15 18:59:41 +04:00
static void
2012-08-05 14:39:37 +04:00
rb_objspace_call_finalizer ( rb_objspace_t * objspace )
2009-07-15 18:59:41 +04:00
{
2012-08-05 14:39:37 +04:00
RVALUE * p , * pend ;
size_t i ;
2009-08-28 06:45:41 +04:00
2013-07-18 03:19:38 +04:00
gc_rest_sweep ( objspace ) ;
2009-07-15 18:59:41 +04:00
2012-08-05 14:39:37 +04:00
if ( ATOMIC_EXCHANGE ( finalizing , 1 ) ) return ;
2009-07-15 18:59:41 +04:00
2012-10-05 13:21:41 +04:00
/* run finalizers */
2012-11-30 02:56:02 +04:00
finalize_deferred ( objspace ) ;
2013-10-22 14:28:31 +04:00
assert ( heap_pages_deferred_final = = 0 ) ;
2012-11-30 02:56:02 +04:00
2012-08-05 14:39:37 +04:00
/* force to run finalizer */
while ( finalizer_table - > num_entries ) {
struct force_finalize_list * list = 0 ;
st_foreach ( finalizer_table , force_chain_object , ( st_data_t ) & list ) ;
while ( list ) {
struct force_finalize_list * curr = list ;
st_data_t obj = ( st_data_t ) curr - > obj ;
run_finalizer ( objspace , curr - > obj , curr - > table ) ;
st_delete ( finalizer_table , & obj , 0 ) ;
list = curr - > next ;
xfree ( curr ) ;
}
}
2009-07-15 18:59:41 +04:00
2012-08-05 14:39:37 +04:00
/* finalizers are part of garbage collection */
during_gc + + ;
2009-07-15 18:59:41 +04:00
2012-08-05 14:39:37 +04:00
/* run data object's finalizers */
2013-10-22 14:28:31 +04:00
for ( i = 0 ; i < heap_pages_used ; i + + ) {
p = heap_pages_sorted [ i ] - > start ; pend = p + heap_pages_sorted [ i ] - > limit ;
2012-08-05 14:39:37 +04:00
while ( p < pend ) {
2013-11-07 22:10:33 +04:00
switch ( BUILTIN_TYPE ( p ) ) {
case T_DATA :
if ( ! DATA_PTR ( p ) | | ! RANY ( p ) - > as . data . dfree ) break ;
if ( rb_obj_is_thread ( ( VALUE ) p ) ) break ;
if ( rb_obj_is_mutex ( ( VALUE ) p ) ) break ;
if ( rb_obj_is_fiber ( ( VALUE ) p ) ) break ;
2012-08-05 14:39:37 +04:00
p - > as . free . flags = 0 ;
if ( RTYPEDDATA_P ( p ) ) {
RDATA ( p ) - > dfree = RANY ( p ) - > as . typeddata . type - > function . dfree ;
}
if ( RANY ( p ) - > as . data . dfree = = ( RUBY_DATA_FUNC ) - 1 ) {
xfree ( DATA_PTR ( p ) ) ;
}
else if ( RANY ( p ) - > as . data . dfree ) {
2013-11-01 17:22:54 +04:00
make_deferred ( objspace , RANY ( p ) ) ;
2012-08-05 14:39:37 +04:00
}
2013-11-07 22:10:33 +04:00
break ;
case T_FILE :
2012-08-05 14:39:37 +04:00
if ( RANY ( p ) - > as . file . fptr ) {
2013-11-01 17:22:54 +04:00
make_io_deferred ( objspace , RANY ( p ) ) ;
2012-08-05 14:39:37 +04:00
}
2013-11-07 22:10:33 +04:00
break ;
2012-08-05 14:39:37 +04:00
}
p + + ;
}
}
during_gc = 0 ;
2013-10-22 14:28:31 +04:00
if ( heap_pages_deferred_final ) {
finalize_list ( objspace , heap_pages_deferred_final ) ;
2012-03-18 12:17:39 +04:00
}
2009-07-15 18:59:41 +04:00
2012-08-05 14:39:37 +04:00
st_free_table ( finalizer_table ) ;
finalizer_table = 0 ;
ATOMIC_SET ( finalizing , 0 ) ;
2010-10-26 21:27:32 +04:00
}
2012-08-05 14:39:37 +04:00
static inline int
is_id_value ( rb_objspace_t * objspace , VALUE ptr )
2010-10-26 21:27:32 +04:00
{
2012-08-05 14:39:37 +04:00
if ( ! is_pointer_to_heap ( objspace , ( void * ) ptr ) ) return FALSE ;
if ( BUILTIN_TYPE ( ptr ) > T_FIXNUM ) return FALSE ;
if ( BUILTIN_TYPE ( ptr ) = = T_ICLASS ) return FALSE ;
return TRUE ;
2010-10-26 21:27:32 +04:00
}
2012-08-05 14:39:37 +04:00
static inline int
2013-10-22 14:28:31 +04:00
heap_is_swept_object ( rb_objspace_t * objspace , rb_heap_t * heap , VALUE ptr )
2010-10-26 21:27:32 +04:00
{
2013-11-19 13:52:52 +04:00
struct heap_page * page = GET_HEAP_PAGE ( ptr ) ;
return page - > before_sweep ? FALSE : TRUE ;
2012-11-22 19:03:46 +04:00
}
static inline int
2013-10-22 14:28:31 +04:00
is_swept_object ( rb_objspace_t * objspace , VALUE ptr )
2012-11-22 19:03:46 +04:00
{
2013-10-22 14:28:31 +04:00
if ( heap_is_swept_object ( objspace , heap_eden , ptr ) ) {
2012-11-22 19:03:46 +04:00
return TRUE ;
2013-10-22 14:28:31 +04:00
}
else {
return FALSE ;
}
}
static inline int
is_dead_object ( rb_objspace_t * objspace , VALUE ptr )
{
if ( ! is_lazy_sweeping ( heap_eden ) | | MARKED_IN_BITMAP ( GET_HEAP_MARK_BITS ( ptr ) , ptr ) ) return FALSE ;
if ( ! is_swept_object ( objspace , ptr ) ) return TRUE ;
2012-08-05 14:39:37 +04:00
return FALSE ;
2010-10-26 21:27:32 +04:00
}
2012-08-05 14:39:37 +04:00
static inline int
is_live_object ( rb_objspace_t * objspace , VALUE ptr )
2010-10-26 21:27:32 +04:00
{
2013-11-01 12:25:34 +04:00
switch ( BUILTIN_TYPE ( ptr ) ) {
case 0 : case T_ZOMBIE :
return FALSE ;
}
2012-08-05 14:39:37 +04:00
if ( is_dead_object ( objspace , ptr ) ) return FALSE ;
return TRUE ;
2010-10-26 21:27:32 +04:00
}
2013-07-18 03:19:38 +04:00
static inline int
is_markable_object ( rb_objspace_t * objspace , VALUE obj )
{
if ( rb_special_const_p ( obj ) ) return 0 ; /* special const is not markable */
if ( RGENGC_CHECK_MODE ) {
if ( ! is_pointer_to_heap ( objspace , ( void * ) obj ) ) rb_bug ( " is_markable_object: %p is not pointer to heap " , ( void * ) obj ) ;
if ( BUILTIN_TYPE ( obj ) = = T_NONE ) rb_bug ( " is_markable_object: %p is T_NONE " , ( void * ) obj ) ;
if ( BUILTIN_TYPE ( obj ) = = T_ZOMBIE ) rb_bug ( " is_markable_object: %p is T_ZOMBIE " , ( void * ) obj ) ;
}
return 1 ;
}
int
rb_objspace_markable_object_p ( VALUE obj )
{
2013-12-16 13:07:52 +04:00
rb_objspace_t * objspace = & rb_objspace ;
2013-12-16 14:22:03 +04:00
return is_markable_object ( objspace , obj ) & & is_live_object ( objspace , obj ) ;
2013-07-18 03:19:38 +04:00
}
2012-08-05 14:39:37 +04:00
/*
* call - seq :
* ObjectSpace . _id2ref ( object_id ) - > an_object
*
* Converts an object id to a reference to the object . May not be
* called on an object id passed as a parameter to a finalizer .
*
* s = " I am a string " # = > " I am a string "
* r = ObjectSpace . _id2ref ( s . object_id ) # = > " I am a string "
* r = = s # = > true
*
*/
2009-07-15 18:59:41 +04:00
2012-08-05 14:39:37 +04:00
static VALUE
id2ref ( VALUE obj , VALUE objid )
1998-01-16 15:13:05 +03:00
{
2012-08-05 14:39:37 +04:00
# if SIZEOF_LONG == SIZEOF_VOIDP
# define NUM2PTR(x) NUM2ULONG(x)
# elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
# define NUM2PTR(x) NUM2ULL(x)
# endif
rb_objspace_t * objspace = & rb_objspace ;
VALUE ptr ;
void * p0 ;
1998-01-16 15:13:05 +03:00
2012-08-05 14:39:37 +04:00
ptr = NUM2PTR ( objid ) ;
p0 = ( void * ) ptr ;
2012-03-13 07:37:06 +04:00
2012-08-05 14:39:37 +04:00
if ( ptr = = Qtrue ) return Qtrue ;
if ( ptr = = Qfalse ) return Qfalse ;
if ( ptr = = Qnil ) return Qnil ;
if ( FIXNUM_P ( ptr ) ) return ( VALUE ) ptr ;
2012-08-23 11:22:40 +04:00
if ( FLONUM_P ( ptr ) ) return ( VALUE ) ptr ;
2012-12-22 08:25:18 +04:00
ptr = obj_id_to_ref ( objid ) ;
2001-11-27 13:00:35 +03:00
2012-08-05 14:39:37 +04:00
if ( ( ptr % sizeof ( RVALUE ) ) = = ( 4 < < 2 ) ) {
ID symid = ptr / sizeof ( RVALUE ) ;
if ( rb_id2name ( symid ) = = 0 )
rb_raise ( rb_eRangeError , " %p is not symbol id value " , p0 ) ;
return ID2SYM ( symid ) ;
}
2003-04-09 12:27:01 +04:00
2012-08-05 14:39:37 +04:00
if ( ! is_id_value ( objspace , ptr ) ) {
rb_raise ( rb_eRangeError , " %p is not id value " , p0 ) ;
2001-11-13 11:19:52 +03:00
}
2012-08-05 14:39:37 +04:00
if ( ! is_live_object ( objspace , ptr ) ) {
rb_raise ( rb_eRangeError , " %p is recycled object " , p0 ) ;
}
return ( VALUE ) ptr ;
2003-11-28 17:23:33 +03:00
}
2012-08-05 14:39:37 +04:00
/*
* Document - method : __id__
* Document - method : object_id
*
* call - seq :
2012-11-29 12:15:53 +04:00
* obj . __id__ - > integer
* obj . object_id - > integer
2012-08-05 14:39:37 +04:00
*
2012-11-29 12:15:53 +04:00
* Returns an integer identifier for + obj + .
*
2014-01-09 21:34:27 +04:00
* The same number will be returned on all calls to + object_id + for a given object ,
2012-11-29 12:15:53 +04:00
* and no two active objects will share an id .
2014-01-09 21:34:39 +04:00
*
* Note that some objects of builtin classes are reused for optimization .
* This is the case for immediate values and frozen string litterals .
2014-01-10 08:13:04 +04:00
* Immediate values are not passed by reference but are passed by value :
2014-01-09 21:49:31 +04:00
* + nil + , + true + , + false + , Fixnums , Symbols . Some Floats may be immediates too .
2014-01-09 21:34:39 +04:00
*
* Object . new . object_id = = Object . new . object_id # = > false
* ( 21 * 2 ) . object_id = = ( 21 * 2 ) . object_id # = > true
* " hello " . object_id = = " hello " . object_id # = > false
* " hi " . freeze . object_id = = " hi " . freeze . object_id # = > true
2012-08-05 14:39:37 +04:00
*/
/*
* call - seq :
* obj . hash - > fixnum
*
2012-11-29 12:15:53 +04:00
* Generates a Fixnum hash value for this object .
*
* This function must have the property that < code > a . eql ? ( b ) < / code > implies
* < code > a . hash = = b . hash < / code > .
*
* The hash value is used by Hash class .
*
* Any hash value that exceeds the capacity of a Fixnum will be truncated
* before being used .
2012-08-05 14:39:37 +04:00
*/
VALUE
rb_obj_id ( VALUE obj )
{
/*
* 32 - bit VALUE space
* MSB - - - - - - - - - - - - - - - - - - - - - - - - LSB
* false 00000000000000000000000000000000
* true 00000000000000000000000000000010
* nil 00000000000000000000000000000100
* undef 00000000000000000000000000000110
* symbol ssssssssssssssssssssssss00001110
* object oooooooooooooooooooooooooooooo00 = 0 ( mod sizeof ( RVALUE ) )
* fixnum fffffffffffffffffffffffffffffff1
*
* object_id space
* LSB
* false 00000000000000000000000000000000
* true 00000000000000000000000000000010
* nil 00000000000000000000000000000100
* undef 00000000000000000000000000000110
* symbol 000 SSSSSSSSSSSSSSSSSSSSSSSSSSS0 S . . . S % A = 4 ( S . . . S = s . . . s * A + 4 )
* object oooooooooooooooooooooooooooooo0 o . . . o % A = 0
* fixnum fffffffffffffffffffffffffffffff1 bignum if required
*
* where A = sizeof ( RVALUE ) / 4
*
* sizeof ( RVALUE ) is
* 20 if 32 - bit , double is 4 - byte aligned
* 24 if 32 - bit , double is 8 - byte aligned
* 40 if 64 - bit
*/
if ( SYMBOL_P ( obj ) ) {
return ( SYM2ID ( obj ) * sizeof ( RVALUE ) + ( 4 < < 2 ) ) | FIXNUM_FLAG ;
}
2012-08-23 11:22:40 +04:00
else if ( FLONUM_P ( obj ) ) {
# if SIZEOF_LONG == SIZEOF_VOIDP
return LONG2NUM ( ( SIGNED_VALUE ) obj ) ;
# else
return LL2NUM ( ( SIGNED_VALUE ) obj ) ;
# endif
}
else if ( SPECIAL_CONST_P ( obj ) ) {
return LONG2NUM ( ( SIGNED_VALUE ) obj ) ;
2012-08-05 14:39:37 +04:00
}
return nonspecial_obj_id ( obj ) ;
}
2013-11-05 08:51:01 +04:00
size_t rb_str_memsize ( VALUE ) ;
size_t rb_ary_memsize ( VALUE ) ;
size_t rb_io_memsize ( const rb_io_t * ) ;
size_t rb_generic_ivar_memsize ( VALUE ) ;
# include "regint.h"
static size_t
obj_memsize_of ( VALUE obj , int use_tdata )
{
size_t size = 0 ;
if ( SPECIAL_CONST_P ( obj ) ) {
return 0 ;
}
if ( FL_TEST ( obj , FL_EXIVAR ) ) {
size + = rb_generic_ivar_memsize ( obj ) ;
}
switch ( BUILTIN_TYPE ( obj ) ) {
case T_OBJECT :
if ( ! ( RBASIC ( obj ) - > flags & ROBJECT_EMBED ) & &
ROBJECT ( obj ) - > as . heap . ivptr ) {
size + = ROBJECT ( obj ) - > as . heap . numiv * sizeof ( VALUE ) ;
}
break ;
case T_MODULE :
case T_CLASS :
2013-12-03 12:11:07 +04:00
if ( RCLASS_M_TBL_WRAPPER ( obj ) ) {
size + = sizeof ( struct method_table_wrapper ) ;
}
2013-11-05 08:51:01 +04:00
if ( RCLASS_M_TBL ( obj ) ) {
size + = st_memsize ( RCLASS_M_TBL ( obj ) ) ;
}
if ( RCLASS_EXT ( obj ) ) {
if ( RCLASS_IV_TBL ( obj ) ) {
size + = st_memsize ( RCLASS_IV_TBL ( obj ) ) ;
}
if ( RCLASS_IV_INDEX_TBL ( obj ) ) {
size + = st_memsize ( RCLASS_IV_INDEX_TBL ( obj ) ) ;
}
if ( RCLASS ( obj ) - > ptr - > iv_tbl ) {
size + = st_memsize ( RCLASS ( obj ) - > ptr - > iv_tbl ) ;
}
if ( RCLASS ( obj ) - > ptr - > const_tbl ) {
size + = st_memsize ( RCLASS ( obj ) - > ptr - > const_tbl ) ;
}
size + = sizeof ( rb_classext_t ) ;
}
break ;
case T_STRING :
size + = rb_str_memsize ( obj ) ;
break ;
case T_ARRAY :
size + = rb_ary_memsize ( obj ) ;
break ;
case T_HASH :
if ( RHASH ( obj ) - > ntbl ) {
size + = st_memsize ( RHASH ( obj ) - > ntbl ) ;
}
break ;
case T_REGEXP :
if ( RREGEXP ( obj ) - > ptr ) {
size + = onig_memsize ( RREGEXP ( obj ) - > ptr ) ;
}
break ;
case T_DATA :
if ( use_tdata ) size + = rb_objspace_data_type_memsize ( obj ) ;
break ;
case T_MATCH :
if ( RMATCH ( obj ) - > rmatch ) {
struct rmatch * rm = RMATCH ( obj ) - > rmatch ;
size + = onig_region_memsize ( & rm - > regs ) ;
size + = sizeof ( struct rmatch_offset ) * rm - > char_offset_num_allocated ;
size + = sizeof ( struct rmatch ) ;
}
break ;
case T_FILE :
if ( RFILE ( obj ) - > fptr ) {
size + = rb_io_memsize ( RFILE ( obj ) - > fptr ) ;
}
break ;
case T_RATIONAL :
case T_COMPLEX :
break ;
case T_ICLASS :
/* iClass shares table with the module */
break ;
case T_FLOAT :
break ;
case T_BIGNUM :
2014-02-16 01:17:34 +04:00
if ( ! ( RBASIC ( obj ) - > flags & BIGNUM_EMBED_FLAG ) & & BIGNUM_DIGITS ( obj ) ) {
size + = BIGNUM_LEN ( obj ) * sizeof ( BDIGIT ) ;
2013-11-05 08:51:01 +04:00
}
break ;
case T_NODE :
switch ( nd_type ( obj ) ) {
case NODE_SCOPE :
if ( RNODE ( obj ) - > u1 . tbl ) {
/* TODO: xfree(RANY(obj)->as.node.u1.tbl); */
}
break ;
case NODE_ALLOCA :
/* TODO: xfree(RANY(obj)->as.node.u1.node); */
;
}
break ; /* no need to free iv_tbl */
case T_STRUCT :
if ( ( RBASIC ( obj ) - > flags & RSTRUCT_EMBED_LEN_MASK ) = = 0 & &
RSTRUCT ( obj ) - > as . heap . ptr ) {
size + = sizeof ( VALUE ) * RSTRUCT_LEN ( obj ) ;
}
break ;
case T_ZOMBIE :
break ;
default :
rb_bug ( " objspace/memsize_of(): unknown data type 0x%x(%p) " ,
BUILTIN_TYPE ( obj ) , ( void * ) obj ) ;
}
return size ;
}
size_t
rb_obj_memsize_of ( VALUE obj )
{
return obj_memsize_of ( obj , TRUE ) ;
}
2012-08-05 14:39:37 +04:00
static int
set_zero ( st_data_t key , st_data_t val , st_data_t arg )
{
VALUE k = ( VALUE ) key ;
VALUE hash = ( VALUE ) arg ;
rb_hash_aset ( hash , k , INT2FIX ( 0 ) ) ;
return ST_CONTINUE ;
}
/*
* call - seq :
* ObjectSpace . count_objects ( [ result_hash ] ) - > hash
*
* Counts objects for each type .
*
2012-11-29 12:15:53 +04:00
* It returns a hash , such as :
* {
* : TOTAL = > 10000 ,
* : FREE = > 3011 ,
* : T_OBJECT = > 6 ,
* : T_CLASS = > 404 ,
* # . . .
* }
2012-08-05 14:39:37 +04:00
*
2012-11-29 12:15:53 +04:00
* The contents of the returned hash are implementation specific .
2012-08-05 14:39:37 +04:00
* It may be changed in future .
*
2012-11-29 12:15:53 +04:00
* If the optional argument + result_hash + is given ,
* it is overwritten and returned . This is intended to avoid probe effect .
*
* This method is only expected to work on C Ruby .
2012-08-05 14:39:37 +04:00
*
*/
static VALUE
count_objects ( int argc , VALUE * argv , VALUE os )
{
rb_objspace_t * objspace = & rb_objspace ;
size_t counts [ T_MASK + 1 ] ;
size_t freed = 0 ;
size_t total = 0 ;
size_t i ;
VALUE hash ;
if ( rb_scan_args ( argc , argv , " 01 " , & hash ) = = 1 ) {
if ( ! RB_TYPE_P ( hash , T_HASH ) )
rb_raise ( rb_eTypeError , " non-hash given " ) ;
}
for ( i = 0 ; i < = T_MASK ; i + + ) {
counts [ i ] = 0 ;
}
2013-10-22 14:28:31 +04:00
for ( i = 0 ; i < heap_pages_used ; i + + ) {
struct heap_page * page = heap_pages_sorted [ i ] ;
2013-07-17 10:52:13 +04:00
RVALUE * p , * pend ;
2012-08-05 14:39:37 +04:00
2013-10-18 10:33:36 +04:00
p = page - > start ; pend = p + page - > limit ;
2013-07-17 10:52:13 +04:00
for ( ; p < pend ; p + + ) {
if ( p - > as . basic . flags ) {
counts [ BUILTIN_TYPE ( p ) ] + + ;
}
else {
freed + + ;
}
}
2013-10-18 10:33:36 +04:00
total + = page - > limit ;
2012-08-05 14:39:37 +04:00
}
if ( hash = = Qnil ) {
hash = rb_hash_new ( ) ;
}
else if ( ! RHASH_EMPTY_P ( hash ) ) {
2013-05-26 20:19:04 +04:00
st_foreach ( RHASH_TBL_RAW ( hash ) , set_zero , hash ) ;
2012-08-05 14:39:37 +04:00
}
rb_hash_aset ( hash , ID2SYM ( rb_intern ( " TOTAL " ) ) , SIZET2NUM ( total ) ) ;
rb_hash_aset ( hash , ID2SYM ( rb_intern ( " FREE " ) ) , SIZET2NUM ( freed ) ) ;
for ( i = 0 ; i < = T_MASK ; i + + ) {
VALUE type ;
switch ( i ) {
# define COUNT_TYPE(t) case (t): type = ID2SYM(rb_intern(#t)); break;
COUNT_TYPE ( T_NONE ) ;
COUNT_TYPE ( T_OBJECT ) ;
COUNT_TYPE ( T_CLASS ) ;
COUNT_TYPE ( T_MODULE ) ;
COUNT_TYPE ( T_FLOAT ) ;
COUNT_TYPE ( T_STRING ) ;
COUNT_TYPE ( T_REGEXP ) ;
COUNT_TYPE ( T_ARRAY ) ;
COUNT_TYPE ( T_HASH ) ;
COUNT_TYPE ( T_STRUCT ) ;
COUNT_TYPE ( T_BIGNUM ) ;
COUNT_TYPE ( T_FILE ) ;
COUNT_TYPE ( T_DATA ) ;
COUNT_TYPE ( T_MATCH ) ;
COUNT_TYPE ( T_COMPLEX ) ;
COUNT_TYPE ( T_RATIONAL ) ;
COUNT_TYPE ( T_NIL ) ;
COUNT_TYPE ( T_TRUE ) ;
COUNT_TYPE ( T_FALSE ) ;
COUNT_TYPE ( T_SYMBOL ) ;
COUNT_TYPE ( T_FIXNUM ) ;
COUNT_TYPE ( T_UNDEF ) ;
COUNT_TYPE ( T_NODE ) ;
COUNT_TYPE ( T_ICLASS ) ;
COUNT_TYPE ( T_ZOMBIE ) ;
# undef COUNT_TYPE
default : type = INT2NUM ( i ) ; break ;
}
if ( counts [ i ] )
rb_hash_aset ( hash , type , SIZET2NUM ( counts [ i ] ) ) ;
}
return hash ;
}
/*
- - - - - - - - - - - - - - - - - - - - - - - - Garbage Collection - - - - - - - - - - - - - - - - - - - - - - - -
*/
/* Sweeping */
static VALUE
lazy_sweep_enable ( void )
{
rb_objspace_t * objspace = & rb_objspace ;
objspace - > flags . dont_lazy_sweep = FALSE ;
return Qnil ;
}
2003-04-09 12:27:01 +04:00
2013-07-18 03:19:38 +04:00
static size_t
2013-11-24 23:18:53 +04:00
objspace_live_slot ( rb_objspace_t * objspace )
2013-07-18 03:19:38 +04:00
{
2013-11-01 16:49:49 +04:00
return objspace - > profile . total_allocated_object_num - objspace - > profile . total_freed_object_num ;
2013-07-18 03:19:38 +04:00
}
2013-10-23 12:48:54 +04:00
static size_t
2013-11-27 05:42:25 +04:00
objspace_total_slot ( rb_objspace_t * objspace )
2013-10-23 12:48:54 +04:00
{
2013-11-27 05:42:25 +04:00
return heap_eden - > total_slots + heap_tomb - > total_slots ;
2013-10-23 12:48:54 +04:00
}
2013-10-04 14:05:40 +04:00
static size_t
2013-11-24 23:18:53 +04:00
objspace_free_slot ( rb_objspace_t * objspace )
2013-10-04 14:05:40 +04:00
{
2013-11-27 05:42:25 +04:00
return objspace_total_slot ( objspace ) - ( objspace_live_slot ( objspace ) - heap_pages_final_slots ) ;
2013-10-04 14:05:40 +04:00
}
2013-06-07 06:32:57 +04:00
static void
2013-10-18 10:33:36 +04:00
gc_setup_mark_bits ( struct heap_page * page )
2012-11-29 09:05:19 +04:00
{
2013-06-21 23:42:04 +04:00
# if USE_RGENGC
/* copy oldgen bitmap to mark bitmap */
2013-10-18 10:33:36 +04:00
memcpy ( & page - > mark_bits [ 0 ] , & page - > oldgen_bits [ 0 ] , HEAP_BITMAP_SIZE ) ;
2013-06-21 23:42:04 +04:00
# else
/* clear mark bitmap */
2013-10-18 10:33:36 +04:00
memset ( & page - > mark_bits [ 0 ] , 0 , HEAP_BITMAP_SIZE ) ;
2013-06-07 06:32:57 +04:00
# endif
2013-06-21 23:42:04 +04:00
}
2012-11-29 09:05:19 +04:00
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
static inline void
2013-10-22 14:28:31 +04:00
gc_page_sweep ( rb_objspace_t * objspace , rb_heap_t * heap , struct heap_page * sweep_page )
2012-08-05 14:39:37 +04:00
{
2013-06-07 06:32:57 +04:00
int i ;
2013-11-24 23:18:53 +04:00
size_t empty_slots = 0 , freed_slots = 0 , final_slots = 0 ;
2013-06-07 06:32:57 +04:00
RVALUE * p , * pend , * offset ;
2013-06-21 03:15:18 +04:00
bits_t * bits , bitset ;
2001-11-13 11:19:52 +03:00
2013-10-18 10:33:36 +04:00
rgengc_report ( 1 , objspace , " page_sweep: start. \n " ) ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
2013-11-01 17:47:39 +04:00
sweep_page - > before_sweep = 0 ;
2013-10-18 10:33:36 +04:00
p = sweep_page - > start ; pend = p + sweep_page - > limit ;
offset = p - NUM_IN_PAGE ( p ) ;
2013-11-09 04:23:02 +04:00
bits = sweep_page - > mark_bits ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
2013-06-07 06:32:57 +04:00
/* create guard : fill 1 out-of-range */
bits [ BITMAP_INDEX ( p ) ] | = BITMAP_BIT ( p ) - 1 ;
bits [ BITMAP_INDEX ( pend ) ] | = ~ ( BITMAP_BIT ( pend ) - 1 ) ;
2013-06-07 06:52:42 +04:00
for ( i = 0 ; i < HEAP_BITMAP_LIMIT ; i + + ) {
2013-06-07 06:32:57 +04:00
bitset = ~ bits [ i ] ;
2013-06-07 06:52:42 +04:00
if ( bitset ) {
2013-06-21 03:15:18 +04:00
p = offset + i * BITS_BITLENGTH ;
2013-06-07 06:32:57 +04:00
do {
if ( ( bitset & 1 ) & & BUILTIN_TYPE ( p ) ! = T_ZOMBIE ) {
if ( p - > as . basic . flags ) {
2013-10-18 10:33:36 +04:00
rgengc_report ( 3 , objspace , " page_sweep: free %p (%s) \n " , p , obj_type_name ( ( VALUE ) p ) ) ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
# if USE_RGENGC && RGENGC_CHECK_MODE
2013-11-04 22:59:33 +04:00
if ( objspace - > rgengc . during_minor_gc & & RVALUE_OLD_P ( ( VALUE ) p ) ) rb_bug ( " page_sweep: %p (%s) is old while minor GC. \n " , p , obj_type_name ( ( VALUE ) p ) ) ;
2013-10-18 10:33:36 +04:00
if ( rgengc_remembered ( objspace , ( VALUE ) p ) ) rb_bug ( " page_sweep: %p (%s) is remembered. \n " , p , obj_type_name ( ( VALUE ) p ) ) ;
2013-06-07 06:32:57 +04:00
# endif
2013-11-01 17:22:54 +04:00
if ( obj_free ( objspace , ( VALUE ) p ) ) {
2013-11-24 23:18:53 +04:00
final_slots + + ;
2013-11-01 17:22:54 +04:00
}
else if ( FL_TEST ( p , FL_FINALIZE ) ) {
RDATA ( p ) - > dfree = 0 ;
make_deferred ( objspace , p ) ;
2013-11-24 23:18:53 +04:00
final_slots + + ;
2013-06-07 06:32:57 +04:00
}
else {
( void ) VALGRIND_MAKE_MEM_UNDEFINED ( ( void * ) p , sizeof ( RVALUE ) ) ;
2013-10-18 10:33:36 +04:00
heap_page_add_freeobj ( objspace , sweep_page , ( VALUE ) p ) ;
rgengc_report ( 3 , objspace , " page_sweep: %p (%s) is added to freelist \n " , p , obj_type_name ( ( VALUE ) p ) ) ;
2013-11-24 23:18:53 +04:00
freed_slots + + ;
2013-06-07 06:32:57 +04:00
}
}
else {
2013-11-24 23:18:53 +04:00
empty_slots + + ;
2013-06-07 06:32:57 +04:00
}
}
p + + ;
bitset > > = 1 ;
} while ( bitset ) ;
}
2012-08-05 14:39:37 +04:00
}
2013-06-21 04:24:14 +04:00
2013-10-18 10:33:36 +04:00
gc_setup_mark_bits ( sweep_page ) ;
2013-06-07 06:32:57 +04:00
2013-06-21 04:24:14 +04:00
# if GC_PROFILE_MORE_DETAIL
2013-12-18 11:58:04 +04:00
if ( gc_prof_enabled ( objspace ) ) {
2013-06-21 04:24:14 +04:00
gc_profile_record * record = gc_prof_record ( objspace ) ;
2013-11-24 23:18:53 +04:00
record - > removing_objects + = final_slots + freed_slots ;
record - > empty_objects + = empty_slots ;
2013-06-21 04:24:14 +04:00
}
# endif
2013-11-24 23:18:53 +04:00
if ( final_slots + freed_slots + empty_slots = = sweep_page - > limit ) {
2013-10-23 12:48:54 +04:00
/* there are no living objects -> move this page to tomb heap */
heap_unlink_page ( objspace , heap , sweep_page ) ;
heap_add_page ( objspace , heap_tomb , sweep_page ) ;
1999-01-20 07:59:39 +03:00
}
2012-08-05 14:39:37 +04:00
else {
2013-11-24 23:18:53 +04:00
if ( freed_slots + empty_slots > 0 ) {
2013-10-22 14:28:31 +04:00
heap_add_freepage ( objspace , heap , sweep_page ) ;
2013-07-16 12:46:15 +04:00
}
else {
2013-10-18 10:33:36 +04:00
sweep_page - > free_next = NULL ;
2013-07-16 12:46:15 +04:00
}
2012-08-05 14:39:37 +04:00
}
2013-11-24 23:18:53 +04:00
heap_pages_swept_slots + = freed_slots + empty_slots ;
objspace - > profile . total_freed_object_num + = freed_slots ;
heap_pages_final_slots + = final_slots ;
sweep_page - > final_slots = final_slots ;
1999-01-20 07:59:39 +03:00
2013-11-27 10:13:19 +04:00
if ( 0 ) fprintf ( stderr , " gc_page_sweep(%d): freed?: %d, limt: %d, freed_slots: %d, empty_slots: %d, final_slots: %d \n " ,
2013-11-27 10:09:55 +04:00
( int ) rb_gc_count ( ) ,
final_slots + freed_slots + empty_slots = = sweep_page - > limit ,
2013-11-27 10:24:37 +04:00
( int ) sweep_page - > limit , ( int ) freed_slots , ( int ) empty_slots , ( int ) final_slots ) ;
2013-11-27 10:09:55 +04:00
2013-10-22 14:28:31 +04:00
if ( heap_pages_deferred_final & & ! finalizing ) {
2012-08-05 14:39:37 +04:00
rb_thread_t * th = GET_THREAD ( ) ;
if ( th ) {
2013-05-27 01:30:44 +04:00
gc_finalize_deferred_register ( ) ;
2012-08-05 14:39:37 +04:00
}
}
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
2013-10-18 10:33:36 +04:00
rgengc_report ( 1 , objspace , " page_sweep: end. \n " ) ;
2013-05-13 20:34:25 +04:00
}
2013-10-22 14:28:31 +04:00
/* allocate additional minimum page to work */
static void
gc_heap_prepare_minimum_pages ( rb_objspace_t * objspace , rb_heap_t * heap )
{
if ( ! heap - > free_pages ) {
/* there is no free after page_sweep() */
2013-11-22 11:40:27 +04:00
heap_set_increment ( objspace , 0 ) ;
2013-10-23 14:16:01 +04:00
if ( ! heap_increment ( objspace , heap ) ) { /* can't allocate additional free objects */
2013-10-22 14:28:31 +04:00
during_gc = 0 ;
rb_memerror ( ) ;
}
}
}
static void
gc_before_heap_sweep ( rb_objspace_t * objspace , rb_heap_t * heap )
{
heap - > sweep_pages = heap - > pages ;
heap - > free_pages = NULL ;
if ( heap - > using_page ) {
2013-10-26 01:37:39 +04:00
RVALUE * * p = & heap - > using_page - > freelist ;
while ( * p ) {
p = & ( * p ) - > as . free . next ;
2013-10-25 23:09:14 +04:00
}
2013-10-26 01:37:39 +04:00
* p = heap - > freelist ;
2013-10-22 14:28:31 +04:00
heap - > using_page = NULL ;
}
heap - > freelist = NULL ;
}
2013-06-05 10:27:43 +04:00
# if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 4
2013-06-07 08:25:20 +04:00
__attribute__ ( ( noinline ) )
2013-06-05 10:27:43 +04:00
# endif
2012-08-05 14:39:37 +04:00
static void
2013-07-18 03:19:38 +04:00
gc_before_sweep ( rb_objspace_t * objspace )
2012-08-05 14:39:37 +04:00
{
2013-10-22 14:28:31 +04:00
rb_heap_t * heap ;
2013-11-24 23:18:53 +04:00
size_t total_limit_slot ;
2013-05-22 03:09:22 +04:00
2013-10-22 14:28:31 +04:00
rgengc_report ( 1 , objspace , " gc_before_sweep \n " ) ;
1998-01-16 15:13:05 +03:00
2012-08-05 14:39:37 +04:00
/* sweep unlinked method entries */
if ( GET_VM ( ) - > unlinked_method_entry_list ) {
rb_sweep_method_entry ( GET_VM ( ) ) ;
}
2013-09-27 12:01:14 +04:00
2013-11-23 03:50:08 +04:00
heap_pages_swept_slots = 0 ;
2013-11-27 05:42:25 +04:00
total_limit_slot = objspace_total_slot ( objspace ) ;
2013-10-23 12:48:54 +04:00
2013-11-24 23:18:53 +04:00
heap_pages_min_free_slots = ( size_t ) ( total_limit_slot * 0.30 ) ;
2013-11-23 07:33:10 +04:00
if ( heap_pages_min_free_slots < gc_params . heap_free_slots ) {
heap_pages_min_free_slots = gc_params . heap_free_slots ;
2013-10-23 12:48:54 +04:00
}
2013-11-24 23:18:53 +04:00
heap_pages_max_free_slots = ( size_t ) ( total_limit_slot * 0.80 ) ;
2013-11-23 07:33:10 +04:00
if ( heap_pages_max_free_slots < gc_params . heap_init_slots ) {
heap_pages_max_free_slots = gc_params . heap_init_slots ;
2013-10-22 14:28:31 +04:00
}
2013-10-23 19:05:22 +04:00
if ( 0 ) fprintf ( stderr , " heap_pages_min_free_slots: %d, heap_pages_max_free_slots: %d \n " ,
( int ) heap_pages_min_free_slots , ( int ) heap_pages_max_free_slots ) ;
2013-10-22 14:28:31 +04:00
heap = heap_eden ;
gc_before_heap_sweep ( objspace , heap ) ;
2013-09-27 12:01:14 +04:00
gc_prof_set_malloc_info ( objspace ) ;
/* reset malloc info */
2013-11-07 14:45:01 +04:00
if ( 0 ) fprintf ( stderr , " %d \t %d \t %d \n " , ( int ) rb_gc_count ( ) , ( int ) malloc_increase , ( int ) malloc_limit ) ;
2013-09-27 12:01:14 +04:00
{
size_t inc = ATOMIC_SIZE_EXCHANGE ( malloc_increase , 0 ) ;
size_t old_limit = malloc_limit ;
if ( inc > malloc_limit ) {
2013-11-21 12:50:40 +04:00
malloc_limit = ( size_t ) ( inc * gc_params . malloc_limit_growth_factor ) ;
if ( gc_params . malloc_limit_max > 0 & & /* ignore max-check if 0 */
malloc_limit > gc_params . malloc_limit_max ) {
2013-11-07 14:45:01 +04:00
malloc_limit = inc ;
2013-09-27 12:01:14 +04:00
}
}
else {
2013-11-06 16:36:34 +04:00
malloc_limit = ( size_t ) ( malloc_limit * 0.98 ) ; /* magic number */
2013-11-21 12:50:40 +04:00
if ( malloc_limit < gc_params . malloc_limit_min ) {
malloc_limit = gc_params . malloc_limit_min ;
2013-09-27 12:01:14 +04:00
}
}
if ( 0 ) {
2013-10-02 13:56:04 +04:00
if ( old_limit ! = malloc_limit ) {
fprintf ( stderr , " [% " PRIuSIZE " ] malloc_limit: % " PRIuSIZE " -> % " PRIuSIZE " \n " ,
rb_gc_count ( ) , old_limit , malloc_limit ) ;
}
else {
fprintf ( stderr , " [% " PRIuSIZE " ] malloc_limit: not changed (% " PRIuSIZE " ) \n " ,
rb_gc_count ( ) , malloc_limit ) ;
}
2013-09-27 12:01:14 +04:00
}
}
2013-11-21 12:20:34 +04:00
2013-11-24 23:49:02 +04:00
/* reset oldmalloc info */
# if RGENGC_ESTIMATE_OLDMALLOC
2013-11-21 12:20:34 +04:00
if ( objspace - > rgengc . during_minor_gc ) {
2013-11-24 23:49:02 +04:00
if ( objspace - > rgengc . oldmalloc_increase > objspace - > rgengc . oldmalloc_increase_limit ) {
objspace - > rgengc . need_major_gc = GPR_FLAG_MAJOR_BY_OLDMALLOC ; ;
objspace - > rgengc . oldmalloc_increase_limit =
( size_t ) ( objspace - > rgengc . oldmalloc_increase_limit * gc_params . oldmalloc_limit_growth_factor ) ;
2013-12-06 14:27:02 +04:00
2013-11-24 23:49:02 +04:00
if ( objspace - > rgengc . oldmalloc_increase_limit > gc_params . oldmalloc_limit_max ) {
objspace - > rgengc . oldmalloc_increase_limit = gc_params . oldmalloc_limit_max ;
2013-11-21 12:20:34 +04:00
}
}
2014-02-06 04:04:14 +04:00
if ( 0 ) fprintf ( stderr , " %d \t %d \t %u \t %u \t %d \n " ,
( int ) rb_gc_count ( ) ,
( int ) objspace - > rgengc . need_major_gc ,
2013-11-24 23:49:02 +04:00
( unsigned int ) objspace - > rgengc . oldmalloc_increase ,
( unsigned int ) objspace - > rgengc . oldmalloc_increase_limit ,
2013-11-24 22:13:48 +04:00
( unsigned int ) gc_params . oldmalloc_limit_max ) ;
2013-11-21 12:20:34 +04:00
}
else {
/* major GC */
2013-11-24 23:49:02 +04:00
objspace - > rgengc . oldmalloc_increase = 0 ;
2013-12-06 14:27:02 +04:00
if ( ( objspace - > profile . latest_gc_info & GPR_FLAG_MAJOR_BY_OLDMALLOC ) = = 0 ) {
objspace - > rgengc . oldmalloc_increase_limit =
( size_t ) ( objspace - > rgengc . oldmalloc_increase_limit / ( ( gc_params . oldmalloc_limit_growth_factor - 1 ) / 10 + 1 ) ) ;
if ( objspace - > rgengc . oldmalloc_increase_limit < gc_params . oldmalloc_limit_min ) {
objspace - > rgengc . oldmalloc_increase_limit = gc_params . oldmalloc_limit_min ;
}
}
2013-11-21 12:20:34 +04:00
}
2013-11-21 12:21:05 +04:00
2013-11-21 12:20:34 +04:00
# endif
2012-08-05 14:39:37 +04:00
}
static void
2013-07-18 03:19:38 +04:00
gc_after_sweep ( rb_objspace_t * objspace )
2012-08-05 14:39:37 +04:00
{
2013-10-22 14:28:31 +04:00
rb_heap_t * heap = heap_eden ;
2013-11-27 05:42:25 +04:00
rgengc_report ( 1 , objspace , " after_gc_sweep: heap->total_slots: %d, heap->swept_slots: %d, min_free_slots: %d \n " ,
( int ) heap - > total_slots , ( int ) heap_pages_swept_slots , ( int ) heap_pages_min_free_slots ) ;
2013-05-22 03:09:22 +04:00
2013-11-23 03:50:08 +04:00
if ( heap_pages_swept_slots < heap_pages_min_free_slots ) {
heap_set_increment ( objspace , ( heap_pages_min_free_slots - heap_pages_swept_slots ) / HEAP_OBJ_LIMIT ) ;
2013-10-23 14:16:01 +04:00
heap_increment ( objspace , heap ) ;
2013-05-25 12:11:04 +04:00
2013-06-21 03:10:34 +04:00
# if USE_RGENGC
2013-11-04 22:59:33 +04:00
if ( objspace - > rgengc . remembered_shady_object_count + objspace - > rgengc . old_object_count > ( heap_pages_length * HEAP_OBJ_LIMIT ) / 2 ) {
/* if [old]+[remembered shady] > [all object count]/2, then do major GC */
2013-11-24 23:49:02 +04:00
objspace - > rgengc . need_major_gc = GPR_FLAG_MAJOR_BY_RESCAN ;
2013-05-24 10:52:38 +04:00
}
2013-06-21 03:10:34 +04:00
# endif
2012-08-05 14:39:37 +04:00
}
2013-06-24 02:58:01 +04:00
gc_prof_set_heap_info ( objspace ) ;
2013-10-23 12:48:54 +04:00
heap_pages_free_unused_pages ( objspace ) ;
2013-10-23 14:16:01 +04:00
/* if heap_pages has unused pages, then assign them to increment */
2013-11-27 05:42:25 +04:00
if ( heap_pages_increment < heap_tomb - > page_length ) {
heap_pages_increment = heap_tomb - > page_length ;
2013-10-23 12:48:54 +04:00
heap_pages_expand_sorted ( objspace ) ;
}
2013-06-22 02:29:09 +04:00
2013-11-04 22:59:33 +04:00
# if RGENGC_PROFILE > 0
if ( 0 ) {
fprintf ( stderr , " %d \t %d \t %d \t %d \t %d \t %d \t %d \n " ,
( int ) rb_gc_count ( ) ,
2013-11-05 11:48:31 +04:00
( int ) objspace - > profile . major_gc_count ,
2013-11-04 22:59:33 +04:00
( int ) objspace - > profile . minor_gc_count ,
( int ) objspace - > profile . promote_infant_count ,
# if RGENGC_THREEGEN
( int ) objspace - > profile . promote_young_count ,
# else
0 ,
# endif
( int ) objspace - > profile . remembered_normal_object_count ,
( int ) objspace - > rgengc . remembered_shady_object_count ) ;
}
# endif
2013-12-05 08:26:04 +04:00
gc_event_hook ( objspace , RUBY_INTERNAL_EVENT_GC_END_SWEEP , 0 ) ;
2012-08-05 14:39:37 +04:00
}
static int
2013-10-22 14:28:31 +04:00
gc_heap_lazy_sweep ( rb_objspace_t * objspace , rb_heap_t * heap )
2012-08-05 14:39:37 +04:00
{
2013-10-22 14:28:31 +04:00
struct heap_page * page = heap - > sweep_pages , * next ;
2013-06-20 00:43:33 +04:00
int result = FALSE ;
2013-10-22 14:28:31 +04:00
if ( page = = NULL ) return FALSE ;
2012-08-05 14:39:37 +04:00
2013-10-26 08:31:10 +04:00
# if GC_ENABLE_LAZY_SWEEP
2013-10-22 14:28:31 +04:00
gc_prof_sweep_timer_start ( objspace ) ;
2013-10-26 08:31:10 +04:00
# endif
2013-07-16 11:33:48 +04:00
2013-10-18 10:33:36 +04:00
while ( page ) {
2013-10-22 14:28:31 +04:00
heap - > sweep_pages = next = page - > next ;
2013-07-16 11:33:48 +04:00
2013-10-22 14:28:31 +04:00
gc_page_sweep ( objspace , heap , page ) ;
2013-05-13 21:02:50 +04:00
2013-07-18 03:19:38 +04:00
if ( ! next ) gc_after_sweep ( objspace ) ;
2013-05-13 21:02:50 +04:00
2013-10-22 14:28:31 +04:00
if ( heap - > free_pages ) {
2013-06-20 00:43:33 +04:00
result = TRUE ;
break ;
2012-08-05 14:39:37 +04:00
}
2013-07-16 11:33:48 +04:00
2013-10-18 10:33:36 +04:00
page = next ;
2012-08-05 14:39:37 +04:00
}
2013-06-20 00:43:33 +04:00
2013-10-26 08:31:10 +04:00
# if GC_ENABLE_LAZY_SWEEP
2013-06-20 00:43:33 +04:00
gc_prof_sweep_timer_stop ( objspace ) ;
2013-10-26 08:31:10 +04:00
# endif
2013-06-20 00:43:33 +04:00
return result ;
2012-08-05 14:39:37 +04:00
}
static void
2013-10-22 14:28:31 +04:00
gc_heap_rest_sweep ( rb_objspace_t * objspace , rb_heap_t * heap )
2012-08-05 14:39:37 +04:00
{
2013-10-22 14:28:31 +04:00
if ( is_lazy_sweeping ( heap ) ) {
2013-05-22 09:21:06 +04:00
during_gc + + ;
2013-10-22 14:28:31 +04:00
while ( is_lazy_sweeping ( heap ) ) {
gc_heap_lazy_sweep ( objspace , heap ) ;
2012-08-05 14:39:37 +04:00
}
2013-05-22 09:21:06 +04:00
during_gc = 0 ;
2012-08-05 14:39:37 +04:00
}
}
2013-10-22 14:28:31 +04:00
static void
gc_rest_sweep ( rb_objspace_t * objspace )
{
rb_heap_t * heap = heap_eden ; /* lazy sweep only for eden */
gc_heap_rest_sweep ( objspace , heap ) ;
}
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
static void
2013-05-22 03:09:22 +04:00
gc_sweep ( rb_objspace_t * objspace , int immediate_sweep )
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
{
2013-05-22 03:09:22 +04:00
if ( immediate_sweep ) {
2013-10-26 08:31:10 +04:00
# if !GC_ENABLE_LAZY_SWEEP
2013-06-21 10:29:30 +04:00
gc_prof_sweep_timer_start ( objspace ) ;
2013-10-26 08:31:10 +04:00
# endif
2013-07-18 03:19:38 +04:00
gc_before_sweep ( objspace ) ;
2013-10-22 14:28:31 +04:00
gc_heap_rest_sweep ( objspace , heap_eden ) ;
2013-10-26 08:31:10 +04:00
# if !GC_ENABLE_LAZY_SWEEP
2013-06-21 10:29:30 +04:00
gc_prof_sweep_timer_stop ( objspace ) ;
2013-10-26 08:31:10 +04:00
# endif
2013-05-22 03:09:22 +04:00
}
else {
2013-11-01 17:47:39 +04:00
struct heap_page * page ;
2013-07-18 03:19:38 +04:00
gc_before_sweep ( objspace ) ;
2013-11-01 17:47:39 +04:00
page = heap_eden - > sweep_pages ;
while ( page ) {
page - > before_sweep = 1 ;
page = page - > next ;
}
2013-10-22 14:28:31 +04:00
gc_heap_lazy_sweep ( objspace , heap_eden ) ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
}
2013-10-22 14:28:31 +04:00
gc_heap_prepare_minimum_pages ( objspace , heap_eden ) ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
}
2012-08-05 14:39:37 +04:00
2013-07-18 03:19:38 +04:00
/* Marking - Marking stack */
2012-10-03 16:30:21 +04:00
static void push_mark_stack ( mark_stack_t * , VALUE ) ;
static int pop_mark_stack ( mark_stack_t * , VALUE * ) ;
static void shrink_stack_chunk_cache ( mark_stack_t * stack ) ;
static stack_chunk_t *
stack_chunk_alloc ( void )
{
stack_chunk_t * res ;
res = malloc ( sizeof ( stack_chunk_t ) ) ;
if ( ! res )
rb_memerror ( ) ;
return res ;
}
static inline int
2013-11-23 19:35:04 +04:00
is_mark_stack_empty ( mark_stack_t * stack )
2012-10-03 16:30:21 +04:00
{
return stack - > chunk = = NULL ;
}
static void
add_stack_chunk_cache ( mark_stack_t * stack , stack_chunk_t * chunk )
{
chunk - > next = stack - > cache ;
stack - > cache = chunk ;
stack - > cache_size + + ;
}
static void
shrink_stack_chunk_cache ( mark_stack_t * stack )
{
stack_chunk_t * chunk ;
if ( stack - > unused_cache_size > ( stack - > cache_size / 2 ) ) {
chunk = stack - > cache ;
stack - > cache = stack - > cache - > next ;
stack - > cache_size - - ;
free ( chunk ) ;
}
stack - > unused_cache_size = stack - > cache_size ;
}
static void
push_mark_stack_chunk ( mark_stack_t * stack )
{
stack_chunk_t * next ;
assert ( stack - > index = = stack - > limit ) ;
if ( stack - > cache_size > 0 ) {
next = stack - > cache ;
stack - > cache = stack - > cache - > next ;
stack - > cache_size - - ;
if ( stack - > unused_cache_size > stack - > cache_size )
stack - > unused_cache_size = stack - > cache_size ;
}
else {
next = stack_chunk_alloc ( ) ;
}
next - > next = stack - > chunk ;
stack - > chunk = next ;
stack - > index = 0 ;
}
static void
pop_mark_stack_chunk ( mark_stack_t * stack )
{
stack_chunk_t * prev ;
prev = stack - > chunk - > next ;
assert ( stack - > index = = 0 ) ;
add_stack_chunk_cache ( stack , stack - > chunk ) ;
stack - > chunk = prev ;
stack - > index = stack - > limit ;
}
2012-10-03 17:23:30 +04:00
# if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
2012-10-03 16:30:21 +04:00
static void
free_stack_chunks ( mark_stack_t * stack )
{
stack_chunk_t * chunk = stack - > chunk ;
stack_chunk_t * next = NULL ;
while ( chunk ! = NULL ) {
next = chunk - > next ;
free ( chunk ) ;
chunk = next ;
}
}
2012-10-03 17:23:30 +04:00
# endif
2012-10-03 16:30:21 +04:00
static void
push_mark_stack ( mark_stack_t * stack , VALUE data )
{
if ( stack - > index = = stack - > limit ) {
push_mark_stack_chunk ( stack ) ;
}
stack - > chunk - > data [ stack - > index + + ] = data ;
}
static int
pop_mark_stack ( mark_stack_t * stack , VALUE * data )
{
2013-11-23 19:35:04 +04:00
if ( is_mark_stack_empty ( stack ) ) {
2012-10-03 16:30:21 +04:00
return FALSE ;
}
if ( stack - > index = = 1 ) {
* data = stack - > chunk - > data [ - - stack - > index ] ;
pop_mark_stack_chunk ( stack ) ;
}
2013-11-21 08:57:37 +04:00
else {
* data = stack - > chunk - > data [ - - stack - > index ] ;
}
2012-10-03 16:30:21 +04:00
return TRUE ;
}
static void
init_mark_stack ( mark_stack_t * stack )
{
int i ;
2013-11-21 09:01:05 +04:00
2013-11-21 08:57:37 +04:00
if ( 0 ) push_mark_stack_chunk ( stack ) ;
stack - > index = stack - > limit = STACK_CHUNK_SIZE ;
2012-10-03 16:30:21 +04:00
2012-12-29 16:22:04 +04:00
for ( i = 0 ; i < 4 ; i + + ) {
2012-10-03 16:30:21 +04:00
add_stack_chunk_cache ( stack , stack_chunk_alloc ( ) ) ;
}
stack - > unused_cache_size = stack - > cache_size ;
}
2013-07-18 03:19:38 +04:00
/* Marking */
1998-01-16 15:13:05 +03:00
2012-08-05 14:39:37 +04:00
# ifdef __ia64
2014-01-28 10:09:58 +04:00
# define SET_STACK_END (SET_MACHINE_STACK_END(&th->machine.stack_end), th->machine.register_stack_end = rb_ia64_bsp())
2012-08-05 14:39:37 +04:00
# else
2014-01-28 10:09:58 +04:00
# define SET_STACK_END SET_MACHINE_STACK_END(&th->machine.stack_end)
2012-08-05 14:39:37 +04:00
# endif
1998-01-16 15:13:05 +03:00
2014-01-28 10:09:58 +04:00
# define STACK_START (th->machine.stack_start)
# define STACK_END (th->machine.stack_end)
# define STACK_LEVEL_MAX (th->machine.stack_maxsize / sizeof(VALUE))
2007-11-20 06:16:53 +03:00
2012-08-05 14:39:37 +04:00
# if STACK_GROW_DIRECTION < 0
# define STACK_LENGTH (size_t)(STACK_START - STACK_END)
# elif STACK_GROW_DIRECTION > 0
# define STACK_LENGTH (size_t)(STACK_END - STACK_START + 1)
# else
# define STACK_LENGTH ((STACK_END < STACK_START) ? (size_t)(STACK_START - STACK_END) \
: ( size_t ) ( STACK_END - STACK_START + 1 ) )
# endif
# if !STACK_GROW_DIRECTION
int ruby_stack_grow_direction ;
int
ruby_get_stack_grow_direction ( volatile VALUE * addr )
{
VALUE * end ;
SET_MACHINE_STACK_END ( & end ) ;
2008-06-28 16:25:45 +04:00
2012-08-05 14:39:37 +04:00
if ( end > addr ) return ruby_stack_grow_direction = 1 ;
return ruby_stack_grow_direction = - 1 ;
}
# endif
1998-01-16 15:13:05 +03:00
2012-08-05 14:39:37 +04:00
size_t
ruby_stack_length ( VALUE * * p )
{
rb_thread_t * th = GET_THREAD ( ) ;
SET_STACK_END ;
if ( p ) * p = STACK_UPPER ( STACK_END , STACK_START , STACK_END ) ;
return STACK_LENGTH ;
}
2008-03-16 03:23:43 +03:00
2012-10-03 16:30:21 +04:00
# if !(defined(POSIX_SIGNAL) && defined(SIGSEGV) && defined(HAVE_SIGALTSTACK))
2012-08-05 14:39:37 +04:00
static int
stack_check ( int water_mark )
{
int ret ;
rb_thread_t * th = GET_THREAD ( ) ;
SET_STACK_END ;
ret = STACK_LENGTH > STACK_LEVEL_MAX - water_mark ;
# ifdef __ia64
if ( ! ret ) {
2014-01-28 10:09:58 +04:00
ret = ( VALUE * ) rb_ia64_bsp ( ) - th - > machine . register_stack_start >
th - > machine . register_stack_maxsize / sizeof ( VALUE ) - water_mark ;
2012-08-05 14:39:37 +04:00
}
# endif
return ret ;
}
2012-10-03 16:30:21 +04:00
# endif
2008-03-16 03:23:43 +03:00
2012-08-05 14:39:37 +04:00
# define STACKFRAME_FOR_CALL_CFUNC 512
int
ruby_stack_check ( void )
{
# if defined(POSIX_SIGNAL) && defined(SIGSEGV) && defined(HAVE_SIGALTSTACK)
return 0 ;
# else
return stack_check ( STACKFRAME_FOR_CALL_CFUNC ) ;
# endif
}
2013-09-26 09:46:52 +04:00
ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS
2012-08-05 14:39:37 +04:00
static void
mark_locations_array ( rb_objspace_t * objspace , register VALUE * x , register long n )
{
VALUE v ;
while ( n - - ) {
v = * x ;
2013-06-17 06:54:25 +04:00
gc_mark_maybe ( objspace , v ) ;
2012-08-05 14:39:37 +04:00
x + + ;
1998-01-16 15:13:05 +03:00
}
}
2012-08-05 14:39:37 +04:00
static void
gc_mark_locations ( rb_objspace_t * objspace , VALUE * start , VALUE * end )
{
long n ;
1998-01-16 15:13:05 +03:00
2012-08-05 14:39:37 +04:00
if ( end < = start ) return ;
n = end - start ;
mark_locations_array ( objspace , start , n ) ;
}
void
rb_gc_mark_locations ( VALUE * start , VALUE * end )
2008-07-27 09:59:32 +04:00
{
2012-08-05 14:39:37 +04:00
gc_mark_locations ( & rb_objspace , start , end ) ;
}
2012-01-07 18:02:23 +04:00
2012-08-05 14:39:37 +04:00
# define rb_gc_mark_locations(start, end) gc_mark_locations(objspace, (start), (end))
2012-01-07 18:02:23 +04:00
2012-08-05 14:39:37 +04:00
struct mark_tbl_arg {
rb_objspace_t * objspace ;
} ;
static int
mark_entry ( st_data_t key , st_data_t value , st_data_t data )
{
struct mark_tbl_arg * arg = ( void * ) data ;
2012-10-03 16:30:21 +04:00
gc_mark ( arg - > objspace , ( VALUE ) value ) ;
2012-08-05 14:39:37 +04:00
return ST_CONTINUE ;
2008-07-27 09:59:32 +04:00
}
2004-09-27 16:25:21 +04:00
static void
2012-10-03 16:30:21 +04:00
mark_tbl ( rb_objspace_t * objspace , st_table * tbl )
2004-09-27 16:25:21 +04:00
{
2012-08-05 14:39:37 +04:00
struct mark_tbl_arg arg ;
if ( ! tbl | | tbl - > num_entries = = 0 ) return ;
arg . objspace = objspace ;
st_foreach ( tbl , mark_entry , ( st_data_t ) & arg ) ;
2004-09-27 16:25:21 +04:00
}
2012-08-05 14:39:37 +04:00
static int
mark_key ( st_data_t key , st_data_t value , st_data_t data )
2010-06-29 07:11:05 +04:00
{
2012-08-05 14:39:37 +04:00
struct mark_tbl_arg * arg = ( void * ) data ;
2012-10-03 16:30:21 +04:00
gc_mark ( arg - > objspace , ( VALUE ) key ) ;
2012-08-05 14:39:37 +04:00
return ST_CONTINUE ;
2010-06-29 07:11:05 +04:00
}
2008-07-05 11:15:41 +04:00
static void
2012-10-03 16:30:21 +04:00
mark_set ( rb_objspace_t * objspace , st_table * tbl )
2004-09-27 16:25:21 +04:00
{
2012-08-05 14:39:37 +04:00
struct mark_tbl_arg arg ;
if ( ! tbl ) return ;
arg . objspace = objspace ;
st_foreach ( tbl , mark_key , ( st_data_t ) & arg ) ;
}
2008-07-02 04:49:10 +04:00
2012-08-05 14:39:37 +04:00
void
rb_mark_set ( st_table * tbl )
{
2012-10-03 16:30:21 +04:00
mark_set ( & rb_objspace , tbl ) ;
2012-08-05 14:39:37 +04:00
}
static int
mark_keyvalue ( st_data_t key , st_data_t value , st_data_t data )
{
struct mark_tbl_arg * arg = ( void * ) data ;
2012-10-03 16:30:21 +04:00
gc_mark ( arg - > objspace , ( VALUE ) key ) ;
gc_mark ( arg - > objspace , ( VALUE ) value ) ;
2012-08-05 14:39:37 +04:00
return ST_CONTINUE ;
2008-07-02 04:49:10 +04:00
}
1998-01-16 15:13:05 +03:00
2012-01-07 18:02:23 +04:00
static void
2012-10-03 16:30:21 +04:00
mark_hash ( rb_objspace_t * objspace , st_table * tbl )
2012-01-07 18:02:23 +04:00
{
2012-08-05 14:39:37 +04:00
struct mark_tbl_arg arg ;
if ( ! tbl ) return ;
arg . objspace = objspace ;
st_foreach ( tbl , mark_keyvalue , ( st_data_t ) & arg ) ;
}
void
rb_mark_hash ( st_table * tbl )
{
2012-10-03 16:30:21 +04:00
mark_hash ( & rb_objspace , tbl ) ;
2012-01-07 18:02:23 +04:00
}
2008-07-02 04:49:10 +04:00
static void
2012-10-03 16:30:21 +04:00
mark_method_entry ( rb_objspace_t * objspace , const rb_method_entry_t * me )
2008-07-02 04:49:10 +04:00
{
2012-08-05 14:39:37 +04:00
const rb_method_definition_t * def = me - > def ;
2008-07-27 09:59:32 +04:00
2012-10-03 16:30:21 +04:00
gc_mark ( objspace , me - > klass ) ;
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 17:08:41 +04:00
again :
2012-08-05 14:39:37 +04:00
if ( ! def ) return ;
switch ( def - > type ) {
case VM_METHOD_TYPE_ISEQ :
2012-10-03 16:30:21 +04:00
gc_mark ( objspace , def - > body . iseq - > self ) ;
2012-08-05 14:39:37 +04:00
break ;
case VM_METHOD_TYPE_BMETHOD :
2012-10-03 16:30:21 +04:00
gc_mark ( objspace , def - > body . proc ) ;
2012-08-05 14:39:37 +04:00
break ;
case VM_METHOD_TYPE_ATTRSET :
case VM_METHOD_TYPE_IVAR :
2012-10-03 16:30:21 +04:00
gc_mark ( objspace , def - > body . attr . location ) ;
2012-08-05 14:39:37 +04:00
break ;
* revised r37993 to avoid SEGV/ILL in tests. In r37993, a method
entry with VM_METHOD_TYPE_REFINED holds only the original method
definition, so ci->me is set to a method entry allocated in the
stack, and it causes SEGV/ILL. In this commit, a method entry
with VM_METHOD_TYPE_REFINED holds the whole original method entry.
Furthermore, rb_thread_mark() is changed to mark cfp->klass to
avoid GC for iclasses created by copy_refinement_iclass().
* vm_method.c (rb_method_entry_make): add a method entry with
VM_METHOD_TYPE_REFINED to the class refined by the refinement if
the target module is a refinement. When a method entry with
VM_METHOD_TYPE_UNDEF is invoked by vm_call_method(), a method with
the same name is searched in refinements. If such a method is
found, the method is invoked. Otherwise, the original method in
the refined class (rb_method_definition_t::body.orig_me) is
invoked. This change is made to simplify the normal method lookup
and to improve the performance of normal method calls.
* vm_method.c (EXPR1, search_method, rb_method_entry),
vm_eval.c (rb_call0, rb_search_method_entry): do not use
refinements for method lookup.
* vm_insnhelper.c (vm_call_method): search methods in refinements if
ci->me is VM_METHOD_TYPE_REFINED. If the method is called by
super (i.e., ci->call == vm_call_super_method), skip the same
method entry as the current method to avoid infinite call of the
same method.
* class.c (include_modules_at): add a refined method entry for each
method defined in a module included in a refinement.
* class.c (rb_prepend_module): set an empty table to
RCLASS_M_TBL(klass) to add refined method entries, because
refinements should have priority over prepended modules.
* proc.c (mnew): use rb_method_entry_with_refinements() to get
a refined method.
* vm.c (rb_thread_mark): mark cfp->klass for iclasses created by
copy_refinement_iclass().
* vm.c (Init_VM), cont.c (fiber_init): initialize th->cfp->klass.
* test/ruby/test_refinement.rb (test_inline_method_cache): do not skip
the test because it should pass successfully.
* test/ruby/test_refinement.rb (test_redefine_refined_method): new
test for the case a refined method is redefined.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38236 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-12-06 17:08:41 +04:00
case VM_METHOD_TYPE_REFINED :
if ( def - > body . orig_me ) {
def = def - > body . orig_me - > def ;
goto again ;
}
break ;
2012-08-05 14:39:37 +04:00
default :
break ; /* ignore */
1998-01-16 15:13:05 +03:00
}
2012-08-05 14:39:37 +04:00
}
2008-07-02 04:49:10 +04:00
2012-08-05 14:39:37 +04:00
void
rb_mark_method_entry ( const rb_method_entry_t * me )
{
2012-10-03 16:30:21 +04:00
mark_method_entry ( & rb_objspace , me ) ;
2012-08-05 14:39:37 +04:00
}
2010-11-04 14:15:36 +03:00
2012-08-05 14:39:37 +04:00
static int
mark_method_entry_i ( ID key , const rb_method_entry_t * me , st_data_t data )
{
struct mark_tbl_arg * arg = ( void * ) data ;
2012-10-03 16:30:21 +04:00
mark_method_entry ( arg - > objspace , me ) ;
2012-08-05 14:39:37 +04:00
return ST_CONTINUE ;
}
static void
2013-12-03 12:11:07 +04:00
mark_m_tbl_wrapper ( rb_objspace_t * objspace , struct method_table_wrapper * wrapper )
2012-08-05 14:39:37 +04:00
{
struct mark_tbl_arg arg ;
2013-12-03 12:11:07 +04:00
if ( ! wrapper | | ! wrapper - > tbl ) return ;
if ( LIKELY ( objspace - > mark_func_data = = 0 ) ) {
/* prevent multiple marking during same GC cycle,
* since m_tbl is shared between several T_ICLASS */
size_t serial = rb_gc_count ( ) ;
if ( wrapper - > serial = = serial ) return ;
wrapper - > serial = serial ;
}
2012-08-05 14:39:37 +04:00
arg . objspace = objspace ;
2013-12-03 12:11:07 +04:00
st_foreach ( wrapper - > tbl , mark_method_entry_i , ( st_data_t ) & arg ) ;
2010-05-28 15:13:42 +04:00
}
2008-07-05 11:15:41 +04:00
2010-05-28 15:13:42 +04:00
static int
2012-08-05 14:39:37 +04:00
mark_const_entry_i ( ID key , const rb_const_entry_t * ce , st_data_t data )
2010-05-28 15:13:42 +04:00
{
2012-08-05 14:39:37 +04:00
struct mark_tbl_arg * arg = ( void * ) data ;
2012-10-03 16:30:21 +04:00
gc_mark ( arg - > objspace , ce - > value ) ;
gc_mark ( arg - > objspace , ce - > file ) ;
2012-08-05 14:39:37 +04:00
return ST_CONTINUE ;
2010-05-28 15:13:42 +04:00
}
2008-07-27 17:08:02 +04:00
2010-05-28 15:13:42 +04:00
static void
2012-10-03 16:30:21 +04:00
mark_const_tbl ( rb_objspace_t * objspace , st_table * tbl )
2010-05-28 15:13:42 +04:00
{
2012-08-05 14:39:37 +04:00
struct mark_tbl_arg arg ;
if ( ! tbl ) return ;
arg . objspace = objspace ;
st_foreach ( tbl , mark_const_entry_i , ( st_data_t ) & arg ) ;
2010-05-28 15:13:42 +04:00
}
2012-08-05 14:39:37 +04:00
# if STACK_GROW_DIRECTION < 0
# define GET_STACK_BOUNDS(start, end, appendix) ((start) = STACK_END, (end) = STACK_START)
# elif STACK_GROW_DIRECTION > 0
# define GET_STACK_BOUNDS(start, end, appendix) ((start) = STACK_START, (end) = STACK_END+(appendix))
# else
# define GET_STACK_BOUNDS(start, end, appendix) \
( ( STACK_END < STACK_START ) ? \
( ( start ) = STACK_END , ( end ) = STACK_START ) : ( ( start ) = STACK_START , ( end ) = STACK_END + ( appendix ) ) )
# endif
2010-05-28 15:13:42 +04:00
static void
2012-08-05 14:39:37 +04:00
mark_current_machine_context ( rb_objspace_t * objspace , rb_thread_t * th )
2010-05-28 15:13:42 +04:00
{
2012-08-05 14:39:37 +04:00
union {
rb_jmp_buf j ;
VALUE v [ sizeof ( rb_jmp_buf ) / sizeof ( VALUE ) ] ;
} save_regs_gc_mark ;
VALUE * stack_start , * stack_end ;
2010-05-28 15:13:42 +04:00
2012-08-05 14:39:37 +04:00
FLUSH_REGISTER_WINDOWS ;
/* This assumes that all registers are saved into the jmp_buf (and stack) */
rb_setjmp ( save_regs_gc_mark . j ) ;
2010-06-06 08:12:20 +04:00
2012-08-05 14:39:37 +04:00
GET_STACK_BOUNDS ( stack_start , stack_end , 1 ) ;
2008-07-02 04:49:10 +04:00
2012-08-05 14:39:37 +04:00
mark_locations_array ( objspace , save_regs_gc_mark . v , numberof ( save_regs_gc_mark . v ) ) ;
rb_gc_mark_locations ( stack_start , stack_end ) ;
# ifdef __ia64
2014-01-28 10:09:58 +04:00
rb_gc_mark_locations ( th - > machine . register_stack_start , th - > machine . register_stack_end ) ;
2012-08-05 14:39:37 +04:00
# endif
# if defined(__mc68000__)
mark_locations_array ( objspace , ( VALUE * ) ( ( char * ) STACK_END + 2 ) ,
( STACK_START - STACK_END ) ) ;
# endif
2010-05-28 15:13:42 +04:00
}
2012-08-05 14:39:37 +04:00
void
rb_gc_mark_machine_stack ( rb_thread_t * th )
2010-05-28 15:13:42 +04:00
{
2012-08-05 14:39:37 +04:00
rb_objspace_t * objspace = & rb_objspace ;
VALUE * stack_start , * stack_end ;
2010-06-29 07:11:05 +04:00
2012-08-05 14:39:37 +04:00
GET_STACK_BOUNDS ( stack_start , stack_end , 0 ) ;
rb_gc_mark_locations ( stack_start , stack_end ) ;
# ifdef __ia64
2014-01-28 10:09:58 +04:00
rb_gc_mark_locations ( th - > machine . register_stack_start , th - > machine . register_stack_end ) ;
2012-08-05 14:39:37 +04:00
# endif
2010-05-28 15:13:42 +04:00
}
2012-08-05 14:39:37 +04:00
void
rb_mark_tbl ( st_table * tbl )
2010-10-21 08:18:09 +04:00
{
2012-10-03 16:30:21 +04:00
mark_tbl ( & rb_objspace , tbl ) ;
2010-10-21 08:18:09 +04:00
}
2013-06-17 06:54:25 +04:00
static void
gc_mark_maybe ( rb_objspace_t * objspace , VALUE obj )
{
( void ) VALGRIND_MAKE_MEM_DEFINED ( & obj , sizeof ( obj ) ) ;
2013-06-18 06:17:59 +04:00
if ( is_pointer_to_heap ( objspace , ( void * ) obj ) ) {
int type = BUILTIN_TYPE ( obj ) ;
if ( type ! = T_ZOMBIE & & type ! = T_NONE ) {
gc_mark ( objspace , obj ) ;
}
2013-06-17 06:54:25 +04:00
}
}
2012-08-05 14:39:37 +04:00
void
rb_gc_mark_maybe ( VALUE obj )
{
2013-06-17 06:54:25 +04:00
gc_mark_maybe ( & rb_objspace , obj ) ;
2012-08-05 14:39:37 +04:00
}
2010-05-28 15:13:42 +04:00
2013-11-04 22:59:33 +04:00
static inline int
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
gc_marked ( rb_objspace_t * objspace , VALUE ptr )
{
2013-06-21 03:15:18 +04:00
register bits_t * bits = GET_HEAP_MARK_BITS ( ptr ) ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
if ( MARKED_IN_BITMAP ( bits , ptr ) ) return 1 ;
return 0 ;
}
2013-11-04 22:59:33 +04:00
static inline int
2012-08-05 14:39:37 +04:00
gc_mark_ptr ( rb_objspace_t * objspace , VALUE ptr )
2010-05-28 15:13:42 +04:00
{
2013-06-21 03:15:18 +04:00
register bits_t * bits = GET_HEAP_MARK_BITS ( ptr ) ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
if ( gc_marked ( objspace , ptr ) ) return 0 ;
2012-08-05 14:39:37 +04:00
MARK_IN_BITMAP ( bits , ptr ) ;
return 1 ;
}
2010-05-28 15:13:42 +04:00
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
static void
2013-12-13 06:38:05 +04:00
rgengc_check_relation ( rb_objspace_t * objspace , VALUE obj )
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
{
# if USE_RGENGC
2013-11-04 22:59:33 +04:00
if ( objspace - > rgengc . parent_object_is_old ) {
2013-12-13 06:38:05 +04:00
if ( ! RVALUE_WB_PROTECTED ( obj ) ) {
2013-11-04 22:59:33 +04:00
if ( rgengc_remember ( objspace , obj ) ) {
objspace - > rgengc . remembered_shady_object_count + + ;
}
2013-05-24 14:21:04 +04:00
}
2013-11-04 22:59:33 +04:00
# if RGENGC_THREEGEN
else {
if ( gc_marked ( objspace , obj ) ) {
if ( ! RVALUE_OLD_P ( obj ) ) {
/* An object pointed from an OLD object should be OLD. */
rgengc_remember ( objspace , obj ) ;
}
}
else {
if ( RVALUE_INFANT_P ( obj ) ) {
RVALUE_PROMOTE_INFANT ( obj ) ;
}
}
}
# endif
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
}
# endif
}
2012-08-05 14:39:37 +04:00
static void
2012-10-03 16:30:21 +04:00
gc_mark ( rb_objspace_t * objspace , VALUE ptr )
2012-08-05 14:39:37 +04:00
{
2013-07-18 03:19:38 +04:00
if ( ! is_markable_object ( objspace , ptr ) ) return ;
2010-05-28 15:13:42 +04:00
2012-10-05 12:14:09 +04:00
if ( LIKELY ( objspace - > mark_func_data = = 0 ) ) {
2013-12-13 06:38:05 +04:00
rgengc_check_relation ( objspace , ptr ) ;
2012-10-05 12:14:09 +04:00
if ( ! gc_mark_ptr ( objspace , ptr ) ) return ; /* already marked */
push_mark_stack ( & objspace - > mark_stack , ptr ) ;
}
else {
2012-10-24 04:04:56 +04:00
objspace - > mark_func_data - > mark_func ( ptr , objspace - > mark_func_data - > data ) ;
2012-10-05 12:14:09 +04:00
}
2012-08-05 14:39:37 +04:00
}
2010-05-28 15:13:42 +04:00
2012-08-05 14:39:37 +04:00
void
rb_gc_mark ( VALUE ptr )
{
2012-10-03 16:30:21 +04:00
gc_mark ( & rb_objspace , ptr ) ;
2010-05-28 15:13:42 +04:00
}
2014-02-08 11:03:43 +04:00
/* CAUTION: THIS FUNCTION ENABLE *ONLY BEFORE* SWEEPING.
* This function is only for GC_END_MARK timing .
*/
int
rb_objspace_marked_object_p ( VALUE obj )
{
rb_objspace_t * objspace = & rb_objspace ;
return gc_marked ( objspace , obj ) ? TRUE : FALSE ;
}
2013-11-19 13:48:47 +04:00
/* resurrect non-marked `obj' if obj is before swept */
void
rb_gc_resurrect ( VALUE obj )
{
rb_objspace_t * objspace = & rb_objspace ;
if ( is_lazy_sweeping ( heap_eden ) & &
! gc_marked ( objspace , obj ) & &
! is_swept_object ( objspace , obj ) ) {
gc_mark_ptr ( objspace , obj ) ;
}
}
2010-05-28 15:13:42 +04:00
static void
2012-10-03 16:30:21 +04:00
gc_mark_children ( rb_objspace_t * objspace , VALUE ptr )
2010-05-28 15:13:42 +04:00
{
2012-08-05 14:39:37 +04:00
register RVALUE * obj = RANY ( ptr ) ;
2010-06-29 07:11:05 +04:00
2012-10-04 11:23:41 +04:00
goto marking ; /* skip */
2010-05-28 15:13:42 +04:00
2012-08-05 14:39:37 +04:00
again :
2012-10-05 12:14:09 +04:00
if ( LIKELY ( objspace - > mark_func_data = = 0 ) ) {
obj = RANY ( ptr ) ;
2013-07-18 03:19:38 +04:00
if ( ! is_markable_object ( objspace , ptr ) ) return ;
2013-12-13 06:38:05 +04:00
rgengc_check_relation ( objspace , ptr ) ;
2012-10-05 12:14:09 +04:00
if ( ! gc_mark_ptr ( objspace , ptr ) ) return ; /* already marked */
}
else {
gc_mark ( objspace , ptr ) ;
return ;
}
2012-08-05 14:39:37 +04:00
marking :
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
# if USE_RGENGC
2013-11-04 22:59:33 +04:00
check_gen_consistency ( ( VALUE ) obj ) ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
2013-11-04 22:59:33 +04:00
if ( LIKELY ( objspace - > mark_func_data = = 0 ) ) {
2013-05-22 03:09:22 +04:00
/* minor/major common */
2013-12-13 06:38:05 +04:00
if ( RVALUE_WB_PROTECTED ( obj ) ) {
2013-11-04 22:59:33 +04:00
if ( RVALUE_INFANT_P ( ( VALUE ) obj ) ) {
/* infant -> young */
RVALUE_PROMOTE_INFANT ( ( VALUE ) obj ) ;
# if RGENGC_THREEGEN
/* infant -> young */
objspace - > rgengc . young_object_count + + ;
objspace - > rgengc . parent_object_is_old = FALSE ;
# else
/* infant -> old */
objspace - > rgengc . old_object_count + + ;
objspace - > rgengc . parent_object_is_old = TRUE ;
# endif
rgengc_report ( 3 , objspace , " gc_mark_children: promote infant -> young %p (%s). \n " , ( void * ) obj , obj_type_name ( ( VALUE ) obj ) ) ;
2013-06-25 07:24:07 +04:00
}
2013-11-04 22:59:33 +04:00
else {
objspace - > rgengc . parent_object_is_old = TRUE ;
# if RGENGC_THREEGEN
if ( RVALUE_YOUNG_P ( ( VALUE ) obj ) ) {
/* young -> old */
RVALUE_PROMOTE_YOUNG ( ( VALUE ) obj ) ;
objspace - > rgengc . old_object_count + + ;
rgengc_report ( 3 , objspace , " gc_mark_children: promote young -> old %p (%s). \n " , ( void * ) obj , obj_type_name ( ( VALUE ) obj ) ) ;
}
else {
# endif
if ( ! objspace - > rgengc . during_minor_gc ) {
/* major/full GC */
objspace - > rgengc . old_object_count + + ;
}
# if RGENGC_THREEGEN
}
# endif
2013-06-07 06:28:03 +04:00
}
2013-05-22 03:09:22 +04:00
}
else {
2013-12-13 06:38:05 +04:00
rgengc_report ( 3 , objspace , " gc_mark_children: do not promote non-WB-protected %p (%s). \n " , ( void * ) obj , obj_type_name ( ( VALUE ) obj ) ) ;
2013-11-04 22:59:33 +04:00
objspace - > rgengc . parent_object_is_old = FALSE ;
2013-05-22 03:09:22 +04:00
}
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
}
2013-11-04 22:59:33 +04:00
check_gen_consistency ( ( VALUE ) obj ) ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
# endif /* USE_RGENGC */
2012-08-05 14:39:37 +04:00
if ( FL_TEST ( obj , FL_EXIVAR ) ) {
rb_mark_generic_ivar ( ptr ) ;
2010-05-28 15:13:42 +04:00
}
2012-08-05 14:39:37 +04:00
switch ( BUILTIN_TYPE ( obj ) ) {
case T_NIL :
case T_FIXNUM :
rb_bug ( " rb_gc_mark() called for broken object " ) ;
break ;
case T_NODE :
switch ( nd_type ( obj ) ) {
case NODE_IF : /* 1,2,3 */
case NODE_FOR :
case NODE_ITER :
case NODE_WHEN :
case NODE_MASGN :
case NODE_RESCUE :
case NODE_RESBODY :
case NODE_CLASS :
case NODE_BLOCK_PASS :
2012-10-04 11:23:41 +04:00
gc_mark ( objspace , ( VALUE ) obj - > as . node . u2 . node ) ;
2012-08-05 14:39:37 +04:00
/* fall through */
case NODE_BLOCK : /* 1,3 */
case NODE_ARRAY :
case NODE_DSTR :
case NODE_DXSTR :
case NODE_DREGX :
case NODE_DREGX_ONCE :
case NODE_ENSURE :
case NODE_CALL :
case NODE_DEFS :
case NODE_OP_ASGN1 :
2012-10-04 11:23:41 +04:00
gc_mark ( objspace , ( VALUE ) obj - > as . node . u1 . node ) ;
2012-08-05 14:39:37 +04:00
/* fall through */
case NODE_SUPER : /* 3 */
case NODE_FCALL :
case NODE_DEFN :
case NODE_ARGS_AUX :
2012-10-04 11:23:41 +04:00
ptr = ( VALUE ) obj - > as . node . u3 . node ;
goto again ;
2010-05-28 15:13:42 +04:00
2012-08-05 14:39:37 +04:00
case NODE_WHILE : /* 1,2 */
case NODE_UNTIL :
case NODE_AND :
case NODE_OR :
case NODE_CASE :
case NODE_SCLASS :
case NODE_DOT2 :
case NODE_DOT3 :
case NODE_FLIP2 :
case NODE_FLIP3 :
case NODE_MATCH2 :
case NODE_MATCH3 :
case NODE_OP_ASGN_OR :
case NODE_OP_ASGN_AND :
case NODE_MODULE :
case NODE_ALIAS :
case NODE_VALIAS :
case NODE_ARGSCAT :
2012-10-04 11:23:41 +04:00
gc_mark ( objspace , ( VALUE ) obj - > as . node . u1 . node ) ;
2012-08-05 14:39:37 +04:00
/* fall through */
case NODE_GASGN : /* 2 */
case NODE_LASGN :
case NODE_DASGN :
case NODE_DASGN_CURR :
case NODE_IASGN :
case NODE_IASGN2 :
case NODE_CVASGN :
case NODE_COLON3 :
case NODE_OPT_N :
case NODE_EVSTR :
case NODE_UNDEF :
case NODE_POSTEXE :
2012-10-04 11:23:41 +04:00
ptr = ( VALUE ) obj - > as . node . u2 . node ;
goto again ;
1998-01-16 15:13:05 +03:00
2012-08-05 14:39:37 +04:00
case NODE_HASH : /* 1 */
case NODE_LIT :
case NODE_STR :
case NODE_XSTR :
case NODE_DEFINED :
case NODE_MATCH :
case NODE_RETURN :
case NODE_BREAK :
case NODE_NEXT :
case NODE_YIELD :
case NODE_COLON2 :
case NODE_SPLAT :
case NODE_TO_ARY :
2012-10-04 11:23:41 +04:00
ptr = ( VALUE ) obj - > as . node . u1 . node ;
goto again ;
2012-01-07 18:02:23 +04:00
2012-08-05 14:39:37 +04:00
case NODE_SCOPE : /* 2,3 */
case NODE_CDECL :
case NODE_OPT_ARG :
2012-10-04 11:23:41 +04:00
gc_mark ( objspace , ( VALUE ) obj - > as . node . u3 . node ) ;
ptr = ( VALUE ) obj - > as . node . u2 . node ;
goto again ;
1998-01-16 15:13:05 +03:00
2012-08-05 14:39:37 +04:00
case NODE_ARGS : /* custom */
{
struct rb_args_info * args = obj - > as . node . u3 . args ;
if ( args ) {
2012-10-03 16:30:21 +04:00
if ( args - > pre_init ) gc_mark ( objspace , ( VALUE ) args - > pre_init ) ;
if ( args - > post_init ) gc_mark ( objspace , ( VALUE ) args - > post_init ) ;
if ( args - > opt_args ) gc_mark ( objspace , ( VALUE ) args - > opt_args ) ;
if ( args - > kw_args ) gc_mark ( objspace , ( VALUE ) args - > kw_args ) ;
if ( args - > kw_rest_arg ) gc_mark ( objspace , ( VALUE ) args - > kw_rest_arg ) ;
2012-08-05 14:39:37 +04:00
}
}
2012-10-04 11:23:41 +04:00
ptr = ( VALUE ) obj - > as . node . u2 . node ;
goto again ;
2008-08-06 15:48:30 +04:00
2012-08-05 14:39:37 +04:00
case NODE_ZARRAY : /* - */
case NODE_ZSUPER :
case NODE_VCALL :
case NODE_GVAR :
case NODE_LVAR :
case NODE_DVAR :
case NODE_IVAR :
case NODE_CVAR :
case NODE_NTH_REF :
case NODE_BACK_REF :
case NODE_REDO :
case NODE_RETRY :
case NODE_SELF :
case NODE_NIL :
case NODE_TRUE :
case NODE_FALSE :
case NODE_ERRINFO :
case NODE_BLOCK_ARG :
break ;
case NODE_ALLOCA :
mark_locations_array ( objspace ,
( VALUE * ) obj - > as . node . u1 . value ,
obj - > as . node . u3 . cnt ) ;
2012-10-04 11:23:41 +04:00
gc_mark ( objspace , ( VALUE ) obj - > as . node . u2 . node ) ;
2012-10-03 16:30:21 +04:00
break ;
2008-10-01 14:13:57 +04:00
2012-08-05 14:39:37 +04:00
case NODE_CREF :
2012-10-08 18:02:46 +04:00
gc_mark ( objspace , obj - > as . node . nd_refinements ) ;
2013-12-07 17:01:17 +04:00
gc_mark ( objspace , ( VALUE ) obj - > as . node . nd_clss ) ;
ptr = ( VALUE ) obj - > as . node . nd_next ;
2012-10-04 11:23:41 +04:00
goto again ;
1998-01-16 15:13:05 +03:00
2012-08-05 14:39:37 +04:00
default : /* unlisted NODE */
2013-06-17 06:54:25 +04:00
gc_mark_maybe ( objspace , ( VALUE ) obj - > as . node . u1 . node ) ;
gc_mark_maybe ( objspace , ( VALUE ) obj - > as . node . u2 . node ) ;
gc_mark_maybe ( objspace , ( VALUE ) obj - > as . node . u3 . node ) ;
2012-08-05 14:39:37 +04:00
}
return ; /* no need to mark class. */
1998-01-16 15:13:05 +03:00
}
1999-01-20 07:59:39 +03:00
2012-10-03 16:30:21 +04:00
gc_mark ( objspace , obj - > as . basic . klass ) ;
2008-07-27 09:59:32 +04:00
switch ( BUILTIN_TYPE ( obj ) ) {
2012-08-05 14:39:37 +04:00
case T_ICLASS :
1998-01-16 15:13:05 +03:00
case T_CLASS :
2012-08-05 14:39:37 +04:00
case T_MODULE :
2013-12-03 12:11:07 +04:00
mark_m_tbl_wrapper ( objspace , RCLASS_M_TBL_WRAPPER ( obj ) ) ;
2012-08-05 14:39:37 +04:00
if ( ! RCLASS_EXT ( obj ) ) break ;
2012-10-04 11:23:41 +04:00
mark_tbl ( objspace , RCLASS_IV_TBL ( obj ) ) ;
mark_const_tbl ( objspace , RCLASS_CONST_TBL ( obj ) ) ;
* include/ruby/ruby.h: constify RBasic::klass and add
RBASIC_CLASS(obj) macro which returns a class of `obj'.
This change is a part of RGENGC branch [ruby-trunk - Feature #8339].
* object.c: add new function rb_obj_reveal().
This function reveal interal (hidden) object by rb_obj_hide().
Note that do not change class before and after hiding.
Only permitted example is:
klass = RBASIC_CLASS(obj);
rb_obj_hide(obj);
....
rb_obj_reveal(obj, klass);
TODO: API design. rb_obj_reveal() should be replaced with others.
TODO: modify constified variables using cast may be harmful for
compiler's analysis and optimizaton.
Any idea to prohibt inserting RBasic::klass directly?
If rename RBasic::klass and force to use RBASIC_CLASS(obj),
then all codes such as `RBASIC(obj)->klass' will be
compilation error. Is it acceptable? (We have similar
experience at Ruby 1.9,
for example "RARRAY(ary)->ptr" to "RARRAY_PTR(ary)".
* internal.h: add some macros.
* RBASIC_CLEAR_CLASS(obj) clear RBasic::klass to make it internal
object.
* RBASIC_SET_CLASS(obj, cls) set RBasic::klass.
* RBASIC_SET_CLASS_RAW(obj, cls) same as RBASIC_SET_CLASS
without write barrier (planned).
* RCLASS_SET_SUPER(a, b) set super class of a.
* array.c, class.c, compile.c, encoding.c, enum.c, error.c, eval.c,
file.c, gc.c, hash.c, io.c, iseq.c, marshal.c, object.c,
parse.y, proc.c, process.c, random.c, ruby.c, sprintf.c,
string.c, thread.c, transcode.c, vm.c, vm_eval.c, win32/file.c:
Use above macros and functions to access RBasic::klass.
* ext/coverage/coverage.c, ext/readline/readline.c,
ext/socket/ancdata.c, ext/socket/init.c,
* ext/zlib/zlib.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40691 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 14:49:11 +04:00
ptr = RCLASS_SUPER ( ( VALUE ) obj ) ;
2012-10-04 11:23:41 +04:00
goto again ;
2012-08-05 14:39:37 +04:00
1998-01-16 15:13:05 +03:00
case T_ARRAY :
2012-08-05 14:39:37 +04:00
if ( FL_TEST ( obj , ELTS_SHARED ) ) {
2012-10-04 11:23:41 +04:00
ptr = obj - > as . array . as . heap . aux . shared ;
goto again ;
2000-09-27 07:43:15 +04:00
}
2012-08-05 14:39:37 +04:00
else {
long i , len = RARRAY_LEN ( obj ) ;
* include/ruby/ruby.h: rename RARRAY_RAWPTR() to RARRAY_CONST_PTR().
RARRAY_RAWPTR(ary) returns (const VALUE *) type pointer and
usecase of this macro is not acquire raw pointer, but acquire
read-only pointer. So we rename to better name.
RSTRUCT_RAWPTR() is also renamed to RSTRUCT_CONST_PTR()
(I expect that nobody use it).
* array.c, compile.c, cont.c, enumerator.c, gc.c, proc.c, random.c,
string.c, struct.c, thread.c, vm_eval.c, vm_insnhelper.c:
catch up this change.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43043 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-09-25 12:24:34 +04:00
const VALUE * ptr = RARRAY_CONST_PTR ( obj ) ;
2012-08-05 14:39:37 +04:00
for ( i = 0 ; i < len ; i + + ) {
2012-10-04 11:23:41 +04:00
gc_mark ( objspace , * ptr + + ) ;
1999-01-20 07:59:39 +03:00
}
}
1998-01-16 15:13:05 +03:00
break ;
2012-08-05 14:39:37 +04:00
case T_HASH :
2012-10-03 16:30:21 +04:00
mark_hash ( objspace , obj - > as . hash . ntbl ) ;
2012-10-04 11:23:41 +04:00
ptr = obj - > as . hash . ifnone ;
goto again ;
2012-08-05 14:39:37 +04:00
case T_STRING :
2014-02-05 06:49:41 +04:00
if ( STR_SHARED_P ( obj ) ) {
2012-10-04 11:23:41 +04:00
ptr = obj - > as . string . as . heap . aux . shared ;
goto again ;
1999-01-20 07:59:39 +03:00
}
1998-01-16 15:13:05 +03:00
break ;
2012-08-05 14:39:37 +04:00
case T_DATA :
if ( RTYPEDDATA_P ( obj ) ) {
RUBY_DATA_FUNC mark_func = obj - > as . typeddata . type - > function . dmark ;
if ( mark_func ) ( * mark_func ) ( DATA_PTR ( obj ) ) ;
}
else {
if ( obj - > as . data . dmark ) ( * obj - > as . data . dmark ) ( DATA_PTR ( obj ) ) ;
}
2008-03-16 03:23:43 +03:00
break ;
2012-08-05 14:39:37 +04:00
case T_OBJECT :
{
long i , len = ROBJECT_NUMIV ( obj ) ;
VALUE * ptr = ROBJECT_IVPTR ( obj ) ;
for ( i = 0 ; i < len ; i + + ) {
2012-10-04 11:23:41 +04:00
gc_mark ( objspace , * ptr + + ) ;
2012-08-05 14:39:37 +04:00
}
}
1998-01-16 15:13:05 +03:00
break ;
2012-08-05 14:39:37 +04:00
case T_FILE :
if ( obj - > as . file . fptr ) {
2012-10-03 16:30:21 +04:00
gc_mark ( objspace , obj - > as . file . fptr - > pathv ) ;
gc_mark ( objspace , obj - > as . file . fptr - > tied_io_for_writing ) ;
gc_mark ( objspace , obj - > as . file . fptr - > writeconv_asciicompat ) ;
gc_mark ( objspace , obj - > as . file . fptr - > writeconv_pre_ecopts ) ;
gc_mark ( objspace , obj - > as . file . fptr - > encs . ecopts ) ;
gc_mark ( objspace , obj - > as . file . fptr - > write_lock ) ;
2012-08-05 14:39:37 +04:00
}
break ;
case T_REGEXP :
2012-10-03 16:30:21 +04:00
ptr = obj - > as . regexp . src ;
goto again ;
2012-08-05 14:39:37 +04:00
1998-01-16 15:13:05 +03:00
case T_FLOAT :
2012-08-05 14:39:37 +04:00
case T_BIGNUM :
1998-01-16 15:13:05 +03:00
break ;
2012-08-05 14:39:37 +04:00
case T_MATCH :
2012-10-04 11:23:41 +04:00
gc_mark ( objspace , obj - > as . match . regexp ) ;
2012-08-05 14:39:37 +04:00
if ( obj - > as . match . str ) {
2012-10-04 11:23:41 +04:00
ptr = obj - > as . match . str ;
goto again ;
2000-09-27 07:43:15 +04:00
}
1998-01-16 15:13:05 +03:00
break ;
2012-08-05 14:39:37 +04:00
case T_RATIONAL :
2012-10-04 11:23:41 +04:00
gc_mark ( objspace , obj - > as . rational . num ) ;
ptr = obj - > as . rational . den ;
goto again ;
2012-08-05 14:39:37 +04:00
case T_COMPLEX :
2012-10-04 11:23:41 +04:00
gc_mark ( objspace , obj - > as . complex . real ) ;
ptr = obj - > as . complex . imag ;
goto again ;
1998-01-16 15:13:05 +03:00
case T_STRUCT :
2012-08-05 14:39:37 +04:00
{
long len = RSTRUCT_LEN ( obj ) ;
* include/ruby/ruby.h: rename RARRAY_RAWPTR() to RARRAY_CONST_PTR().
RARRAY_RAWPTR(ary) returns (const VALUE *) type pointer and
usecase of this macro is not acquire raw pointer, but acquire
read-only pointer. So we rename to better name.
RSTRUCT_RAWPTR() is also renamed to RSTRUCT_CONST_PTR()
(I expect that nobody use it).
* array.c, compile.c, cont.c, enumerator.c, gc.c, proc.c, random.c,
string.c, struct.c, thread.c, vm_eval.c, vm_insnhelper.c:
catch up this change.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43043 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-09-25 12:24:34 +04:00
const VALUE * ptr = RSTRUCT_CONST_PTR ( obj ) ;
2012-08-05 14:39:37 +04:00
while ( len - - ) {
2012-10-04 11:23:41 +04:00
gc_mark ( objspace , * ptr + + ) ;
2012-08-05 14:39:37 +04:00
}
2000-09-27 07:43:15 +04:00
}
1998-01-16 15:13:05 +03:00
break ;
default :
2013-08-19 16:00:51 +04:00
# if GC_DEBUG
2013-06-19 10:11:15 +04:00
rb_gcdebug_print_obj_condition ( ( VALUE ) obj ) ;
# endif
if ( BUILTIN_TYPE ( obj ) = = T_NONE ) rb_bug ( " rb_gc_mark(): %p is T_NONE " , ( void * ) obj ) ;
if ( BUILTIN_TYPE ( obj ) = = T_ZOMBIE ) rb_bug ( " rb_gc_mark(): %p is T_ZOMBIE " , ( void * ) obj ) ;
2012-08-05 14:39:37 +04:00
rb_bug ( " rb_gc_mark(): unknown data type 0x%x(%p) %s " ,
BUILTIN_TYPE ( obj ) , ( void * ) obj ,
is_pointer_to_heap ( objspace , obj ) ? " corrupted object " : " non object " ) ;
1998-01-16 15:13:05 +03:00
}
}
2012-10-04 11:31:31 +04:00
static void
gc_mark_stacked_objects ( rb_objspace_t * objspace )
{
mark_stack_t * mstack = & objspace - > mark_stack ;
VALUE obj = 0 ;
if ( ! mstack - > index ) return ;
while ( pop_mark_stack ( mstack , & obj ) ) {
2013-11-27 12:56:48 +04:00
if ( RGENGC_CHECK_MODE > 0 & & ! gc_marked ( objspace , obj ) ) {
2013-11-21 08:57:37 +04:00
rb_bug ( " gc_mark_stacked_objects: %p (%s) is infant, but not marked. " , ( void * ) obj , obj_type_name ( obj ) ) ;
}
2012-10-04 11:31:31 +04:00
gc_mark_children ( objspace , obj ) ;
}
shrink_stack_chunk_cache ( mstack ) ;
}
2013-10-15 14:22:33 +04:00
# ifndef RGENGC_PRINT_TICK
2013-10-11 22:27:18 +04:00
# define RGENGC_PRINT_TICK 0
2013-10-15 14:22:33 +04:00
# endif
2013-09-27 12:12:31 +04:00
/* the following code is only for internal tuning. */
/* Source code to use RDTSC is quoted and modified from
* http : //www.mcs.anl.gov/~kazutomo/rdtsc.html
* written by Kazutomo Yoshii < kazutomo @ mcs . anl . gov >
*/
# if RGENGC_PRINT_TICK
# if defined(__GNUC__) && defined(__i386__)
typedef unsigned long long tick_t ;
static inline tick_t
tick ( void )
{
unsigned long long int x ;
__asm__ __volatile__ ( " rdtsc " : " =A " ( x ) ) ;
return x ;
}
2013-10-11 15:46:42 +04:00
# elif defined(__GNUC__) && defined(__x86_64__)
2013-09-27 12:12:31 +04:00
typedef unsigned long long tick_t ;
static __inline__ tick_t
tick ( void )
{
unsigned long hi , lo ;
__asm__ __volatile__ ( " rdtsc " : " =a " ( lo ) , " =d " ( hi ) ) ;
return ( ( unsigned long long ) lo ) | ( ( ( unsigned long long ) hi ) < < 32 ) ;
}
# elif defined(_WIN32) && defined(_MSC_VER)
# include <intrin.h>
typedef unsigned __int64 tick_t ;
static inline tick_t
tick ( void )
{
return __rdtsc ( ) ;
}
# else /* use clock */
typedef clock_t tick_t ;
static inline tick_t
tick ( void )
{
return clock ( ) ;
}
# endif
# define MAX_TICKS 0x100
static tick_t mark_ticks [ MAX_TICKS ] ;
2013-10-15 14:22:33 +04:00
static const char * mark_ticks_categories [ MAX_TICKS ] ;
2013-09-27 12:12:31 +04:00
static void
show_mark_ticks ( void )
{
int i ;
fprintf ( stderr , " mark ticks result: \n " ) ;
for ( i = 0 ; i < MAX_TICKS ; i + + ) {
2013-10-15 14:22:33 +04:00
const char * category = mark_ticks_categories [ i ] ;
if ( category ) {
fprintf ( stderr , " %s \t %8lu \n " , category , ( unsigned long ) mark_ticks [ i ] ) ;
}
else {
break ;
}
2013-09-27 12:12:31 +04:00
}
}
# endif /* RGENGC_PRINT_TICK */
2010-05-28 15:13:42 +04:00
static void
2013-10-15 14:22:33 +04:00
gc_mark_roots ( rb_objspace_t * objspace , int full_mark , const char * * categoryp )
1998-01-16 15:13:05 +03:00
{
2008-07-05 11:15:41 +04:00
struct gc_list * list ;
2013-06-21 06:20:10 +04:00
rb_thread_t * th = GET_THREAD ( ) ;
2013-11-21 08:57:37 +04:00
if ( categoryp ) * categoryp = " xxx " ;
2012-10-24 05:39:45 +04:00
2013-09-27 12:12:31 +04:00
# if RGENGC_PRINT_TICK
tick_t start_tick = tick ( ) ;
2013-10-15 14:22:33 +04:00
int tick_count = 0 ;
const char * prev_category = 0 ;
if ( mark_ticks_categories [ 0 ] = = 0 ) {
2013-09-27 12:12:31 +04:00
atexit ( show_mark_ticks ) ;
}
# endif
2013-10-15 14:22:33 +04:00
# if RGENGC_PRINT_TICK
# define MARK_CHECKPOINT_PRINT_TICK(category) do { \
if ( prev_category ) { \
tick_t t = tick ( ) ; \
mark_ticks [ tick_count ] = t - start_tick ; \
mark_ticks_categories [ tick_count ] = prev_category ; \
tick_count + + ; \
} \
prev_category = category ; \
start_tick = tick ( ) ; \
} while ( 0 )
# else /* RGENGC_PRINT_TICK */
# define MARK_CHECKPOINT_PRINT_TICK(category)
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
# endif
1998-01-16 15:13:05 +03:00
2013-10-15 14:22:33 +04:00
# define MARK_CHECKPOINT(category) do { \
if ( categoryp ) * categoryp = category ; \
MARK_CHECKPOINT_PRINT_TICK ( category ) ; \
} while ( 0 )
MARK_CHECKPOINT ( " vm " ) ;
2007-02-05 15:21:01 +03:00
SET_STACK_END ;
2007-05-24 06:47:22 +04:00
th - > vm - > self ? rb_gc_mark ( th - > vm - > self ) : rb_vm_mark ( th - > vm ) ;
2006-01-10 13:50:17 +03:00
2013-10-16 02:33:36 +04:00
MARK_CHECKPOINT ( " finalizers " ) ;
2013-10-11 22:03:43 +04:00
mark_tbl ( objspace , finalizer_table ) ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
2013-10-16 02:33:36 +04:00
MARK_CHECKPOINT ( " machine_context " ) ;
2008-04-27 07:20:35 +04:00
mark_current_machine_context ( objspace , th ) ;
2006-12-31 18:02:22 +03:00
2013-10-16 02:33:36 +04:00
MARK_CHECKPOINT ( " symbols " ) ;
2013-11-04 22:59:33 +04:00
# if USE_RGENGC
objspace - > rgengc . parent_object_is_old = TRUE ;
2013-10-11 16:00:35 +04:00
rb_gc_mark_symbols ( full_mark ) ;
2013-11-04 22:59:33 +04:00
objspace - > rgengc . parent_object_is_old = FALSE ;
# else
rb_gc_mark_symbols ( full_mark ) ;
# endif
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
2013-10-16 02:33:36 +04:00
MARK_CHECKPOINT ( " encodings " ) ;
2007-10-13 20:32:40 +04:00
rb_gc_mark_encodings ( ) ;
1998-01-16 15:13:05 +03:00
/* mark protected global variables */
2013-10-16 02:33:36 +04:00
MARK_CHECKPOINT ( " global_list " ) ;
2001-10-31 09:53:22 +03:00
for ( list = global_List ; list ; list = list - > next ) {
2003-04-21 12:17:18 +04:00
rb_gc_mark_maybe ( * list - > varptr ) ;
1998-01-16 15:13:05 +03:00
}
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
2013-10-16 02:33:36 +04:00
MARK_CHECKPOINT ( " end_proc " ) ;
1999-11-26 12:07:26 +03:00
rb_mark_end_proc ( ) ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
2013-10-16 02:33:36 +04:00
MARK_CHECKPOINT ( " global_tbl " ) ;
1999-01-20 07:59:39 +03:00
rb_gc_mark_global_tbl ( ) ;
1998-01-16 15:13:05 +03:00
1999-01-20 07:59:39 +03:00
/* mark generic instance variables for special constants */
2013-10-16 02:33:36 +04:00
MARK_CHECKPOINT ( " generic_ivars " ) ;
1999-01-20 07:59:39 +03:00
rb_mark_generic_ivar_tbl ( ) ;
2002-09-06 00:00:52 +04:00
2013-10-16 02:33:36 +04:00
MARK_CHECKPOINT ( " parser " ) ;
2002-09-06 00:00:52 +04:00
rb_gc_mark_parser ( ) ;
2005-06-19 21:16:14 +04:00
2013-10-16 02:33:36 +04:00
MARK_CHECKPOINT ( " live_method_entries " ) ;
2011-07-25 18:29:28 +04:00
rb_gc_mark_unlinked_live_method_entries ( th - > vm ) ;
2013-10-15 14:22:33 +04:00
MARK_CHECKPOINT ( " finish " ) ;
2013-06-20 00:43:33 +04:00
# undef MARK_CHECKPOINT
2013-10-15 14:22:33 +04:00
}
static void
gc_marks_body ( rb_objspace_t * objspace , int full_mark )
{
/* start marking */
rgengc_report ( 1 , objspace , " gc_marks_body: start (%s) \n " , full_mark ? " full " : " minor " ) ;
# if USE_RGENGC
2013-11-04 22:59:33 +04:00
objspace - > rgengc . parent_object_is_old = FALSE ;
2013-10-15 14:22:33 +04:00
objspace - > rgengc . during_minor_gc = full_mark ? FALSE : TRUE ;
if ( objspace - > rgengc . during_minor_gc ) {
objspace - > profile . minor_gc_count + + ;
2013-10-22 14:28:31 +04:00
rgengc_rememberset_mark ( objspace , heap_eden ) ;
2013-10-15 14:22:33 +04:00
}
else {
objspace - > profile . major_gc_count + + ;
2013-10-22 14:28:31 +04:00
rgengc_mark_and_rememberset_clear ( objspace , heap_eden ) ;
2013-10-15 14:22:33 +04:00
}
# endif
gc_mark_roots ( objspace , full_mark , 0 ) ;
2013-11-21 08:57:37 +04:00
gc_mark_stacked_objects ( objspace ) ;
2013-06-20 00:43:33 +04:00
2013-12-05 08:26:04 +04:00
gc_event_hook ( objspace , RUBY_INTERNAL_EVENT_GC_END_MARK , 0 ) ;
2013-10-11 16:00:35 +04:00
rgengc_report ( 1 , objspace , " gc_marks_body: end (%s) \n " , full_mark ? " full " : " minor " ) ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
}
2013-12-16 08:12:48 +04:00
struct verify_internal_consistency_struct {
rb_objspace_t * objspace ;
int err_count ;
VALUE parent ;
} ;
# if USE_RGENGC
static void
verify_internal_consistency_reachable_i ( VALUE child , void * ptr )
{
struct verify_internal_consistency_struct * data = ( struct verify_internal_consistency_struct * ) ptr ;
assert ( RVALUE_OLD_P ( data - > parent ) ) ;
if ( ! RVALUE_OLD_P ( child ) ) {
if ( ! MARKED_IN_BITMAP ( GET_HEAP_PAGE ( data - > parent ) - > rememberset_bits , data - > parent ) & &
! MARKED_IN_BITMAP ( GET_HEAP_PAGE ( child ) - > rememberset_bits , child ) ) {
fprintf ( stderr , " verify_internal_consistency_reachable_i: WB miss %p (%s) -> %p (%s) \n " ,
( void * ) data - > parent , obj_type_name ( data - > parent ) ,
( void * ) child , obj_type_name ( child ) ) ;
data - > err_count + + ;
}
}
}
static int
verify_internal_consistency_i ( void * page_start , void * page_end , size_t stride , void * ptr )
{
struct verify_internal_consistency_struct * data = ( struct verify_internal_consistency_struct * ) ptr ;
VALUE v ;
for ( v = ( VALUE ) page_start ; v ! = ( VALUE ) page_end ; v + = stride ) {
if ( is_live_object ( data - > objspace , v ) ) {
if ( RVALUE_OLD_P ( v ) ) {
data - > parent = v ;
/* reachable objects from an oldgen object should be old or (young with remember) */
rb_objspace_reachable_objects_from ( v , verify_internal_consistency_reachable_i , ( void * ) data ) ;
}
}
}
return 0 ;
}
# endif /* USE_RGENGC */
/*
* call - seq :
* GC . verify_internal_consistency - > nil
*
* Verify internal consistency .
*
* This method is implementation specific .
2014-01-19 09:43:28 +04:00
* Now this method checks generational consistency
2013-12-16 08:12:48 +04:00
* if RGenGC is supported .
*/
static VALUE
gc_verify_internal_consistency ( VALUE self )
{
struct verify_internal_consistency_struct data ;
data . objspace = & rb_objspace ;
data . err_count = 0 ;
# if USE_RGENGC
2013-12-16 13:19:24 +04:00
{
struct each_obj_args eo_args ;
eo_args . callback = verify_internal_consistency_i ;
eo_args . data = ( void * ) & data ;
objspace_each_objects ( ( VALUE ) & eo_args ) ;
}
2013-12-16 08:12:48 +04:00
# endif
if ( data . err_count ! = 0 ) {
rb_bug ( " gc_verify_internal_consistency: found internal consistency. \n " ) ;
}
return Qnil ;
}
2013-12-16 09:18:21 +04:00
# if RGENGC_CHECK_MODE >= 3
2013-06-22 10:43:30 +04:00
2013-11-21 08:57:37 +04:00
# define MAKE_ROOTSIG(obj) (((VALUE)(obj) << 1) | 0x01)
# define IS_ROOTSIG(obj) ((VALUE)(obj) & 0x01)
# define GET_ROOTSIG(obj) ((const char *)((VALUE)(obj) >> 1))
struct reflist {
VALUE * list ;
int pos ;
int size ;
} ;
static struct reflist *
reflist_create ( VALUE obj )
{
struct reflist * refs = xmalloc ( sizeof ( struct reflist ) ) ;
refs - > size = 1 ;
refs - > list = ALLOC_N ( VALUE , refs - > size ) ;
refs - > list [ 0 ] = obj ;
refs - > pos = 1 ;
return refs ;
}
2013-06-22 10:43:30 +04:00
static void
2013-11-21 08:57:37 +04:00
reflist_destruct ( struct reflist * refs )
2013-06-22 10:43:30 +04:00
{
2013-11-21 08:57:37 +04:00
xfree ( refs - > list ) ;
xfree ( refs ) ;
}
2013-06-22 10:43:30 +04:00
2013-12-10 10:58:48 +04:00
static void
2013-11-21 08:57:37 +04:00
reflist_add ( struct reflist * refs , VALUE obj )
{
if ( refs - > pos = = refs - > size ) {
refs - > size * = 2 ;
SIZED_REALLOC_N ( refs - > list , VALUE , refs - > size , refs - > size / 2 ) ;
2013-06-22 10:43:30 +04:00
}
2013-12-10 09:46:48 +04:00
2013-11-21 08:57:37 +04:00
refs - > list [ refs - > pos + + ] = obj ;
2013-06-22 10:43:30 +04:00
}
2013-11-21 08:57:37 +04:00
static void
reflist_dump ( struct reflist * refs )
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
{
2013-11-21 08:57:37 +04:00
int i ;
for ( i = 0 ; i < refs - > pos ; i + + ) {
VALUE obj = refs - > list [ i ] ;
if ( IS_ROOTSIG ( obj ) ) { /* root */
fprintf ( stderr , " <root@%s> " , GET_ROOTSIG ( obj ) ) ;
}
else {
fprintf ( stderr , " <%p@%s> " , ( void * ) obj , obj_type_name ( obj ) ) ;
}
if ( i + 1 < refs - > pos ) fprintf ( stderr , " , " ) ;
2013-06-19 18:59:35 +04:00
}
2013-06-22 10:43:30 +04:00
}
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
2013-12-10 10:44:35 +04:00
# if RGENGC_CHECK_MODE >= 3
2013-11-21 08:57:37 +04:00
static int
reflist_refered_from_machine_context ( struct reflist * refs )
2013-06-19 18:59:35 +04:00
{
2013-11-21 08:57:37 +04:00
int i ;
for ( i = 0 ; i < refs - > pos ; i + + ) {
VALUE obj = refs - > list [ i ] ;
if ( IS_ROOTSIG ( obj ) & & strcmp ( GET_ROOTSIG ( obj ) , " machine_context " ) = = 0 ) return 1 ;
}
return 0 ;
}
2013-12-10 10:44:35 +04:00
# endif
2013-06-19 18:59:35 +04:00
2013-11-21 08:57:37 +04:00
struct allrefs {
rb_objspace_t * objspace ;
/* a -> obj1
* b - > obj1
* c - > obj1
* c - > obj2
* d - > obj3
* # = > { obj1 = > [ a , b , c ] , obj2 = > [ c , d ] }
*/
struct st_table * references ;
const char * category ;
VALUE root_obj ;
} ;
2013-06-19 18:59:35 +04:00
2013-12-10 09:46:48 +04:00
static int
2013-11-21 08:57:37 +04:00
allrefs_add ( struct allrefs * data , VALUE obj )
{
struct reflist * refs ;
2013-06-19 18:59:35 +04:00
2013-11-21 08:57:37 +04:00
if ( st_lookup ( data - > references , obj , ( st_data_t * ) & refs ) ) {
2013-12-10 10:47:15 +04:00
reflist_add ( refs , data - > root_obj ) ;
return 0 ;
2013-11-21 08:57:37 +04:00
}
else {
refs = reflist_create ( data - > root_obj ) ;
st_insert ( data - > references , obj , ( st_data_t ) refs ) ;
2013-12-10 09:46:48 +04:00
return 1 ;
2013-06-19 18:59:35 +04:00
}
}
static void
2013-11-21 08:57:37 +04:00
allrefs_i ( VALUE obj , void * ptr )
2013-06-19 18:59:35 +04:00
{
2013-11-21 08:57:37 +04:00
struct allrefs * data = ( struct allrefs * ) ptr ;
2013-12-10 10:47:15 +04:00
if ( allrefs_add ( data , obj ) ) {
2013-12-10 09:46:48 +04:00
push_mark_stack ( & data - > objspace - > mark_stack , obj ) ;
2013-12-10 10:58:48 +04:00
}
2013-12-10 10:47:15 +04:00
}
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
2013-06-19 18:59:35 +04:00
static void
2013-11-21 08:57:37 +04:00
allrefs_roots_i ( VALUE obj , void * ptr )
2013-06-19 18:59:35 +04:00
{
2013-11-21 08:57:37 +04:00
struct allrefs * data = ( struct allrefs * ) ptr ;
if ( strlen ( data - > category ) = = 0 ) rb_bug ( " !!! " ) ;
data - > root_obj = MAKE_ROOTSIG ( data - > category ) ;
2013-12-10 10:47:15 +04:00
if ( allrefs_add ( data , obj ) ) {
2013-12-10 10:58:48 +04:00
push_mark_stack ( & data - > objspace - > mark_stack , obj ) ;
}
2013-12-10 10:47:15 +04:00
}
2013-06-22 10:43:30 +04:00
2013-11-21 08:57:37 +04:00
static st_table *
objspace_allrefs ( rb_objspace_t * objspace )
{
struct allrefs data ;
struct mark_func_data_struct mfd ;
VALUE obj ;
data . objspace = objspace ;
data . references = st_init_numtable ( ) ;
mfd . mark_func = allrefs_roots_i ;
mfd . data = & data ;
/* traverse root objects */
objspace - > mark_func_data = & mfd ;
gc_mark_roots ( objspace , TRUE , & data . category ) ;
objspace - > mark_func_data = 0 ;
2013-06-22 10:43:30 +04:00
2013-11-21 08:57:37 +04:00
/* traverse rest objects reachable from root objects */
while ( pop_mark_stack ( & objspace - > mark_stack , & obj ) ) {
rb_objspace_reachable_objects_from ( data . root_obj = obj , allrefs_i , & data ) ;
2013-06-22 10:43:30 +04:00
}
2013-11-21 08:57:37 +04:00
shrink_stack_chunk_cache ( & objspace - > mark_stack ) ;
2013-06-22 10:43:30 +04:00
2013-11-21 08:57:37 +04:00
return data . references ;
}
static int
objspaec_allrefs_destruct_i ( st_data_t key , st_data_t value , void * ptr )
{
struct reflist * refs = ( struct reflist * ) value ;
reflist_destruct ( refs ) ;
return ST_CONTINUE ;
2013-06-22 10:43:30 +04:00
}
static void
2013-12-10 07:25:28 +04:00
objspace_allrefs_destruct ( struct st_table * refs )
2013-06-22 10:43:30 +04:00
{
2013-11-21 08:57:37 +04:00
st_foreach ( refs , objspaec_allrefs_destruct_i , 0 ) ;
st_free_table ( refs ) ;
}
2013-06-22 10:43:30 +04:00
2013-12-10 10:44:35 +04:00
# if RGENGC_CHECK_MODE >= 4
2013-11-21 08:57:37 +04:00
static int
allrefs_dump_i ( st_data_t k , st_data_t v , st_data_t ptr )
{
VALUE obj = ( VALUE ) k ;
struct reflist * refs = ( struct reflist * ) v ;
2013-11-21 09:07:04 +04:00
fprintf ( stderr , " [allrefs_dump_i] %p (%s%s%s%s) <- " ,
2013-11-21 08:57:37 +04:00
( void * ) obj , obj_type_name ( obj ) ,
2013-12-13 06:38:05 +04:00
RVALUE_OLD_P ( obj ) ? " [O] " : " [Y] " ,
RVALUE_WB_PROTECTED ( obj ) ? " [W] " : " " ,
2013-11-21 08:57:37 +04:00
MARKED_IN_BITMAP ( GET_HEAP_REMEMBERSET_BITS ( obj ) , obj ) ? " [R] " : " " ) ;
reflist_dump ( refs ) ;
fprintf ( stderr , " \n " ) ;
return ST_CONTINUE ;
}
2013-06-22 10:43:30 +04:00
2013-11-21 08:57:37 +04:00
static void
allrefs_dump ( rb_objspace_t * objspace )
{
fprintf ( stderr , " [all refs] (size: %d) \n " , ( int ) objspace - > rgengc . allrefs_table - > num_entries ) ;
st_foreach ( objspace - > rgengc . allrefs_table , allrefs_dump_i , 0 ) ;
}
# endif
2013-06-22 10:43:30 +04:00
2013-12-10 10:44:35 +04:00
# if RGENGC_CHECK_MODE >= 3
2013-11-21 08:57:37 +04:00
static int
gc_check_after_marks_i ( st_data_t k , st_data_t v , void * ptr )
2013-06-22 10:43:30 +04:00
{
2013-11-21 08:57:37 +04:00
VALUE obj = k ;
struct reflist * refs = ( struct reflist * ) v ;
rb_objspace_t * objspace = ( rb_objspace_t * ) ptr ;
2013-06-22 10:43:30 +04:00
2013-11-21 08:57:37 +04:00
/* object should be marked or oldgen */
if ( ! MARKED_IN_BITMAP ( GET_HEAP_MARK_BITS ( obj ) , obj ) ) {
fprintf ( stderr , " gc_check_after_marks_i: %p (%s) is not marked and not oldgen. \n " , ( void * ) obj , obj_type_name ( obj ) ) ;
fprintf ( stderr , " gc_check_after_marks_i: %p is referred from " , ( void * ) obj ) ;
reflist_dump ( refs ) ;
2013-06-24 19:57:16 +04:00
2013-11-21 08:57:37 +04:00
if ( reflist_refered_from_machine_context ( refs ) ) {
fprintf ( stderr , " (marked from machine stack). \n " ) ;
/* marked from machine context can be false positive */
}
else {
objspace - > rgengc . error_count + + ;
fprintf ( stderr , " \n " ) ;
}
2013-06-24 19:57:16 +04:00
}
2013-11-21 08:57:37 +04:00
return ST_CONTINUE ;
}
2013-12-10 10:44:35 +04:00
# endif
2013-06-19 18:59:35 +04:00
2013-11-21 08:57:37 +04:00
static void
gc_marks_check ( rb_objspace_t * objspace , int ( * checker_func ) ( ANYARGS ) , const char * checker_name )
{
2013-12-10 10:26:05 +04:00
2013-12-10 10:21:52 +04:00
size_t saved_malloc_increase = objspace - > malloc_params . increase ;
# if RGENGC_ESTIMATE_OLDMALLOC
size_t saved_oldmalloc_increase = objspace - > rgengc . oldmalloc_increase ;
# endif
VALUE already_disabled = rb_gc_disable ( ) ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
2013-12-10 10:21:52 +04:00
objspace - > rgengc . allrefs_table = objspace_allrefs ( objspace ) ;
2013-11-21 08:57:37 +04:00
st_foreach ( objspace - > rgengc . allrefs_table , checker_func , ( st_data_t ) objspace ) ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
2013-11-21 08:57:37 +04:00
if ( objspace - > rgengc . error_count > 0 ) {
2013-12-10 10:44:35 +04:00
# if RGENGC_CHECK_MODE >= 4
2013-11-21 08:57:37 +04:00
allrefs_dump ( objspace ) ;
# endif
rb_bug ( " %s: GC has problem. " , checker_name ) ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
}
2013-06-19 02:04:30 +04:00
2013-12-10 07:25:28 +04:00
objspace_allrefs_destruct ( objspace - > rgengc . allrefs_table ) ;
2013-11-21 08:57:37 +04:00
objspace - > rgengc . allrefs_table = 0 ;
2013-12-10 10:21:52 +04:00
if ( already_disabled = = Qfalse ) rb_gc_enable ( ) ;
objspace - > malloc_params . increase = saved_malloc_increase ;
# if RGENGC_ESTIMATE_OLDMALLOC
objspace - > rgengc . oldmalloc_increase = saved_oldmalloc_increase ;
# endif
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
}
2013-11-21 08:57:37 +04:00
2013-06-22 10:43:30 +04:00
# endif /* RGENGC_CHECK_MODE >= 2 */
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
static void
2013-10-11 16:00:35 +04:00
gc_marks ( rb_objspace_t * objspace , int full_mark )
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
{
struct mark_func_data_struct * prev_mark_func_data ;
gc_prof_mark_timer_start ( objspace ) ;
2013-05-21 11:52:03 +04:00
{
/* setup marking */
prev_mark_func_data = objspace - > mark_func_data ;
objspace - > mark_func_data = 0 ;
2013-05-24 14:21:04 +04:00
2013-06-21 03:10:34 +04:00
# if USE_RGENGC
2013-11-21 08:57:37 +04:00
# if RGENGC_CHECK_MODE >= 2
2013-12-16 09:18:21 +04:00
gc_verify_internal_consistency ( Qnil ) ;
2013-11-21 08:57:37 +04:00
# endif
2013-10-11 16:00:35 +04:00
if ( full_mark = = TRUE ) { /* major/full GC */
2013-05-24 14:21:04 +04:00
objspace - > rgengc . remembered_shady_object_count = 0 ;
2013-11-04 22:59:33 +04:00
objspace - > rgengc . old_object_count = 0 ;
# if RGENGC_THREEGEN
objspace - > rgengc . young_object_count = 0 ;
# endif
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
2013-10-11 16:00:35 +04:00
gc_marks_body ( objspace , TRUE ) ;
2014-02-17 07:27:13 +04:00
{
/* See the comment about RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR */
const double r = gc_params . oldobject_limit_factor ;
objspace - > rgengc . remembered_shady_object_limit = objspace - > rgengc . remembered_shady_object_count * r ;
objspace - > rgengc . old_object_limit = objspace - > rgengc . old_object_count * r ;
}
2013-05-24 14:21:04 +04:00
}
else { /* minor GC */
2013-10-11 16:00:35 +04:00
gc_marks_body ( objspace , FALSE ) ;
2013-05-21 11:52:03 +04:00
}
2013-06-22 02:29:09 +04:00
# if RGENGC_PROFILE > 0
2013-09-26 06:31:26 +04:00
if ( gc_prof_record ( objspace ) ) {
gc_profile_record * record = gc_prof_record ( objspace ) ;
2013-11-04 22:59:33 +04:00
record - > old_objects = objspace - > rgengc . old_object_count ;
2013-09-26 06:31:26 +04:00
}
2013-06-22 02:29:09 +04:00
# endif
2013-12-10 10:44:35 +04:00
# if RGENGC_CHECK_MODE >= 3
2013-11-21 08:57:37 +04:00
gc_marks_check ( objspace , gc_check_after_marks_i , " after_marks " ) ;
# endif
2013-06-21 03:10:34 +04:00
# else /* USE_RGENGC */
2013-10-11 16:00:35 +04:00
gc_marks_body ( objspace , TRUE ) ;
2013-06-21 03:10:34 +04:00
# endif
2013-05-21 11:52:03 +04:00
objspace - > mark_func_data = prev_mark_func_data ;
}
gc_prof_mark_timer_stop ( objspace ) ;
2010-05-28 15:13:42 +04:00
}
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
/* RGENGC */
2013-07-18 03:19:38 +04:00
static void
rgengc_report_body ( int level , rb_objspace_t * objspace , const char * fmt , . . . )
{
if ( level < = RGENGC_DEBUG ) {
char buf [ 1024 ] ;
FILE * out = stderr ;
va_list args ;
const char * status = " " ;
# if USE_RGENGC
if ( during_gc ) {
status = objspace - > rgengc . during_minor_gc ? " - " : " + " ;
}
# endif
va_start ( args , fmt ) ;
vsnprintf ( buf , 1024 , fmt , args ) ;
va_end ( args ) ;
fprintf ( out , " %s| " , status ) ;
fputs ( buf , out ) ;
}
}
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
# if USE_RGENGC
/* bit operations */
static int
rgengc_remembersetbits_get ( rb_objspace_t * objspace , VALUE obj )
{
2013-06-21 03:15:18 +04:00
bits_t * bits = GET_HEAP_REMEMBERSET_BITS ( obj ) ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
return MARKED_IN_BITMAP ( bits , obj ) ? 1 : 0 ;
}
2013-06-25 07:24:07 +04:00
static int
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
rgengc_remembersetbits_set ( rb_objspace_t * objspace , VALUE obj )
{
2013-06-21 03:15:18 +04:00
bits_t * bits = GET_HEAP_REMEMBERSET_BITS ( obj ) ;
2013-06-25 07:24:07 +04:00
if ( MARKED_IN_BITMAP ( bits , obj ) ) {
return FALSE ;
}
else {
MARK_IN_BITMAP ( bits , obj ) ;
return TRUE ;
}
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
}
/* wb, etc */
2013-06-25 07:24:07 +04:00
/* return FALSE if already remembered */
static int
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
rgengc_remember ( rb_objspace_t * objspace , VALUE obj )
{
2013-06-19 02:12:39 +04:00
rgengc_report ( 2 , objspace , " rgengc_remember: %p (%s, %s) %s \n " , ( void * ) obj , obj_type_name ( obj ) ,
2013-12-13 06:38:05 +04:00
RVALUE_WB_PROTECTED ( obj ) ? " WB-protected " : " non-WB-protected " ,
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
rgengc_remembersetbits_get ( objspace , obj ) ? " was already remembered " : " is remembered now " ) ;
2013-06-19 02:07:09 +04:00
# if RGENGC_CHECK_MODE > 0
{
switch ( BUILTIN_TYPE ( obj ) ) {
case T_NONE :
case T_ZOMBIE :
rb_bug ( " rgengc_remember: should not remember %p (%s) \n " ,
( void * ) obj , obj_type_name ( obj ) ) ;
default :
;
}
}
# endif
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
if ( RGENGC_PROFILE ) {
if ( ! rgengc_remembered ( objspace , obj ) ) {
2013-11-04 22:59:33 +04:00
# if RGENGC_PROFILE > 0
2013-12-13 06:38:05 +04:00
if ( RVALUE_WB_PROTECTED ( obj ) ) {
2013-06-07 05:17:19 +04:00
objspace - > profile . remembered_normal_object_count + + ;
2013-05-26 20:43:21 +04:00
# if RGENGC_PROFILE >= 2
2013-06-07 05:17:19 +04:00
objspace - > profile . remembered_normal_object_count_types [ BUILTIN_TYPE ( obj ) ] + + ;
2013-05-26 20:43:21 +04:00
# endif
}
else {
objspace - > profile . remembered_shady_object_count + + ;
# if RGENGC_PROFILE >= 2
objspace - > profile . remembered_shady_object_count_types [ BUILTIN_TYPE ( obj ) ] + + ;
# endif
}
2013-12-13 06:38:05 +04:00
# endif /* RGENGC_PROFILE > 0 */
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
}
}
2013-06-25 07:24:07 +04:00
return rgengc_remembersetbits_set ( objspace , obj ) ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
}
static int
rgengc_remembered ( rb_objspace_t * objspace , VALUE obj )
{
int result = rgengc_remembersetbits_get ( objspace , obj ) ;
2013-11-04 22:59:33 +04:00
check_gen_consistency ( obj ) ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
rgengc_report ( 6 , objspace , " gc_remembered: %p (%s) => %d \n " , ( void * ) obj , obj_type_name ( obj ) , result ) ;
return result ;
}
2013-06-25 07:24:07 +04:00
static void
2013-10-22 14:28:31 +04:00
rgengc_rememberset_mark ( rb_objspace_t * objspace , rb_heap_t * heap )
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
{
2013-10-22 14:28:31 +04:00
size_t j ;
2013-06-05 19:57:12 +04:00
RVALUE * p , * offset ;
2013-06-21 03:15:18 +04:00
bits_t * bits , bitset ;
2013-10-22 14:28:31 +04:00
struct heap_page * page = heap - > pages ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
2013-06-25 07:24:07 +04:00
# if RGENGC_PROFILE > 0
size_t shady_object_count = 0 , clear_count = 0 ;
# endif
2013-10-22 14:28:31 +04:00
while ( page ) {
p = page - > start ;
2013-11-09 04:23:02 +04:00
bits = page - > rememberset_bits ;
2013-10-18 10:33:36 +04:00
offset = p - NUM_IN_PAGE ( p ) ;
2013-06-05 19:57:12 +04:00
2013-06-07 06:52:42 +04:00
for ( j = 0 ; j < HEAP_BITMAP_LIMIT ; j + + ) {
if ( bits [ j ] ) {
2013-06-21 03:15:18 +04:00
p = offset + j * BITS_BITLENGTH ;
2013-06-05 19:57:12 +04:00
bitset = bits [ j ] ;
2013-06-07 06:32:57 +04:00
do {
2013-06-05 19:57:12 +04:00
if ( bitset & 1 ) {
2013-11-04 22:59:33 +04:00
/* mark before RVALUE_PROMOTE_... */
2013-06-22 00:10:03 +04:00
gc_mark_ptr ( objspace , ( VALUE ) p ) ;
2013-12-13 06:38:05 +04:00
if ( RVALUE_WB_PROTECTED ( p ) ) {
2013-06-05 19:57:12 +04:00
rgengc_report ( 2 , objspace , " rgengc_rememberset_mark: clear %p (%s) \n " , p , obj_type_name ( ( VALUE ) p ) ) ;
2013-11-04 22:59:33 +04:00
# if RGENGC_THREEGEN
if ( RVALUE_INFANT_P ( ( VALUE ) p ) ) RVALUE_PROMOTE_INFANT ( ( VALUE ) p ) ;
if ( RVALUE_YOUNG_P ( ( VALUE ) p ) ) RVALUE_PROMOTE_YOUNG ( ( VALUE ) p ) ;
# endif
2013-06-05 19:57:12 +04:00
CLEAR_IN_BITMAP ( bits , p ) ;
2013-06-25 07:24:07 +04:00
# if RGENGC_PROFILE > 0
2013-06-19 02:12:39 +04:00
clear_count + + ;
2013-06-25 07:24:07 +04:00
# endif
2013-06-05 19:57:12 +04:00
}
else {
2013-06-25 07:24:07 +04:00
# if RGENGC_PROFILE > 0
2013-06-05 19:57:12 +04:00
shady_object_count + + ;
2013-06-25 07:24:07 +04:00
# endif
2013-06-05 19:57:12 +04:00
}
2013-11-04 22:59:33 +04:00
rgengc_report ( 2 , objspace , " rgengc_rememberset_mark: mark %p (%s) \n " , p , obj_type_name ( ( VALUE ) p ) ) ;
gc_mark_children ( objspace , ( VALUE ) p ) ;
2013-06-05 19:57:12 +04:00
}
p + + ;
2013-06-07 06:32:57 +04:00
bitset > > = 1 ;
} while ( bitset ) ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
}
}
2013-10-22 14:28:31 +04:00
page = page - > next ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
}
2013-10-22 14:28:31 +04:00
rgengc_report ( 2 , objspace , " rgengc_rememberset_mark: finished \n " ) ;
2013-06-22 02:29:09 +04:00
2013-06-20 16:20:27 +04:00
# if RGENGC_PROFILE > 0
2013-06-25 07:24:07 +04:00
rgengc_report ( 2 , objspace , " rgengc_rememberset_mark: clear_count: % " PRIdSIZE " , shady_object_count: % " PRIdSIZE " \n " , clear_count , shady_object_count ) ;
2013-06-22 02:29:09 +04:00
if ( gc_prof_record ( objspace ) ) {
gc_profile_record * record = gc_prof_record ( objspace ) ;
record - > remembered_normal_objects = clear_count ;
record - > remembered_shady_objects = shady_object_count ;
}
2013-06-20 16:20:27 +04:00
# endif
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
}
static void
2013-10-22 14:28:31 +04:00
rgengc_mark_and_rememberset_clear ( rb_objspace_t * objspace , rb_heap_t * heap )
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
{
2013-10-22 14:28:31 +04:00
struct heap_page * page = heap - > pages ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
2013-10-22 14:28:31 +04:00
while ( page ) {
2013-10-18 10:33:36 +04:00
memset ( & page - > mark_bits [ 0 ] , 0 , HEAP_BITMAP_SIZE ) ;
memset ( & page - > rememberset_bits [ 0 ] , 0 , HEAP_BITMAP_SIZE ) ;
2013-10-22 14:28:31 +04:00
page = page - > next ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
}
}
/* RGENGC: APIs */
void
rb_gc_writebarrier ( VALUE a , VALUE b )
{
if ( RGENGC_CHECK_MODE ) {
2013-11-04 22:59:33 +04:00
if ( ! RVALUE_PROMOTED_P ( a ) ) rb_bug ( " rb_gc_writebarrier: referer object %p (%s) is not promoted. \n " , ( void * ) a , obj_type_name ( a ) ) ;
}
if ( ! RVALUE_OLD_P ( b ) & & RVALUE_OLD_BITMAP_P ( a ) ) {
rb_objspace_t * objspace = & rb_objspace ;
if ( ! rgengc_remembered ( objspace , a ) ) {
int type = BUILTIN_TYPE ( a ) ;
/* TODO: 2 << 16 is just a magic number. */
if ( ( type = = T_ARRAY & & RARRAY_LEN ( a ) > = 2 < < 16 ) | |
( type = = T_HASH & & RHASH_SIZE ( a ) > = 2 < < 16 ) ) {
if ( ! rgengc_remembered ( objspace , b ) ) {
rgengc_report ( 2 , objspace , " rb_gc_wb: %p (%s) -> %p (%s) \n " , ( void * ) a , obj_type_name ( a ) , ( void * ) b , obj_type_name ( b ) ) ;
rgengc_remember ( objspace , b ) ;
}
}
else {
rgengc_report ( 2 , objspace , " rb_gc_wb: %p (%s) -> %p (%s) \n " ,
( void * ) a , obj_type_name ( a ) , ( void * ) b , obj_type_name ( b ) ) ;
rgengc_remember ( objspace , a ) ;
}
}
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
}
}
void
2013-06-23 01:54:10 +04:00
rb_gc_writebarrier_unprotect_promoted ( VALUE obj )
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
{
rb_objspace_t * objspace = & rb_objspace ;
if ( RGENGC_CHECK_MODE ) {
2013-11-04 22:59:33 +04:00
if ( ! RVALUE_PROMOTED_P ( obj ) ) rb_bug ( " rb_gc_writebarrier_unprotect_promoted: called on non-promoted object " ) ;
2013-12-13 06:38:05 +04:00
if ( ! RVALUE_WB_PROTECTED ( obj ) ) rb_bug ( " rb_gc_writebarrier_unprotect_promoted: called on shady object " ) ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
}
2013-11-04 22:59:33 +04:00
rgengc_report ( 0 , objspace , " rb_gc_writebarrier_unprotect_promoted: %p (%s)%s \n " , ( void * ) obj , obj_type_name ( obj ) ,
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
rgengc_remembered ( objspace , obj ) ? " (already remembered) " : " " ) ;
2013-11-04 22:59:33 +04:00
if ( RVALUE_OLD_P ( obj ) ) {
RVALUE_DEMOTE_FROM_OLD ( obj ) ;
2013-06-25 07:24:07 +04:00
2013-11-04 22:59:33 +04:00
rgengc_remember ( objspace , obj ) ;
objspace - > rgengc . remembered_shady_object_count + + ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
# if RGENGC_PROFILE
2013-11-04 22:59:33 +04:00
objspace - > profile . shade_operation_count + + ;
2013-05-26 20:43:21 +04:00
# if RGENGC_PROFILE >= 2
2013-11-04 22:59:33 +04:00
objspace - > profile . shade_operation_count_types [ BUILTIN_TYPE ( obj ) ] + + ;
2013-05-26 20:43:21 +04:00
# endif /* RGENGC_PROFILE >= 2 */
2013-11-04 22:59:33 +04:00
# endif /* RGENGC_PROFILE */
}
# if RGENGC_THREEGEN
else {
RVALUE_DEMOTE_FROM_YOUNG ( obj ) ;
}
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
# endif
}
2013-07-19 10:11:09 +04:00
void
rb_gc_writebarrier_remember_promoted ( VALUE obj )
{
rb_objspace_t * objspace = & rb_objspace ;
rgengc_remember ( objspace , obj ) ;
}
2013-07-24 13:42:43 +04:00
static st_table * rgengc_unprotect_logging_table ;
static int
rgengc_unprotect_logging_exit_func_i ( st_data_t key , st_data_t val )
{
fprintf ( stderr , " %s \t %d \n " , ( char * ) key , ( int ) val ) ;
return ST_CONTINUE ;
}
static void
rgengc_unprotect_logging_exit_func ( void )
{
st_foreach ( rgengc_unprotect_logging_table , rgengc_unprotect_logging_exit_func_i , 0 ) ;
}
void
rb_gc_unprotect_logging ( void * objptr , const char * filename , int line )
{
VALUE obj = ( VALUE ) objptr ;
if ( rgengc_unprotect_logging_table = = 0 ) {
rgengc_unprotect_logging_table = st_init_strtable ( ) ;
atexit ( rgengc_unprotect_logging_exit_func ) ;
}
if ( OBJ_WB_PROTECTED ( obj ) ) {
char buff [ 0x100 ] ;
st_data_t cnt = 1 ;
char * ptr = buff ;
snprintf ( ptr , 0x100 - 1 , " %s|%s:%d " , obj_type_name ( obj ) , filename , line ) ;
if ( st_lookup ( rgengc_unprotect_logging_table , ( st_data_t ) ptr , & cnt ) ) {
cnt + + ;
}
else {
ptr = ( char * ) malloc ( strlen ( buff ) + 1 ) ;
strcpy ( ptr , buff ) ;
}
st_insert ( rgengc_unprotect_logging_table , ( st_data_t ) ptr , cnt ) ;
}
}
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
# endif /* USE_RGENGC */
/* RGENGC analysis information */
VALUE
rb_obj_rgengc_writebarrier_protected_p ( VALUE obj )
{
return OBJ_WB_PROTECTED ( obj ) ? Qtrue : Qfalse ;
}
VALUE
rb_obj_rgengc_promoted_p ( VALUE obj )
{
return OBJ_PROMOTED ( obj ) ? Qtrue : Qfalse ;
}
2013-12-10 06:26:09 +04:00
size_t
rb_obj_gc_flags ( VALUE obj , ID * flags , size_t max )
{
size_t n = 0 ;
static ID ID_marked ;
# if USE_RGENGC
static ID ID_wb_protected , ID_old , ID_remembered ;
# if RGENGC_THREEGEN
static ID ID_young , ID_infant ;
# endif
# endif
if ( ! ID_marked ) {
# define I(s) ID_##s = rb_intern(#s);
I ( marked ) ;
# if USE_RGENGC
I ( wb_protected ) ;
I ( old ) ;
I ( remembered ) ;
# if RGENGC_THREEGEN
I ( young ) ;
I ( infant ) ;
# endif
# endif
# undef I
}
# if USE_RGENGC
if ( OBJ_WB_PROTECTED ( obj ) & & n < max )
flags [ n + + ] = ID_wb_protected ;
if ( RVALUE_OLD_P ( obj ) & & n < max )
flags [ n + + ] = ID_old ;
# if RGENGC_THREEGEN
if ( RVALUE_YOUNG_P ( obj ) & & n < max )
flags [ n + + ] = ID_young ;
if ( RVALUE_INFANT_P ( obj ) & & n < max )
flags [ n + + ] = ID_infant ;
# endif
if ( MARKED_IN_BITMAP ( GET_HEAP_REMEMBERSET_BITS ( obj ) , obj ) & & n < max )
flags [ n + + ] = ID_remembered ;
# endif
if ( MARKED_IN_BITMAP ( GET_HEAP_MARK_BITS ( obj ) , obj ) & & n < max )
flags [ n + + ] = ID_marked ;
return n ;
}
2012-08-05 14:39:37 +04:00
/* GC */
void
rb_gc_force_recycle ( VALUE p )
{
rb_objspace_t * objspace = & rb_objspace ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
# if USE_RGENGC
CLEAR_IN_BITMAP ( GET_HEAP_REMEMBERSET_BITS ( p ) , p ) ;
2013-06-19 18:30:13 +04:00
CLEAR_IN_BITMAP ( GET_HEAP_OLDGEN_BITS ( p ) , p ) ;
2013-11-01 17:47:39 +04:00
if ( ! GET_HEAP_PAGE ( p ) - > before_sweep ) {
2013-06-25 20:20:39 +04:00
CLEAR_IN_BITMAP ( GET_HEAP_MARK_BITS ( p ) , p ) ;
}
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
# endif
2013-11-01 16:49:49 +04:00
objspace - > profile . total_freed_object_num + + ;
2013-10-18 10:33:36 +04:00
heap_page_add_freeobj ( objspace , GET_HEAP_PAGE ( p ) , p ) ;
2013-07-16 12:32:32 +04:00
2013-11-23 03:50:08 +04:00
/* Disable counting swept_slots because there are no meaning.
2013-10-22 14:28:31 +04:00
* if ( ! MARKED_IN_BITMAP ( GET_HEAP_MARK_BITS ( p ) , p ) ) {
2013-11-23 03:50:08 +04:00
* objspace - > heap . swept_slots + + ;
2013-10-22 14:28:31 +04:00
* }
*/
2012-08-05 14:39:37 +04:00
}
void
rb_gc_register_mark_object ( VALUE obj )
{
VALUE ary = GET_THREAD ( ) - > vm - > mark_object_ary ;
rb_ary_push ( ary , obj ) ;
}
void
rb_gc_register_address ( VALUE * addr )
{
rb_objspace_t * objspace = & rb_objspace ;
struct gc_list * tmp ;
tmp = ALLOC ( struct gc_list ) ;
tmp - > next = global_List ;
tmp - > varptr = addr ;
global_List = tmp ;
}
void
rb_gc_unregister_address ( VALUE * addr )
{
rb_objspace_t * objspace = & rb_objspace ;
struct gc_list * tmp = global_List ;
if ( tmp - > varptr = = addr ) {
global_List = tmp - > next ;
xfree ( tmp ) ;
return ;
}
while ( tmp - > next ) {
if ( tmp - > next - > varptr = = addr ) {
struct gc_list * t = tmp - > next ;
tmp - > next = tmp - > next - > next ;
xfree ( t ) ;
break ;
}
tmp = tmp - > next ;
}
}
2013-07-17 12:25:11 +04:00
void
rb_global_variable ( VALUE * var )
{
rb_gc_register_address ( var ) ;
}
2012-08-05 14:39:37 +04:00
# define GC_NOTIFY 0
2010-05-28 15:13:42 +04:00
static int
2013-05-22 03:09:22 +04:00
garbage_collect_body ( rb_objspace_t * objspace , int full_mark , int immediate_sweep , int reason )
2010-05-28 15:13:42 +04:00
{
2013-05-22 03:09:22 +04:00
if ( ruby_gc_stress & & ! ruby_disable_gc_stress ) {
2013-06-21 16:31:13 +04:00
int flag = FIXNUM_P ( ruby_gc_stress ) ? FIX2INT ( ruby_gc_stress ) : 0 ;
2013-06-19 01:35:40 +04:00
2013-06-21 16:31:13 +04:00
if ( flag & 0x01 )
reason & = ~ GPR_FLAG_MAJOR_MASK ;
else
reason | = GPR_FLAG_MAJOR_BY_STRESS ;
immediate_sweep = ! ( flag & 0x02 ) ;
2010-05-28 15:13:42 +04:00
}
2013-05-22 03:09:22 +04:00
else {
2013-12-18 19:27:41 +04:00
if ( ! GC_ENABLE_LAZY_SWEEP | | objspace - > flags . dont_lazy_sweep ) {
immediate_sweep = TRUE ;
}
# if USE_RGENGC
2013-10-11 16:00:35 +04:00
if ( full_mark ) {
2013-06-21 16:31:13 +04:00
reason | = GPR_FLAG_MAJOR_BY_NOFREE ;
2013-10-11 16:00:35 +04:00
}
2013-06-21 16:31:13 +04:00
if ( objspace - > rgengc . need_major_gc ) {
2013-11-24 23:49:02 +04:00
reason | = objspace - > rgengc . need_major_gc ;
2013-12-06 13:34:26 +04:00
objspace - > rgengc . need_major_gc = GPR_FLAG_NONE ;
2013-05-22 03:09:22 +04:00
}
2013-10-11 16:00:35 +04:00
if ( objspace - > rgengc . remembered_shady_object_count > objspace - > rgengc . remembered_shady_object_limit ) {
2013-06-21 16:31:13 +04:00
reason | = GPR_FLAG_MAJOR_BY_SHADY ;
2013-10-11 16:00:35 +04:00
}
2013-11-04 22:59:33 +04:00
if ( objspace - > rgengc . old_object_count > objspace - > rgengc . old_object_limit ) {
2013-06-21 16:31:13 +04:00
reason | = GPR_FLAG_MAJOR_BY_OLDGEN ;
2013-10-11 16:00:35 +04:00
}
2013-06-21 03:10:34 +04:00
# endif
2013-12-18 19:27:41 +04:00
}
2010-05-28 15:13:42 +04:00
2013-10-11 16:00:35 +04:00
if ( immediate_sweep ) reason | = GPR_FLAG_IMMEDIATE_SWEEP ;
full_mark = ( reason & GPR_FLAG_MAJOR_MASK ) ? TRUE : FALSE ;
2012-02-21 13:35:07 +04:00
2013-12-06 14:27:02 +04:00
if ( GC_NOTIFY ) fprintf ( stderr , " start garbage_collect(%d, %d, %d) \n " , full_mark , immediate_sweep , reason ) ;
2013-06-21 16:31:13 +04:00
2013-11-01 16:49:49 +04:00
objspace - > profile . count + + ;
2013-12-05 14:30:38 +04:00
objspace - > profile . latest_gc_info = reason ;
2013-12-13 07:02:03 +04:00
2013-06-22 02:29:09 +04:00
gc_event_hook ( objspace , RUBY_INTERNAL_EVENT_GC_START , 0 /* TODO: pass minor/immediate flag? */ ) ;
2013-11-01 16:49:49 +04:00
objspace - > profile . total_allocated_object_num_at_gc_start = objspace - > profile . total_allocated_object_num ;
2013-10-22 14:28:31 +04:00
objspace - > profile . heap_used_at_gc_start = heap_pages_used ;
2013-05-27 04:21:02 +04:00
2013-06-24 02:58:01 +04:00
gc_prof_setup_new_record ( objspace , reason ) ;
gc_prof_timer_start ( objspace ) ;
2013-05-21 11:52:03 +04:00
{
2013-12-13 07:02:03 +04:00
if ( during_gc = = 0 ) {
rb_bug ( " during_gc should not be 0. RUBY_INTERNAL_EVENT_GC_START user should not cause GC in events. " ) ;
}
2013-10-11 16:00:35 +04:00
gc_marks ( objspace , full_mark ) ;
2013-05-22 03:09:22 +04:00
gc_sweep ( objspace , immediate_sweep ) ;
during_gc = 0 ;
2013-05-21 11:52:03 +04:00
}
2013-05-21 12:21:59 +04:00
gc_prof_timer_stop ( objspace ) ;
2013-05-21 11:52:03 +04:00
2013-05-27 21:46:20 +04:00
if ( GC_NOTIFY ) fprintf ( stderr , " end garbage_collect() \n " ) ;
2009-07-18 12:05:32 +04:00
return TRUE ;
1998-01-16 15:13:05 +03:00
}
2013-07-17 12:25:11 +04:00
static int
2013-10-22 14:28:31 +04:00
heap_ready_to_gc ( rb_objspace_t * objspace , rb_heap_t * heap )
2013-07-17 12:25:11 +04:00
{
if ( dont_gc | | during_gc ) {
2013-10-22 14:28:31 +04:00
if ( ! heap - > freelist & & ! heap - > free_pages ) {
2013-10-23 14:16:01 +04:00
if ( ! heap_increment ( objspace , heap ) ) {
2013-11-22 11:40:27 +04:00
heap_set_increment ( objspace , 0 ) ;
2013-10-23 14:16:01 +04:00
heap_increment ( objspace , heap ) ;
2013-07-17 12:25:11 +04:00
}
}
return FALSE ;
}
return TRUE ;
}
2013-10-22 14:28:31 +04:00
static int
ready_to_gc ( rb_objspace_t * objspace )
{
return heap_ready_to_gc ( objspace , heap_eden ) ;
}
2013-05-22 03:09:22 +04:00
static int
garbage_collect ( rb_objspace_t * objspace , int full_mark , int immediate_sweep , int reason )
{
2013-10-22 14:28:31 +04:00
if ( ! heap_pages_used ) {
2013-05-22 03:09:22 +04:00
during_gc = 0 ;
return FALSE ;
}
if ( ! ready_to_gc ( objspace ) ) {
during_gc = 0 ;
return TRUE ;
}
2013-06-16 00:18:11 +04:00
# if GC_PROFILE_MORE_DETAIL
objspace - > profile . prepare_time = getrusage_time ( ) ;
# endif
2013-07-18 03:19:38 +04:00
gc_rest_sweep ( objspace ) ;
2013-06-16 00:18:11 +04:00
# if GC_PROFILE_MORE_DETAIL
objspace - > profile . prepare_time = getrusage_time ( ) - objspace - > profile . prepare_time ;
# endif
2013-05-22 03:09:22 +04:00
during_gc + + ;
return garbage_collect_body ( objspace , full_mark , immediate_sweep , reason ) ;
}
2013-05-21 12:19:07 +04:00
struct objspace_and_reason {
rb_objspace_t * objspace ;
int reason ;
2013-05-22 03:09:22 +04:00
int full_mark ;
int immediate_sweep ;
2013-05-21 12:19:07 +04:00
} ;
2012-08-05 14:39:37 +04:00
static void *
gc_with_gvl ( void * ptr )
{
2013-05-21 12:19:07 +04:00
struct objspace_and_reason * oar = ( struct objspace_and_reason * ) ptr ;
2013-05-22 03:09:22 +04:00
return ( void * ) ( VALUE ) garbage_collect ( oar - > objspace , oar - > full_mark , oar - > immediate_sweep , oar - > reason ) ;
2012-08-05 14:39:37 +04:00
}
static int
2013-05-22 03:09:22 +04:00
garbage_collect_with_gvl ( rb_objspace_t * objspace , int full_mark , int immediate_sweep , int reason )
2012-08-05 14:39:37 +04:00
{
if ( dont_gc ) return TRUE ;
if ( ruby_thread_has_gvl_p ( ) ) {
2013-05-22 03:09:22 +04:00
return garbage_collect ( objspace , full_mark , immediate_sweep , reason ) ;
2012-08-05 14:39:37 +04:00
}
else {
if ( ruby_native_thread_p ( ) ) {
2013-05-21 12:19:07 +04:00
struct objspace_and_reason oar ;
oar . objspace = objspace ;
oar . reason = reason ;
2013-05-22 03:09:22 +04:00
oar . full_mark = full_mark ;
oar . immediate_sweep = immediate_sweep ;
2013-05-21 12:19:07 +04:00
return ( int ) ( VALUE ) rb_thread_call_with_gvl ( gc_with_gvl , ( void * ) & oar ) ;
2012-08-05 14:39:37 +04:00
}
else {
/* no ruby thread */
fprintf ( stderr , " [FATAL] failed to allocate memory \n " ) ;
exit ( EXIT_FAILURE ) ;
}
}
}
2007-12-21 09:16:56 +03:00
int
rb_garbage_collect ( void )
{
2013-05-22 03:09:22 +04:00
return garbage_collect ( & rb_objspace , TRUE , TRUE , GPR_FLAG_CAPI ) ;
2007-12-21 09:16:56 +03:00
}
2012-08-05 14:39:37 +04:00
# undef Init_stack
2009-11-01 02:17:52 +03:00
2012-08-05 14:39:37 +04:00
void
Init_stack ( volatile VALUE * addr )
{
ruby_init_stack ( addr ) ;
2006-12-31 18:02:22 +03:00
}
2003-12-22 09:20:14 +03:00
/*
* call - seq :
2010-05-18 01:07:33 +04:00
* GC . start - > nil
2013-12-05 16:34:39 +04:00
* GC . garbage_collect - > nil
2010-05-18 01:07:33 +04:00
* ObjectSpace . garbage_collect - > nil
2013-12-06 09:11:51 +04:00
* GC . start ( full_mark : false ) - > nil
2003-12-22 09:20:14 +03:00
*
* Initiates garbage collection , unless manually disabled .
2005-06-19 21:16:14 +04:00
*
2013-12-06 09:11:51 +04:00
* This method is defined with keyword arguments that default to true :
*
* def GC . start ( full_mark : true , immediate_sweep : true ) end
*
* Use full_mark : false to perform a minor GC .
* Use immediate_sweep : false to defer sweeping ( use lazy sweep ) .
2013-12-06 09:32:11 +04:00
*
* Note : These keyword arguments are implementation and version dependent . They
* are not guaranteed to be future - compatible , and may be ignored if the
* underlying implementation does not support them .
2003-12-22 09:20:14 +03:00
*/
2013-12-06 09:11:51 +04:00
static VALUE
gc_start_internal ( int argc , VALUE * argv , VALUE self )
{
rb_objspace_t * objspace = & rb_objspace ;
int full_mark = TRUE , immediate_sweep = TRUE ;
VALUE opt = Qnil ;
static ID keyword_ids [ 2 ] ;
rb_scan_args ( argc , argv , " 0: " , & opt ) ;
2013-12-06 11:22:25 +04:00
if ( ! NIL_P ( opt ) ) {
2013-12-06 12:10:47 +04:00
VALUE kwvals [ 2 ] ;
2013-12-06 11:22:25 +04:00
if ( ! keyword_ids [ 0 ] ) {
keyword_ids [ 0 ] = rb_intern ( " full_mark " ) ;
keyword_ids [ 1 ] = rb_intern ( " immediate_sweep " ) ;
}
2013-12-06 09:11:51 +04:00
2013-12-06 12:10:47 +04:00
rb_get_kwargs ( opt , keyword_ids , 0 , 2 , kwvals ) ;
2013-12-06 09:11:51 +04:00
2013-12-06 12:10:47 +04:00
if ( kwvals [ 0 ] ! = Qundef )
full_mark = RTEST ( kwvals [ 0 ] ) ;
if ( kwvals [ 1 ] ! = Qundef )
immediate_sweep = RTEST ( kwvals [ 1 ] ) ;
2013-12-06 11:22:25 +04:00
}
2013-12-06 09:11:51 +04:00
garbage_collect ( objspace , full_mark , immediate_sweep , GPR_FLAG_METHOD ) ;
if ( ! finalizing ) finalize_deferred ( objspace ) ;
return Qnil ;
}
2001-01-29 08:10:42 +03:00
VALUE
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
rb_gc_start ( void )
1998-01-16 15:13:05 +03:00
{
1999-01-20 07:59:39 +03:00
rb_gc ( ) ;
1998-01-16 15:13:05 +03:00
return Qnil ;
}
void
2012-08-05 14:39:37 +04:00
rb_gc ( void )
1998-01-16 15:13:05 +03:00
{
2012-08-05 14:39:37 +04:00
rb_objspace_t * objspace = & rb_objspace ;
2013-12-06 10:26:02 +04:00
garbage_collect ( objspace , TRUE , TRUE , GPR_FLAG_CAPI ) ;
2012-08-05 14:39:37 +04:00
if ( ! finalizing ) finalize_deferred ( objspace ) ;
}
int
rb_during_gc ( void )
{
rb_objspace_t * objspace = & rb_objspace ;
return during_gc ;
1998-01-16 15:13:05 +03:00
}
2013-05-26 20:43:21 +04:00
# if RGENGC_PROFILE >= 2
static void
2013-05-26 21:27:42 +04:00
gc_count_add_each_types ( VALUE hash , const char * name , const size_t * types )
2013-05-26 20:43:21 +04:00
{
VALUE result = rb_hash_new ( ) ;
int i ;
for ( i = 0 ; i < T_MASK ; i + + ) {
const char * type = type_name ( i , 0 ) ;
rb_hash_aset ( result , ID2SYM ( rb_intern ( type ) ) , SIZET2NUM ( types [ i ] ) ) ;
}
rb_hash_aset ( hash , ID2SYM ( rb_intern ( name ) ) , result ) ;
}
# endif
2013-05-27 14:01:45 +04:00
size_t
rb_gc_count ( void )
{
2013-11-01 16:49:49 +04:00
return rb_objspace . profile . count ;
2013-05-27 14:01:45 +04:00
}
2003-12-22 09:20:14 +03:00
/*
2012-08-05 14:39:37 +04:00
* call - seq :
* GC . count - > Integer
2005-06-19 21:16:14 +04:00
*
2012-08-05 14:39:37 +04:00
* The number of times GC occurred .
2005-06-19 21:16:14 +04:00
*
2012-08-05 14:39:37 +04:00
* It returns the number of times GC occurred since the process started .
2005-06-19 21:16:14 +04:00
*
2003-12-22 09:20:14 +03:00
*/
2010-10-21 08:18:09 +04:00
static VALUE
2012-08-05 14:39:37 +04:00
gc_count ( VALUE self )
2010-10-21 08:18:09 +04:00
{
2013-05-27 14:01:45 +04:00
return SIZET2NUM ( rb_gc_count ( ) ) ;
2010-10-21 08:18:09 +04:00
}
2013-12-05 14:30:38 +04:00
static VALUE
gc_info_decode ( int flags , VALUE hash_or_key )
{
static VALUE sym_major_by = Qnil , sym_gc_by , sym_immediate_sweep , sym_have_finalizer ;
2013-12-16 06:50:45 +04:00
static VALUE sym_nofree , sym_oldgen , sym_shady , sym_rescan , sym_stress ;
# if RGENGC_ESTIMATE_OLDMALLOC
static VALUE sym_oldmalloc ;
# endif
2013-12-05 14:30:38 +04:00
static VALUE sym_newobj , sym_malloc , sym_method , sym_capi ;
VALUE hash = Qnil , key = Qnil ;
2013-12-05 16:06:59 +04:00
VALUE major_by ;
2013-12-05 14:30:38 +04:00
if ( SYMBOL_P ( hash_or_key ) )
key = hash_or_key ;
else if ( RB_TYPE_P ( hash_or_key , T_HASH ) )
hash = hash_or_key ;
else
rb_raise ( rb_eTypeError , " non-hash or symbol given " ) ;
if ( sym_major_by = = Qnil ) {
# define S(s) sym_##s = ID2SYM(rb_intern_const(#s))
S ( major_by ) ;
S ( gc_by ) ;
S ( immediate_sweep ) ;
S ( have_finalizer ) ;
S ( nofree ) ;
S ( oldgen ) ;
S ( shady ) ;
S ( rescan ) ;
S ( stress ) ;
2013-12-16 06:50:45 +04:00
# if RGENGC_ESTIMATE_OLDMALLOC
2013-12-05 14:30:38 +04:00
S ( oldmalloc ) ;
2013-12-16 06:50:45 +04:00
# endif
2013-12-05 14:30:38 +04:00
S ( newobj ) ;
S ( malloc ) ;
S ( method ) ;
S ( capi ) ;
# undef S
}
# define SET(name, attr) \
if ( key = = sym_ # # name ) \
return ( attr ) ; \
else if ( hash ! = Qnil ) \
rb_hash_aset ( hash , sym_ # # name , ( attr ) ) ;
2013-12-05 16:49:07 +04:00
major_by =
2013-12-05 16:06:59 +04:00
( flags & GPR_FLAG_MAJOR_BY_OLDGEN ) ? sym_oldgen :
( flags & GPR_FLAG_MAJOR_BY_SHADY ) ? sym_shady :
( flags & GPR_FLAG_MAJOR_BY_RESCAN ) ? sym_rescan :
( flags & GPR_FLAG_MAJOR_BY_STRESS ) ? sym_stress :
2013-12-05 14:30:38 +04:00
# if RGENGC_ESTIMATE_OLDMALLOC
2013-12-05 16:06:59 +04:00
( flags & GPR_FLAG_MAJOR_BY_OLDMALLOC ) ? sym_oldmalloc :
2013-12-05 14:30:38 +04:00
# endif
2013-12-13 11:30:33 +04:00
( flags & GPR_FLAG_MAJOR_BY_NOFREE ) ? sym_nofree :
2013-12-05 16:06:59 +04:00
Qnil ;
SET ( major_by , major_by ) ;
2013-12-05 14:30:38 +04:00
SET ( gc_by ,
( flags & GPR_FLAG_NEWOBJ ) ? sym_newobj :
( flags & GPR_FLAG_MALLOC ) ? sym_malloc :
( flags & GPR_FLAG_METHOD ) ? sym_method :
( flags & GPR_FLAG_CAPI ) ? sym_capi :
( flags & GPR_FLAG_STRESS ) ? sym_stress :
Qnil
) ;
SET ( have_finalizer , ( flags & GPR_FLAG_HAVE_FINALIZE ) ? Qtrue : Qfalse ) ;
SET ( immediate_sweep , ( flags & GPR_FLAG_IMMEDIATE_SWEEP ) ? Qtrue : Qfalse ) ;
# undef SET
if ( key ! = Qnil ) /* matched key should return above */
rb_raise ( rb_eArgError , " unknown key: %s " , RSTRING_PTR ( rb_id2str ( SYM2ID ( key ) ) ) ) ;
return hash ;
}
VALUE
rb_gc_latest_gc_info ( VALUE key )
{
rb_objspace_t * objspace = & rb_objspace ;
return gc_info_decode ( objspace - > profile . latest_gc_info , key ) ;
}
/*
* call - seq :
* GC . latest_gc_info - > { : gc_by = > : newobj }
* GC . latest_gc_info ( hash ) - > hash
* GC . latest_gc_info ( : major_by ) - > : malloc
*
* Returns information about the most recent garbage collection .
*/
static VALUE
gc_latest_gc_info ( int argc , VALUE * argv , VALUE self )
{
rb_objspace_t * objspace = & rb_objspace ;
VALUE arg = Qnil ;
if ( rb_scan_args ( argc , argv , " 01 " , & arg ) = = 1 ) {
if ( ! SYMBOL_P ( arg ) & & ! RB_TYPE_P ( arg , T_HASH ) ) {
rb_raise ( rb_eTypeError , " non-hash or symbol given " ) ;
}
}
if ( arg = = Qnil )
arg = rb_hash_new ( ) ;
return gc_info_decode ( objspace - > profile . latest_gc_info , arg ) ;
}
2012-08-05 14:39:37 +04:00
static VALUE
2013-12-05 11:45:13 +04:00
gc_stat_internal ( VALUE hash_or_sym , size_t * out )
1998-01-16 15:13:05 +03:00
{
2012-11-29 09:29:22 +04:00
static VALUE sym_count ;
static VALUE sym_heap_used , sym_heap_length , sym_heap_increment ;
2013-11-24 23:08:33 +04:00
static VALUE sym_heap_live_slot , sym_heap_free_slot , sym_heap_final_slot , sym_heap_swept_slot ;
2013-11-27 10:09:55 +04:00
static VALUE sym_heap_eden_page_length , sym_heap_tomb_page_length ;
2012-11-29 09:29:22 +04:00
static VALUE sym_total_allocated_object , sym_total_freed_object ;
2013-11-24 23:08:33 +04:00
static VALUE sym_malloc_increase , sym_malloc_limit ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
# if USE_RGENGC
static VALUE sym_minor_gc_count , sym_major_gc_count ;
2013-11-24 23:08:33 +04:00
static VALUE sym_remembered_shady_object , sym_remembered_shady_object_limit ;
static VALUE sym_old_object , sym_old_object_limit ;
2013-11-24 23:49:02 +04:00
# if RGENGC_ESTIMATE_OLDMALLOC
2013-11-24 23:08:33 +04:00
static VALUE sym_oldmalloc_increase , sym_oldmalloc_limit ;
# endif
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
# if RGENGC_PROFILE
2013-06-07 05:17:19 +04:00
static VALUE sym_generated_normal_object_count , sym_generated_shady_object_count ;
2013-11-04 22:59:33 +04:00
static VALUE sym_shade_operation_count , sym_promote_infant_count , sym_promote_young_count ;
2013-06-07 05:17:19 +04:00
static VALUE sym_remembered_normal_object_count , sym_remembered_shady_object_count ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
# endif /* RGENGC_PROFILE */
# endif /* USE_RGENGC */
2013-12-05 11:45:13 +04:00
rb_objspace_t * objspace = & rb_objspace ;
VALUE hash = Qnil , key = Qnil ;
if ( RB_TYPE_P ( hash_or_sym , T_HASH ) )
hash = hash_or_sym ;
else if ( SYMBOL_P ( hash_or_sym ) & & out )
key = hash_or_sym ;
else
2013-12-05 14:30:38 +04:00
rb_raise ( rb_eTypeError , " non-hash or symbol argument " ) ;
2013-12-05 11:45:13 +04:00
2012-11-29 09:29:22 +04:00
if ( sym_count = = 0 ) {
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
# define S(s) sym_##s = ID2SYM(rb_intern_const(#s))
S ( count ) ;
S ( heap_used ) ;
S ( heap_length ) ;
S ( heap_increment ) ;
2013-11-24 23:08:33 +04:00
S ( heap_live_slot ) ;
S ( heap_free_slot ) ;
S ( heap_final_slot ) ;
S ( heap_swept_slot ) ;
2013-11-27 10:09:55 +04:00
S ( heap_eden_page_length ) ;
S ( heap_tomb_page_length ) ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
S ( total_allocated_object ) ;
S ( total_freed_object ) ;
2013-11-24 23:08:33 +04:00
S ( malloc_increase ) ;
S ( malloc_limit ) ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
# if USE_RGENGC
S ( minor_gc_count ) ;
S ( major_gc_count ) ;
2013-11-24 23:08:33 +04:00
S ( remembered_shady_object ) ;
S ( remembered_shady_object_limit ) ;
S ( old_object ) ;
S ( old_object_limit ) ;
2013-11-24 23:49:02 +04:00
# if RGENGC_ESTIMATE_OLDMALLOC
2013-11-24 23:08:33 +04:00
S ( oldmalloc_increase ) ;
S ( oldmalloc_limit ) ;
# endif
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
# if RGENGC_PROFILE
2013-06-07 05:17:19 +04:00
S ( generated_normal_object_count ) ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
S ( generated_shady_object_count ) ;
S ( shade_operation_count ) ;
2013-11-04 22:59:33 +04:00
S ( promote_infant_count ) ;
S ( promote_young_count ) ;
2013-06-07 05:17:19 +04:00
S ( remembered_normal_object_count ) ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
S ( remembered_shady_object_count ) ;
# endif /* USE_RGENGC */
# endif /* RGENGC_PROFILE */
# undef S
2012-11-29 09:29:22 +04:00
}
2008-06-05 17:52:02 +04:00
2013-12-05 11:45:13 +04:00
# define SET(name, attr) \
if ( key = = sym_ # # name ) \
return ( * out = attr , Qnil ) ; \
else if ( hash ! = Qnil ) \
rb_hash_aset ( hash , sym_ # # name , SIZET2NUM ( attr ) ) ;
2009-06-17 01:07:26 +04:00
2013-11-24 23:08:33 +04:00
SET ( count , objspace - > profile . count ) ;
2013-10-22 14:28:31 +04:00
2013-11-24 23:08:33 +04:00
/* implementation dependent counters */
SET ( heap_used , heap_pages_used ) ;
SET ( heap_length , heap_pages_length ) ;
SET ( heap_increment , heap_pages_increment ) ;
2013-11-24 23:18:53 +04:00
SET ( heap_live_slot , objspace_live_slot ( objspace ) ) ;
SET ( heap_free_slot , objspace_free_slot ( objspace ) ) ;
SET ( heap_final_slot , heap_pages_final_slots ) ;
2013-11-24 23:08:33 +04:00
SET ( heap_swept_slot , heap_pages_swept_slots ) ;
2013-11-27 10:09:55 +04:00
SET ( heap_eden_page_length , heap_eden - > page_length ) ;
SET ( heap_tomb_page_length , heap_tomb - > page_length ) ;
2013-11-24 23:08:33 +04:00
SET ( total_allocated_object , objspace - > profile . total_allocated_object_num ) ;
SET ( total_freed_object , objspace - > profile . total_freed_object_num ) ;
SET ( malloc_increase , malloc_increase ) ;
SET ( malloc_limit , malloc_limit ) ;
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
# if USE_RGENGC
2013-11-24 23:08:33 +04:00
SET ( minor_gc_count , objspace - > profile . minor_gc_count ) ;
SET ( major_gc_count , objspace - > profile . major_gc_count ) ;
SET ( remembered_shady_object , objspace - > rgengc . remembered_shady_object_count ) ;
SET ( remembered_shady_object_limit , objspace - > rgengc . remembered_shady_object_limit ) ;
SET ( old_object , objspace - > rgengc . old_object_count ) ;
SET ( old_object_limit , objspace - > rgengc . old_object_limit ) ;
2013-11-24 23:49:02 +04:00
# if RGENGC_ESTIMATE_OLDMALLOC
SET ( oldmalloc_increase , objspace - > rgengc . oldmalloc_increase ) ;
SET ( oldmalloc_limit , objspace - > rgengc . oldmalloc_increase_limit ) ;
2013-11-24 23:08:33 +04:00
# endif
* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC.
* gc.c: Add several flags:
* RGENGC_DEBUG: if >0, then prints debug information.
* RGENGC_CHECK_MODE: if >0, add assertions.
* RGENGC_PROFILE: if >0, add profiling features.
check GC.stat and GC::Profiler.
* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
* array.c: add write barriers for T_ARRAY and generate sunny objects.
* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
you want to access raw pointers. If you modify the contents which
pointer pointed, then you need to care write barrier.
* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
and generate sunny objects.
* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
barriers for T_RATIONAL and generate sunny objects.
* internal.h: add write barriers for RBasic::klass.
* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
* object.c (rb_class_allocate_instance), range.c:
generate sunny T_OBJECT objects.
* string.c: add write barriers for T_STRING and generate sunny objects.
* variable.c: add write barriers for ivars.
* vm_insnhelper.c (vm_setivar): ditto.
* include/ruby/ruby.h, debug.c: use two flags
FL_WB_PROTECTED and FL_OLDGEN.
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
move flag bits.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 22:07:47 +04:00
# if RGENGC_PROFILE
2013-11-24 23:08:33 +04:00
SET ( generated_normal_object_count , objspace - > profile . generated_normal_object_count ) ;
SET ( generated_shady_object_count , objspace - > profile . generated_shady_object_count ) ;
SET ( shade_operation_count , objspace - > profile . shade_operation_count ) ;
SET ( promote_infant_count , objspace - > profile . promote_infant_count ) ;
2013-11-04 22:59:33 +04:00
# if RGENGC_THREEGEN
2013-11-24 23:08:33 +04:00
SET ( promote_young_count , objspace - > profile . promote_young_count ) ;
2013-11-04 22:59:33 +04:00
# endif
2013-11-24 23:08:33 +04:00
SET ( remembered_normal_object_count , objspace - > profile . remembered_normal_object_count ) ;
SET ( remembered_shady_object_count , objspace - > profile . remembered_shady_object_count ) ;
2013-12-05 11:45:13 +04:00
# endif /* RGENGC_PROFILE */
# endif /* USE_RGENGC */
# undef SET
if ( key ! = Qnil ) /* matched key should return above */
rb_raise ( rb_eArgError , " unknown key: %s " , RSTRING_PTR ( rb_id2str ( SYM2ID ( key ) ) ) ) ;
# if defined(RGENGC_PROFILE) && RGENGC_PROFILE >= 2
if ( hash ! = Qnil ) {
2013-06-18 06:27:37 +04:00
gc_count_add_each_types ( hash , " generated_normal_object_count_types " , objspace - > profile . generated_normal_object_count_types ) ;
2013-05-26 20:43:21 +04:00
gc_count_add_each_types ( hash , " generated_shady_object_count_types " , objspace - > profile . generated_shady_object_count_types ) ;
gc_count_add_each_types ( hash , " shade_operation_count_types " , objspace - > profile . shade_operation_count_types ) ;
2013-11-04 22:59:33 +04:00
gc_count_add_each_types ( hash , " promote_infant_types " , objspace - > profile . promote_infant_types ) ;
# if RGENGC_THREEGEN
gc_count_add_each_types ( hash , " promote_young_types " , objspace - > profile . promote_young_types ) ;
# endif
2013-06-07 05:17:19 +04:00
gc_count_add_each_types ( hash , " remembered_normal_object_count_types " , objspace - > profile . remembered_normal_object_count_types ) ;
2013-05-26 20:43:21 +04:00
gc_count_add_each_types ( hash , " remembered_shady_object_count_types " , objspace - > profile . remembered_shady_object_count_types ) ;
2013-05-15 12:07:30 +04:00
}
# endif
2013-12-05 11:45:13 +04:00
2012-08-05 14:39:37 +04:00
return hash ;
1998-01-16 15:13:05 +03:00
}
2013-12-05 11:45:13 +04:00
/*
* call - seq :
* GC . stat - > Hash
* GC . stat ( hash ) - > hash
* GC . stat ( : key ) - > Numeric
*
* Returns a Hash containing information about the GC .
*
* The hash includes information about internal statistics about GC such as :
*
* {
* : count = > 2 ,
* : heap_used = > 9 ,
* : heap_length = > 11 ,
* : heap_increment = > 2 ,
* : heap_live_slot = > 6836 ,
* : heap_free_slot = > 519 ,
* : heap_final_slot = > 0 ,
* : heap_swept_slot = > 818 ,
* : total_allocated_object = > 7674 ,
* : total_freed_object = > 838 ,
* : malloc_increase = > 181034 ,
* : malloc_limit = > 16777216 ,
* : minor_gc_count = > 2 ,
* : major_gc_count = > 0 ,
* : remembered_shady_object = > 55 ,
* : remembered_shady_object_limit = > 0 ,
* : old_object = > 2422 ,
* : old_object_limit = > 0 ,
* : oldmalloc_increase = > 277386 ,
* : oldmalloc_limit = > 16777216
* }
*
* The contents of the hash are implementation specific and may be changed in
* the future .
*
* This method is only expected to work on C Ruby .
*
*/
static VALUE
gc_stat ( int argc , VALUE * argv , VALUE self )
{
VALUE arg = Qnil ;
if ( rb_scan_args ( argc , argv , " 01 " , & arg ) = = 1 ) {
if ( SYMBOL_P ( arg ) ) {
size_t value = 0 ;
gc_stat_internal ( arg , & value ) ;
return SIZET2NUM ( value ) ;
} else if ( ! RB_TYPE_P ( arg , T_HASH ) ) {
2013-12-05 14:30:38 +04:00
rb_raise ( rb_eTypeError , " non-hash or symbol given " ) ;
2013-12-05 11:45:13 +04:00
}
}
if ( arg = = Qnil ) {
arg = rb_hash_new ( ) ;
}
gc_stat_internal ( arg , 0 ) ;
return arg ;
}
size_t
rb_gc_stat ( VALUE key )
{
if ( SYMBOL_P ( key ) ) {
size_t value = 0 ;
gc_stat_internal ( key , & value ) ;
return value ;
} else {
gc_stat_internal ( key , 0 ) ;
return 0 ;
}
}
2003-12-22 09:20:14 +03:00
/*
* call - seq :
2013-06-19 15:53:07 +04:00
* GC . stress - > fixnum , true or false
2005-06-19 21:16:14 +04:00
*
2012-11-29 12:15:53 +04:00
* Returns current status of GC stress mode .
2003-12-22 09:20:14 +03:00
*/
1998-01-16 15:13:05 +03:00
static VALUE
2012-08-05 14:39:37 +04:00
gc_stress_get ( VALUE self )
1998-01-16 15:13:05 +03:00
{
2012-08-05 14:39:37 +04:00
rb_objspace_t * objspace = & rb_objspace ;
2013-06-19 15:53:07 +04:00
return ruby_gc_stress ;
1998-01-16 15:13:05 +03:00
}
2003-12-22 09:20:14 +03:00
/*
* call - seq :
2012-08-05 14:39:37 +04:00
* GC . stress = bool - > bool
2005-06-19 21:16:14 +04:00
*
2012-08-05 14:39:37 +04:00
* Updates the GC stress mode .
2005-06-19 21:16:14 +04:00
*
2012-11-29 12:15:53 +04:00
* When stress mode is enabled , the GC is invoked at every GC opportunity :
2012-08-05 14:39:37 +04:00
* all memory and object allocations .
*
2012-11-29 12:15:53 +04:00
* Enabling stress mode will degrade performance , it is only for debugging .
2003-12-22 09:20:14 +03:00
*/
2000-07-15 17:37:03 +04:00
static VALUE
2012-08-05 14:39:37 +04:00
gc_stress_set ( VALUE self , VALUE flag )
2012-03-13 07:37:06 +04:00
{
2012-08-05 14:39:37 +04:00
rb_objspace_t * objspace = & rb_objspace ;
rb_secure ( 2 ) ;
2013-06-19 01:35:40 +04:00
ruby_gc_stress = FIXNUM_P ( flag ) ? flag : ( RTEST ( flag ) ? Qtrue : Qfalse ) ;
2012-08-05 14:39:37 +04:00
return flag ;
2012-03-13 07:37:06 +04:00
}
2012-08-05 14:39:37 +04:00
/*
* call - seq :
* GC . enable - > true or false
*
2012-11-29 12:15:53 +04:00
* Enables garbage collection , returning + true + if garbage
2012-08-05 14:39:37 +04:00
* collection was previously disabled .
*
* GC . disable # = > false
* GC . enable # = > true
* GC . enable # = > false
*
*/
2012-03-13 07:37:06 +04:00
VALUE
2012-08-05 14:39:37 +04:00
rb_gc_enable ( void )
2000-07-15 17:37:03 +04:00
{
2008-04-27 07:20:35 +04:00
rb_objspace_t * objspace = & rb_objspace ;
2012-08-05 14:39:37 +04:00
int old = dont_gc ;
dont_gc = FALSE ;
return old ? Qtrue : Qfalse ;
2000-07-15 17:37:03 +04:00
}
2003-12-22 09:20:14 +03:00
/*
* call - seq :
2012-08-05 14:39:37 +04:00
* GC . disable - > true or false
2005-06-19 21:16:14 +04:00
*
2012-11-29 12:15:53 +04:00
* Disables garbage collection , returning + true + if garbage
2012-08-05 14:39:37 +04:00
* collection was already disabled .
*
* GC . disable # = > false
* GC . disable # = > true
2005-06-19 21:16:14 +04:00
*
2003-12-22 09:20:14 +03:00
*/
2012-08-05 14:39:37 +04:00
VALUE
rb_gc_disable ( void )
2000-07-15 17:37:03 +04:00
{
2012-08-05 14:39:37 +04:00
rb_objspace_t * objspace = & rb_objspace ;
int old = dont_gc ;
2000-07-15 17:37:03 +04:00
2013-09-30 06:20:28 +04:00
gc_rest_sweep ( objspace ) ;
2012-08-05 14:39:37 +04:00
dont_gc = TRUE ;
return old ? Qtrue : Qfalse ;
2012-03-13 07:37:06 +04:00
}
2013-09-27 13:36:48 +04:00
static int
2014-02-07 05:54:26 +04:00
get_envparam_size ( const char * name , size_t * default_value , size_t lower_bound )
2012-03-13 07:37:06 +04:00
{
2013-09-27 13:36:48 +04:00
char * ptr = getenv ( name ) ;
2014-02-07 05:54:26 +04:00
ssize_t val ;
2000-07-15 17:37:03 +04:00
2014-02-07 06:02:58 +04:00
if ( ptr ! = NULL & & * ptr ) {
2014-02-14 09:04:07 +04:00
size_t unit = 0 ;
2014-02-06 15:49:14 +04:00
char * end ;
2014-02-07 05:54:26 +04:00
# if SIZEOF_SIZE_T == SIZEOF_LONG_LONG
val = strtoll ( ptr , & end , 0 ) ;
# else
val = strtol ( ptr , & end , 0 ) ;
# endif
2014-02-14 09:04:07 +04:00
switch ( * end ) {
case ' k ' : case ' K ' :
unit = 1024 ;
+ + end ;
break ;
case ' m ' : case ' M ' :
unit = 1024 * 1024 ;
+ + end ;
break ;
case ' g ' : case ' G ' :
unit = 1024 * 1024 * 1024 ;
+ + end ;
break ;
}
while ( * end & & isspace ( * end ) ) end + + ;
if ( * end ) {
2014-02-06 15:49:14 +04:00
if ( RTEST ( ruby_verbose ) ) fprintf ( stderr , " invalid string for %s: %s \n " , name , ptr ) ;
return 0 ;
}
2014-02-14 09:04:07 +04:00
if ( unit > 0 ) {
if ( val < - ( ssize_t ) ( SIZE_MAX / 2 / unit ) | | ( ssize_t ) ( SIZE_MAX / 2 / unit ) < val ) {
if ( RTEST ( ruby_verbose ) ) fprintf ( stderr , " %s=%s is ignored because it overflows \n " , name , ptr ) ;
return 0 ;
}
val * = unit ;
}
2014-02-07 05:54:26 +04:00
if ( val > 0 & & ( size_t ) val > lower_bound ) {
if ( RTEST ( ruby_verbose ) ) {
fprintf ( stderr , " %s=% " PRIdSIZE " (default value: % " PRIdSIZE " ) \n " , name , val , * default_value ) ;
}
* default_value = ( size_t ) val ;
2014-02-07 05:59:16 +04:00
return 1 ;
2013-09-27 13:36:48 +04:00
}
else {
2014-02-07 05:54:26 +04:00
if ( RTEST ( ruby_verbose ) ) {
fprintf ( stderr , " %s=% " PRIdSIZE " (default value: % " PRIdSIZE " ) is ignored because it must be greater than % " PRIdSIZE " . \n " ,
name , val , * default_value , lower_bound ) ;
}
return 0 ;
2012-08-05 14:39:37 +04:00
}
2000-07-15 17:37:03 +04:00
}
2013-09-27 13:36:48 +04:00
return 0 ;
}
2012-08-05 14:39:37 +04:00
2013-09-27 13:36:48 +04:00
static int
get_envparam_double ( const char * name , double * default_value , double lower_bound )
{
char * ptr = getenv ( name ) ;
double val ;
2013-07-17 12:25:11 +04:00
2014-02-07 06:02:58 +04:00
if ( ptr ! = NULL & & * ptr ) {
2014-02-06 15:49:14 +04:00
char * end ;
val = strtod ( ptr , & end ) ;
if ( ! * ptr | | * end ) {
if ( RTEST ( ruby_verbose ) ) fprintf ( stderr , " invalid string for %s: %s \n " , name , ptr ) ;
return 0 ;
}
2014-02-06 10:26:01 +04:00
if ( val > lower_bound ) {
2013-09-27 13:36:48 +04:00
if ( RTEST ( ruby_verbose ) ) fprintf ( stderr , " %s=%f (%f) \n " , name , val , * default_value ) ;
* default_value = val ;
return 1 ;
2012-08-05 14:39:37 +04:00
}
2013-09-27 13:36:48 +04:00
else {
2014-02-06 10:28:40 +04:00
if ( RTEST ( ruby_verbose ) ) fprintf ( stderr , " %s=%f (default value: %f) is ignored because it must be greater than %f. \n " , name , val , * default_value , lower_bound ) ;
2013-03-13 18:52:00 +04:00
}
}
2013-09-27 13:36:48 +04:00
return 0 ;
}
2013-03-13 18:52:00 +04:00
2013-11-23 07:33:10 +04:00
static void
gc_set_initial_pages ( void )
{
size_t min_pages ;
rb_objspace_t * objspace = & rb_objspace ;
min_pages = gc_params . heap_init_slots / HEAP_OBJ_LIMIT ;
2013-11-27 05:42:25 +04:00
if ( min_pages > heap_eden - > page_length ) {
heap_add_pages ( objspace , heap_eden , min_pages - heap_eden - > page_length ) ;
2013-11-23 07:33:10 +04:00
}
}
/*
* GC tuning environment variables
*
* * RUBY_GC_HEAP_INIT_SLOTS
* - Initial allocation slots .
* * RUBY_GC_HEAP_FREE_SLOTS
2014-01-19 09:43:28 +04:00
* - Prepare at least this amount of slots after GC .
2013-11-23 07:33:10 +04:00
* - Allocate slots if there are not enough slots .
* * RUBY_GC_HEAP_GROWTH_FACTOR ( new from 2.1 )
* - Allocate slots by this factor .
* - ( next slots number ) = ( current slots number ) * ( this factor )
* * RUBY_GC_HEAP_GROWTH_MAX_SLOTS ( new from 2.1 )
* - Allocation rate is limited to this factor .
2014-02-17 07:27:13 +04:00
* * RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR ( new from 2.1 .1 )
* - Do full GC when the number of old objects is more than R * N
* where R is this factor and
* N is the number of old objects just after last full GC .
2013-11-23 07:33:10 +04:00
*
* * obsolete
* * RUBY_FREE_MIN - > RUBY_GC_HEAP_FREE_SLOTS ( from 2.1 )
* * RUBY_HEAP_MIN_SLOTS - > RUBY_GC_HEAP_INIT_SLOTS ( from 2.1 )
*
* * RUBY_GC_MALLOC_LIMIT
* * RUBY_GC_MALLOC_LIMIT_MAX ( new from 2.1 )
* * RUBY_GC_MALLOC_LIMIT_GROWTH_FACTOR ( new from 2.1 )
*
2013-11-24 22:13:48 +04:00
* * RUBY_GC_OLDMALLOC_LIMIT ( new from 2.1 )
* * RUBY_GC_OLDMALLOC_LIMIT_MAX ( new from 2.1 )
* * RUBY_GC_OLDMALLOC_LIMIT_GROWTH_FACTOR ( new from 2.1 )
2013-11-23 07:33:10 +04:00
*/
2013-09-27 13:36:48 +04:00
void
2013-12-05 04:19:13 +04:00
ruby_gc_set_params ( int safe_level )
2013-09-27 13:36:48 +04:00
{
2013-12-05 04:19:13 +04:00
if ( safe_level > 0 ) return ;
2013-09-27 13:36:48 +04:00
2013-11-23 07:33:10 +04:00
/* RUBY_GC_HEAP_FREE_SLOTS */
2014-02-07 05:54:26 +04:00
if ( get_envparam_size ( " RUBY_GC_HEAP_FREE_SLOTS " , & gc_params . heap_free_slots , 0 ) ) {
2013-12-21 23:11:12 +04:00
/* ok */
}
2014-02-07 05:54:26 +04:00
else if ( get_envparam_size ( " RUBY_FREE_MIN " , & gc_params . heap_free_slots , 0 ) ) {
2013-11-23 07:33:10 +04:00
rb_warn ( " RUBY_FREE_MIN is obsolete. Use RUBY_GC_HEAP_FREE_SLOTS instead. " ) ;
}
2013-09-27 13:36:48 +04:00
2013-11-23 07:33:10 +04:00
/* RUBY_GC_HEAP_INIT_SLOTS */
2014-02-07 05:54:26 +04:00
if ( get_envparam_size ( " RUBY_GC_HEAP_INIT_SLOTS " , & gc_params . heap_init_slots , 0 ) ) {
2013-11-23 07:33:10 +04:00
gc_set_initial_pages ( ) ;
2012-03-13 07:37:06 +04:00
}
2014-02-07 05:54:26 +04:00
else if ( get_envparam_size ( " RUBY_HEAP_MIN_SLOTS " , & gc_params . heap_init_slots , 0 ) ) {
2013-12-21 23:11:12 +04:00
rb_warn ( " RUBY_HEAP_MIN_SLOTS is obsolete. Use RUBY_GC_HEAP_INIT_SLOTS instead. " ) ;
2013-11-23 07:33:10 +04:00
gc_set_initial_pages ( ) ;
}
get_envparam_double ( " RUBY_GC_HEAP_GROWTH_FACTOR " , & gc_params . growth_factor , 1.0 ) ;
2014-02-07 05:54:26 +04:00
get_envparam_size ( " RUBY_GC_HEAP_GROWTH_MAX_SLOTS " , & gc_params . growth_max_slots , 0 ) ;
2014-02-17 07:27:13 +04:00
get_envparam_double ( " RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR " , & gc_params . oldobject_limit_factor , 0.0 ) ;
2013-09-27 13:36:48 +04:00
2014-02-07 05:54:26 +04:00
get_envparam_size ( " RUBY_GC_MALLOC_LIMIT " , & gc_params . malloc_limit_min , 0 ) ;
get_envparam_size ( " RUBY_GC_MALLOC_LIMIT_MAX " , & gc_params . malloc_limit_max , 0 ) ;
2013-11-21 12:50:40 +04:00
get_envparam_double ( " RUBY_GC_MALLOC_LIMIT_GROWTH_FACTOR " , & gc_params . malloc_limit_growth_factor , 1.0 ) ;
2013-11-05 08:51:01 +04:00
2013-11-24 23:49:02 +04:00
# ifdef RGENGC_ESTIMATE_OLDMALLOC
2014-02-07 05:54:26 +04:00
if ( get_envparam_size ( " RUBY_GC_OLDMALLOC_LIMIT " , & gc_params . oldmalloc_limit_min , 0 ) ) {
2014-02-06 04:04:14 +04:00
rb_objspace_t * objspace = & rb_objspace ;
objspace - > rgengc . oldmalloc_increase_limit = gc_params . oldmalloc_limit_min ;
}
2014-02-07 05:54:26 +04:00
get_envparam_size ( " RUBY_GC_OLDMALLOC_LIMIT_MAX " , & gc_params . oldmalloc_limit_max , 0 ) ;
2013-11-24 22:13:48 +04:00
get_envparam_double ( " RUBY_GC_OLDMALLOC_LIMIT_GROWTH_FACTOR " , & gc_params . oldmalloc_limit_growth_factor , 1.0 ) ;
# endif
2012-03-13 07:37:06 +04:00
}
2012-10-24 04:04:56 +04:00
void
rb_objspace_reachable_objects_from ( VALUE obj , void ( func ) ( VALUE , void * ) , void * data )
2012-10-05 12:14:09 +04:00
{
rb_objspace_t * objspace = & rb_objspace ;
2013-07-18 03:19:38 +04:00
if ( is_markable_object ( objspace , obj ) ) {
2012-10-05 12:14:09 +04:00
struct mark_func_data_struct mfd ;
2012-10-24 04:04:56 +04:00
mfd . mark_func = func ;
mfd . data = data ;
2012-10-05 12:14:09 +04:00
objspace - > mark_func_data = & mfd ;
gc_mark_children ( objspace , obj ) ;
objspace - > mark_func_data = 0 ;
}
}
2013-10-15 14:22:33 +04:00
struct root_objects_data {
const char * category ;
void ( * func ) ( const char * category , VALUE , void * ) ;
void * data ;
} ;
static void
root_objects_from ( VALUE obj , void * ptr )
{
const struct root_objects_data * data = ( struct root_objects_data * ) ptr ;
( * data - > func ) ( data - > category , obj , data - > data ) ;
}
void
rb_objspace_reachable_objects_from_root ( void ( func ) ( const char * category , VALUE , void * ) , void * passing_data )
{
rb_objspace_t * objspace = & rb_objspace ;
struct root_objects_data data ;
struct mark_func_data_struct mfd ;
data . func = func ;
data . data = passing_data ;
2013-10-15 17:12:03 +04:00
2013-10-15 14:22:33 +04:00
mfd . mark_func = root_objects_from ;
mfd . data = & data ;
objspace - > mark_func_data = & mfd ;
{
2013-11-19 13:50:14 +04:00
gc_mark_roots ( objspace , TRUE , & data . category ) ;
2013-10-15 14:22:33 +04:00
}
objspace - > mark_func_data = 0 ;
}
2012-08-05 14:39:37 +04:00
/*
- - - - - - - - - - - - - - - - - - - - - - - - Extended allocator - - - - - - - - - - - - - - - - - - - - - - - -
*/
2002-12-04 10:39:32 +03:00
2013-12-05 12:52:30 +04:00
static void objspace_xfree ( rb_objspace_t * objspace , void * ptr , size_t size ) ;
2002-12-04 10:39:32 +03:00
2012-08-05 14:39:37 +04:00
static void *
negative_size_allocation_error_with_gvl ( void * ptr )
1999-08-13 09:45:20 +04:00
{
2012-08-05 14:39:37 +04:00
rb_raise ( rb_eNoMemError , " %s " , ( const char * ) ptr ) ;
return 0 ; /* should not be reached */
1999-08-13 09:45:20 +04:00
}
1998-01-16 15:13:05 +03:00
static void
2012-08-05 14:39:37 +04:00
negative_size_allocation_error ( const char * msg )
1998-01-16 15:13:05 +03:00
{
2012-08-05 14:39:37 +04:00
if ( ruby_thread_has_gvl_p ( ) ) {
rb_raise ( rb_eNoMemError , " %s " , msg ) ;
2010-02-16 15:34:09 +03:00
}
2010-11-04 14:46:26 +03:00
else {
2012-08-05 14:39:37 +04:00
if ( ruby_native_thread_p ( ) ) {
rb_thread_call_with_gvl ( negative_size_allocation_error_with_gvl , ( void * ) msg ) ;
}
else {
fprintf ( stderr , " [FATAL] %s \n " , msg ) ;
exit ( EXIT_FAILURE ) ;
}
2010-02-16 15:34:09 +03:00
}
}
2012-08-05 14:39:37 +04:00
static void *
ruby_memerror_body ( void * dummy )
2010-02-16 15:34:09 +03:00
{
2012-08-05 14:39:37 +04:00
rb_memerror ( ) ;
return 0 ;
1998-01-16 15:19:22 +03:00
}
2008-04-27 07:20:35 +04:00
static void
2012-08-05 14:39:37 +04:00
ruby_memerror ( void )
2008-06-30 13:57:07 +04:00
{
2012-08-05 14:39:37 +04:00
if ( ruby_thread_has_gvl_p ( ) ) {
rb_memerror ( ) ;
}
else {
if ( ruby_native_thread_p ( ) ) {
rb_thread_call_with_gvl ( ruby_memerror_body , 0 ) ;
}
else {
/* no ruby thread */
fprintf ( stderr , " [FATAL] failed to allocate memory \n " ) ;
exit ( EXIT_FAILURE ) ;
2008-07-27 09:59:32 +04:00
}
2008-06-30 13:57:07 +04:00
}
2010-02-16 15:34:09 +03:00
}
2012-08-05 14:39:37 +04:00
void
rb_memerror ( void )
2010-02-16 15:34:09 +03:00
{
2012-08-05 14:39:37 +04:00
rb_thread_t * th = GET_THREAD ( ) ;
if ( ! nomem_error | |
2013-08-18 14:36:51 +04:00
rb_thread_raised_p ( th , RAISED_NOMEMORY ) ) {
2012-08-05 14:39:37 +04:00
fprintf ( stderr , " [FATAL] failed to allocate memory \n " ) ;
exit ( EXIT_FAILURE ) ;
}
if ( rb_thread_raised_p ( th , RAISED_NOMEMORY ) ) {
rb_thread_raised_clear ( th ) ;
GET_THREAD ( ) - > errinfo = nomem_error ;
JUMP_TAG ( TAG_RAISE ) ;
}
rb_thread_raised_set ( th , RAISED_NOMEMORY ) ;
rb_exc_raise ( nomem_error ) ;
2008-06-30 13:57:07 +04:00
}
2012-08-05 14:39:37 +04:00
static void *
aligned_malloc ( size_t alignment , size_t size )
1998-01-16 15:19:22 +03:00
{
2012-08-05 14:39:37 +04:00
void * res ;
# if defined __MINGW32__
res = __mingw_aligned_malloc ( size , alignment ) ;
# elif defined _WIN32 && !defined __CYGWIN__
2013-03-31 01:08:30 +04:00
void * _aligned_malloc ( size_t , size_t ) ;
2012-08-05 14:39:37 +04:00
res = _aligned_malloc ( size , alignment ) ;
# elif defined(HAVE_POSIX_MEMALIGN)
if ( posix_memalign ( & res , alignment , size ) = = 0 ) {
return res ;
}
else {
return NULL ;
}
# elif defined(HAVE_MEMALIGN)
res = memalign ( alignment , size ) ;
# else
char * aligned ;
res = malloc ( alignment + size + sizeof ( void * ) ) ;
aligned = ( char * ) res + alignment + sizeof ( void * ) ;
aligned - = ( ( VALUE ) aligned & ( alignment - 1 ) ) ;
( ( void * * ) aligned ) [ - 1 ] = res ;
res = ( void * ) aligned ;
# endif
2013-08-19 16:00:51 +04:00
# if defined(_DEBUG) || GC_DEBUG
2012-08-05 14:39:37 +04:00
/* alignment must be a power of 2 */
2013-08-19 16:00:51 +04:00
assert ( ( ( alignment - 1 ) & alignment ) = = 0 ) ;
2012-08-05 14:39:37 +04:00
assert ( alignment % sizeof ( void * ) = = 0 ) ;
# endif
return res ;
2009-09-18 11:29:17 +04:00
}
2010-10-31 18:41:14 +03:00
static void
2012-08-05 14:39:37 +04:00
aligned_free ( void * ptr )
2009-09-18 11:29:17 +04:00
{
2012-08-05 14:39:37 +04:00
# if defined __MINGW32__
__mingw_aligned_free ( ptr ) ;
# elif defined _WIN32 && !defined __CYGWIN__
_aligned_free ( ptr ) ;
# elif defined(HAVE_MEMALIGN) || defined(HAVE_POSIX_MEMALIGN)
free ( ptr ) ;
# else
free ( ( ( void * * ) ptr ) [ - 1 ] ) ;
# endif
}
2011-09-29 20:54:14 +04:00
2013-12-05 08:54:20 +04:00
static inline size_t
2013-12-05 12:52:30 +04:00
objspace_malloc_size ( rb_objspace_t * objspace , void * ptr , size_t hint )
2013-12-05 08:54:20 +04:00
{
# ifdef HAVE_MALLOC_USABLE_SIZE
return malloc_usable_size ( ptr ) ;
# else
return hint ;
# endif
}
enum memop_type {
MEMOP_TYPE_MALLOC = 1 ,
MEMOP_TYPE_FREE = 2 ,
MEMOP_TYPE_REALLOC = 3
} ;
2013-12-06 12:53:47 +04:00
static inline void
atomic_sub_nounderflow ( size_t * var , size_t sub )
{
if ( sub = = 0 ) return ;
while ( 1 ) {
size_t val = * var ;
2013-12-06 14:09:38 +04:00
if ( val < sub ) sub = val ;
2013-12-06 12:53:47 +04:00
if ( ATOMIC_SIZE_CAS ( * var , val , val - sub ) = = val ) break ;
}
}
2013-09-27 12:01:14 +04:00
static void
2013-12-05 12:52:30 +04:00
objspace_malloc_increase ( rb_objspace_t * objspace , void * mem , size_t new_size , size_t old_size , enum memop_type type )
2013-09-27 12:01:14 +04:00
{
2013-10-17 11:57:03 +04:00
if ( new_size > old_size ) {
ATOMIC_SIZE_ADD ( malloc_increase , new_size - old_size ) ;
2013-12-16 06:50:45 +04:00
# if RGENGC_ESTIMATE_OLDMALLOC
2013-12-06 14:27:02 +04:00
ATOMIC_SIZE_ADD ( objspace - > rgengc . oldmalloc_increase , new_size - old_size ) ;
2013-12-16 06:50:45 +04:00
# endif
2013-10-17 11:57:03 +04:00
}
else {
2013-12-06 12:53:47 +04:00
atomic_sub_nounderflow ( & malloc_increase , old_size - new_size ) ;
2013-12-16 06:50:45 +04:00
# if RGENGC_ESTIMATE_OLDMALLOC
2013-12-06 14:27:02 +04:00
atomic_sub_nounderflow ( & objspace - > rgengc . oldmalloc_increase , old_size - new_size ) ;
2013-12-16 06:50:45 +04:00
# endif
2013-10-17 11:57:03 +04:00
}
2013-09-27 12:01:14 +04:00
2013-12-05 08:54:20 +04:00
if ( type = = MEMOP_TYPE_MALLOC ) {
2013-10-26 06:34:23 +04:00
if ( ruby_gc_stress & & ! ruby_disable_gc_stress ) {
2013-11-09 20:35:54 +04:00
garbage_collect_with_gvl ( objspace , FALSE , TRUE , GPR_FLAG_MALLOC ) ;
2013-10-17 11:57:03 +04:00
}
2013-10-26 06:34:23 +04:00
else {
retry :
if ( malloc_increase > malloc_limit ) {
2013-11-07 22:03:12 +04:00
if ( ruby_thread_has_gvl_p ( ) & & is_lazy_sweeping ( heap_eden ) ) {
2013-10-26 06:34:23 +04:00
gc_rest_sweep ( objspace ) ; /* rest_sweep can reduce malloc_increase */
goto retry ;
}
2013-11-09 20:35:54 +04:00
garbage_collect_with_gvl ( objspace , FALSE , TRUE , GPR_FLAG_MALLOC ) ;
2013-10-26 06:34:23 +04:00
}
}
2013-09-27 12:01:14 +04:00
}
2013-12-05 08:54:20 +04:00
# if MALLOC_ALLOCATED_SIZE
if ( new_size > = old_size ) {
ATOMIC_SIZE_ADD ( objspace - > malloc_params . allocated_size , new_size - old_size ) ;
}
else {
size_t dec_size = old_size - new_size ;
2013-12-06 12:53:47 +04:00
size_t allocated_size = objspace - > malloc_params . allocated_size ;
2013-12-05 08:54:20 +04:00
# if MALLOC_ALLOCATED_SIZE_CHECK
2013-12-06 12:53:47 +04:00
if ( allocated_size < dec_size ) {
rb_bug ( " objspace_malloc_increase: underflow malloc_params.allocated_size. " ) ;
2013-12-05 08:54:20 +04:00
}
2013-12-06 12:53:47 +04:00
# endif
atomic_sub_nounderflow ( objspace - > malloc_params . allocated_size , dec_size ) ;
2013-12-05 08:54:20 +04:00
}
if ( 0 ) fprintf ( stderr , " incraese - ptr: %p, type: %s, new_size: %d, old_size: %d \n " ,
mem ,
type = = MEMOP_TYPE_MALLOC ? " malloc " :
type = = MEMOP_TYPE_FREE ? " free " :
type = = MEMOP_TYPE_REALLOC ? " realloc " : " error " ,
( int ) new_size , ( int ) old_size ) ;
switch ( type ) {
case MEMOP_TYPE_MALLOC :
ATOMIC_SIZE_INC ( objspace - > malloc_params . allocations ) ;
break ;
case MEMOP_TYPE_FREE :
2013-12-06 12:53:47 +04:00
{
2013-12-05 08:54:20 +04:00
size_t allocations = objspace - > malloc_params . allocations ;
if ( allocations > 0 ) {
2013-12-06 12:53:47 +04:00
atomic_sub_nounderflow ( objspace - > malloc_params . allocations , 1 ) ;
2013-12-05 08:54:20 +04:00
}
# if MALLOC_ALLOCATED_SIZE_CHECK
2013-12-06 12:53:47 +04:00
else {
2013-12-05 08:54:20 +04:00
assert ( objspace - > malloc_params . allocations > 0 ) ;
}
2013-12-06 12:53:47 +04:00
# endif
2013-12-05 08:54:20 +04:00
}
break ;
case MEMOP_TYPE_REALLOC : /* ignore */ break ;
}
# endif
2013-09-27 12:01:14 +04:00
}
2012-08-05 14:39:37 +04:00
static inline size_t
2013-12-05 12:52:30 +04:00
objspace_malloc_prepare ( rb_objspace_t * objspace , size_t size )
2012-08-05 14:39:37 +04:00
{
if ( ( ssize_t ) size < 0 ) {
negative_size_allocation_error ( " negative allocation size (or too big) " ) ;
1999-01-20 07:59:39 +03:00
}
2012-08-05 14:39:37 +04:00
if ( size = = 0 ) size = 1 ;
2010-10-31 18:41:14 +03:00
2012-08-05 14:39:37 +04:00
# if CALC_EXACT_MALLOC_SIZE
size + = sizeof ( size_t ) ;
# endif
2010-10-31 18:41:14 +03:00
2012-08-05 14:39:37 +04:00
return size ;
1998-01-16 15:19:22 +03:00
}
2012-08-05 14:39:37 +04:00
static inline void *
2013-12-05 12:52:30 +04:00
objspace_malloc_fixup ( rb_objspace_t * objspace , void * mem , size_t size )
2008-04-27 07:20:35 +04:00
{
2012-08-05 14:39:37 +04:00
# if CALC_EXACT_MALLOC_SIZE
( ( size_t * ) mem ) [ 0 ] = size ;
mem = ( size_t * ) mem + 1 ;
# endif
return mem ;
2011-09-29 15:10:46 +04:00
}
2012-08-05 14:39:37 +04:00
# define TRY_WITH_GC(alloc) do { \
if ( ! ( alloc ) & & \
2013-05-22 03:09:22 +04:00
( ! garbage_collect_with_gvl ( objspace , 1 , 1 , GPR_FLAG_MALLOC ) | | /* full mark && immediate sweep */ \
2012-08-05 14:39:37 +04:00
! ( alloc ) ) ) { \
ruby_memerror ( ) ; \
} \
} while ( 0 )
static void *
2013-12-05 12:52:30 +04:00
objspace_xmalloc ( rb_objspace_t * objspace , size_t size )
2011-09-08 04:02:55 +04:00
{
2012-08-05 14:39:37 +04:00
void * mem ;
2013-12-05 12:52:30 +04:00
size = objspace_malloc_prepare ( objspace , size ) ;
2012-08-05 14:39:37 +04:00
TRY_WITH_GC ( mem = malloc ( size ) ) ;
2013-12-05 12:52:30 +04:00
size = objspace_malloc_size ( objspace , mem , size ) ;
objspace_malloc_increase ( objspace , mem , size , 0 , MEMOP_TYPE_MALLOC ) ;
return objspace_malloc_fixup ( objspace , mem , size ) ;
2011-09-08 04:02:55 +04:00
}
2012-08-05 14:39:37 +04:00
static void *
2013-12-05 12:52:30 +04:00
objspace_xrealloc ( rb_objspace_t * objspace , void * ptr , size_t new_size , size_t old_size )
2011-09-29 15:10:46 +04:00
{
2012-08-05 14:39:37 +04:00
void * mem ;
2011-09-29 15:10:46 +04:00
2013-10-17 11:57:03 +04:00
if ( ( ssize_t ) new_size < 0 ) {
2012-08-05 14:39:37 +04:00
negative_size_allocation_error ( " negative re-allocation size " ) ;
}
2013-01-05 00:05:42 +04:00
2013-12-05 12:52:30 +04:00
if ( ! ptr ) return objspace_xmalloc ( objspace , new_size ) ;
2013-01-05 00:05:42 +04:00
/*
* The behavior of realloc ( ptr , 0 ) is implementation defined .
* Therefore we don ' t use realloc ( ptr , 0 ) for portability reason .
* see http : //www.open-std.org/jtc1/sc22/wg14/www/docs/dr_400.htm
*/
2013-10-17 11:57:03 +04:00
if ( new_size = = 0 ) {
2013-12-05 12:52:30 +04:00
objspace_xfree ( objspace , ptr , old_size ) ;
2012-08-05 14:39:37 +04:00
return 0 ;
}
2013-09-27 12:01:14 +04:00
2012-08-05 14:39:37 +04:00
# if CALC_EXACT_MALLOC_SIZE
2013-10-17 13:51:41 +04:00
new_size + = sizeof ( size_t ) ;
2012-08-05 14:39:37 +04:00
ptr = ( size_t * ) ptr - 1 ;
2013-12-05 08:54:20 +04:00
oldsize = ( ( size_t * ) ptr ) [ 0 ] ;
2005-07-27 11:27:19 +04:00
# endif
1998-01-16 15:19:22 +03:00
2013-12-05 12:52:30 +04:00
old_size = objspace_malloc_size ( objspace , ptr , old_size ) ;
2013-10-17 11:57:03 +04:00
TRY_WITH_GC ( mem = realloc ( ptr , new_size ) ) ;
2013-12-05 12:52:30 +04:00
new_size = objspace_malloc_size ( objspace , mem , new_size ) ;
2005-07-27 11:27:19 +04:00
2012-08-05 14:39:37 +04:00
# if CALC_EXACT_MALLOC_SIZE
2013-10-17 13:51:41 +04:00
( ( size_t * ) mem ) [ 0 ] = new_size ;
2012-08-05 14:39:37 +04:00
mem = ( size_t * ) mem + 1 ;
# endif
2006-03-02 08:22:30 +03:00
2013-12-05 12:52:30 +04:00
objspace_malloc_increase ( objspace , mem , new_size , old_size , MEMOP_TYPE_REALLOC ) ;
2013-12-05 08:54:20 +04:00
2012-08-05 14:39:37 +04:00
return mem ;
}
1999-01-20 07:59:39 +03:00
2012-08-05 14:39:37 +04:00
static void
2013-12-05 12:52:30 +04:00
objspace_xfree ( rb_objspace_t * objspace , void * ptr , size_t old_size )
2012-08-05 14:39:37 +04:00
{
# if CALC_EXACT_MALLOC_SIZE
ptr = ( ( size_t * ) ptr ) - 1 ;
2013-12-05 08:54:20 +04:00
oldsize = ( ( size_t * ) ptr ) [ 0 ] ;
2012-08-05 14:39:37 +04:00
# endif
2013-12-05 12:52:30 +04:00
old_size = objspace_malloc_size ( objspace , ptr , old_size ) ;
1998-01-16 15:13:05 +03:00
2012-08-05 14:39:37 +04:00
free ( ptr ) ;
2013-12-05 08:54:20 +04:00
2013-12-05 12:52:30 +04:00
objspace_malloc_increase ( objspace , ptr , 0 , old_size , MEMOP_TYPE_FREE ) ;
2012-08-05 14:39:37 +04:00
}
2006-03-02 08:22:30 +03:00
2012-08-05 14:39:37 +04:00
void *
ruby_xmalloc ( size_t size )
{
2013-12-05 12:52:30 +04:00
return objspace_xmalloc ( & rb_objspace , size ) ;
2012-08-05 14:39:37 +04:00
}
2006-03-02 08:22:30 +03:00
2012-08-05 14:39:37 +04:00
static inline size_t
xmalloc2_size ( size_t n , size_t size )
2006-03-02 08:22:30 +03:00
{
2012-08-05 14:39:37 +04:00
size_t len = size * n ;
if ( n ! = 0 & & size ! = len / n ) {
rb_raise ( rb_eArgError , " malloc: possible integer overflow " ) ;
2006-03-02 08:22:30 +03:00
}
2012-08-05 14:39:37 +04:00
return len ;
2006-03-02 08:22:30 +03:00
}
2012-08-05 14:39:37 +04:00
void *
ruby_xmalloc2 ( size_t n , size_t size )
2008-05-31 18:03:23 +04:00
{
2013-12-05 12:52:30 +04:00
return objspace_xmalloc ( & rb_objspace , xmalloc2_size ( n , size ) ) ;
2008-05-31 18:03:23 +04:00
}
2012-08-05 14:39:37 +04:00
static void *
2013-12-05 12:52:30 +04:00
objspace_xcalloc ( rb_objspace_t * objspace , size_t count , size_t elsize )
2007-11-03 18:09:10 +03:00
{
2012-08-05 14:39:37 +04:00
void * mem ;
size_t size ;
2007-11-03 18:09:10 +03:00
2012-08-05 14:39:37 +04:00
size = xmalloc2_size ( count , elsize ) ;
2013-12-05 12:52:30 +04:00
size = objspace_malloc_prepare ( objspace , size ) ;
2007-11-03 18:09:10 +03:00
2012-08-05 14:39:37 +04:00
TRY_WITH_GC ( mem = calloc ( 1 , size ) ) ;
2013-12-05 12:52:30 +04:00
return objspace_malloc_fixup ( objspace , mem , size ) ;
2012-08-05 14:39:37 +04:00
}
2007-11-03 18:09:10 +03:00
2012-08-05 14:39:37 +04:00
void *
ruby_xcalloc ( size_t n , size_t size )
{
2013-12-05 12:52:30 +04:00
return objspace_xcalloc ( & rb_objspace , n , size ) ;
2012-08-05 14:39:37 +04:00
}
2007-11-03 18:09:10 +03:00
2013-11-25 05:13:31 +04:00
# ifdef ruby_sized_xrealloc
# undef ruby_sized_xrealloc
# endif
2012-08-05 14:39:37 +04:00
void *
2013-10-17 12:41:23 +04:00
ruby_sized_xrealloc ( void * ptr , size_t new_size , size_t old_size )
2012-08-05 14:39:37 +04:00
{
2013-12-05 12:52:30 +04:00
return objspace_xrealloc ( & rb_objspace , ptr , new_size , old_size ) ;
2013-10-17 11:57:03 +04:00
}
void *
ruby_xrealloc ( void * ptr , size_t new_size )
{
2013-10-17 12:41:23 +04:00
return ruby_sized_xrealloc ( ptr , new_size , 0 ) ;
2012-08-05 14:39:37 +04:00
}
2008-08-11 13:36:57 +04:00
2013-12-10 11:16:06 +04:00
# ifdef ruby_sized_xrealloc2
# undef ruby_sized_xrealloc2
# endif
2012-08-05 14:39:37 +04:00
void *
2013-12-10 11:16:06 +04:00
ruby_sized_xrealloc2 ( void * ptr , size_t n , size_t size , size_t old_n )
2012-08-05 14:39:37 +04:00
{
size_t len = size * n ;
if ( n ! = 0 & & size ! = len / n ) {
rb_raise ( rb_eArgError , " realloc: possible integer overflow " ) ;
2007-11-03 18:09:10 +03:00
}
2013-12-10 11:16:06 +04:00
return objspace_xrealloc ( & rb_objspace , ptr , len , old_n * size ) ;
}
void *
ruby_xrealloc2 ( void * ptr , size_t n , size_t size )
{
return ruby_sized_xrealloc2 ( ptr , n , size , 0 ) ;
2012-08-05 14:39:37 +04:00
}
2007-11-03 18:09:10 +03:00
2013-11-25 05:13:31 +04:00
# ifdef ruby_sized_xfree
# undef ruby_sized_xfree
# endif
2012-08-05 14:39:37 +04:00
void
2013-10-17 12:41:23 +04:00
ruby_sized_xfree ( void * x , size_t size )
2012-08-05 14:39:37 +04:00
{
2013-10-17 11:57:03 +04:00
if ( x ) {
2013-12-05 12:52:30 +04:00
objspace_xfree ( & rb_objspace , x , size ) ;
2013-10-17 11:57:03 +04:00
}
2012-08-05 14:39:37 +04:00
}
2013-10-17 11:57:03 +04:00
void
ruby_xfree ( void * x )
{
2013-10-17 12:41:23 +04:00
ruby_sized_xfree ( x , 0 ) ;
2013-10-17 11:57:03 +04:00
}
2012-08-05 14:39:37 +04:00
/* Mimic ruby_xmalloc, but need not rb_objspace.
* should return pointer suitable for ruby_xfree
*/
void *
ruby_mimmalloc ( size_t size )
{
void * mem ;
# if CALC_EXACT_MALLOC_SIZE
size + = sizeof ( size_t ) ;
# endif
mem = malloc ( size ) ;
# if CALC_EXACT_MALLOC_SIZE
/* set 0 for consistency of allocated_size/allocations */
( ( size_t * ) mem ) [ 0 ] = 0 ;
mem = ( size_t * ) mem + 1 ;
# endif
return mem ;
2007-11-03 18:09:10 +03:00
}
2013-11-22 05:38:08 +04:00
void
ruby_mimfree ( void * ptr )
{
size_t * mem = ( size_t * ) ptr ;
# if CALC_EXACT_MALLOC_SIZE
mem = mem - 1 ;
# endif
free ( mem ) ;
}
2013-12-05 08:54:20 +04:00
# if MALLOC_ALLOCATED_SIZE
2012-03-13 07:37:06 +04:00
/*
2012-08-05 14:39:37 +04:00
* call - seq :
* GC . malloc_allocated_size - > Integer
2012-03-13 07:37:06 +04:00
*
2012-11-29 12:15:53 +04:00
* Returns the size of memory allocated by malloc ( ) .
*
* Only available if ruby was built with + CALC_EXACT_MALLOC_SIZE + .
2012-08-05 14:39:37 +04:00
*/
static VALUE
gc_malloc_allocated_size ( VALUE self )
{
return UINT2NUM ( rb_objspace . malloc_params . allocated_size ) ;
}
/*
* call - seq :
* GC . malloc_allocations - > Integer
*
2012-11-29 12:15:53 +04:00
* Returns the number of malloc ( ) allocations .
*
* Only available if ruby was built with + CALC_EXACT_MALLOC_SIZE + .
2012-03-13 07:37:06 +04:00
*/
2012-08-05 14:39:37 +04:00
static VALUE
gc_malloc_allocations ( VALUE self )
{
return UINT2NUM ( rb_objspace . malloc_params . allocations ) ;
}
# endif
/*
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - WeakMap - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
2012-03-13 07:37:06 +04:00
struct weakmap {
st_table * obj2wmap ; /* obj -> [ref,...] */
st_table * wmap2obj ; /* ref -> obj */
VALUE final ;
} ;
2013-12-12 11:43:36 +04:00
# define WMAP_DELETE_DEAD_OBJECT_IN_MARK 0
# if WMAP_DELETE_DEAD_OBJECT_IN_MARK
2012-03-13 07:37:06 +04:00
static int
wmap_mark_map ( st_data_t key , st_data_t val , st_data_t arg )
{
2013-11-01 18:24:34 +04:00
rb_objspace_t * objspace = ( rb_objspace_t * ) arg ;
VALUE obj = ( VALUE ) val ;
if ( ! is_live_object ( objspace , obj ) ) return ST_DELETE ;
2012-03-13 07:37:06 +04:00
return ST_CONTINUE ;
}
2013-12-12 11:43:36 +04:00
# endif
2012-03-13 07:37:06 +04:00
static void
wmap_mark ( void * ptr )
{
struct weakmap * w = ptr ;
2013-12-12 11:43:36 +04:00
# if WMAP_DELETE_DEAD_OBJECT_IN_MARK
2013-06-10 11:12:14 +04:00
if ( w - > obj2wmap ) st_foreach ( w - > obj2wmap , wmap_mark_map , ( st_data_t ) & rb_objspace ) ;
2013-12-12 11:43:36 +04:00
# endif
2012-03-13 07:37:06 +04:00
rb_gc_mark ( w - > final ) ;
}
static int
wmap_free_map ( st_data_t key , st_data_t val , st_data_t arg )
{
2013-12-10 12:21:33 +04:00
VALUE * ptr = ( VALUE * ) val ;
ruby_sized_xfree ( ptr , ( ptr [ 0 ] + 1 ) * sizeof ( VALUE ) ) ;
2012-03-13 07:37:06 +04:00
return ST_CONTINUE ;
}
static void
wmap_free ( void * ptr )
{
struct weakmap * w = ptr ;
st_foreach ( w - > obj2wmap , wmap_free_map , 0 ) ;
st_free_table ( w - > obj2wmap ) ;
st_free_table ( w - > wmap2obj ) ;
}
static int
wmap_memsize_map ( st_data_t key , st_data_t val , st_data_t arg )
{
2013-12-10 12:21:33 +04:00
VALUE * ptr = ( VALUE * ) val ;
* ( size_t * ) arg + = ( ptr [ 0 ] + 1 ) * sizeof ( VALUE ) ;
2012-03-13 07:37:06 +04:00
return ST_CONTINUE ;
}
static size_t
wmap_memsize ( const void * ptr )
{
size_t size ;
const struct weakmap * w = ptr ;
if ( ! w ) return 0 ;
size = sizeof ( * w ) ;
size + = st_memsize ( w - > obj2wmap ) ;
size + = st_memsize ( w - > wmap2obj ) ;
st_foreach ( w - > obj2wmap , wmap_memsize_map , ( st_data_t ) & size ) ;
return size ;
}
static const rb_data_type_t weakmap_type = {
" weakmap " ,
{
wmap_mark ,
wmap_free ,
wmap_memsize ,
2013-10-29 15:16:54 +04:00
} ,
NULL , NULL , RUBY_TYPED_FREE_IMMEDIATELY
2012-03-13 07:37:06 +04:00
} ;
static VALUE
wmap_allocate ( VALUE klass )
{
struct weakmap * w ;
VALUE obj = TypedData_Make_Struct ( klass , struct weakmap , & weakmap_type , w ) ;
w - > obj2wmap = st_init_numtable ( ) ;
w - > wmap2obj = st_init_numtable ( ) ;
w - > final = rb_obj_method ( obj , ID2SYM ( rb_intern ( " finalize " ) ) ) ;
return obj ;
}
static int
2012-03-29 18:50:20 +04:00
wmap_final_func ( st_data_t * key , st_data_t * value , st_data_t arg , int existing )
2012-03-13 07:37:06 +04:00
{
2013-12-10 12:21:33 +04:00
VALUE wmap , * ptr , size , i , j ;
2012-03-29 11:36:12 +04:00
if ( ! existing ) return ST_STOP ;
2013-12-10 12:21:33 +04:00
wmap = ( VALUE ) arg , ptr = ( VALUE * ) * value ;
for ( i = j = 1 , size = ptr [ 0 ] ; i < = size ; + + i ) {
if ( ptr [ i ] ! = wmap ) {
ptr [ j + + ] = ptr [ i ] ;
}
}
if ( j = = 1 ) {
ruby_sized_xfree ( ptr , i * sizeof ( VALUE ) ) ;
return ST_DELETE ;
}
if ( j < i ) {
ptr = ruby_sized_xrealloc2 ( ptr , j , sizeof ( VALUE ) , i ) ;
ptr [ 0 ] = j ;
2013-12-13 20:19:49 +04:00
* value = ( st_data_t ) ptr ;
2013-12-10 12:21:33 +04:00
}
2012-03-13 07:37:06 +04:00
return ST_CONTINUE ;
}
static VALUE
2012-11-24 16:26:57 +04:00
wmap_finalize ( VALUE self , VALUE objid )
2012-03-13 07:37:06 +04:00
{
2012-11-24 16:26:57 +04:00
st_data_t orig , wmap , data ;
2013-12-10 12:21:33 +04:00
VALUE obj , * rids , i , size ;
2012-03-13 07:37:06 +04:00
struct weakmap * w ;
TypedData_Get_Struct ( self , struct weakmap , & weakmap_type , w ) ;
2012-11-24 16:26:54 +04:00
/* Get reference from object id. */
2012-12-22 08:25:18 +04:00
obj = obj_id_to_ref ( objid ) ;
2012-03-13 07:37:06 +04:00
2012-11-24 16:26:54 +04:00
/* obj is original referenced object and/or weak reference. */
2012-11-24 16:26:57 +04:00
orig = ( st_data_t ) obj ;
if ( st_delete ( w - > obj2wmap , & orig , & data ) ) {
2013-12-10 12:21:33 +04:00
rids = ( VALUE * ) data ;
size = * rids + + ;
for ( i = 0 ; i < size ; + + i ) {
wmap = ( st_data_t ) rids [ i ] ;
2012-11-24 16:26:57 +04:00
st_delete ( w - > wmap2obj , & wmap , NULL ) ;
2012-03-13 07:37:06 +04:00
}
2013-12-10 12:21:33 +04:00
ruby_sized_xfree ( ( VALUE * ) data , ( size + 1 ) * sizeof ( VALUE ) ) ;
2012-03-13 07:37:06 +04:00
}
2012-11-24 16:26:57 +04:00
wmap = ( st_data_t ) obj ;
if ( st_delete ( w - > wmap2obj , & wmap , & orig ) ) {
wmap = ( st_data_t ) obj ;
st_update ( w - > obj2wmap , orig , wmap_final_func , wmap ) ;
2012-03-13 07:37:06 +04:00
}
return self ;
}
2013-10-18 10:59:14 +04:00
struct wmap_iter_arg {
rb_objspace_t * objspace ;
VALUE value ;
} ;
static int
wmap_inspect_i ( st_data_t key , st_data_t val , st_data_t arg )
{
2013-10-18 11:04:42 +04:00
VALUE str = ( VALUE ) arg ;
2013-10-18 10:59:14 +04:00
VALUE k = ( VALUE ) key , v = ( VALUE ) val ;
2013-10-18 11:06:43 +04:00
if ( RSTRING_PTR ( str ) [ 0 ] = = ' # ' ) {
2013-10-18 10:59:14 +04:00
rb_str_cat2 ( str , " , " ) ;
2013-10-18 11:06:43 +04:00
}
else {
rb_str_cat2 ( str , " : " ) ;
2013-10-18 10:59:14 +04:00
RSTRING_PTR ( str ) [ 0 ] = ' # ' ;
}
k = SPECIAL_CONST_P ( k ) ? rb_inspect ( k ) : rb_any_to_s ( k ) ;
rb_str_append ( str , k ) ;
rb_str_cat2 ( str , " => " ) ;
v = SPECIAL_CONST_P ( v ) ? rb_inspect ( v ) : rb_any_to_s ( v ) ;
rb_str_append ( str , v ) ;
OBJ_INFECT ( str , k ) ;
OBJ_INFECT ( str , v ) ;
return ST_CONTINUE ;
}
static VALUE
wmap_inspect ( VALUE self )
{
VALUE str ;
VALUE c = rb_class_name ( CLASS_OF ( self ) ) ;
struct weakmap * w ;
TypedData_Get_Struct ( self , struct weakmap , & weakmap_type , w ) ;
str = rb_sprintf ( " -<% " PRIsVALUE " :%p " , c , ( void * ) self ) ;
2013-12-10 09:02:17 +04:00
if ( w - > wmap2obj ) {
st_foreach ( w - > wmap2obj , wmap_inspect_i , str ) ;
2013-10-18 10:59:14 +04:00
}
RSTRING_PTR ( str ) [ 0 ] = ' # ' ;
2013-10-18 11:04:42 +04:00
rb_str_cat2 ( str , " > " ) ;
2013-10-18 10:59:14 +04:00
return str ;
}
static int
wmap_each_i ( st_data_t key , st_data_t val , st_data_t arg )
{
rb_objspace_t * objspace = ( rb_objspace_t * ) arg ;
VALUE obj = ( VALUE ) val ;
if ( is_id_value ( objspace , obj ) & & is_live_object ( objspace , obj ) ) {
rb_yield_values ( 2 , ( VALUE ) key , obj ) ;
}
return ST_CONTINUE ;
}
/* Iterates over keys and objects in a weakly referenced object */
static VALUE
wmap_each ( VALUE self )
{
struct weakmap * w ;
rb_objspace_t * objspace = & rb_objspace ;
TypedData_Get_Struct ( self , struct weakmap , & weakmap_type , w ) ;
st_foreach ( w - > wmap2obj , wmap_each_i , ( st_data_t ) objspace ) ;
return self ;
}
static int
wmap_each_key_i ( st_data_t key , st_data_t val , st_data_t arg )
{
rb_objspace_t * objspace = ( rb_objspace_t * ) arg ;
VALUE obj = ( VALUE ) val ;
if ( is_id_value ( objspace , obj ) & & is_live_object ( objspace , obj ) ) {
rb_yield ( ( VALUE ) key ) ;
}
return ST_CONTINUE ;
}
/* Iterates over keys and objects in a weakly referenced object */
static VALUE
wmap_each_key ( VALUE self )
{
struct weakmap * w ;
rb_objspace_t * objspace = & rb_objspace ;
TypedData_Get_Struct ( self , struct weakmap , & weakmap_type , w ) ;
st_foreach ( w - > wmap2obj , wmap_each_key_i , ( st_data_t ) objspace ) ;
return self ;
}
static int
wmap_each_value_i ( st_data_t key , st_data_t val , st_data_t arg )
{
rb_objspace_t * objspace = ( rb_objspace_t * ) arg ;
VALUE obj = ( VALUE ) val ;
if ( is_id_value ( objspace , obj ) & & is_live_object ( objspace , obj ) ) {
rb_yield ( obj ) ;
}
return ST_CONTINUE ;
}
/* Iterates over keys and objects in a weakly referenced object */
static VALUE
wmap_each_value ( VALUE self )
{
struct weakmap * w ;
rb_objspace_t * objspace = & rb_objspace ;
TypedData_Get_Struct ( self , struct weakmap , & weakmap_type , w ) ;
st_foreach ( w - > wmap2obj , wmap_each_value_i , ( st_data_t ) objspace ) ;
return self ;
}
static int
wmap_keys_i ( st_data_t key , st_data_t val , st_data_t arg )
{
2013-12-12 06:01:18 +04:00
struct wmap_iter_arg * argp = ( struct wmap_iter_arg * ) arg ;
rb_objspace_t * objspace = argp - > objspace ;
VALUE ary = argp - > value ;
VALUE obj = ( VALUE ) val ;
if ( is_id_value ( objspace , obj ) & & is_live_object ( objspace , obj ) ) {
rb_ary_push ( ary , ( VALUE ) key ) ;
}
2013-10-18 10:59:14 +04:00
return ST_CONTINUE ;
}
/* Iterates over keys and objects in a weakly referenced object */
static VALUE
wmap_keys ( VALUE self )
{
struct weakmap * w ;
2013-12-12 06:01:18 +04:00
struct wmap_iter_arg args ;
2013-10-18 10:59:14 +04:00
TypedData_Get_Struct ( self , struct weakmap , & weakmap_type , w ) ;
2013-12-12 06:01:18 +04:00
args . objspace = & rb_objspace ;
args . value = rb_ary_new ( ) ;
st_foreach ( w - > wmap2obj , wmap_keys_i , ( st_data_t ) & args ) ;
return args . value ;
2013-10-18 10:59:14 +04:00
}
static int
wmap_values_i ( st_data_t key , st_data_t val , st_data_t arg )
{
struct wmap_iter_arg * argp = ( struct wmap_iter_arg * ) arg ;
rb_objspace_t * objspace = argp - > objspace ;
VALUE ary = argp - > value ;
VALUE obj = ( VALUE ) val ;
if ( is_id_value ( objspace , obj ) & & is_live_object ( objspace , obj ) ) {
rb_ary_push ( ary , obj ) ;
}
return ST_CONTINUE ;
}
/* Iterates over values and objects in a weakly referenced object */
static VALUE
wmap_values ( VALUE self )
{
struct weakmap * w ;
struct wmap_iter_arg args ;
TypedData_Get_Struct ( self , struct weakmap , & weakmap_type , w ) ;
args . objspace = & rb_objspace ;
args . value = rb_ary_new ( ) ;
st_foreach ( w - > wmap2obj , wmap_values_i , ( st_data_t ) & args ) ;
return args . value ;
}
2013-12-10 11:16:08 +04:00
static int
wmap_aset_update ( st_data_t * key , st_data_t * val , st_data_t arg , int existing )
{
2013-12-10 12:21:33 +04:00
VALUE size , * ptr , * optr ;
2013-12-10 11:16:08 +04:00
if ( existing ) {
2013-12-10 12:21:33 +04:00
size = ( ptr = optr = ( VALUE * ) * val ) [ 0 ] ;
+ + size ;
ptr = ruby_sized_xrealloc2 ( ptr , size + 1 , sizeof ( VALUE ) , size ) ;
2013-12-10 11:16:08 +04:00
}
else {
2013-12-10 12:21:33 +04:00
optr = 0 ;
size = 1 ;
ptr = ruby_xmalloc2 ( 2 , sizeof ( VALUE ) ) ;
}
ptr [ 0 ] = size ;
ptr [ size ] = ( VALUE ) arg ;
if ( ptr = = optr ) return ST_STOP ;
* val = ( st_data_t ) ptr ;
2013-12-10 11:16:08 +04:00
return ST_CONTINUE ;
}
2012-11-29 12:15:53 +04:00
/* Creates a weak reference from the given key to the given value */
2012-03-13 07:37:06 +04:00
static VALUE
wmap_aset ( VALUE self , VALUE wmap , VALUE orig )
{
struct weakmap * w ;
TypedData_Get_Struct ( self , struct weakmap , & weakmap_type , w ) ;
2013-12-10 09:17:19 +04:00
should_be_finalizable ( orig ) ;
should_be_finalizable ( wmap ) ;
define_final0 ( orig , w - > final ) ;
define_final0 ( wmap , w - > final ) ;
2013-12-10 11:16:08 +04:00
st_update ( w - > obj2wmap , ( st_data_t ) orig , wmap_aset_update , wmap ) ;
2012-03-13 07:37:06 +04:00
st_insert ( w - > wmap2obj , ( st_data_t ) wmap , ( st_data_t ) orig ) ;
return nonspecial_obj_id ( orig ) ;
}
2012-11-29 12:15:53 +04:00
/* Retrieves a weakly referenced object with the given key */
2012-03-13 07:37:06 +04:00
static VALUE
wmap_aref ( VALUE self , VALUE wmap )
{
st_data_t data ;
VALUE obj ;
struct weakmap * w ;
rb_objspace_t * objspace = & rb_objspace ;
TypedData_Get_Struct ( self , struct weakmap , & weakmap_type , w ) ;
if ( ! st_lookup ( w - > wmap2obj , ( st_data_t ) wmap , & data ) ) return Qnil ;
obj = ( VALUE ) data ;
if ( ! is_id_value ( objspace , obj ) ) return Qnil ;
if ( ! is_live_object ( objspace , obj ) ) return Qnil ;
return obj ;
}
2013-10-18 10:59:12 +04:00
/* Returns +true+ if +key+ is registered */
static VALUE
wmap_has_key ( VALUE self , VALUE key )
{
return NIL_P ( wmap_aref ( self , key ) ) ? Qfalse : Qtrue ;
}
2013-12-09 11:13:40 +04:00
static VALUE
wmap_size ( VALUE self )
{
struct weakmap * w ;
st_index_t n ;
TypedData_Get_Struct ( self , struct weakmap , & weakmap_type , w ) ;
n = w - > wmap2obj - > num_entries ;
# if SIZEOF_ST_INDEX_T <= SIZEOF_LONG
return ULONG2NUM ( n ) ;
# else
return ULL2NUM ( n ) ;
# endif
}
2008-06-08 14:27:06 +04:00
2012-08-04 18:12:12 +04:00
/*
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - GC profiler - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
2012-11-21 17:15:10 +04:00
# define GC_PROFILE_RECORD_DEFAULT_SIZE 100
2012-08-04 18:12:12 +04:00
static double
getrusage_time ( void )
{
2012-12-05 18:53:16 +04:00
# if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID)
2013-08-21 12:34:48 +04:00
{
static int try_clock_gettime = 1 ;
struct timespec ts ;
if ( try_clock_gettime & & clock_gettime ( CLOCK_PROCESS_CPUTIME_ID , & ts ) = = 0 ) {
return ts . tv_sec + ts . tv_nsec * 1e-9 ;
}
else {
try_clock_gettime = 0 ;
}
2012-12-05 18:53:16 +04:00
}
2013-08-21 12:34:48 +04:00
# endif
# ifdef RUSAGE_SELF
2012-08-04 18:12:12 +04:00
{
2013-08-21 12:34:48 +04:00
struct rusage usage ;
struct timeval time ;
if ( getrusage ( RUSAGE_SELF , & usage ) = = 0 ) {
time = usage . ru_utime ;
return time . tv_sec + time . tv_usec * 1e-6 ;
}
2012-08-04 18:12:12 +04:00
}
2013-08-21 12:34:48 +04:00
# endif
# ifdef _WIN32
{
FILETIME creation_time , exit_time , kernel_time , user_time ;
ULARGE_INTEGER ui ;
LONG_LONG q ;
double t ;
if ( GetProcessTimes ( GetCurrentProcess ( ) ,
& creation_time , & exit_time , & kernel_time , & user_time ) ! = 0 ) {
memcpy ( & ui , & user_time , sizeof ( FILETIME ) ) ;
q = ui . QuadPart / 10L ;
t = ( DWORD ) ( q % 1000000L ) * 1e-6 ;
q / = 1000000L ;
2012-08-04 18:12:12 +04:00
# ifdef __GNUC__
2013-08-21 12:34:48 +04:00
t + = q ;
2012-08-04 18:12:12 +04:00
# else
2013-08-21 12:34:48 +04:00
t + = ( double ) ( DWORD ) ( q > > 16 ) * ( 1 < < 16 ) ;
t + = ( DWORD ) q & ~ ( ~ 0 < < 16 ) ;
2012-08-04 18:12:12 +04:00
# endif
2013-08-21 12:34:48 +04:00
return t ;
}
}
2012-08-04 18:12:12 +04:00
# endif
2013-08-21 12:34:48 +04:00
return 0.0 ;
2012-08-04 18:12:12 +04:00
}
static inline void
2013-06-24 02:58:01 +04:00
gc_prof_setup_new_record ( rb_objspace_t * objspace , int reason )
2012-08-04 18:12:12 +04:00
{
if ( objspace - > profile . run ) {
2013-05-13 20:34:25 +04:00
size_t index = objspace - > profile . next_index ;
gc_profile_record * record ;
2012-08-04 18:12:12 +04:00
2013-05-21 12:19:07 +04:00
/* create new record */
2013-05-13 20:34:25 +04:00
objspace - > profile . next_index + + ;
2013-06-22 01:51:41 +04:00
if ( ! objspace - > profile . records ) {
2013-05-13 20:34:25 +04:00
objspace - > profile . size = GC_PROFILE_RECORD_DEFAULT_SIZE ;
2013-06-22 01:51:41 +04:00
objspace - > profile . records = malloc ( sizeof ( gc_profile_record ) * objspace - > profile . size ) ;
2013-05-13 20:34:25 +04:00
}
if ( index > = objspace - > profile . size ) {
objspace - > profile . size + = 1000 ;
2013-06-22 01:51:41 +04:00
objspace - > profile . records = realloc ( objspace - > profile . records , sizeof ( gc_profile_record ) * objspace - > profile . size ) ;
2013-05-13 20:34:25 +04:00
}
2013-06-22 01:51:41 +04:00
if ( ! objspace - > profile . records ) {
2013-05-13 20:34:25 +04:00
rb_bug ( " gc_profile malloc or realloc miss " ) ;
}
2013-06-22 01:51:41 +04:00
record = objspace - > profile . current_record = & objspace - > profile . records [ objspace - > profile . next_index - 1 ] ;
2013-05-13 20:34:25 +04:00
MEMZERO ( record , gc_profile_record , 1 ) ;
2013-06-24 03:01:06 +04:00
2013-06-24 02:58:01 +04:00
/* setup before-GC parameter */
record - > flags = reason | ( ( ruby_gc_stress & & ! ruby_disable_gc_stress ) ? GPR_FLAG_STRESS : 0 ) ;
2013-12-05 08:54:20 +04:00
# if MALLOC_ALLOCATED_SIZE
2013-06-24 02:58:01 +04:00
record - > allocated_size = malloc_allocated_size ;
2013-11-09 03:59:20 +04:00
# endif
# if GC_PROFILE_DETAIL_MEMORY
# ifdef RUSAGE_SELF
{
struct rusage usage ;
if ( getrusage ( RUSAGE_SELF , & usage ) = = 0 ) {
record - > maxrss = usage . ru_maxrss ;
record - > minflt = usage . ru_minflt ;
record - > majflt = usage . ru_majflt ;
}
}
# endif
2013-06-24 02:58:01 +04:00
# endif
}
}
2013-05-13 20:34:25 +04:00
2013-06-24 02:58:01 +04:00
static inline void
gc_prof_timer_start ( rb_objspace_t * objspace )
{
2013-12-18 11:58:04 +04:00
if ( gc_prof_enabled ( objspace ) ) {
2013-06-24 02:58:01 +04:00
gc_profile_record * record = gc_prof_record ( objspace ) ;
2013-06-16 00:18:11 +04:00
# if GC_PROFILE_MORE_DETAIL
record - > prepare_time = objspace - > profile . prepare_time ;
# endif
2013-06-20 00:43:33 +04:00
record - > gc_time = 0 ;
record - > gc_invoke_time = getrusage_time ( ) ;
2012-08-04 18:12:12 +04:00
}
}
2013-06-20 00:43:33 +04:00
static double
elapsed_time_from ( double time )
{
double now = getrusage_time ( ) ;
if ( now > time ) {
return now - time ;
}
else {
return 0 ;
}
}
2012-08-04 18:12:12 +04:00
static inline void
2013-05-21 12:21:59 +04:00
gc_prof_timer_stop ( rb_objspace_t * objspace )
2012-08-04 18:12:12 +04:00
{
2013-12-18 11:58:04 +04:00
if ( gc_prof_enabled ( objspace ) ) {
2013-05-13 20:34:25 +04:00
gc_profile_record * record = gc_prof_record ( objspace ) ;
2013-06-20 00:43:33 +04:00
record - > gc_time = elapsed_time_from ( record - > gc_invoke_time ) ;
record - > gc_invoke_time - = objspace - > profile . invoke_time ;
2012-08-04 18:12:12 +04:00
}
}
static inline void
gc_prof_mark_timer_start ( rb_objspace_t * objspace )
{
* probes.d: add DTrace probe declarations. [ruby-core:27448]
* array.c (empty_ary_alloc, ary_new): added array create DTrace probe.
* compile.c (rb_insns_name): allowing DTrace probes to access
instruction sequence name.
* Makefile.in: translate probes.d file to appropriate header file.
* common.mk: declare dependencies on the DTrace header.
* configure.in: add a test for existence of DTrace.
* eval.c (setup_exception): add a probe for when an exception is
raised.
* gc.c: Add DTrace probes for mark begin and end, and sweep begin and
end.
* hash.c (empty_hash_alloc): Add a probe for hash allocation.
* insns.def: Add probes for function entry and return.
* internal.h: function declaration for compile.c change.
* load.c (rb_f_load): add probes for `load` entry and exit, require
entry and exit, and wrapping search_required for load path search.
* object.c (rb_obj_alloc): added a probe for general object creation.
* parse.y (yycompile0): added a probe around parse and compile phase.
* string.c (empty_str_alloc, str_new): DTrace probes for string
allocation.
* test/dtrace/*: tests for DTrace probes.
* vm.c (vm_invoke_proc): add probes for function return on exception
raise, hash create, and instruction sequence execution.
* vm_core.h: add probe declarations for function entry and exit.
* vm_dump.c: add probes header file.
* vm_eval.c (vm_call0_cfunc, vm_call0_cfunc_with_frame): add probe on
function entry and return.
* vm_exec.c: expose instruction number to instruction name function.
* vm_insnshelper.c: add function entry and exit probes for cfunc
methods.
* vm_insnhelper.h: vm usage information is always collected, so
uncomment the functions.
12 19:14:50 2012 Akinori MUSHA <knu@iDaemons.org>
* configure.in (isinf, isnan): isinf() and isnan() are macros on
DragonFly which cannot be found by AC_REPLACE_FUNCS(). This
workaround enforces the fact that they exist on DragonFly.
12 15:59:38 2012 Shugo Maeda <shugo@ruby-lang.org>
* vm_core.h (rb_call_info_t::refinements), compile.c (new_callinfo),
vm_insnhelper.c (vm_search_method): revert r37616 because it's too
slow. [ruby-dev:46477]
* test/ruby/test_refinement.rb (test_inline_method_cache): skip
the test until the bug is fixed efficiently.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37631 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-11-13 01:52:12 +04:00
if ( RUBY_DTRACE_GC_MARK_BEGIN_ENABLED ( ) ) {
RUBY_DTRACE_GC_MARK_BEGIN ( ) ;
}
2013-06-15 21:06:15 +04:00
# if GC_PROFILE_MORE_DETAIL
2013-12-18 11:58:04 +04:00
if ( gc_prof_enabled ( objspace ) ) {
2013-05-13 20:34:25 +04:00
gc_prof_record ( objspace ) - > gc_mark_time = getrusage_time ( ) ;
2012-08-04 18:12:12 +04:00
}
2013-06-15 21:06:15 +04:00
# endif
2012-08-04 18:12:12 +04:00
}
static inline void
gc_prof_mark_timer_stop ( rb_objspace_t * objspace )
{
* probes.d: add DTrace probe declarations. [ruby-core:27448]
* array.c (empty_ary_alloc, ary_new): added array create DTrace probe.
* compile.c (rb_insns_name): allowing DTrace probes to access
instruction sequence name.
* Makefile.in: translate probes.d file to appropriate header file.
* common.mk: declare dependencies on the DTrace header.
* configure.in: add a test for existence of DTrace.
* eval.c (setup_exception): add a probe for when an exception is
raised.
* gc.c: Add DTrace probes for mark begin and end, and sweep begin and
end.
* hash.c (empty_hash_alloc): Add a probe for hash allocation.
* insns.def: Add probes for function entry and return.
* internal.h: function declaration for compile.c change.
* load.c (rb_f_load): add probes for `load` entry and exit, require
entry and exit, and wrapping search_required for load path search.
* object.c (rb_obj_alloc): added a probe for general object creation.
* parse.y (yycompile0): added a probe around parse and compile phase.
* string.c (empty_str_alloc, str_new): DTrace probes for string
allocation.
* test/dtrace/*: tests for DTrace probes.
* vm.c (vm_invoke_proc): add probes for function return on exception
raise, hash create, and instruction sequence execution.
* vm_core.h: add probe declarations for function entry and exit.
* vm_dump.c: add probes header file.
* vm_eval.c (vm_call0_cfunc, vm_call0_cfunc_with_frame): add probe on
function entry and return.
* vm_exec.c: expose instruction number to instruction name function.
* vm_insnshelper.c: add function entry and exit probes for cfunc
methods.
* vm_insnhelper.h: vm usage information is always collected, so
uncomment the functions.
12 19:14:50 2012 Akinori MUSHA <knu@iDaemons.org>
* configure.in (isinf, isnan): isinf() and isnan() are macros on
DragonFly which cannot be found by AC_REPLACE_FUNCS(). This
workaround enforces the fact that they exist on DragonFly.
12 15:59:38 2012 Shugo Maeda <shugo@ruby-lang.org>
* vm_core.h (rb_call_info_t::refinements), compile.c (new_callinfo),
vm_insnhelper.c (vm_search_method): revert r37616 because it's too
slow. [ruby-dev:46477]
* test/ruby/test_refinement.rb (test_inline_method_cache): skip
the test until the bug is fixed efficiently.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37631 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-11-13 01:52:12 +04:00
if ( RUBY_DTRACE_GC_MARK_END_ENABLED ( ) ) {
RUBY_DTRACE_GC_MARK_END ( ) ;
}
2013-06-15 21:06:15 +04:00
# if GC_PROFILE_MORE_DETAIL
2013-12-18 11:58:04 +04:00
if ( gc_prof_enabled ( objspace ) ) {
2013-05-13 20:34:25 +04:00
gc_profile_record * record = gc_prof_record ( objspace ) ;
2013-06-20 00:43:33 +04:00
record - > gc_mark_time = elapsed_time_from ( record - > gc_mark_time ) ;
2012-08-04 18:12:12 +04:00
}
2013-06-15 21:06:15 +04:00
# endif
2012-08-04 18:12:12 +04:00
}
static inline void
2013-06-20 00:43:33 +04:00
gc_prof_sweep_timer_start ( rb_objspace_t * objspace )
2012-08-04 18:12:12 +04:00
{
* probes.d: add DTrace probe declarations. [ruby-core:27448]
* array.c (empty_ary_alloc, ary_new): added array create DTrace probe.
* compile.c (rb_insns_name): allowing DTrace probes to access
instruction sequence name.
* Makefile.in: translate probes.d file to appropriate header file.
* common.mk: declare dependencies on the DTrace header.
* configure.in: add a test for existence of DTrace.
* eval.c (setup_exception): add a probe for when an exception is
raised.
* gc.c: Add DTrace probes for mark begin and end, and sweep begin and
end.
* hash.c (empty_hash_alloc): Add a probe for hash allocation.
* insns.def: Add probes for function entry and return.
* internal.h: function declaration for compile.c change.
* load.c (rb_f_load): add probes for `load` entry and exit, require
entry and exit, and wrapping search_required for load path search.
* object.c (rb_obj_alloc): added a probe for general object creation.
* parse.y (yycompile0): added a probe around parse and compile phase.
* string.c (empty_str_alloc, str_new): DTrace probes for string
allocation.
* test/dtrace/*: tests for DTrace probes.
* vm.c (vm_invoke_proc): add probes for function return on exception
raise, hash create, and instruction sequence execution.
* vm_core.h: add probe declarations for function entry and exit.
* vm_dump.c: add probes header file.
* vm_eval.c (vm_call0_cfunc, vm_call0_cfunc_with_frame): add probe on
function entry and return.
* vm_exec.c: expose instruction number to instruction name function.
* vm_insnshelper.c: add function entry and exit probes for cfunc
methods.
* vm_insnhelper.h: vm usage information is always collected, so
uncomment the functions.
12 19:14:50 2012 Akinori MUSHA <knu@iDaemons.org>
* configure.in (isinf, isnan): isinf() and isnan() are macros on
DragonFly which cannot be found by AC_REPLACE_FUNCS(). This
workaround enforces the fact that they exist on DragonFly.
12 15:59:38 2012 Shugo Maeda <shugo@ruby-lang.org>
* vm_core.h (rb_call_info_t::refinements), compile.c (new_callinfo),
vm_insnhelper.c (vm_search_method): revert r37616 because it's too
slow. [ruby-dev:46477]
* test/ruby/test_refinement.rb (test_inline_method_cache): skip
the test until the bug is fixed efficiently.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37631 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-11-13 01:52:12 +04:00
if ( RUBY_DTRACE_GC_SWEEP_BEGIN_ENABLED ( ) ) {
RUBY_DTRACE_GC_SWEEP_BEGIN ( ) ;
}
2013-12-18 11:58:04 +04:00
if ( gc_prof_enabled ( objspace ) ) {
2013-06-20 00:49:28 +04:00
gc_profile_record * record = gc_prof_record ( objspace ) ;
2013-06-20 00:43:33 +04:00
if ( record - > gc_time > 0 | | GC_PROFILE_MORE_DETAIL ) {
objspace - > profile . gc_sweep_start_time = getrusage_time ( ) ;
}
2012-08-04 18:12:12 +04:00
}
}
static inline void
2013-06-20 00:43:33 +04:00
gc_prof_sweep_timer_stop ( rb_objspace_t * objspace )
2012-08-04 18:12:12 +04:00
{
* probes.d: add DTrace probe declarations. [ruby-core:27448]
* array.c (empty_ary_alloc, ary_new): added array create DTrace probe.
* compile.c (rb_insns_name): allowing DTrace probes to access
instruction sequence name.
* Makefile.in: translate probes.d file to appropriate header file.
* common.mk: declare dependencies on the DTrace header.
* configure.in: add a test for existence of DTrace.
* eval.c (setup_exception): add a probe for when an exception is
raised.
* gc.c: Add DTrace probes for mark begin and end, and sweep begin and
end.
* hash.c (empty_hash_alloc): Add a probe for hash allocation.
* insns.def: Add probes for function entry and return.
* internal.h: function declaration for compile.c change.
* load.c (rb_f_load): add probes for `load` entry and exit, require
entry and exit, and wrapping search_required for load path search.
* object.c (rb_obj_alloc): added a probe for general object creation.
* parse.y (yycompile0): added a probe around parse and compile phase.
* string.c (empty_str_alloc, str_new): DTrace probes for string
allocation.
* test/dtrace/*: tests for DTrace probes.
* vm.c (vm_invoke_proc): add probes for function return on exception
raise, hash create, and instruction sequence execution.
* vm_core.h: add probe declarations for function entry and exit.
* vm_dump.c: add probes header file.
* vm_eval.c (vm_call0_cfunc, vm_call0_cfunc_with_frame): add probe on
function entry and return.
* vm_exec.c: expose instruction number to instruction name function.
* vm_insnshelper.c: add function entry and exit probes for cfunc
methods.
* vm_insnhelper.h: vm usage information is always collected, so
uncomment the functions.
12 19:14:50 2012 Akinori MUSHA <knu@iDaemons.org>
* configure.in (isinf, isnan): isinf() and isnan() are macros on
DragonFly which cannot be found by AC_REPLACE_FUNCS(). This
workaround enforces the fact that they exist on DragonFly.
12 15:59:38 2012 Shugo Maeda <shugo@ruby-lang.org>
* vm_core.h (rb_call_info_t::refinements), compile.c (new_callinfo),
vm_insnhelper.c (vm_search_method): revert r37616 because it's too
slow. [ruby-dev:46477]
* test/ruby/test_refinement.rb (test_inline_method_cache): skip
the test until the bug is fixed efficiently.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37631 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-11-13 01:52:12 +04:00
if ( RUBY_DTRACE_GC_SWEEP_END_ENABLED ( ) ) {
RUBY_DTRACE_GC_SWEEP_END ( ) ;
}
2013-06-21 10:29:30 +04:00
2013-12-18 11:58:04 +04:00
if ( gc_prof_enabled ( objspace ) ) {
2013-06-20 00:43:33 +04:00
double sweep_time ;
gc_profile_record * record = gc_prof_record ( objspace ) ;
2012-08-04 18:12:12 +04:00
2013-06-21 00:39:20 +04:00
if ( record - > gc_time > 0 ) {
2013-06-20 00:43:33 +04:00
sweep_time = elapsed_time_from ( objspace - > profile . gc_sweep_start_time ) ;
2013-06-21 00:39:20 +04:00
/* need to accumulate GC time for lazy sweep after gc() */
2013-06-20 00:43:33 +04:00
record - > gc_time + = sweep_time ;
}
2013-06-21 00:39:20 +04:00
else if ( GC_PROFILE_MORE_DETAIL ) {
sweep_time = elapsed_time_from ( objspace - > profile . gc_sweep_start_time ) ;
}
2013-05-21 12:19:07 +04:00
2013-06-20 00:43:33 +04:00
# if GC_PROFILE_MORE_DETAIL
record - > gc_sweep_time + = sweep_time ;
2013-10-23 09:22:10 +04:00
if ( heap_pages_deferred_final ) record - > flags | = GPR_FLAG_HAVE_FINALIZE ;
2013-06-15 21:06:15 +04:00
# endif
2013-12-05 14:30:38 +04:00
if ( heap_pages_deferred_final ) objspace - > profile . latest_gc_info | = GPR_FLAG_HAVE_FINALIZE ;
2013-06-20 00:43:33 +04:00
}
2012-08-04 18:12:12 +04:00
}
static inline void
gc_prof_set_malloc_info ( rb_objspace_t * objspace )
{
2013-06-15 21:06:15 +04:00
# if GC_PROFILE_MORE_DETAIL
2013-12-18 11:58:04 +04:00
if ( gc_prof_enabled ( objspace ) ) {
2013-05-13 20:34:25 +04:00
gc_profile_record * record = gc_prof_record ( objspace ) ;
2013-09-27 12:01:14 +04:00
record - > allocate_increase = malloc_increase ;
2013-05-13 20:34:25 +04:00
record - > allocate_limit = malloc_limit ;
2012-08-04 18:12:12 +04:00
}
2013-06-15 21:06:15 +04:00
# endif
2012-08-04 18:12:12 +04:00
}
static inline void
2013-06-22 02:29:09 +04:00
gc_prof_set_heap_info ( rb_objspace_t * objspace )
2012-08-04 18:12:12 +04:00
{
2013-12-18 11:58:04 +04:00
if ( gc_prof_enabled ( objspace ) ) {
2013-06-22 02:29:09 +04:00
gc_profile_record * record = gc_prof_record ( objspace ) ;
2013-11-01 16:49:49 +04:00
size_t live = objspace - > profile . total_allocated_object_num_at_gc_start - objspace - > profile . total_freed_object_num ;
2013-07-17 09:55:39 +04:00
size_t total = objspace - > profile . heap_used_at_gc_start * HEAP_OBJ_LIMIT ;
2012-08-04 18:12:12 +04:00
2013-06-15 21:06:15 +04:00
# if GC_PROFILE_MORE_DETAIL
2013-10-18 10:33:36 +04:00
record - > heap_use_pages = objspace - > profile . heap_used_at_gc_start ;
2013-06-22 02:29:09 +04:00
record - > heap_live_objects = live ;
record - > heap_free_objects = total - live ;
2013-06-15 21:06:15 +04:00
# endif
2013-06-20 16:20:27 +04:00
2013-06-22 02:29:09 +04:00
record - > heap_total_objects = total ;
record - > heap_use_size = live * sizeof ( RVALUE ) ;
record - > heap_total_size = total * sizeof ( RVALUE ) ;
}
2012-08-04 18:12:12 +04:00
}
/*
* call - seq :
* GC : : Profiler . clear - > nil
*
* Clears the GC profiler data .
*
*/
static VALUE
gc_profile_clear ( void )
{
rb_objspace_t * objspace = & rb_objspace ;
2012-11-21 17:15:10 +04:00
if ( GC_PROFILE_RECORD_DEFAULT_SIZE * 2 < objspace - > profile . size ) {
objspace - > profile . size = GC_PROFILE_RECORD_DEFAULT_SIZE * 2 ;
2013-06-22 01:51:41 +04:00
objspace - > profile . records = realloc ( objspace - > profile . records , sizeof ( gc_profile_record ) * objspace - > profile . size ) ;
if ( ! objspace - > profile . records ) {
2012-11-21 17:15:10 +04:00
rb_memerror ( ) ;
}
}
2013-06-22 01:51:41 +04:00
MEMZERO ( objspace - > profile . records , gc_profile_record , objspace - > profile . size ) ;
2013-05-13 20:34:25 +04:00
objspace - > profile . next_index = 0 ;
2013-06-22 01:51:41 +04:00
objspace - > profile . current_record = 0 ;
2012-08-04 18:12:12 +04:00
return Qnil ;
}
2011-09-08 07:57:41 +04:00
/*
* call - seq :
2012-11-29 12:15:53 +04:00
* GC : : Profiler . raw_data - > [ Hash , . . . ]
2011-09-08 07:57:41 +04:00
*
* Returns an Array of individual raw profile data Hashes ordered
2012-11-29 12:15:53 +04:00
* from earliest to latest by + : GC_INVOKE_TIME + .
*
* For example :
2011-09-08 07:57:41 +04:00
*
2012-11-29 12:15:53 +04:00
* [
* {
* : GC_TIME = > 1.3000000000000858e-05 ,
* : GC_INVOKE_TIME = > 0.010634999999999999 ,
* : HEAP_USE_SIZE = > 289640 ,
* : HEAP_TOTAL_SIZE = > 588960 ,
* : HEAP_TOTAL_OBJECTS = > 14724 ,
* : GC_IS_MARKED = > false
* } ,
* # . . .
2011-09-08 07:57:41 +04:00
* ]
*
* The keys mean :
*
2012-11-29 12:15:53 +04:00
* + : GC_TIME + : :
* Time elapsed in seconds for this GC run
* + : GC_INVOKE_TIME + : :
* Time elapsed in seconds from startup to when the GC was invoked
* + : HEAP_USE_SIZE + : :
* Total bytes of heap used
* + : HEAP_TOTAL_SIZE + : :
* Total size of heap in bytes
* + : HEAP_TOTAL_OBJECTS + : :
* Total number of objects
* + : GC_IS_MARKED + : :
* Returns + true + if the GC is in mark phase
*
* If ruby was built with + GC_PROFILE_MORE_DETAIL + , you will also have access
* to the following hash keys :
*
* + : GC_MARK_TIME + : :
* + : GC_SWEEP_TIME + : :
* + : ALLOCATE_INCREASE + : :
* + : ALLOCATE_LIMIT + : :
2013-10-18 10:33:36 +04:00
* + : HEAP_USE_PAGES + : :
2012-11-29 12:15:53 +04:00
* + : HEAP_LIVE_OBJECTS + : :
* + : HEAP_FREE_OBJECTS + : :
* + : HAVE_FINALIZE + : :
2011-09-08 07:57:41 +04:00
*
*/
2008-09-04 14:47:39 +04:00
static VALUE
2008-08-11 13:36:57 +04:00
gc_profile_record_get ( void )
{
VALUE prof ;
VALUE gc_profile = rb_ary_new ( ) ;
size_t i ;
rb_objspace_t * objspace = ( & rb_objspace ) ;
2009-02-22 17:23:33 +03:00
2013-12-18 12:04:08 +04:00
if ( ! objspace - > profile . run ) {
2008-08-11 13:36:57 +04:00
return Qnil ;
}
2013-05-13 20:34:25 +04:00
for ( i = 0 ; i < objspace - > profile . next_index ; i + + ) {
2013-06-22 01:51:41 +04:00
gc_profile_record * record = & objspace - > profile . records [ i ] ;
2008-08-11 13:36:57 +04:00
prof = rb_hash_new ( ) ;
2013-12-05 14:30:38 +04:00
rb_hash_aset ( prof , ID2SYM ( rb_intern ( " GC_FLAGS " ) ) , gc_info_decode ( record - > flags , rb_hash_new ( ) ) ) ;
2013-06-22 01:51:41 +04:00
rb_hash_aset ( prof , ID2SYM ( rb_intern ( " GC_TIME " ) ) , DBL2NUM ( record - > gc_time ) ) ;
rb_hash_aset ( prof , ID2SYM ( rb_intern ( " GC_INVOKE_TIME " ) ) , DBL2NUM ( record - > gc_invoke_time ) ) ;
rb_hash_aset ( prof , ID2SYM ( rb_intern ( " HEAP_USE_SIZE " ) ) , SIZET2NUM ( record - > heap_use_size ) ) ;
rb_hash_aset ( prof , ID2SYM ( rb_intern ( " HEAP_TOTAL_SIZE " ) ) , SIZET2NUM ( record - > heap_total_size ) ) ;
rb_hash_aset ( prof , ID2SYM ( rb_intern ( " HEAP_TOTAL_OBJECTS " ) ) , SIZET2NUM ( record - > heap_total_objects ) ) ;
2013-05-21 12:21:59 +04:00
rb_hash_aset ( prof , ID2SYM ( rb_intern ( " GC_IS_MARKED " ) ) , Qtrue ) ;
2008-08-11 13:36:57 +04:00
# if GC_PROFILE_MORE_DETAIL
2013-06-22 01:51:41 +04:00
rb_hash_aset ( prof , ID2SYM ( rb_intern ( " GC_MARK_TIME " ) ) , DBL2NUM ( record - > gc_mark_time ) ) ;
rb_hash_aset ( prof , ID2SYM ( rb_intern ( " GC_SWEEP_TIME " ) ) , DBL2NUM ( record - > gc_sweep_time ) ) ;
rb_hash_aset ( prof , ID2SYM ( rb_intern ( " ALLOCATE_INCREASE " ) ) , SIZET2NUM ( record - > allocate_increase ) ) ;
rb_hash_aset ( prof , ID2SYM ( rb_intern ( " ALLOCATE_LIMIT " ) ) , SIZET2NUM ( record - > allocate_limit ) ) ;
2013-10-18 10:33:36 +04:00
rb_hash_aset ( prof , ID2SYM ( rb_intern ( " HEAP_USE_PAGES " ) ) , SIZET2NUM ( record - > heap_use_pages ) ) ;
2013-06-22 01:51:41 +04:00
rb_hash_aset ( prof , ID2SYM ( rb_intern ( " HEAP_LIVE_OBJECTS " ) ) , SIZET2NUM ( record - > heap_live_objects ) ) ;
rb_hash_aset ( prof , ID2SYM ( rb_intern ( " HEAP_FREE_OBJECTS " ) ) , SIZET2NUM ( record - > heap_free_objects ) ) ;
rb_hash_aset ( prof , ID2SYM ( rb_intern ( " REMOVING_OBJECTS " ) ) , SIZET2NUM ( record - > removing_objects ) ) ;
rb_hash_aset ( prof , ID2SYM ( rb_intern ( " EMPTY_OBJECTS " ) ) , SIZET2NUM ( record - > empty_objects ) ) ;
rb_hash_aset ( prof , ID2SYM ( rb_intern ( " HAVE_FINALIZE " ) ) , ( record - > flags & GPR_FLAG_HAVE_FINALIZE ) ? Qtrue : Qfalse ) ;
2008-08-11 13:36:57 +04:00
# endif
2013-06-20 16:20:27 +04:00
# if RGENGC_PROFILE > 0
2013-11-04 22:59:33 +04:00
rb_hash_aset ( prof , ID2SYM ( rb_intern ( " OLD_OBJECTS " ) ) , SIZET2NUM ( record - > old_objects ) ) ;
2013-06-22 01:51:41 +04:00
rb_hash_aset ( prof , ID2SYM ( rb_intern ( " REMEMBED_NORMAL_OBJECTS " ) ) , SIZET2NUM ( record - > remembered_normal_objects ) ) ;
rb_hash_aset ( prof , ID2SYM ( rb_intern ( " REMEMBED_SHADY_OBJECTS " ) ) , SIZET2NUM ( record - > remembered_shady_objects ) ) ;
2013-06-20 16:20:27 +04:00
# endif
2008-08-11 13:36:57 +04:00
rb_ary_push ( gc_profile , prof ) ;
}
return gc_profile ;
}
2013-11-24 23:49:02 +04:00
# if GC_PROFILE_MORE_DETAIL
2013-12-18 18:34:23 +04:00
# define MAJOR_REASON_MAX 0x10
static char *
gc_profile_dump_major_reason ( int flags , char * buff )
{
int reason = flags & GPR_FLAG_MAJOR_MASK ;
int i = 0 ;
if ( reason = = GPR_FLAG_NONE ) {
buff [ 0 ] = ' - ' ;
buff [ 1 ] = 0 ;
}
else {
# define C(x, s) \
if ( reason & GPR_FLAG_MAJOR_BY_ # # x ) { \
buff [ i + + ] = # x [ 0 ] ; \
if ( i > = MAJOR_REASON_MAX ) rb_bug ( " gc_profile_dump_major_reason: overflow " ) ; \
buff [ i ] = 0 ; \
}
C ( NOFREE , N ) ;
C ( OLDGEN , O ) ;
C ( SHADY , S ) ;
C ( RESCAN , R ) ;
C ( STRESS , T ) ;
2013-11-24 23:49:02 +04:00
# if RGENGC_ESTIMATE_OLDMALLOC
2013-12-18 18:34:23 +04:00
C ( OLDMALLOC , M ) ;
2013-11-24 23:49:02 +04:00
# endif
# undef C
}
2013-12-18 18:34:23 +04:00
return buff ;
2013-11-24 23:49:02 +04:00
}
# endif
2012-10-27 18:36:22 +04:00
static void
gc_profile_dump_on ( VALUE out , VALUE ( * append ) ( VALUE , VALUE ) )
2008-08-11 13:36:57 +04:00
{
rb_objspace_t * objspace = & rb_objspace ;
2013-05-22 11:50:20 +04:00
size_t count = objspace - > profile . next_index ;
2013-12-18 18:34:23 +04:00
# ifdef MAJOR_REASON_MAX
char reason_str [ MAJOR_REASON_MAX ] ;
# endif
2009-02-22 17:23:33 +03:00
2013-05-22 11:50:20 +04:00
if ( objspace - > profile . run & & count /* > 1 */ ) {
size_t i ;
2013-05-21 11:27:32 +04:00
const gc_profile_record * record ;
2013-11-01 16:49:49 +04:00
append ( out , rb_sprintf ( " GC % " PRIuSIZE " invokes. \n " , objspace - > profile . count ) ) ;
2012-10-27 18:36:22 +04:00
append ( out , rb_str_new_cstr ( " Index Invoke Time(sec) Use Size(byte) Total Size(byte) Total Object GC Time(ms) \n " ) ) ;
2013-05-21 11:27:32 +04:00
2012-10-27 18:36:22 +04:00
for ( i = 0 ; i < count ; i + + ) {
2013-06-22 01:51:41 +04:00
record = & objspace - > profile . records [ i ] ;
2013-05-22 11:50:20 +04:00
append ( out , rb_sprintf ( " %5 " PRIdSIZE " %19.3f %20 " PRIuSIZE " %20 " PRIuSIZE " %20 " PRIuSIZE " %30.20f \n " ,
i + 1 , record - > gc_invoke_time , record - > heap_use_size ,
2013-05-21 12:19:07 +04:00
record - > heap_total_size , record - > heap_total_objects , record - > gc_time * 1000 ) ) ;
2008-08-11 13:36:57 +04:00
}
2013-06-21 02:38:08 +04:00
2008-08-11 13:36:57 +04:00
# if GC_PROFILE_MORE_DETAIL
2012-10-27 18:36:22 +04:00
append ( out , rb_str_new_cstr ( " \n \n " \
2013-05-21 11:27:32 +04:00
" More detail. \n " \
2013-06-16 00:18:11 +04:00
" Prepare Time = Previously GC's rest sweep time \n "
2013-12-18 18:34:23 +04:00
" Index Flags Allocate Inc. Allocate Limit "
2013-06-16 00:18:11 +04:00
# if CALC_EXACT_MALLOC_SIZE
" Allocated Size "
# endif
2013-10-26 09:35:43 +04:00
" Use Page Mark Time(ms) Sweep Time(ms) Prepare Time(ms) LivingObj FreeObj RemovedObj EmptyObj "
2013-06-21 02:38:08 +04:00
# if RGENGC_PROFILE
" OldgenObj RemNormObj RemShadObj "
2013-11-09 03:59:20 +04:00
# endif
# if GC_PROFILE_DETAIL_MEMORY
" MaxRSS(KB) MinorFLT MajorFLT "
2013-06-21 02:38:08 +04:00
# endif
" \n " ) ) ;
2012-10-27 18:36:22 +04:00
for ( i = 0 ; i < count ; i + + ) {
2013-06-22 01:51:41 +04:00
record = & objspace - > profile . records [ i ] ;
2013-12-18 18:34:23 +04:00
append ( out , rb_sprintf ( " %5 " PRIdSIZE " %4s/%c/%6s%c %13 " PRIuSIZE " %15 " PRIuSIZE
2013-06-16 00:18:11 +04:00
# if CALC_EXACT_MALLOC_SIZE
" %15 " PRIuSIZE
# endif
2013-06-21 02:38:08 +04:00
" %9 " PRIuSIZE " %17.12f %17.12f %17.12f %10 " PRIuSIZE " %10 " PRIuSIZE " %10 " PRIuSIZE " %10 " PRIuSIZE
# if RGENGC_PROFILE
2013-06-21 04:24:14 +04:00
" %10 " PRIuSIZE " %10 " PRIuSIZE " %10 " PRIuSIZE
2013-06-21 02:38:08 +04:00
# endif
2013-11-09 03:59:20 +04:00
# if GC_PROFILE_DETAIL_MEMORY
" %11ld %8ld %8ld "
# endif
2013-06-21 04:24:14 +04:00
" \n " ,
2013-05-22 11:50:20 +04:00
i + 1 ,
2013-12-18 18:34:23 +04:00
gc_profile_dump_major_reason ( record - > flags , reason_str ) ,
2013-05-21 12:19:07 +04:00
( record - > flags & GPR_FLAG_HAVE_FINALIZE ) ? ' F ' : ' . ' ,
( record - > flags & GPR_FLAG_NEWOBJ ) ? " NEWOBJ " :
( record - > flags & GPR_FLAG_MALLOC ) ? " MALLOC " :
( record - > flags & GPR_FLAG_METHOD ) ? " METHOD " :
2013-06-16 00:18:11 +04:00
( record - > flags & GPR_FLAG_CAPI ) ? " CAPI__ " : " ?????? " ,
2013-05-21 12:19:07 +04:00
( record - > flags & GPR_FLAG_STRESS ) ? ' ! ' : ' ' ,
record - > allocate_increase , record - > allocate_limit ,
2013-06-16 00:18:11 +04:00
# if CALC_EXACT_MALLOC_SIZE
record - > allocated_size ,
# endif
2013-10-18 10:33:36 +04:00
record - > heap_use_pages ,
2013-06-21 02:38:08 +04:00
record - > gc_mark_time * 1000 ,
record - > gc_sweep_time * 1000 ,
2013-06-16 00:18:11 +04:00
record - > prepare_time * 1000 ,
2013-06-21 02:38:08 +04:00
record - > heap_live_objects ,
record - > heap_free_objects ,
2013-06-16 00:18:11 +04:00
record - > removing_objects ,
record - > empty_objects
2013-06-21 02:38:08 +04:00
# if RGENGC_PROFILE
,
2013-11-04 22:59:33 +04:00
record - > old_objects ,
2013-06-21 02:38:08 +04:00
record - > remembered_normal_objects ,
record - > remembered_shady_objects
# endif
2013-11-09 03:59:20 +04:00
# if GC_PROFILE_DETAIL_MEMORY
,
record - > maxrss / 1024 ,
record - > minflt ,
record - > majflt
# endif
2013-06-16 00:18:11 +04:00
) ) ;
2008-08-11 13:36:57 +04:00
}
# endif
}
}
2012-10-27 18:36:22 +04:00
/*
* call - seq :
2012-11-29 12:15:53 +04:00
* GC : : Profiler . result - > String
2012-10-27 18:36:22 +04:00
*
* Returns a profile data report such as :
*
* GC 1 invokes .
* Index Invoke Time ( sec ) Use Size ( byte ) Total Size ( byte ) Total Object GC time ( ms )
* 1 0.012 159240 212940 10647 0.00000000000001530000
*/
static VALUE
gc_profile_result ( void )
{
VALUE str = rb_str_buf_new ( 0 ) ;
gc_profile_dump_on ( str , rb_str_buf_append ) ;
return str ;
}
2008-08-11 13:36:57 +04:00
/*
* call - seq :
* GC : : Profiler . report
2012-11-29 12:15:53 +04:00
* GC : : Profiler . report ( io )
2008-08-11 13:36:57 +04:00
*
2012-11-29 12:15:53 +04:00
* Writes the GC : : Profiler . result to < tt > $ stdout < / tt > or the given IO object .
2009-02-22 17:23:33 +03:00
*
2008-08-11 13:36:57 +04:00
*/
2008-09-04 14:47:39 +04:00
static VALUE
2008-08-11 13:36:57 +04:00
gc_profile_report ( int argc , VALUE * argv , VALUE self )
{
VALUE out ;
if ( argc = = 0 ) {
out = rb_stdout ;
}
else {
rb_scan_args ( argc , argv , " 01 " , & out ) ;
}
2012-10-27 18:36:22 +04:00
gc_profile_dump_on ( out , rb_io_write ) ;
2008-08-11 13:36:57 +04:00
return Qnil ;
}
2010-03-04 07:51:43 +03:00
/*
* call - seq :
2012-11-29 12:15:53 +04:00
* GC : : Profiler . total_time - > float
2010-03-04 07:51:43 +03:00
*
2012-10-20 15:36:46 +04:00
* The total time used for garbage collection in seconds
2010-03-04 07:51:43 +03:00
*/
static VALUE
gc_profile_total_time ( VALUE self )
{
double time = 0 ;
rb_objspace_t * objspace = & rb_objspace ;
2013-06-20 01:21:16 +04:00
if ( objspace - > profile . run & & objspace - > profile . next_index > 0 ) {
size_t i ;
2013-10-29 06:11:26 +04:00
size_t count = objspace - > profile . next_index ;
2013-06-20 01:21:16 +04:00
2013-05-13 20:34:25 +04:00
for ( i = 0 ; i < count ; i + + ) {
2013-06-22 01:51:41 +04:00
time + = objspace - > profile . records [ i ] . gc_time ;
2010-03-04 07:51:43 +03:00
}
}
return DBL2NUM ( time ) ;
}
2012-08-05 14:39:37 +04:00
/*
* call - seq :
2012-11-29 12:15:53 +04:00
* GC : : Profiler . enabled ? - > true or false
2012-08-05 14:39:37 +04:00
*
* The current status of GC profile mode .
*/
static VALUE
gc_profile_enable_get ( VALUE self )
{
rb_objspace_t * objspace = & rb_objspace ;
return objspace - > profile . run ? Qtrue : Qfalse ;
}
/*
* call - seq :
2012-11-29 12:15:53 +04:00
* GC : : Profiler . enable - > nil
2012-08-05 14:39:37 +04:00
*
* Starts the GC profiler .
*
*/
static VALUE
gc_profile_enable ( void )
{
rb_objspace_t * objspace = & rb_objspace ;
objspace - > profile . run = TRUE ;
2013-12-18 11:58:04 +04:00
objspace - > profile . current_record = 0 ;
2012-08-05 14:39:37 +04:00
return Qnil ;
}
/*
* call - seq :
2012-11-29 12:15:53 +04:00
* GC : : Profiler . disable - > nil
2012-08-05 14:39:37 +04:00
*
* Stops the GC profiler .
*
*/
static VALUE
gc_profile_disable ( void )
{
rb_objspace_t * objspace = & rb_objspace ;
objspace - > profile . run = FALSE ;
2013-06-22 01:51:41 +04:00
objspace - > profile . current_record = 0 ;
2012-08-05 14:39:37 +04:00
return Qnil ;
}
2012-11-22 19:03:46 +04:00
/*
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - DEBUG - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
2013-07-18 03:19:38 +04:00
static const char *
type_name ( int type , VALUE obj )
{
switch ( type ) {
# define TYPE_NAME(t) case (t): return #t;
TYPE_NAME ( T_NONE ) ;
TYPE_NAME ( T_OBJECT ) ;
TYPE_NAME ( T_CLASS ) ;
TYPE_NAME ( T_MODULE ) ;
TYPE_NAME ( T_FLOAT ) ;
TYPE_NAME ( T_STRING ) ;
TYPE_NAME ( T_REGEXP ) ;
TYPE_NAME ( T_ARRAY ) ;
TYPE_NAME ( T_HASH ) ;
TYPE_NAME ( T_STRUCT ) ;
TYPE_NAME ( T_BIGNUM ) ;
TYPE_NAME ( T_FILE ) ;
TYPE_NAME ( T_MATCH ) ;
TYPE_NAME ( T_COMPLEX ) ;
TYPE_NAME ( T_RATIONAL ) ;
TYPE_NAME ( T_NIL ) ;
TYPE_NAME ( T_TRUE ) ;
TYPE_NAME ( T_FALSE ) ;
TYPE_NAME ( T_SYMBOL ) ;
TYPE_NAME ( T_FIXNUM ) ;
TYPE_NAME ( T_UNDEF ) ;
TYPE_NAME ( T_NODE ) ;
TYPE_NAME ( T_ICLASS ) ;
TYPE_NAME ( T_ZOMBIE ) ;
case T_DATA :
if ( obj & & rb_objspace_data_type_name ( obj ) ) {
return rb_objspace_data_type_name ( obj ) ;
}
return " T_DATA " ;
# undef TYPE_NAME
}
return " unknown " ;
}
static const char *
obj_type_name ( VALUE obj )
{
return type_name ( TYPE ( obj ) , obj ) ;
}
2013-08-19 16:00:51 +04:00
# if GC_DEBUG
2013-07-18 03:19:38 +04:00
2012-11-22 19:03:46 +04:00
void
rb_gcdebug_print_obj_condition ( VALUE obj )
{
rb_objspace_t * objspace = & rb_objspace ;
2013-08-20 21:32:18 +04:00
fprintf ( stderr , " created at: %s:%d \n " , RSTRING_PTR ( RANY ( obj ) - > file ) , FIX2INT ( RANY ( obj ) - > line ) ) ;
2012-11-22 19:03:46 +04:00
if ( is_pointer_to_heap ( objspace , ( void * ) obj ) ) {
fprintf ( stderr , " pointer to heap?: true \n " ) ;
}
else {
fprintf ( stderr , " pointer to heap?: false \n " ) ;
return ;
}
2013-08-20 21:32:18 +04:00
2013-12-13 06:38:05 +04:00
fprintf ( stderr , " marked? : %s \n " , MARKED_IN_BITMAP ( GET_HEAP_MARK_BITS ( obj ) , obj ) ? " true " : " false " ) ;
2013-08-20 21:32:18 +04:00
# if USE_RGENGC
2013-11-04 22:59:33 +04:00
# if RGENGC_THREEGEN
2013-12-13 06:38:05 +04:00
fprintf ( stderr , " young? : %s \n " , RVALUE_YOUNG_P ( obj ) ? " true " : " false " ) ;
2013-11-04 22:59:33 +04:00
# endif
2013-12-13 06:38:05 +04:00
fprintf ( stderr , " old? : %s \n " , RVALUE_OLD_P ( obj ) ? " true " : " false " ) ;
fprintf ( stderr , " WB-protected?: %s \n " , RVALUE_WB_PROTECTED ( obj ) ? " true " : " false " ) ;
fprintf ( stderr , " remembered? : %s \n " , MARKED_IN_BITMAP ( GET_HEAP_REMEMBERSET_BITS ( obj ) , obj ) ? " true " : " false " ) ;
2013-08-20 21:32:18 +04:00
# endif
2013-10-26 14:42:07 +04:00
if ( is_lazy_sweeping ( heap_eden ) ) {
2012-11-22 19:03:46 +04:00
fprintf ( stderr , " lazy sweeping?: true \n " ) ;
2013-08-20 21:32:18 +04:00
fprintf ( stderr , " swept?: %s \n " , is_swept_object ( objspace , obj ) ? " done " : " not yet " ) ;
2012-11-22 19:03:46 +04:00
}
else {
fprintf ( stderr , " lazy sweeping?: false \n " ) ;
}
}
static VALUE
gcdebug_sential ( VALUE obj , VALUE name )
{
fprintf ( stderr , " WARNING: object %s(%p) is inadvertently collected \n " , ( char * ) name , ( void * ) obj ) ;
return Qnil ;
}
void
rb_gcdebug_sentinel ( VALUE obj , const char * name )
{
2013-11-10 03:03:11 +04:00
rb_define_finalizer ( obj , rb_proc_new ( gcdebug_sential , ( VALUE ) name ) ) ;
2012-11-22 19:03:46 +04:00
}
# endif /* GC_DEBUG */
2012-08-05 14:39:37 +04:00
/*
2013-06-17 12:44:56 +04:00
* Document - module : ObjectSpace
2012-08-05 14:39:37 +04:00
*
2012-11-29 12:15:53 +04:00
* The ObjectSpace module contains a number of routines
2012-08-05 14:39:37 +04:00
* that interact with the garbage collection facility and allow you to
* traverse all living objects with an iterator .
*
2012-11-29 12:15:53 +04:00
* ObjectSpace also provides support for object finalizers , procs that will be
* called when a specific object is about to be destroyed by garbage
* collection .
2012-08-05 14:39:37 +04:00
*
* a = " A "
* b = " B "
*
2013-06-17 12:39:39 +04:00
* ObjectSpace . define_finalizer ( a , proc { | id | puts " Finalizer one on #{id} " } )
* ObjectSpace . define_finalizer ( b , proc { | id | puts " Finalizer two on #{id} " } )
2012-08-05 14:39:37 +04:00
*
2012-11-29 12:15:53 +04:00
* _produces : _
2012-08-05 14:39:37 +04:00
*
2013-06-17 12:39:39 +04:00
* Finalizer two on 537763470
2012-08-05 14:39:37 +04:00
* Finalizer one on 537763480
*/
/*
* Document - class : ObjectSpace : : WeakMap
*
2012-11-29 12:15:53 +04:00
* An ObjectSpace : : WeakMap object holds references to
2013-02-23 11:06:10 +04:00
* any objects , but those objects can get garbage collected .
2012-12-02 11:45:17 +04:00
*
* This class is mostly used internally by WeakRef , please use
* + lib / weakref . rb + for the public interface .
2012-08-05 14:39:37 +04:00
*/
2011-07-08 04:18:39 +04:00
/* Document-class: GC::Profiler
*
* The GC profiler provides access to information on GC runs including time ,
* length and object space size .
*
* Example :
*
* GC : : Profiler . enable
*
* require ' rdoc / rdoc '
*
2012-11-29 12:15:53 +04:00
* GC : : Profiler . report
2011-07-08 04:18:39 +04:00
*
* GC : : Profiler . disable
*
* See also GC . count , GC . malloc_allocated_size and GC . malloc_allocations
*/
2010-05-28 15:13:42 +04:00
2003-12-22 09:20:14 +03:00
/*
2012-11-29 12:15:53 +04:00
* The GC module provides an interface to Ruby ' s mark and
* sweep garbage collection mechanism .
*
* Some of the underlying methods are also available via the ObjectSpace
* module .
2011-07-08 04:18:39 +04:00
*
* You may obtain information about the operation of the GC through
* GC : : Profiler .
2003-12-22 09:20:14 +03:00
*/
1998-01-16 15:13:05 +03:00
void
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
Init_GC ( void )
1998-01-16 15:13:05 +03:00
{
2013-06-18 16:59:02 +04:00
VALUE rb_mObjSpace ;
2008-08-11 13:36:57 +04:00
VALUE rb_mProfiler ;
2013-11-27 10:57:14 +04:00
VALUE gc_constants ;
1999-01-20 07:59:39 +03:00
rb_mGC = rb_define_module ( " GC " ) ;
2013-12-06 09:11:51 +04:00
rb_define_singleton_method ( rb_mGC , " start " , gc_start_internal , - 1 ) ;
2001-01-29 08:10:42 +03:00
rb_define_singleton_method ( rb_mGC , " enable " , rb_gc_enable , 0 ) ;
rb_define_singleton_method ( rb_mGC , " disable " , rb_gc_disable , 0 ) ;
2006-01-10 01:32:55 +03:00
rb_define_singleton_method ( rb_mGC , " stress " , gc_stress_get , 0 ) ;
rb_define_singleton_method ( rb_mGC , " stress= " , gc_stress_set , 1 ) ;
2008-04-27 10:28:08 +04:00
rb_define_singleton_method ( rb_mGC , " count " , gc_count , 0 ) ;
2010-10-27 23:02:24 +04:00
rb_define_singleton_method ( rb_mGC , " stat " , gc_stat , - 1 ) ;
2013-12-05 14:30:38 +04:00
rb_define_singleton_method ( rb_mGC , " latest_gc_info " , gc_latest_gc_info , - 1 ) ;
2013-12-06 09:11:51 +04:00
rb_define_method ( rb_mGC , " garbage_collect " , gc_start_internal , - 1 ) ;
1999-01-20 07:59:39 +03:00
2013-11-27 10:57:14 +04:00
gc_constants = rb_hash_new ( ) ;
rb_hash_aset ( gc_constants , ID2SYM ( rb_intern ( " RVALUE_SIZE " ) ) , SIZET2NUM ( sizeof ( RVALUE ) ) ) ;
rb_hash_aset ( gc_constants , ID2SYM ( rb_intern ( " HEAP_OBJ_LIMIT " ) ) , SIZET2NUM ( HEAP_OBJ_LIMIT ) ) ;
rb_hash_aset ( gc_constants , ID2SYM ( rb_intern ( " HEAP_BITMAP_SIZE " ) ) , SIZET2NUM ( HEAP_BITMAP_SIZE ) ) ;
rb_hash_aset ( gc_constants , ID2SYM ( rb_intern ( " HEAP_BITMAP_PLANES " ) ) , SIZET2NUM ( HEAP_BITMAP_PLANES ) ) ;
OBJ_FREEZE ( gc_constants ) ;
rb_define_const ( rb_mGC , " INTERNAL_CONSTANTS " , gc_constants ) ;
2008-08-11 13:36:57 +04:00
rb_mProfiler = rb_define_module_under ( rb_mGC , " Profiler " ) ;
rb_define_singleton_method ( rb_mProfiler , " enabled? " , gc_profile_enable_get , 0 ) ;
rb_define_singleton_method ( rb_mProfiler , " enable " , gc_profile_enable , 0 ) ;
2011-09-08 07:57:41 +04:00
rb_define_singleton_method ( rb_mProfiler , " raw_data " , gc_profile_record_get , 0 ) ;
2008-08-11 13:36:57 +04:00
rb_define_singleton_method ( rb_mProfiler , " disable " , gc_profile_disable , 0 ) ;
rb_define_singleton_method ( rb_mProfiler , " clear " , gc_profile_clear , 0 ) ;
rb_define_singleton_method ( rb_mProfiler , " result " , gc_profile_result , 0 ) ;
rb_define_singleton_method ( rb_mProfiler , " report " , gc_profile_report , - 1 ) ;
2010-03-04 07:51:43 +03:00
rb_define_singleton_method ( rb_mProfiler , " total_time " , gc_profile_total_time , 0 ) ;
2008-08-11 13:36:57 +04:00
2013-06-18 16:59:02 +04:00
rb_mObjSpace = rb_define_module ( " ObjectSpace " ) ;
rb_define_module_function ( rb_mObjSpace , " each_object " , os_each_obj , - 1 ) ;
2013-12-06 09:11:51 +04:00
rb_define_module_function ( rb_mObjSpace , " garbage_collect " , gc_start_internal , - 1 ) ;
2000-07-15 17:37:03 +04:00
2013-06-18 16:59:02 +04:00
rb_define_module_function ( rb_mObjSpace , " define_finalizer " , define_final , - 1 ) ;
rb_define_module_function ( rb_mObjSpace , " undefine_finalizer " , undefine_final , 1 ) ;
2000-07-15 17:37:03 +04:00
2013-06-18 16:59:02 +04:00
rb_define_module_function ( rb_mObjSpace , " _id2ref " , id2ref , 1 ) ;
1998-01-16 15:13:05 +03:00
2008-07-03 02:02:58 +04:00
nomem_error = rb_exc_new3 ( rb_eNoMemError ,
rb_obj_freeze ( rb_str_new2 ( " failed to allocate memory " ) ) ) ;
2008-06-15 13:17:06 +04:00
OBJ_TAINT ( nomem_error ) ;
OBJ_FREEZE ( nomem_error ) ;
2006-03-02 08:22:30 +03:00
2010-12-17 16:25:19 +03:00
rb_define_method ( rb_cBasicObject , " __id__ " , rb_obj_id , 0 ) ;
2010-12-22 08:38:41 +03:00
rb_define_method ( rb_mKernel , " object_id " , rb_obj_id , 0 ) ;
2007-11-03 18:09:10 +03:00
2013-06-18 16:59:02 +04:00
rb_define_module_function ( rb_mObjSpace , " count_objects " , count_objects , - 1 ) ;
2008-06-08 14:27:06 +04:00
2012-03-13 07:37:06 +04:00
{
2013-06-18 16:59:02 +04:00
VALUE rb_cWeakMap = rb_define_class_under ( rb_mObjSpace , " WeakMap " , rb_cObject ) ;
2012-03-13 07:37:06 +04:00
rb_define_alloc_func ( rb_cWeakMap , wmap_allocate ) ;
rb_define_method ( rb_cWeakMap , " []= " , wmap_aset , 2 ) ;
rb_define_method ( rb_cWeakMap , " [] " , wmap_aref , 1 ) ;
2013-10-18 10:59:12 +04:00
rb_define_method ( rb_cWeakMap , " include? " , wmap_has_key , 1 ) ;
rb_define_method ( rb_cWeakMap , " member? " , wmap_has_key , 1 ) ;
2013-10-19 03:50:13 +04:00
rb_define_method ( rb_cWeakMap , " key? " , wmap_has_key , 1 ) ;
2013-10-18 10:59:14 +04:00
rb_define_method ( rb_cWeakMap , " inspect " , wmap_inspect , 0 ) ;
rb_define_method ( rb_cWeakMap , " each " , wmap_each , 0 ) ;
rb_define_method ( rb_cWeakMap , " each_pair " , wmap_each , 0 ) ;
rb_define_method ( rb_cWeakMap , " each_key " , wmap_each_key , 0 ) ;
rb_define_method ( rb_cWeakMap , " each_value " , wmap_each_value , 0 ) ;
rb_define_method ( rb_cWeakMap , " keys " , wmap_keys , 0 ) ;
rb_define_method ( rb_cWeakMap , " values " , wmap_values , 0 ) ;
2013-12-09 11:13:40 +04:00
rb_define_method ( rb_cWeakMap , " size " , wmap_size , 0 ) ;
rb_define_method ( rb_cWeakMap , " length " , wmap_size , 0 ) ;
2012-03-13 07:37:06 +04:00
rb_define_private_method ( rb_cWeakMap , " finalize " , wmap_finalize , 1 ) ;
2013-10-18 10:59:14 +04:00
rb_include_module ( rb_cWeakMap , rb_mEnumerable ) ;
2012-03-13 07:37:06 +04:00
}
2013-12-16 08:12:48 +04:00
/* internal methods */
rb_define_singleton_method ( rb_mGC , " verify_internal_consistency " , gc_verify_internal_consistency , 0 ) ;
2013-12-05 08:54:20 +04:00
# if MALLOC_ALLOCATED_SIZE
2008-06-08 14:27:06 +04:00
rb_define_singleton_method ( rb_mGC , " malloc_allocated_size " , gc_malloc_allocated_size , 0 ) ;
rb_define_singleton_method ( rb_mGC , " malloc_allocations " , gc_malloc_allocations , 0 ) ;
# endif
2013-11-06 02:13:51 +04:00
/* ::GC::OPTS, which shows GC build options */
{
VALUE opts ;
rb_define_const ( rb_mGC , " OPTS " , opts = rb_ary_new ( ) ) ;
# define OPT(o) if (o) rb_ary_push(opts, rb_str_new2(#o))
OPT ( GC_DEBUG ) ;
OPT ( USE_RGENGC ) ;
OPT ( RGENGC_DEBUG ) ;
OPT ( RGENGC_CHECK_MODE ) ;
OPT ( RGENGC_PROFILE ) ;
OPT ( RGENGC_THREEGEN ) ;
2013-11-24 23:49:02 +04:00
OPT ( RGENGC_ESTIMATE_OLDMALLOC ) ;
2013-11-06 02:13:51 +04:00
OPT ( GC_PROFILE_MORE_DETAIL ) ;
OPT ( GC_ENABLE_LAZY_SWEEP ) ;
OPT ( CALC_EXACT_MALLOC_SIZE ) ;
2013-12-05 08:54:20 +04:00
OPT ( MALLOC_ALLOCATED_SIZE ) ;
OPT ( MALLOC_ALLOCATED_SIZE_CHECK ) ;
2013-11-09 03:59:20 +04:00
OPT ( GC_PROFILE_DETAIL_MEMORY ) ;
2013-11-06 02:13:51 +04:00
# undef OPT
}
1998-01-16 15:13:05 +03:00
}