diff --git a/patches/ruby/1.8.7/head/railsexpress/01-ignore-generated-files.patch b/patches/ruby/1.8.7/head/railsexpress/01-ignore-generated-files.patch deleted file mode 100644 index b669ad44bd..0000000000 --- a/patches/ruby/1.8.7/head/railsexpress/01-ignore-generated-files.patch +++ /dev/null @@ -1,101 +0,0 @@ -diff --git a/.gitignore b/.gitignore -new file mode 100644 -index 0000000..00c347a ---- /dev/null -+++ b/.gitignore -@@ -0,0 +1,95 @@ -+.ext -+.installed.list -+.rbconfig.time -+Makefile -+autom4te.cache/ -+config.h -+config.status -+configure -+ext/Win32API/Makefile -+ext/bigdecimal/Makefile -+ext/curses/Makefile -+ext/dbm/Makefile -+ext/digest/Makefile -+ext/digest/bubblebabble/Makefile -+ext/digest/md5/Makefile -+ext/digest/rmd160/Makefile -+ext/digest/sha1/Makefile -+ext/digest/sha2/Makefile -+ext/dl/Makefile -+ext/dl/call.func -+ext/dl/callback.func -+ext/dl/cbtable.func -+ext/dl/dlconfig.h -+ext/dl/dlconfig.rb -+ext/enumerator/Makefile -+ext/etc/Makefile -+ext/fcntl/Makefile -+ext/gdbm/Makefile -+ext/iconv/Makefile -+ext/io/wait/Makefile -+ext/nkf/Makefile -+ext/openssl/Makefile -+ext/openssl/extconf.h -+ext/pty/Makefile -+ext/racc/cparse/Makefile -+ext/readline/Makefile -+ext/sdbm/Makefile -+ext/socket/Makefile -+ext/stringio/Makefile -+ext/strscan/Makefile -+ext/syck/Makefile -+ext/syslog/Makefile -+ext/thread/Makefile -+ext/tk/Makefile -+ext/tk/tkutil/Makefile -+ext/win32ole/Makefile -+ext/win32ole/.document -+ext/zlib/Makefile -+largefile.h -+miniruby -+parse.c -+rbconfig.rb -+ruby -+enc.mk -+ext/bigdecimal/extconf.h -+ext/continuation/ -+ext/coverage/ -+ext/curses/extconf.h -+ext/dbm/extconf.h -+ext/digest/bubblebabble/extconf.h -+ext/digest/extconf.h -+ext/digest/md5/extconf.h -+ext/digest/rmd160/extconf.h -+ext/digest/sha1/extconf.h -+ext/digest/sha2/extconf.h -+ext/dl/callback.h -+ext/dl/extconf.h -+ext/etc/extconf.h -+ext/fcntl/extconf.h -+ext/fiber/ -+ext/iconv/extconf.h -+ext/io/wait/extconf.h -+ext/json/ -+ext/nkf/extconf.h -+ext/pty/extconf.h -+ext/racc/cparse/extconf.h -+ext/readline/extconf.h -+ext/ripper/ -+ext/sdbm/extconf.h -+ext/socket/constants.h -+ext/socket/extconf.h -+ext/stringio/extconf.h -+ext/strscan/extconf.h -+ext/syck/extconf.h -+ext/syslog/extconf.h -+ext/tk/extconf.h -+ext/tk/tkutil/extconf.h -+ext/zlib/extconf.h -+miniprelude.c -+prelude.c -+revision.h -+*.dylib -+*.log -+*.dSYM -+patches-ruby* diff --git a/patches/ruby/1.8.7/head/railsexpress/02-fix-tests-for-osx.patch b/patches/ruby/1.8.7/head/railsexpress/02-fix-tests-for-osx.patch deleted file mode 100644 index 6250e97f36..0000000000 --- a/patches/ruby/1.8.7/head/railsexpress/02-fix-tests-for-osx.patch +++ /dev/null @@ -1,139 +0,0 @@ -diff --git a/test/drb/drbtest.rb b/test/drb/drbtest.rb -index bc16ab1..c12b168 100644 ---- a/test/drb/drbtest.rb -+++ b/test/drb/drbtest.rb -@@ -22,7 +22,7 @@ class DRbService - %w(ut_drb.rb ut_array.rb ut_port.rb ut_large.rb ut_safe1.rb ut_eval.rb).each do |nm| - add_service_command(nm) - end -- @server = @@server = DRb::DRbServer.new('druby://localhost:0', @@manager, {}) -+ @server = @@server = DRb::DRbServer.new('druby://127.0.0.1:0', @@manager, {}) - @@manager.uri = @@server.uri - def self.manager - @@manager -@@ -79,16 +79,16 @@ module DRbCore - end - - def test_00_DRbObject -- ro = DRbObject.new(nil, 'druby://localhost:12345') -- assert_equal('druby://localhost:12345', ro.__drburi) -+ ro = DRbObject.new(nil, 'druby://127.0.0.1:12345') -+ assert_equal('druby://127.0.0.1:12345', ro.__drburi) - assert_equal(nil, ro.__drbref) - -- ro = DRbObject.new_with_uri('druby://localhost:12345') -- assert_equal('druby://localhost:12345', ro.__drburi) -+ ro = DRbObject.new_with_uri('druby://127.0.0.1:12345') -+ assert_equal('druby://127.0.0.1:12345', ro.__drburi) - assert_equal(nil, ro.__drbref) - -- ro = DRbObject.new_with_uri('druby://localhost:12345?foobar') -- assert_equal('druby://localhost:12345', ro.__drburi) -+ ro = DRbObject.new_with_uri('druby://127.0.0.1:12345?foobar') -+ assert_equal('druby://127.0.0.1:12345', ro.__drburi) - assert_equal(DRb::DRbURIOption.new('foobar'), ro.__drbref) - end - -diff --git a/test/drb/ut_drb.rb b/test/drb/ut_drb.rb -index f5720cf..265713d 100644 ---- a/test/drb/ut_drb.rb -+++ b/test/drb/ut_drb.rb -@@ -154,7 +154,7 @@ if __FILE__ == $0 - - DRb::DRbServer.default_argc_limit(8) - DRb::DRbServer.default_load_limit(4096) -- DRb.start_service('druby://localhost:0', DRbEx.new) -+ DRb.start_service('druby://127.0.0.1:0', DRbEx.new) - es = DRb::ExtServ.new(ARGV.shift, ARGV.shift) - DRb.thread.join - end -diff --git a/test/drb/ut_drb_drbssl.rb b/test/drb/ut_drb_drbssl.rb -index 0a2191e..bca3012 100644 ---- a/test/drb/ut_drb_drbssl.rb -+++ b/test/drb/ut_drb_drbssl.rb -@@ -18,7 +18,7 @@ if __FILE__ == $0 - - DRb::DRbServer.default_argc_limit(8) - DRb::DRbServer.default_load_limit(4096) -- DRb.start_service('drbssl://localhost:0', DRbEx.new, config) -+ DRb.start_service('drbssl://127.0.0.1:0', DRbEx.new, config) - es = DRb::ExtServ.new(ARGV.shift, ARGV.shift) - DRb.thread.join - end -diff --git a/test/drb/ut_eval.rb b/test/drb/ut_eval.rb -index 4df963e..9127939 100644 ---- a/test/drb/ut_eval.rb -+++ b/test/drb/ut_eval.rb -@@ -3,7 +3,7 @@ require 'drb/extserv' - - class EvalAttack - def initialize -- @four = DRb::DRbServer.new('druby://localhost:0', self, {:safe_level => 4}) -+ @four = DRb::DRbServer.new('druby://127.0.0.1:0', self, {:safe_level => 4}) - end - - def four -@@ -25,7 +25,7 @@ if __FILE__ == $0 - - $SAFE = 1 - -- DRb.start_service('druby://localhost:0', EvalAttack.new, {:safe_level => 2}) -+ DRb.start_service('druby://127.0.0.1:0', EvalAttack.new, {:safe_level => 2}) - es = DRb::ExtServ.new(ARGV.shift, ARGV.shift) - DRb.thread.join - end -diff --git a/test/drb/ut_large.rb b/test/drb/ut_large.rb -index d6717c5..0aefd1b 100644 ---- a/test/drb/ut_large.rb -+++ b/test/drb/ut_large.rb -@@ -31,7 +31,7 @@ if __FILE__ == $0 - - DRb::DRbServer.default_argc_limit(3) - DRb::DRbServer.default_load_limit(100000) -- DRb.start_service('druby://localhost:0', DRbLarge.new) -+ DRb.start_service('druby://127.0.0.1:0', DRbLarge.new) - es = DRb::ExtServ.new(ARGV.shift, ARGV.shift) - DRb.thread.join - end -diff --git a/test/drb/ut_safe1.rb b/test/drb/ut_safe1.rb -index 4df8e1e..ee097f6 100644 ---- a/test/drb/ut_safe1.rb -+++ b/test/drb/ut_safe1.rb -@@ -8,7 +8,7 @@ if __FILE__ == $0 - it - end - -- DRb.start_service('druby://localhost:0', [1, 2, 'III', 4, "five", 6], -+ DRb.start_service('druby://127.0.0.1:0', [1, 2, 'III', 4, "five", 6], - {:safe_level => 1}) - es = DRb::ExtServ.new(ARGV.shift, ARGV.shift) - DRb.thread.join -diff --git a/test/net/pop/test_pop.rb b/test/net/pop/test_pop.rb -index c8aa9a8..129ca08 100644 ---- a/test/net/pop/test_pop.rb -+++ b/test/net/pop/test_pop.rb -@@ -3,10 +3,14 @@ require 'test/unit' - require 'digest/md5' - - class TestPOP < Test::Unit::TestCase -+ def localhost -+ '127.0.0.1' -+ end -+ - def setup - @users = {'user' => 'pass' } - @ok_user = 'user' -- @stamp_base = "#{$$}.#{Time.now.to_i}@localhost" -+ @stamp_base = "#{$$}.#{Time.now.to_i}@#{localhost}" - end - - def test_pop_auth_ok -@@ -64,7 +68,7 @@ class TestPOP < Test::Unit::TestCase - end - - def pop_test(apop=false) -- host = 'localhost' -+ host = localhost - server = TCPServer.new(host, 0) - port = server.addr[1] - thread = Thread.start do diff --git a/patches/ruby/1.8.7/head/railsexpress/03-sigvtalrm-fix.patch b/patches/ruby/1.8.7/head/railsexpress/03-sigvtalrm-fix.patch deleted file mode 100644 index fe99f6eed6..0000000000 --- a/patches/ruby/1.8.7/head/railsexpress/03-sigvtalrm-fix.patch +++ /dev/null @@ -1,27 +0,0 @@ -diff --git a/eval.c b/eval.c -index 7886e17..6ff2560 100644 ---- a/eval.c -+++ b/eval.c -@@ -12461,6 +12461,11 @@ rb_thread_start_0(fn, arg, th) - curr_thread->next = th; - th->priority = curr_thread->priority; - th->thgroup = curr_thread->thgroup; -+#if defined(HAVE_SETITIMER) || defined(_THREAD_SAFE) -+ if (!thread_init) { -+ rb_thread_start_timer(); -+ } -+#endif - } - START_TIMER(); - -@@ -13189,7 +13194,9 @@ rb_thread_atfork() - main_thread = curr_thread; - curr_thread->next = curr_thread; - curr_thread->prev = curr_thread; -- STOP_TIMER(); -+#if defined(HAVE_SETITIMER) || defined(_THREAD_SAFE) -+ rb_thread_stop_timer(); -+#endif - } - - diff --git a/patches/ruby/1.8.7/head/railsexpress/04-railsbench-gc-patch.patch b/patches/ruby/1.8.7/head/railsexpress/04-railsbench-gc-patch.patch deleted file mode 100644 index 7b6c0e251a..0000000000 --- a/patches/ruby/1.8.7/head/railsexpress/04-railsbench-gc-patch.patch +++ /dev/null @@ -1,1876 +0,0 @@ -diff --git a/gc.c b/gc.c -index fa45cd1..ab71d22 100644 ---- a/gc.c -+++ b/gc.c -@@ -22,8 +22,16 @@ - #include - #include - -+#ifdef _WIN32 -+#include -+#else -+#include -+#endif -+ - #ifdef HAVE_SYS_TIME_H - #include -+#elif defined(_WIN32) -+#include - #endif - - #ifdef HAVE_SYS_RESOURCE_H -@@ -42,7 +50,6 @@ void rb_io_fptr_finalize _((struct rb_io_t*)); - #ifdef __CYGWIN__ - int _setjmp(), _longjmp(); - #endif -- - /* Make alloca work the best possible way. */ - #ifdef __GNUC__ - # ifndef atarist -@@ -86,12 +93,12 @@ rb_memerror() - rb_thread_t th = rb_curr_thread; - - if (!nomem_error || -- (rb_thread_raised_p(th, RAISED_NOMEMORY) && rb_safe_level() < 4)) { -- fprintf(stderr, "[FATAL] failed to allocate memory\n"); -- exit(1); -+ (rb_thread_raised_p(th, RAISED_NOMEMORY) && rb_safe_level() < 4)) { -+ fprintf(stderr, "[FATAL] failed to allocate memory\n"); -+ exit(1); - } - if (rb_thread_raised_p(th, RAISED_NOMEMORY)) { -- rb_exc_jump(nomem_error); -+ rb_exc_jump(nomem_error); - } - rb_thread_raised_set(th, RAISED_NOMEMORY); - rb_exc_raise(nomem_error); -@@ -139,7 +146,7 @@ ruby_xmalloc(size) - void *mem; - - if (size < 0) { -- rb_raise(rb_eNoMemError, "negative allocation size (or too big)"); -+ rb_raise(rb_eNoMemError, "negative allocation size (or too big)"); - } - if (size == 0) size = 1; - -@@ -148,11 +155,11 @@ ruby_xmalloc(size) - } - RUBY_CRITICAL(mem = malloc(size)); - if (!mem) { -- garbage_collect(); -- RUBY_CRITICAL(mem = malloc(size)); -- if (!mem) { -- rb_memerror(); -- } -+ garbage_collect(); -+ RUBY_CRITICAL(mem = malloc(size)); -+ if (!mem) { -+ rb_memerror(); -+ } - } - malloc_increase += size; - -@@ -179,17 +186,17 @@ ruby_xrealloc(ptr, size) - void *mem; - - if (size < 0) { -- rb_raise(rb_eArgError, "negative re-allocation size"); -+ rb_raise(rb_eArgError, "negative re-allocation size"); - } - if (!ptr) return xmalloc(size); - if (size == 0) size = 1; - if (ruby_gc_stress) garbage_collect(); - RUBY_CRITICAL(mem = realloc(ptr, size)); - if (!mem) { -- garbage_collect(); -- RUBY_CRITICAL(mem = realloc(ptr, size)); -- if (!mem) { -- rb_memerror(); -+ garbage_collect(); -+ RUBY_CRITICAL(mem = realloc(ptr, size)); -+ if (!mem) { -+ rb_memerror(); - } - } - malloc_increase += size; -@@ -202,11 +209,20 @@ ruby_xfree(x) - void *x; - { - if (x) -- RUBY_CRITICAL(free(x)); -+ RUBY_CRITICAL(free(x)); - } - -+#if HAVE_LONG_LONG -+#define GC_TIME_TYPE LONG_LONG -+#else -+#define GC_TIME_TYPE long -+#endif -+ - extern int ruby_in_compile; - static int dont_gc; -+static int gc_statistics = 0; -+static GC_TIME_TYPE gc_time = 0; -+static int gc_collections = 0; - static int during_gc; - static int need_call_final = 0; - static st_table *finalizer_table = 0; -@@ -241,7 +257,7 @@ rb_gc_enable() - * Disables garbage collection, returning true if garbage - * collection was already disabled. - * -- * GC.disable #=> false -+ * GC.disable #=> false or true - * GC.disable #=> true - * - */ -@@ -255,6 +271,104 @@ rb_gc_disable() - return old; - } - -+/* -+ * call-seq: -+ * GC.enable_stats => true or false -+ * -+ * Enables garbage collection statistics, returning true if garbage -+ * collection statistics was already enabled. -+ * -+ * GC.enable_stats #=> false or true -+ * GC.enable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_stats() -+{ -+ int old = gc_statistics; -+ gc_statistics = Qtrue; -+ return old; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_stats => true or false -+ * -+ * Disables garbage collection statistics, returning true if garbage -+ * collection statistics was already disabled. -+ * -+ * GC.disable_stats #=> false or true -+ * GC.disable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_stats() -+{ -+ int old = gc_statistics; -+ gc_statistics = Qfalse; -+ return old; -+} -+ -+/* -+ * call-seq: -+ * GC.clear_stats => nil -+ * -+ * Clears garbage collection statistics, returning nil. This resets the number -+ * of collections (GC.collections) and the time used (GC.time) to 0. -+ * -+ * GC.clear_stats #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_clear_stats() -+{ -+ gc_collections = 0; -+ gc_time = 0; -+ return Qnil; -+} -+ -+/* -+ * call-seq: -+ * GC.collections => Integer -+ * -+ * Returns the number of garbage collections performed while GC statistics collection -+ * was enabled. -+ * -+ * GC.collections #=> 35 -+ * -+ */ -+ -+VALUE -+rb_gc_collections() -+{ -+ return INT2NUM(gc_collections); -+} -+ -+/* -+ * call-seq: -+ * GC.time => Integer -+ * -+ * Returns the time spent during garbage collection while GC statistics collection -+ * was enabled (in micro seconds). -+ * -+ * GC.time #=> 20000 -+ * -+ */ -+ -+VALUE -+rb_gc_time() -+{ -+#if HAVE_LONG_LONG -+ return LL2NUM(gc_time); -+#else -+ return LONG2NUM(gc_time); -+#endif -+} -+ -+ - VALUE rb_mGC; - - static struct gc_list { -@@ -281,19 +395,19 @@ rb_gc_unregister_address(addr) - struct gc_list *tmp = global_List; - - if (tmp->varptr == addr) { -- global_List = tmp->next; -- RUBY_CRITICAL(free(tmp)); -- return; -+ global_List = tmp->next; -+ RUBY_CRITICAL(free(tmp)); -+ return; - } - while (tmp->next) { -- if (tmp->next->varptr == addr) { -- struct gc_list *t = tmp->next; -+ if (tmp->next->varptr == addr) { -+ struct gc_list *t = tmp->next; - -- tmp->next = tmp->next->next; -- RUBY_CRITICAL(free(t)); -- break; -- } -- tmp = tmp->next; -+ tmp->next = tmp->next->next; -+ RUBY_CRITICAL(free(t)); -+ break; -+ } -+ tmp = tmp->next; - } - } - -@@ -312,26 +426,26 @@ rb_global_variable(var) - - typedef struct RVALUE { - union { -- struct { -- unsigned long flags; /* always 0 for freed obj */ -- 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; -- struct RStruct rstruct; -- struct RBignum bignum; -- struct RFile file; -- struct RNode node; -- struct RMatch match; -- struct RVarmap varmap; -- struct SCOPE scope; -+ struct { -+ unsigned long flags; /* always 0 for freed obj */ -+ 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; -+ struct RStruct rstruct; -+ struct RBignum bignum; -+ struct RFile file; -+ struct RNode node; -+ struct RMatch match; -+ struct RVarmap varmap; -+ struct SCOPE scope; - } as; - #ifdef GC_DEBUG - char *file; -@@ -346,7 +460,7 @@ typedef struct RVALUE { - static RVALUE *freelist = 0; - static RVALUE *deferred_final_list = 0; - --#define HEAPS_INCREMENT 10 -+static int heaps_increment = 10; - static struct heaps_slot { - void *membase; - RVALUE *slot; -@@ -355,45 +469,197 @@ static struct heaps_slot { - static int heaps_length = 0; - static int heaps_used = 0; - --#define HEAP_MIN_SLOTS 10000 --static int heap_slots = HEAP_MIN_SLOTS; -+static int heap_min_slots = 10000; -+static int heap_slots = 10000; - --#define FREE_MIN 4096 -+static int heap_free_min = 4096; -+static int heap_slots_increment = 10000; -+static double heap_slots_growth_factor = 1.8; -+ -+static long initial_malloc_limit = GC_MALLOC_LIMIT; -+ -+static int verbose_gc_stats = Qfalse; -+ -+static FILE* gc_data_file = NULL; - - static RVALUE *himem, *lomem; - -+static void set_gc_parameters() -+{ -+ char *gc_stats_ptr, *min_slots_ptr, *free_min_ptr, *heap_slots_incr_ptr, -+ *heap_incr_ptr, *malloc_limit_ptr, *gc_heap_file_ptr, *heap_slots_growth_factor_ptr; -+ -+ gc_data_file = stderr; -+ -+ gc_stats_ptr = getenv("RUBY_GC_STATS"); -+ if (gc_stats_ptr != NULL) { -+ int gc_stats_i = atoi(gc_stats_ptr); -+ if (gc_stats_i > 0) { -+ verbose_gc_stats = Qtrue; -+ } -+ } -+ -+ gc_heap_file_ptr = getenv("RUBY_GC_DATA_FILE"); -+ if (gc_heap_file_ptr != NULL) { -+ FILE* data_file = fopen(gc_heap_file_ptr, "w"); -+ if (data_file != NULL) { -+ gc_data_file = data_file; -+ } -+ else { -+ fprintf(stderr, -+ "can't open gc log file %s for writing, using default\n", gc_heap_file_ptr); -+ } -+ } -+ -+ min_slots_ptr = getenv("RUBY_HEAP_MIN_SLOTS"); -+ if (min_slots_ptr != NULL) { -+ int min_slots_i = atoi(min_slots_ptr); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_MIN_SLOTS=%s\n", min_slots_ptr); -+ } -+ if (min_slots_i > 0) { -+ heap_slots = min_slots_i; -+ heap_min_slots = min_slots_i; -+ } -+ } -+ -+ free_min_ptr = getenv("RUBY_HEAP_FREE_MIN"); -+ if (free_min_ptr != NULL) { -+ int free_min_i = atoi(free_min_ptr); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_FREE_MIN=%s\n", free_min_ptr); -+ } -+ if (free_min_i > 0) { -+ heap_free_min = free_min_i; -+ } -+ } -+ -+ heap_incr_ptr = getenv("RUBY_HEAP_INCREMENT"); -+ if (heap_incr_ptr != NULL) { -+ int heap_incr_i = atoi(heap_incr_ptr); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_INCREMENT=%s\n", heap_incr_ptr); -+ } -+ if (heap_incr_i > 0) { -+ heaps_increment = heap_incr_i; -+ } -+ } -+ -+ heap_slots_incr_ptr = getenv("RUBY_HEAP_SLOTS_INCREMENT"); -+ if (heap_slots_incr_ptr != NULL) { -+ int heap_slots_incr_i = atoi(heap_slots_incr_ptr); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_INCREMENT=%s\n", heap_slots_incr_ptr); -+ } -+ if (heap_slots_incr_i > 0) { -+ heap_slots_increment = heap_slots_incr_i; -+ } -+ } -+ -+ heap_slots_growth_factor_ptr = getenv("RUBY_HEAP_SLOTS_GROWTH_FACTOR"); -+ if (heap_slots_growth_factor_ptr != NULL) { -+ double heap_slots_growth_factor_d = atoi(heap_slots_growth_factor_ptr); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_GROWTH_FACTOR=%s\n", heap_slots_growth_factor_ptr); -+ } -+ if (heap_slots_growth_factor_d > 0) { -+ heap_slots_growth_factor = heap_slots_growth_factor_d; -+ } -+ } -+ -+ malloc_limit_ptr = getenv("RUBY_GC_MALLOC_LIMIT"); -+ if (malloc_limit_ptr != NULL) { -+ int malloc_limit_i = atol(malloc_limit_ptr); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_GC_MALLOC_LIMIT=%s\n", malloc_limit_ptr); -+ } -+ if (malloc_limit_i > 0) { -+ initial_malloc_limit = malloc_limit_i; -+ } -+ } -+} -+ -+/* -+ * call-seq: -+ * GC.dump => nil -+ * -+ * dumps information about the current GC data structures to the GC log file -+ * -+ * GC.dump #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_dump() -+{ -+ int i; -+ -+ for (i = 0; i < heaps_used; i++) { -+ int heap_size = heaps[i].limit; -+ fprintf(gc_data_file, "HEAP[%2d]: size=%7d\n", i, heap_size); -+ } -+ -+ return Qnil; -+} -+ -+/* -+ * call-seq: -+ * GC.log String => String -+ * -+ * Logs string to the GC data file and returns it. -+ * -+ * GC.log "manual GC call" #=> "manual GC call" -+ * -+ */ -+ -+VALUE -+rb_gc_log(self, original_str) -+ VALUE self, original_str; -+{ -+ if (original_str == Qnil) { -+ fprintf(gc_data_file, "\n"); -+ } -+ else { -+ VALUE str = StringValue(original_str); -+ char *p = RSTRING(str)->ptr; -+ fprintf(gc_data_file, "%s\n", p); -+ } -+ return original_str; -+} -+ -+ - static void - add_heap() - { - RVALUE *p, *pend; - - if (heaps_used == heaps_length) { -- /* Realloc heaps */ -- struct heaps_slot *p; -- int length; -- -- heaps_length += HEAPS_INCREMENT; -- length = heaps_length*sizeof(struct heaps_slot); -- RUBY_CRITICAL( -- if (heaps_used > 0) { -- p = (struct heaps_slot *)realloc(heaps, length); -- if (p) heaps = p; -- } -- else { -- p = heaps = (struct heaps_slot *)malloc(length); -- }); -- if (p == 0) rb_memerror(); -+ /* Realloc heaps */ -+ struct heaps_slot *p; -+ int length; -+ -+ heaps_length += heaps_increment; -+ length = heaps_length*sizeof(struct heaps_slot); -+ RUBY_CRITICAL( -+ if (heaps_used > 0) { -+ p = (struct heaps_slot *)realloc(heaps, length); -+ if (p) heaps = p; -+ } -+ else { -+ p = heaps = (struct heaps_slot *)malloc(length); -+ }); -+ if (p == 0) rb_memerror(); - } - - for (;;) { -- RUBY_CRITICAL(p = (RVALUE*)malloc(sizeof(RVALUE)*(heap_slots+1))); -- if (p == 0) { -- if (heap_slots == HEAP_MIN_SLOTS) { -- rb_memerror(); -- } -- heap_slots = HEAP_MIN_SLOTS; -- continue; -- } -+ RUBY_CRITICAL(p = (RVALUE*)malloc(sizeof(RVALUE)*(heap_slots+1))); -+ if (p == 0) { -+ if (heap_slots == heap_min_slots) { -+ rb_memerror(); -+ } -+ heap_slots = heap_min_slots; -+ continue; -+ } - heaps[heaps_used].membase = p; - if ((VALUE)p % sizeof(RVALUE) == 0) - heap_slots += 1; -@@ -401,25 +667,26 @@ add_heap() - p = (RVALUE*)((VALUE)p + sizeof(RVALUE) - ((VALUE)p % sizeof(RVALUE))); - heaps[heaps_used].slot = p; - heaps[heaps_used].limit = heap_slots; -- break; -+ break; - } - pend = p + heap_slots; - if (lomem == 0 || lomem > p) lomem = p; - if (himem < pend) himem = pend; - heaps_used++; -- heap_slots *= 1.8; -- if (heap_slots <= 0) heap_slots = HEAP_MIN_SLOTS; -+ heap_slots += heap_slots_increment; -+ heap_slots_increment *= heap_slots_growth_factor; -+ if (heap_slots <= 0) heap_slots = heap_min_slots; - - while (p < pend) { -- p->as.free.flags = 0; -- p->as.free.next = freelist; -- freelist = p; -- p++; -+ p->as.free.flags = 0; -+ p->as.free.next = freelist; -+ freelist = p; -+ p++; - } - } - #define RANY(o) ((RVALUE*)(o)) - --int -+int - rb_during_gc() - { - return during_gc; -@@ -431,7 +698,7 @@ rb_newobj() - VALUE obj; - - if (during_gc) -- rb_bug("object allocation during garbage collection phase"); -+ rb_bug("object allocation during garbage collection phase"); - - if (ruby_gc_stress || !freelist) garbage_collect(); - -@@ -580,13 +847,13 @@ rb_source_filename(f) - st_data_t name; - - if (!st_lookup(source_filenames, (st_data_t)f, &name)) { -- long len = strlen(f) + 1; -- char *ptr = ALLOC_N(char, len + 1); -- name = (st_data_t)ptr; -- *ptr++ = 0; -- MEMCPY(ptr, f, char, len); -- st_add_direct(source_filenames, (st_data_t)ptr, name); -- return ptr; -+ long len = strlen(f) + 1; -+ char *ptr = ALLOC_N(char, len + 1); -+ name = (st_data_t)ptr; -+ *ptr++ = 0; -+ MEMCPY(ptr, f, char, len); -+ st_add_direct(source_filenames, (st_data_t)ptr, name); -+ return ptr; - } - return (char *)name + 1; - } -@@ -596,7 +863,7 @@ mark_source_filename(f) - char *f; - { - if (f) { -- f[-1] = 1; -+ f[-1] = 1; - } - } - -@@ -605,12 +872,12 @@ sweep_source_filename(key, value) - char *key, *value; - { - if (*value) { -- *value = 0; -- return ST_CONTINUE; -+ *value = 0; -+ return ST_CONTINUE; - } - else { -- free(value); -- return ST_DELETE; -+ free(value); -+ return ST_DELETE; - } - } - -@@ -625,14 +892,14 @@ gc_mark_all() - - init_mark_stack(); - for (i = 0; i < heaps_used; i++) { -- p = heaps[i].slot; pend = p + heaps[i].limit; -- while (p < pend) { -- if ((p->as.basic.flags & FL_MARK) && -- (p->as.basic.flags != FL_MARK)) { -- gc_mark_children((VALUE)p, 0); -- } -- p++; -- } -+ p = heaps[i].slot; pend = p + heaps[i].limit; -+ while (p < pend) { -+ if ((p->as.basic.flags & FL_MARK) && -+ (p->as.basic.flags != FL_MARK)) { -+ gc_mark_children((VALUE)p, 0); -+ } -+ p++; -+ } - } - } - -@@ -647,8 +914,8 @@ gc_mark_rest() - - init_mark_stack(); - while(p != tmp_arry){ -- p--; -- gc_mark_children(*p, 0); -+ p--; -+ gc_mark_children(*p, 0); - } - } - -@@ -665,9 +932,9 @@ is_pointer_to_heap(ptr) - - /* check if p looks like a pointer */ - for (i=0; i < heaps_used; i++) { -- heap_org = heaps[i].slot; -- if (heap_org <= p && p < heap_org + heaps[i].limit) -- return Qtrue; -+ heap_org = heaps[i].slot; -+ if (heap_org <= p && p < heap_org + heaps[i].limit) -+ return Qtrue; - } - return Qfalse; - } -@@ -680,10 +947,10 @@ mark_locations_array(x, n) - VALUE v; - while (n--) { - v = *x; -- if (is_pointer_to_heap((void *)v)) { -- gc_mark(v, 0); -- } -- x++; -+ if (is_pointer_to_heap((void *)v)) { -+ gc_mark(v, 0); -+ } -+ x++; - } - } - -@@ -780,7 +1047,7 @@ rb_gc_mark_maybe(obj) - VALUE obj; - { - if (is_pointer_to_heap((void *)obj)) { -- gc_mark(obj, 0); -+ gc_mark(obj, 0); - } - } - -@@ -828,7 +1095,7 @@ gc_mark_children(ptr, lev) - { - register RVALUE *obj = RANY(ptr); - -- goto marking; /* skip */ -+ goto marking; /* skip */ - - again: - obj = RANY(ptr); -@@ -839,148 +1106,148 @@ gc_mark_children(ptr, lev) - - marking: - if (FL_TEST(obj, FL_EXIVAR)) { -- rb_mark_generic_ivar(ptr); -+ rb_mark_generic_ivar(ptr); - } - - switch (obj->as.basic.flags & T_MASK) { - case T_NIL: - case T_FIXNUM: -- rb_bug("rb_gc_mark() called for broken object"); -- break; -+ rb_bug("rb_gc_mark() called for broken object"); -+ break; - - case T_NODE: -- mark_source_filename(obj->as.node.nd_file); -- switch (nd_type(obj)) { -- case NODE_IF: /* 1,2,3 */ -- case NODE_FOR: -- case NODE_ITER: -- case NODE_CREF: -- case NODE_WHEN: -- case NODE_MASGN: -- case NODE_RESCUE: -- case NODE_RESBODY: -- case NODE_CLASS: -- gc_mark((VALUE)obj->as.node.u2.node, lev); -- /* 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_FBODY: -- case NODE_ENSURE: -- case NODE_CALL: -- case NODE_DEFS: -- case NODE_OP_ASGN1: -- gc_mark((VALUE)obj->as.node.u1.node, lev); -- /* fall through */ -- case NODE_SUPER: /* 3 */ -- case NODE_FCALL: -- case NODE_DEFN: -- case NODE_NEWLINE: -- ptr = (VALUE)obj->as.node.u3.node; -- goto again; -- -- 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_ARGS: -- gc_mark((VALUE)obj->as.node.u1.node, lev); -- /* fall through */ -- case NODE_METHOD: /* 2 */ -- case NODE_NOT: -- case NODE_GASGN: -- case NODE_LASGN: -- case NODE_DASGN: -- case NODE_DASGN_CURR: -- case NODE_IASGN: -- case NODE_CVDECL: -- case NODE_CVASGN: -- case NODE_COLON3: -- case NODE_OPT_N: -- case NODE_EVSTR: -- case NODE_UNDEF: -- ptr = (VALUE)obj->as.node.u2.node; -- goto again; -- -- 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: -- case NODE_SVALUE: -- ptr = (VALUE)obj->as.node.u1.node; -- goto again; -- -- case NODE_SCOPE: /* 2,3 */ -- case NODE_BLOCK_PASS: -- case NODE_CDECL: -- gc_mark((VALUE)obj->as.node.u3.node, lev); -- ptr = (VALUE)obj->as.node.u2.node; -- goto again; -- -- case NODE_ZARRAY: /* - */ -- case NODE_ZSUPER: -- case NODE_CFUNC: -- 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_ATTRSET: -- case NODE_BLOCK_ARG: -- case NODE_POSTEXE: -- break; -- case NODE_ALLOCA: -- mark_locations_array((VALUE*)obj->as.node.u1.value, -- obj->as.node.u3.cnt); -- ptr = (VALUE)obj->as.node.u2.node; -- goto again; -- -- default: /* unlisted NODE */ -- if (is_pointer_to_heap(obj->as.node.u1.node)) { -- gc_mark((VALUE)obj->as.node.u1.node, lev); -- } -- if (is_pointer_to_heap(obj->as.node.u2.node)) { -- gc_mark((VALUE)obj->as.node.u2.node, lev); -- } -- if (is_pointer_to_heap(obj->as.node.u3.node)) { -- gc_mark((VALUE)obj->as.node.u3.node, lev); -- } -- } -- return; /* no need to mark class. */ -+ mark_source_filename(obj->as.node.nd_file); -+ switch (nd_type(obj)) { -+ case NODE_IF: /* 1,2,3 */ -+ case NODE_FOR: -+ case NODE_ITER: -+ case NODE_CREF: -+ case NODE_WHEN: -+ case NODE_MASGN: -+ case NODE_RESCUE: -+ case NODE_RESBODY: -+ case NODE_CLASS: -+ gc_mark((VALUE)obj->as.node.u2.node, lev); -+ /* 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_FBODY: -+ case NODE_ENSURE: -+ case NODE_CALL: -+ case NODE_DEFS: -+ case NODE_OP_ASGN1: -+ gc_mark((VALUE)obj->as.node.u1.node, lev); -+ /* fall through */ -+ case NODE_SUPER: /* 3 */ -+ case NODE_FCALL: -+ case NODE_DEFN: -+ case NODE_NEWLINE: -+ ptr = (VALUE)obj->as.node.u3.node; -+ goto again; -+ -+ 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_ARGS: -+ gc_mark((VALUE)obj->as.node.u1.node, lev); -+ /* fall through */ -+ case NODE_METHOD: /* 2 */ -+ case NODE_NOT: -+ case NODE_GASGN: -+ case NODE_LASGN: -+ case NODE_DASGN: -+ case NODE_DASGN_CURR: -+ case NODE_IASGN: -+ case NODE_CVDECL: -+ case NODE_CVASGN: -+ case NODE_COLON3: -+ case NODE_OPT_N: -+ case NODE_EVSTR: -+ case NODE_UNDEF: -+ ptr = (VALUE)obj->as.node.u2.node; -+ goto again; -+ -+ 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: -+ case NODE_SVALUE: -+ ptr = (VALUE)obj->as.node.u1.node; -+ goto again; -+ -+ case NODE_SCOPE: /* 2,3 */ -+ case NODE_BLOCK_PASS: -+ case NODE_CDECL: -+ gc_mark((VALUE)obj->as.node.u3.node, lev); -+ ptr = (VALUE)obj->as.node.u2.node; -+ goto again; -+ -+ case NODE_ZARRAY: /* - */ -+ case NODE_ZSUPER: -+ case NODE_CFUNC: -+ 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_ATTRSET: -+ case NODE_BLOCK_ARG: -+ case NODE_POSTEXE: -+ break; -+ case NODE_ALLOCA: -+ mark_locations_array((VALUE*)obj->as.node.u1.value, -+ obj->as.node.u3.cnt); -+ ptr = (VALUE)obj->as.node.u2.node; -+ goto again; -+ -+ default: /* unlisted NODE */ -+ if (is_pointer_to_heap(obj->as.node.u1.node)) { -+ gc_mark((VALUE)obj->as.node.u1.node, lev); -+ } -+ if (is_pointer_to_heap(obj->as.node.u2.node)) { -+ gc_mark((VALUE)obj->as.node.u2.node, lev); -+ } -+ if (is_pointer_to_heap(obj->as.node.u3.node)) { -+ gc_mark((VALUE)obj->as.node.u3.node, lev); -+ } -+ } -+ return; /* no need to mark class. */ - } - - gc_mark(obj->as.basic.klass, lev); -@@ -988,92 +1255,92 @@ gc_mark_children(ptr, lev) - case T_ICLASS: - case T_CLASS: - case T_MODULE: -- mark_tbl(obj->as.klass.m_tbl, lev); -- mark_tbl(obj->as.klass.iv_tbl, lev); -- ptr = obj->as.klass.super; -- goto again; -+ mark_tbl(obj->as.klass.m_tbl, lev); -+ mark_tbl(obj->as.klass.iv_tbl, lev); -+ ptr = obj->as.klass.super; -+ goto again; - - case T_ARRAY: -- if (FL_TEST(obj, ELTS_SHARED)) { -- ptr = obj->as.array.aux.shared; -- goto again; -- } -- else { -- long i, len = obj->as.array.len; -- VALUE *ptr = obj->as.array.ptr; -+ if (FL_TEST(obj, ELTS_SHARED)) { -+ ptr = obj->as.array.aux.shared; -+ goto again; -+ } -+ else { -+ long i, len = obj->as.array.len; -+ VALUE *ptr = obj->as.array.ptr; - -- for (i=0; i < len; i++) { -- gc_mark(*ptr++, lev); -- } -- } -- break; -+ for (i=0; i < len; i++) { -+ gc_mark(*ptr++, lev); -+ } -+ } -+ break; - - case T_HASH: -- mark_hash(obj->as.hash.tbl, lev); -- ptr = obj->as.hash.ifnone; -- goto again; -+ mark_hash(obj->as.hash.tbl, lev); -+ ptr = obj->as.hash.ifnone; -+ goto again; - - case T_STRING: - #define STR_ASSOC FL_USER3 /* copied from string.c */ -- if (FL_TEST(obj, ELTS_SHARED|STR_ASSOC)) { -- ptr = obj->as.string.aux.shared; -- goto again; -- } -- break; -+ if (FL_TEST(obj, ELTS_SHARED|STR_ASSOC)) { -+ ptr = obj->as.string.aux.shared; -+ goto again; -+ } -+ break; - - case T_DATA: -- if (obj->as.data.dmark) (*obj->as.data.dmark)(DATA_PTR(obj)); -- break; -+ if (obj->as.data.dmark) (*obj->as.data.dmark)(DATA_PTR(obj)); -+ break; - - case T_OBJECT: -- mark_tbl(obj->as.object.iv_tbl, lev); -- break; -+ mark_tbl(obj->as.object.iv_tbl, lev); -+ break; - - case T_FILE: - case T_REGEXP: - case T_FLOAT: - case T_BIGNUM: - case T_BLKTAG: -- break; -+ break; - - case T_MATCH: -- if (obj->as.match.str) { -- ptr = obj->as.match.str; -- goto again; -- } -- break; -+ if (obj->as.match.str) { -+ ptr = obj->as.match.str; -+ goto again; -+ } -+ break; - - case T_VARMAP: -- gc_mark(obj->as.varmap.val, lev); -- ptr = (VALUE)obj->as.varmap.next; -- goto again; -+ gc_mark(obj->as.varmap.val, lev); -+ ptr = (VALUE)obj->as.varmap.next; -+ goto again; - - case T_SCOPE: -- if (obj->as.scope.local_vars && (obj->as.scope.flags & SCOPE_MALLOC)) { -- int n = obj->as.scope.local_tbl[0]+1; -- VALUE *vars = &obj->as.scope.local_vars[-1]; -+ if (obj->as.scope.local_vars && (obj->as.scope.flags & SCOPE_MALLOC)) { -+ int n = obj->as.scope.local_tbl[0]+1; -+ VALUE *vars = &obj->as.scope.local_vars[-1]; - -- while (n--) { -- gc_mark(*vars++, lev); -- } -- } -- break; -+ while (n--) { -+ gc_mark(*vars++, lev); -+ } -+ } -+ break; - - case T_STRUCT: -- { -- long len = obj->as.rstruct.len; -- VALUE *ptr = obj->as.rstruct.ptr; -+ { -+ long len = obj->as.rstruct.len; -+ VALUE *ptr = obj->as.rstruct.ptr; - -- while (len--) { -- gc_mark(*ptr++, lev); -- } -- } -- break; -+ while (len--) { -+ gc_mark(*ptr++, lev); -+ } -+ } -+ break; - - default: -- rb_bug("rb_gc_mark(): unknown data type 0x%lx(0x%lx) %s", -- obj->as.basic.flags & T_MASK, obj, -- is_pointer_to_heap(obj) ? "corrupted object" : "non object"); -+ rb_bug("rb_gc_mark(): unknown data type 0x%lx(0x%lx) %s", -+ obj->as.basic.flags & T_MASK, obj, -+ is_pointer_to_heap(obj) ? "corrupted object" : "non object"); - } - } - -@@ -1102,22 +1369,55 @@ finalize_list(p) - } - } - -+static char* obj_type(int tp) -+{ -+ switch (tp) { -+ case T_NIL : return "NIL"; -+ case T_OBJECT : return "OBJECT"; -+ case T_CLASS : return "CLASS"; -+ case T_ICLASS : return "ICLASS"; -+ case T_MODULE : return "MODULE"; -+ case T_FLOAT : return "FLOAT"; -+ case T_STRING : return "STRING"; -+ case T_REGEXP : return "REGEXP"; -+ case T_ARRAY : return "ARRAY"; -+ case T_FIXNUM : return "FIXNUM"; -+ case T_HASH : return "HASH"; -+ case T_STRUCT : return "STRUCT"; -+ case T_BIGNUM : return "BIGNUM"; -+ case T_FILE : return "FILE"; -+ -+ case T_TRUE : return "TRUE"; -+ case T_FALSE : return "FALSE"; -+ case T_DATA : return "DATA"; -+ case T_MATCH : return "MATCH"; -+ case T_SYMBOL : return "SYMBOL"; -+ -+ case T_BLKTAG : return "BLKTAG"; -+ case T_UNDEF : return "UNDEF"; -+ case T_VARMAP : return "VARMAP"; -+ case T_SCOPE : return "SCOPE"; -+ case T_NODE : return "NODE"; -+ default: return "____"; -+ } -+} -+ - static void - free_unused_heaps() - { - int i, j; - - for (i = j = 1; j < heaps_used; i++) { -- if (heaps[i].limit == 0) { -- free(heaps[i].membase); -- heaps_used--; -- } -- else { -- if (i != j) { -- heaps[j] = heaps[i]; -- } -- j++; -- } -+ if (heaps[i].limit == 0) { -+ free(heaps[i].membase); -+ heaps_used--; -+ } -+ else { -+ if (i != j) { -+ heaps[j] = heaps[i]; -+ } -+ j++; -+ } - } - } - -@@ -1134,24 +1434,33 @@ gc_sweep() - unsigned long live = 0; - unsigned long free_min = 0; - -+ unsigned long really_freed = 0; -+ int free_counts[256]; -+ int live_counts[256]; -+ int do_gc_stats = gc_statistics & verbose_gc_stats; -+ - for (i = 0; i < heaps_used; i++) { - free_min += heaps[i].limit; - } - free_min = free_min * 0.2; -- if (free_min < FREE_MIN) -- free_min = FREE_MIN; -+ if (free_min < heap_free_min) -+ free_min = heap_free_min; -+ -+ if (do_gc_stats) { -+ for (i = 0 ; i< 256; i++) { free_counts[i] = live_counts[i] = 0; } -+ } - - if (ruby_in_compile && ruby_parser_stack_on_heap()) { -- /* should not reclaim nodes during compilation -+ /* should not reclaim nodes during compilation - if yacc's semantic stack is not allocated on machine stack */ -- for (i = 0; i < heaps_used; i++) { -- p = heaps[i].slot; pend = p + heaps[i].limit; -- while (p < pend) { -- if (!(p->as.basic.flags&FL_MARK) && BUILTIN_TYPE(p) == T_NODE) -- gc_mark((VALUE)p, 0); -- p++; -- } -- } -+ for (i = 0; i < heaps_used; i++) { -+ p = heaps[i].slot; pend = p + heaps[i].limit; -+ while (p < pend) { -+ if (!(p->as.basic.flags&FL_MARK) && BUILTIN_TYPE(p) == T_NODE) -+ gc_mark((VALUE)p, 0); -+ p++; -+ } -+ } - } - - mark_source_filename(ruby_sourcefile); -@@ -1172,7 +1481,7 @@ gc_sweep() - while (p < pend) { - if (!(p->as.basic.flags & FL_MARK)) { - if (p->as.basic.flags && -- ((deferred = obj_free((VALUE)p)) || -+ (((do_gc_stats && really_freed++), deferred = obj_free((VALUE)p)) || - ((FL_TEST(p, FL_FINALIZE)) && need_call_final))) { - if (!deferred) { - p->as.free.flags = T_DEFERRED; -@@ -1183,6 +1492,12 @@ gc_sweep() - final_list = p; - } - else { -+ if (do_gc_stats) { -+ int obt = p->as.basic.flags & T_MASK; -+ if (obt) { -+ free_counts[obt]++; -+ } -+ } - add_freelist(p); - } - n++; -@@ -1194,6 +1509,9 @@ gc_sweep() - else { - RBASIC(p)->flags &= ~FL_MARK; - live++; -+ if (do_gc_stats) { -+ live_counts[RANY((VALUE)p)->as.basic.flags & T_MASK]++; -+ } - } - p++; - } -@@ -1211,15 +1529,29 @@ gc_sweep() - } - } - if (malloc_increase > malloc_limit) { -- malloc_limit += (malloc_increase - malloc_limit) * (double)live / (live + freed); -- if (malloc_limit < GC_MALLOC_LIMIT) malloc_limit = GC_MALLOC_LIMIT; -+ malloc_limit += (malloc_increase - malloc_limit) * (double)live / (live + freed); -+ if (malloc_limit < initial_malloc_limit) malloc_limit = initial_malloc_limit; - } - malloc_increase = 0; - if (freed < free_min) { -- add_heap(); -+ add_heap(); - } - during_gc = 0; - -+ if (do_gc_stats) { -+ fprintf(gc_data_file, "objects processed: %.7d\n", live+freed); -+ fprintf(gc_data_file, "live objects : %.7d\n", live); -+ fprintf(gc_data_file, "freelist objects : %.7d\n", freed - really_freed); -+ fprintf(gc_data_file, "freed objects : %.7d\n", really_freed); -+ for(i=0; i<256; i++) { -+ if (free_counts[i]>0 || live_counts[i]>0) { -+ fprintf(gc_data_file, -+ "kept %.7d / freed %.7d objects of type %s\n", -+ live_counts[i], free_counts[i], obj_type(i)); -+ } -+ } -+ } -+ - /* clear finalization list */ - if (final_list) { - deferred_final_list = final_list; -@@ -1260,51 +1592,51 @@ obj_free(obj) - case T_FIXNUM: - case T_TRUE: - case T_FALSE: -- rb_bug("obj_free() called for broken object"); -- break; -+ rb_bug("obj_free() called for broken object"); -+ break; - } - - if (FL_TEST(obj, FL_EXIVAR)) { -- rb_free_generic_ivar((VALUE)obj); -+ rb_free_generic_ivar((VALUE)obj); - } - - switch (BUILTIN_TYPE(obj)) { - case T_OBJECT: -- if (RANY(obj)->as.object.iv_tbl) { -- st_free_table(RANY(obj)->as.object.iv_tbl); -- } -- break; -+ if (RANY(obj)->as.object.iv_tbl) { -+ st_free_table(RANY(obj)->as.object.iv_tbl); -+ } -+ break; - case T_MODULE: - case T_CLASS: -- rb_clear_cache_by_class((VALUE)obj); -- st_free_table(RANY(obj)->as.klass.m_tbl); -- if (RANY(obj)->as.object.iv_tbl) { -- st_free_table(RANY(obj)->as.object.iv_tbl); -- } -- break; -+ rb_clear_cache_by_class((VALUE)obj); -+ st_free_table(RANY(obj)->as.klass.m_tbl); -+ if (RANY(obj)->as.object.iv_tbl) { -+ st_free_table(RANY(obj)->as.object.iv_tbl); -+ } -+ break; - case T_STRING: -- if (RANY(obj)->as.string.ptr && !FL_TEST(obj, ELTS_SHARED)) { -- RUBY_CRITICAL(free(RANY(obj)->as.string.ptr)); -- } -- break; -+ if (RANY(obj)->as.string.ptr && !FL_TEST(obj, ELTS_SHARED)) { -+ RUBY_CRITICAL(free(RANY(obj)->as.string.ptr)); -+ } -+ break; - case T_ARRAY: -- if (RANY(obj)->as.array.ptr && !FL_TEST(obj, ELTS_SHARED)) { -- RUBY_CRITICAL(free(RANY(obj)->as.array.ptr)); -- } -- break; -+ if (RANY(obj)->as.array.ptr && !FL_TEST(obj, ELTS_SHARED)) { -+ RUBY_CRITICAL(free(RANY(obj)->as.array.ptr)); -+ } -+ break; - case T_HASH: -- if (RANY(obj)->as.hash.tbl) { -- st_free_table(RANY(obj)->as.hash.tbl); -- } -- break; -+ if (RANY(obj)->as.hash.tbl) { -+ st_free_table(RANY(obj)->as.hash.tbl); -+ } -+ break; - case T_REGEXP: -- if (RANY(obj)->as.regexp.ptr) { -- re_free_pattern(RANY(obj)->as.regexp.ptr); -- } -- if (RANY(obj)->as.regexp.str) { -- RUBY_CRITICAL(free(RANY(obj)->as.regexp.str)); -- } -- break; -+ if (RANY(obj)->as.regexp.ptr) { -+ re_free_pattern(RANY(obj)->as.regexp.ptr); -+ } -+ if (RANY(obj)->as.regexp.str) { -+ RUBY_CRITICAL(free(RANY(obj)->as.regexp.str)); -+ } -+ break; - case T_DATA: - if (DATA_PTR(obj)) { - if ((long)RANY(obj)->as.data.dfree == -1) { -@@ -1317,11 +1649,11 @@ obj_free(obj) - } - break; - case T_MATCH: -- if (RANY(obj)->as.match.regs) { -- re_free_registers(RANY(obj)->as.match.regs); -- RUBY_CRITICAL(free(RANY(obj)->as.match.regs)); -- } -- break; -+ if (RANY(obj)->as.match.regs) { -+ re_free_registers(RANY(obj)->as.match.regs); -+ RUBY_CRITICAL(free(RANY(obj)->as.match.regs)); -+ } -+ break; - case T_FILE: - if (RANY(obj)->as.file.fptr) { - struct rb_io_t *fptr = RANY(obj)->as.file.fptr; -@@ -1332,19 +1664,19 @@ obj_free(obj) - } - break; - case T_ICLASS: -- /* iClass shares table with the module */ -- break; -+ /* iClass shares table with the module */ -+ break; - - case T_FLOAT: - case T_VARMAP: - case T_BLKTAG: -- break; -+ break; - - case T_BIGNUM: -- if (RANY(obj)->as.bignum.digits) { -- RUBY_CRITICAL(free(RANY(obj)->as.bignum.digits)); -- } -- break; -+ if (RANY(obj)->as.bignum.digits) { -+ RUBY_CRITICAL(free(RANY(obj)->as.bignum.digits)); -+ } -+ break; - case T_NODE: - switch (nd_type(obj)) { - case NODE_SCOPE: -@@ -1359,7 +1691,7 @@ obj_free(obj) - break; /* no need to free iv_tbl */ - - case T_SCOPE: -- if (RANY(obj)->as.scope.local_vars && -+ if (RANY(obj)->as.scope.local_vars && - RANY(obj)->as.scope.flags != SCOPE_ALLOCA) { - VALUE *vars = RANY(obj)->as.scope.local_vars-1; - if (!(RANY(obj)->as.scope.flags & SCOPE_CLONE) && vars[0] == 0) -@@ -1370,14 +1702,14 @@ obj_free(obj) - break; - - case T_STRUCT: -- if (RANY(obj)->as.rstruct.ptr) { -- RUBY_CRITICAL(free(RANY(obj)->as.rstruct.ptr)); -- } -- break; -+ if (RANY(obj)->as.rstruct.ptr) { -+ RUBY_CRITICAL(free(RANY(obj)->as.rstruct.ptr)); -+ } -+ break; - - default: -- rb_bug("gc_sweep(): unknown data type 0x%lx(0x%lx)", -- RANY(obj)->as.basic.flags & T_MASK, obj); -+ rb_bug("gc_sweep(): unknown data type 0x%lx(0x%lx)", -+ RANY(obj)->as.basic.flags & T_MASK, obj); - } - - return 0; -@@ -1407,18 +1739,18 @@ _rb_setjmp:\n\ - typedef unsigned long rb_jmp_buf[6]; - __asm__ (".align 4\n\ - _rb_setjmp:\n\ -- pushl %ebp\n\ -- movl %esp,%ebp\n\ -- movl 8(%ebp),%ebp\n\ -- movl %eax,(%ebp)\n\ -- movl %ebx,4(%ebp)\n\ -- movl %ecx,8(%ebp)\n\ -- movl %edx,12(%ebp)\n\ -- movl %esi,16(%ebp)\n\ -- movl %edi,20(%ebp)\n\ -- popl %ebp\n\ -- xorl %eax,%eax\n\ -- ret"); -+ pushl %ebp\n\ -+ movl %esp,%ebp\n\ -+ movl 8(%ebp),%ebp\n\ -+ movl %eax,(%ebp)\n\ -+ movl %ebx,4(%ebp)\n\ -+ movl %ecx,8(%ebp)\n\ -+ movl %edx,12(%ebp)\n\ -+ movl %esi,16(%ebp)\n\ -+ movl %edi,20(%ebp)\n\ -+ popl %ebp\n\ -+ xorl %eax,%eax\n\ -+ ret"); - #endif - #endif - int rb_setjmp (rb_jmp_buf); -@@ -1431,41 +1763,50 @@ garbage_collect() - struct gc_list *list; - struct FRAME * volatile frame; /* gcc 2.7.2.3 -O2 bug?? */ - jmp_buf save_regs_gc_mark; -+ struct timeval gctv1, gctv2; - SET_STACK_END; - - #ifdef HAVE_NATIVETHREAD - if (!is_ruby_native_thread()) { -- rb_bug("cross-thread violation on rb_gc()"); -+ rb_bug("cross-thread violation on rb_gc()"); - } - #endif - if (dont_gc || during_gc) { -- if (!freelist) { -- add_heap(); -- } -- return; -+ if (!freelist) { -+ add_heap(); -+ } -+ return; - } - if (during_gc) return; - during_gc++; - -+ if (gc_statistics) { -+ gc_collections++; -+ gettimeofday(&gctv1, NULL); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "Garbage collection started\n"); -+ } -+ } -+ - init_mark_stack(); - - gc_mark((VALUE)ruby_current_node, 0); - - /* mark frame stack */ - for (frame = ruby_frame; frame; frame = frame->prev) { -- rb_gc_mark_frame(frame); -- if (frame->tmp) { -- struct FRAME *tmp = frame->tmp; -- while (tmp) { -- rb_gc_mark_frame(tmp); -- tmp = tmp->prev; -- } -- } -+ rb_gc_mark_frame(frame); -+ if (frame->tmp) { -+ struct FRAME *tmp = frame->tmp; -+ while (tmp) { -+ rb_gc_mark_frame(tmp); -+ tmp = tmp->prev; -+ } -+ } - } - gc_mark((VALUE)ruby_scope, 0); - gc_mark((VALUE)ruby_dyna_vars, 0); - if (finalizer_table) { -- mark_tbl(finalizer_table, 0); -+ mark_tbl(finalizer_table, 0); - } - - FLUSH_REGISTER_WINDOWS; -@@ -1478,9 +1819,9 @@ garbage_collect() - rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)STACK_END + 1); - #else - if ((VALUE*)STACK_END < rb_gc_stack_start) -- rb_gc_mark_locations((VALUE*)STACK_END, rb_gc_stack_start); -+ rb_gc_mark_locations((VALUE*)STACK_END, rb_gc_stack_start); - else -- rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)STACK_END + 1); -+ rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)STACK_END + 1); - #endif - #ifdef __ia64 - /* mark backing store (flushed register window on the stack) */ -@@ -1489,13 +1830,13 @@ garbage_collect() - #endif - #if defined(__human68k__) || defined(__mc68000__) - rb_gc_mark_locations((VALUE*)((char*)STACK_END + 2), -- (VALUE*)((char*)rb_gc_stack_start + 2)); -+ (VALUE*)((char*)rb_gc_stack_start + 2)); - #endif - rb_gc_mark_threads(); - - /* mark protected global variables */ - for (list = global_List; list; list = list->next) { -- rb_gc_mark_maybe(*list->varptr); -+ rb_gc_mark_maybe(*list->varptr); - } - rb_mark_end_proc(); - rb_gc_mark_global_tbl(); -@@ -1510,18 +1851,30 @@ garbage_collect() - - /* gc_mark objects whose marking are not completed*/ - do { -- while (!MARK_STACK_EMPTY) { -- if (mark_stack_overflow){ -- gc_mark_all(); -- } -- else { -- gc_mark_rest(); -- } -- } -- rb_gc_abort_threads(); -+ while (!MARK_STACK_EMPTY) { -+ if (mark_stack_overflow){ -+ gc_mark_all(); -+ } -+ else { -+ gc_mark_rest(); -+ } -+ } -+ rb_gc_abort_threads(); - } while (!MARK_STACK_EMPTY); - - gc_sweep(); -+ -+ if (gc_statistics) { -+ GC_TIME_TYPE musecs_used; -+ gettimeofday(&gctv2, NULL); -+ musecs_used = ((GC_TIME_TYPE)(gctv2.tv_sec - gctv1.tv_sec) * 1000000) + (gctv2.tv_usec - gctv1.tv_usec); -+ gc_time += musecs_used; -+ -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "GC time: %d msec\n", musecs_used / 1000); -+ fflush(gc_data_file); -+ } -+ } - } - - void -@@ -1588,8 +1941,8 @@ Init_stack(addr) - memset(&m, 0, sizeof(m)); - VirtualQuery(&m, &m, sizeof(m)); - rb_gc_stack_start = -- STACK_UPPER((VALUE *)&m, (VALUE *)m.BaseAddress, -- (VALUE *)((char *)m.BaseAddress + m.RegionSize) - 1); -+ STACK_UPPER((VALUE *)&m, (VALUE *)m.BaseAddress, -+ (VALUE *)((char *)m.BaseAddress + m.RegionSize) - 1); - #elif defined(STACK_END_ADDRESS) - { - extern void *STACK_END_ADDRESS; -@@ -1599,24 +1952,24 @@ Init_stack(addr) - if (!addr) addr = (void *)&addr; - STACK_UPPER(&addr, addr, ++addr); - if (rb_gc_stack_start) { -- if (STACK_UPPER(&addr, -- rb_gc_stack_start > addr, -- rb_gc_stack_start < addr)) -- rb_gc_stack_start = addr; -- return; -+ if (STACK_UPPER(&addr, -+ rb_gc_stack_start > addr, -+ rb_gc_stack_start < addr)) -+ rb_gc_stack_start = addr; -+ return; - } - rb_gc_stack_start = addr; - #endif - #ifdef HAVE_GETRLIMIT - { -- struct rlimit rlim; -+ struct rlimit rlim; - -- if (getrlimit(RLIMIT_STACK, &rlim) == 0) { -- unsigned int space = rlim.rlim_cur/5; -+ if (getrlimit(RLIMIT_STACK, &rlim) == 0) { -+ unsigned int space = rlim.rlim_cur/5; - -- if (space > 1024*1024) space = 1024*1024; -- STACK_LEVEL_MAX = (rlim.rlim_cur - space) / sizeof(VALUE); -- } -+ if (space > 1024*1024) space = 1024*1024; -+ STACK_LEVEL_MAX = (rlim.rlim_cur - space) / sizeof(VALUE); -+ } - } - #endif - } -@@ -1652,16 +2005,16 @@ void ruby_init_stack(VALUE *addr - } - #elif defined _WIN32 - { -- MEMORY_BASIC_INFORMATION mi; -- DWORD size; -- DWORD space; -- -- if (VirtualQuery(&mi, &mi, sizeof(mi))) { -- size = (char *)mi.BaseAddress - (char *)mi.AllocationBase; -- space = size / 5; -- if (space > 1024*1024) space = 1024*1024; -- STACK_LEVEL_MAX = (size - space) / sizeof(VALUE); -- } -+ MEMORY_BASIC_INFORMATION mi; -+ DWORD size; -+ DWORD space; -+ -+ if (VirtualQuery(&mi, &mi, sizeof(mi))) { -+ size = (char *)mi.BaseAddress - (char *)mi.AllocationBase; -+ space = size / 5; -+ if (space > 1024*1024) space = 1024*1024; -+ STACK_LEVEL_MAX = (size - space) / sizeof(VALUE); -+ } - } - #endif - } -@@ -1701,8 +2054,9 @@ void - Init_heap() - { - if (!rb_gc_stack_start) { -- Init_stack(0); -+ Init_stack(0); - } -+ set_gc_parameters(); - add_heap(); - } - -@@ -1715,7 +2069,7 @@ os_obj_of(of) - volatile VALUE v; - - for (i = 0; i < heaps_used; i++) { -- RVALUE *p, *pend; -+ RVALUE *p, *pend; - - p = heaps[i].slot; pend = p + heaps[i].limit; - for (;p < pend; p++) { -@@ -1808,8 +2162,8 @@ add_final(os, block) - { - rb_warn("ObjectSpace::add_finalizer is deprecated; use define_finalizer"); - if (!rb_respond_to(block, rb_intern("call"))) { -- rb_raise(rb_eArgError, "wrong type argument %s (should be callable)", -- rb_obj_classname(block)); -+ rb_raise(rb_eArgError, "wrong type argument %s (should be callable)", -+ rb_obj_classname(block)); - } - rb_ary_push(finalizers, block); - return block; -@@ -1864,7 +2218,7 @@ undefine_final(os, obj) - VALUE os, obj; - { - if (finalizer_table) { -- st_delete(finalizer_table, (st_data_t*)&obj, 0); -+ st_delete(finalizer_table, (st_data_t*)&obj, 0); - } - return obj; - } -@@ -1888,11 +2242,11 @@ define_final(argc, argv, os) - - rb_scan_args(argc, argv, "11", &obj, &block); - if (argc == 1) { -- block = rb_block_proc(); -+ block = rb_block_proc(); - } - else if (!rb_respond_to(block, rb_intern("call"))) { -- rb_raise(rb_eArgError, "wrong type argument %s (should be callable)", -- rb_obj_classname(block)); -+ rb_raise(rb_eArgError, "wrong type argument %s (should be callable)", -+ rb_obj_classname(block)); - } - need_call_final = 1; - if (!FL_ABLE(obj)) { -@@ -1905,10 +2259,10 @@ define_final(argc, argv, os) - OBJ_FREEZE(block); - - if (!finalizer_table) { -- finalizer_table = st_init_numtable(); -+ finalizer_table = st_init_numtable(); - } - if (st_lookup(finalizer_table, obj, &table)) { -- rb_ary_push(table, block); -+ rb_ary_push(table, block); - } - else { - table = rb_ary_new3(1, block); -@@ -1927,7 +2281,7 @@ rb_gc_copy_finalizer(dest, obj) - if (!finalizer_table) return; - if (!FL_TEST(obj, FL_FINALIZE)) return; - if (st_lookup(finalizer_table, obj, &table)) { -- st_insert(finalizer_table, dest, table); -+ st_insert(finalizer_table, dest, table); - } - RBASIC(dest)->flags |= FL_FINALIZE; - } -@@ -1957,18 +2311,18 @@ run_final(obj) - args[1] = 0; - args[2] = (VALUE)ruby_safe_level; - for (i=0; ilen; i++) { -- args[0] = RARRAY(finalizers)->ptr[i]; -- if (!args[1]) args[1] = rb_ary_new3(1, objid); -- rb_protect((VALUE(*)_((VALUE)))run_single_final, (VALUE)args, &status); -+ args[0] = RARRAY(finalizers)->ptr[i]; -+ if (!args[1]) args[1] = rb_ary_new3(1, objid); -+ rb_protect((VALUE(*)_((VALUE)))run_single_final, (VALUE)args, &status); - } - if (finalizer_table && st_delete(finalizer_table, (st_data_t*)&obj, &table)) { -- for (i=0; ilen; i++) { -- VALUE final = RARRAY(table)->ptr[i]; -- args[0] = RARRAY(final)->ptr[1]; -- if (!args[1]) args[1] = rb_ary_new3(1, objid); -- args[2] = FIX2INT(RARRAY(final)->ptr[0]); -- rb_protect((VALUE(*)_((VALUE)))run_single_final, (VALUE)args, &status); -- } -+ for (i=0; ilen; i++) { -+ VALUE final = RARRAY(table)->ptr[i]; -+ args[0] = RARRAY(final)->ptr[1]; -+ if (!args[1]) args[1] = rb_ary_new3(1, objid); -+ args[2] = FIX2INT(RARRAY(final)->ptr[0]); -+ rb_protect((VALUE(*)_((VALUE)))run_single_final, (VALUE)args, &status); -+ } - } - rb_thread_critical = critical_save; - } -@@ -1980,8 +2334,8 @@ rb_gc_finalize_deferred() - - deferred_final_list = 0; - if (p) { -- finalize_list(p); -- free_unused_heaps(); -+ finalize_list(p); -+ free_unused_heaps(); - } - } - -@@ -2061,7 +2415,7 @@ id2ref(obj, objid) - if (ptr == Qfalse) return Qfalse; - if (ptr == Qnil) return Qnil; - if (FIXNUM_P(ptr)) return (VALUE)ptr; -- ptr = objid ^ FIXNUM_FLAG; /* unset FIXNUM_FLAG */ -+ ptr = objid ^ FIXNUM_FLAG; /* unset FIXNUM_FLAG */ - - if ((ptr % sizeof(RVALUE)) == (4 << 2)) { - ID symid = ptr / sizeof(RVALUE); -@@ -2075,7 +2429,7 @@ id2ref(obj, objid) - rb_raise(rb_eRangeError, "0x%lx is not id value", p0); - } - if (BUILTIN_TYPE(ptr) == 0 || RBASIC(ptr)->klass == 0) { -- rb_raise(rb_eRangeError, "0x%lx is recycled object", p0); -+ rb_raise(rb_eRangeError, "0x%lx is recycled object", p0); - } - return (VALUE)ptr; - } -@@ -2166,6 +2520,14 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "stress=", gc_stress_set, 1); - rb_define_method(rb_mGC, "garbage_collect", rb_gc_start, 0); - -+ rb_define_singleton_method(rb_mGC, "enable_stats", rb_gc_enable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "disable_stats", rb_gc_disable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0); -+ rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); -+ rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); -+ rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); -+ rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); -+ - rb_mObSpace = rb_define_module("ObjectSpace"); - rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1); - rb_define_module_function(rb_mObSpace, "garbage_collect", rb_gc_start, 0); -@@ -2188,7 +2550,7 @@ Init_GC() - - rb_global_variable(&nomem_error); - nomem_error = rb_exc_new3(rb_eNoMemError, -- rb_obj_freeze(rb_str_new2("failed to allocate memory"))); -+ rb_obj_freeze(rb_str_new2("failed to allocate memory"))); - OBJ_TAINT(nomem_error); - OBJ_FREEZE(nomem_error); - diff --git a/patches/ruby/1.8.7/head/railsexpress/05-display-full-stack-trace.patch b/patches/ruby/1.8.7/head/railsexpress/05-display-full-stack-trace.patch deleted file mode 100644 index a927a80ba6..0000000000 --- a/patches/ruby/1.8.7/head/railsexpress/05-display-full-stack-trace.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/eval.c b/eval.c -index 6ff2560..fb3307c 100644 ---- a/eval.c -+++ b/eval.c -@@ -1325,8 +1325,8 @@ error_print() - int truncate = eclass == rb_eSysStackError; - - #define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5) --#define TRACE_HEAD 8 --#define TRACE_TAIL 5 -+#define TRACE_HEAD 100 -+#define TRACE_TAIL 100 - - ep = RARRAY(errat); - for (i=1; ilen; i++) { diff --git a/patches/ruby/1.8.7/head/railsexpress/06-better-source-file-tracing.patch b/patches/ruby/1.8.7/head/railsexpress/06-better-source-file-tracing.patch deleted file mode 100644 index f7a4d4f24f..0000000000 --- a/patches/ruby/1.8.7/head/railsexpress/06-better-source-file-tracing.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/eval.c b/eval.c -index fb3307c..356226e 100644 ---- a/eval.c -+++ b/eval.c -@@ -1161,7 +1161,7 @@ static VALUE trace_func = 0; - static int tracing = 0; - static void call_trace_func _((rb_event_t,NODE*,VALUE,ID,VALUE)); - --#if 0 -+#if 1 - #define SET_CURRENT_SOURCE() (ruby_sourcefile = ruby_current_node->nd_file, \ - ruby_sourceline = nd_line(ruby_current_node)) - #else diff --git a/patches/ruby/1.8.7/head/railsexpress/07-heap-dump-support.patch b/patches/ruby/1.8.7/head/railsexpress/07-heap-dump-support.patch deleted file mode 100644 index 5235be6bcc..0000000000 --- a/patches/ruby/1.8.7/head/railsexpress/07-heap-dump-support.patch +++ /dev/null @@ -1,159 +0,0 @@ -diff --git a/configure.in b/configure.in -index 62b34a8..4be088c 100644 ---- a/configure.in -+++ b/configure.in -@@ -1595,6 +1595,14 @@ fi - LDFLAGS="-L. $LDFLAGS" - AC_SUBST(ARCHFILE) - -+dnl enable gc debugging -+AC_ARG_ENABLE(gcdebug, -+ [ --enable-gcdebug build garbage collector with debugging enabled. ], -+ [enable_gcdebug=$enableval]) -+if test "$enable_gcdebug" = 'yes'; then -+ AC_DEFINE(GC_DEBUG, 1) -+fi -+ - dnl build rdoc index if requested - RDOCTARGET="" - AC_ARG_ENABLE(install-doc, -diff --git a/gc.c b/gc.c -index ab71d22..9ad716f 100644 ---- a/gc.c -+++ b/gc.c -@@ -411,7 +411,6 @@ rb_gc_unregister_address(addr) - } - } - --#undef GC_DEBUG - - void - rb_global_variable(var) -@@ -602,6 +601,85 @@ rb_gc_dump() - return Qnil; - } - -+ -+static char* obj_type(int tp); -+ -+#ifdef GC_DEBUG -+/* -+ * call-seq: -+ * GC.dump_file_and_line_info(String, boolean) => nil -+ * -+ * dumps information on which currently allocated object was created by which file and on which line -+ * -+ * GC.dump_file_and_line_info(String, boolean) #=> nil -+ * -+ * The second parameter specifies whether class names should be included in the dump. -+ * Note that including class names will allocate additional string objects on the heap. -+ * -+ */ -+ -+VALUE -+rb_gc_dump_file_and_line_info(int argc, VALUE *argv) -+{ -+ VALUE filename, str, include_classnames = Qnil; -+ char *fname = NULL; -+ char *klass = NULL; -+ FILE* f = NULL; -+ int i,n = 0; -+ -+ rb_scan_args(argc, argv, "11", &filename, &include_classnames); -+ -+ str = StringValue(filename); -+ fname = RSTRING(str)->ptr; -+ f = fopen(fname, "w"); -+ -+ for (i = 0; i < heaps_used; i++) { -+ RVALUE *p, *pend; -+ -+ p = heaps[i].slot; pend = p + heaps[i].limit; -+ for (;p < pend; p++) { -+ if (p->as.basic.flags) { -+ fprintf(f, "%s:%s:%d", obj_type(p->as.basic.flags & T_MASK), p->file, p->line); -+ // rb_obj_classname will create objects on the heap, we need a better solution -+ if (include_classnames == Qtrue) { -+ /* write the class */ -+ fprintf(f, ":"); -+ switch (TYPE(p)) { -+ case T_NONE: -+ fprintf(f, "__none__"); -+ break; -+ case T_BLKTAG: -+ fprintf(f, "__blktag__"); -+ break; -+ case T_UNDEF: -+ fprintf(f, "__undef__"); -+ break; -+ case T_VARMAP: -+ fprintf(f, "__varmap__"); -+ break; -+ case T_SCOPE: -+ fprintf(f, "__scope__"); -+ break; -+ case T_NODE: -+ fprintf(f, "__node__"); -+ break; -+ default: -+ if (!p->as.basic.klass) { -+ fprintf(f, "__unknown__"); -+ } else { -+ fprintf(f, rb_obj_classname((VALUE)p)); -+ } -+ } -+ } -+ fprintf(f, "\n"); -+ } -+ } -+ } -+ fclose(f); -+ return Qnil; -+} -+#endif -+ - /* - * call-seq: - * GC.log String => String -@@ -1066,6 +1144,11 @@ gc_mark(ptr, lev) - if (obj->as.basic.flags & FL_MARK) return; /* already marked */ - obj->as.basic.flags |= FL_MARK; - -+#ifdef GC_DEBUG -+ /* mark our new reference point for sourcefile objects */ -+ mark_source_filename(RANY(obj)->file); -+#endif -+ - if (lev > GC_LEVEL_MAX || (lev == 0 && ruby_stack_check())) { - if (!mark_stack_overflow) { - if (mark_stack_ptr - mark_stack < MARK_STACK_MAX) { -@@ -1104,6 +1187,11 @@ gc_mark_children(ptr, lev) - if (obj->as.basic.flags & FL_MARK) return; /* already marked */ - obj->as.basic.flags |= FL_MARK; - -+#ifdef GC_DEBUG -+ /* mark our new reference point for sourcefile objects */ -+ mark_source_filename(RANY(obj)->file); -+#endif -+ - marking: - if (FL_TEST(obj, FL_EXIVAR)) { - rb_mark_generic_ivar(ptr); -@@ -1550,6 +1638,7 @@ gc_sweep() - live_counts[i], free_counts[i], obj_type(i)); - } - } -+ fflush(gc_data_file); - } - - /* clear finalization list */ -@@ -2526,6 +2615,9 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); - rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); - rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); -+#ifdef GC_DEBUG -+ rb_define_singleton_method(rb_mGC, "dump_file_and_line_info", rb_gc_dump_file_and_line_info, -1); -+#endif - rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); - - rb_mObSpace = rb_define_module("ObjectSpace"); diff --git a/patches/ruby/1.8.7/head/railsexpress/08-fork-support-for-gc-logging.patch b/patches/ruby/1.8.7/head/railsexpress/08-fork-support-for-gc-logging.patch deleted file mode 100644 index 0f01a75db0..0000000000 --- a/patches/ruby/1.8.7/head/railsexpress/08-fork-support-for-gc-logging.patch +++ /dev/null @@ -1,249 +0,0 @@ -diff --git a/gc.c b/gc.c -index 9ad716f..a3cbe91 100644 ---- a/gc.c -+++ b/gc.c -@@ -223,6 +223,8 @@ static int dont_gc; - static int gc_statistics = 0; - static GC_TIME_TYPE gc_time = 0; - static int gc_collections = 0; -+static int verbose_gc_stats = Qfalse; -+static FILE* gc_data_file = NULL; - static int during_gc; - static int need_call_final = 0; - static st_table *finalizer_table = 0; -@@ -368,9 +370,148 @@ rb_gc_time() - #endif - } - -- - VALUE rb_mGC; - -+/* -+ * call-seq: -+ * GC.enable_trace => true or false -+ * -+ * Enables garbage collection tracing, returning true if garbage -+ * collection tracing was already enabled. -+ * -+ * GC.enable_trace #=> false or true -+ * GC.enable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_trace() -+{ -+ int old = verbose_gc_stats; -+ verbose_gc_stats = Qtrue; -+ return old; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_trace => true or false -+ * -+ * Disables garbage collection tracing, returning true if garbage -+ * collection tracing was already disabled. -+ * -+ * GC.disable_trace #=> false or true -+ * GC.disable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_trace() -+{ -+ int old = verbose_gc_stats; -+ verbose_gc_stats = Qfalse; -+ return old; -+} -+ -+char* GC_LOGFILE_IVAR = "@gc_logfile_name"; -+ -+/* -+ * call-seq: -+ * GC.log_file(filename=nil, mode="w") => boolean -+ * -+ * Changes the GC data log file. Closes the currently open logfile. -+ * Returns true if the file was successfully opened for -+ * writing. Returns false if the file could not be opened for -+ * writing. Returns the name of the current logfile (or nil) if no -+ * parameter is given. Restores logging to stderr when given nil as -+ * an argument. -+ * -+ * GC.log_file #=> nil -+ * GC.log_file "/tmp/gc.log" #=> true -+ * GC.log_file #=> "/tmp/gc.log" -+ * GC.log_file nil #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_log_file(int argc, VALUE *argv, VALUE self) -+{ -+ VALUE filename = Qnil; -+ VALUE mode_str = Qnil; -+ FILE* f = NULL; -+ char* mode = "w"; -+ -+ VALUE current_logfile_name = rb_iv_get(rb_mGC, GC_LOGFILE_IVAR); -+ -+ if (argc==0) -+ return current_logfile_name; -+ -+ rb_scan_args(argc, argv, "02", &filename, &mode_str); -+ -+ if (filename == Qnil) { -+ /* close current logfile and reset logfile to stderr */ -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+ } -+ return Qtrue; -+ } -+ -+ /* we have a real logfile name */ -+ filename = StringValue(filename); -+ -+ if (rb_equal(current_logfile_name, filename) == Qtrue) { -+ /* do nothing if we get the file name we're already logging to */ -+ return Qtrue; -+ } -+ -+ /* get mode for file opening */ -+ if (mode_str != Qnil) -+ { -+ mode = RSTRING(StringValue(mode_str))->ptr; -+ } -+ -+ /* try to open file in given mode */ -+ if (f = fopen(RSTRING(filename)->ptr, mode)) { -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ } -+ gc_data_file = f; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, filename); -+ } else { -+ return Qfalse; -+ } -+ return Qtrue; -+} -+ -+ -+/* -+ * Called from process.c before a fork. Flushes the gc log file to -+ * avoid writing the buffered output twice (once in the parent, and -+ * once in the child). -+ */ -+void -+rb_gc_before_fork() -+{ -+ /* flush gc log file */ -+ fflush(gc_data_file); -+} -+ -+/* -+ * Called from process.c after a fork in the child process. Turns off -+ * logging, disables GC stats and resets all gc counters and timing -+ * information. -+ */ -+void -+rb_gc_after_fork() -+{ -+ rb_gc_disable_stats(); -+ rb_gc_clear_stats(); -+ rb_gc_disable_trace(); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+} -+ - static struct gc_list { - VALUE *varptr; - struct gc_list *next; -@@ -477,10 +618,6 @@ static double heap_slots_growth_factor = 1.8; - - static long initial_malloc_limit = GC_MALLOC_LIMIT; - --static int verbose_gc_stats = Qfalse; -- --static FILE* gc_data_file = NULL; -- - static RVALUE *himem, *lomem; - - static void set_gc_parameters() -@@ -496,6 +633,8 @@ static void set_gc_parameters() - if (gc_stats_i > 0) { - verbose_gc_stats = Qtrue; - } -+ /* child processes should not inherit RUBY_GC_STATS */ -+ unsetenv("RUBY_GC_STATS"); - } - - gc_heap_file_ptr = getenv("RUBY_GC_DATA_FILE"); -@@ -508,6 +647,8 @@ static void set_gc_parameters() - fprintf(stderr, - "can't open gc log file %s for writing, using default\n", gc_heap_file_ptr); - } -+ /* child processes should not inherit RUBY_GC_DATA_FILE to avoid clobbering */ -+ unsetenv("RUBY_GC_DATA_FILE"); - } - - min_slots_ptr = getenv("RUBY_HEAP_MIN_SLOTS"); -@@ -2619,6 +2760,9 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "dump_file_and_line_info", rb_gc_dump_file_and_line_info, -1); - #endif - rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); -+ rb_define_singleton_method(rb_mGC, "log_file", rb_gc_log_file, -1); -+ rb_define_singleton_method(rb_mGC, "enable_trace", rb_gc_enable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "disable_trace", rb_gc_disable_trace, 0); - - rb_mObSpace = rb_define_module("ObjectSpace"); - rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1); -diff --git a/intern.h b/intern.h -index 950ae9d..99696f1 100644 ---- a/intern.h -+++ b/intern.h -@@ -270,6 +270,8 @@ void rb_gc_call_finalizer_at_exit _((void)); - VALUE rb_gc_enable _((void)); - VALUE rb_gc_disable _((void)); - VALUE rb_gc_start _((void)); -+void rb_gc_before_fork _((void)); -+void rb_gc_after_fork _((void)); - /* hash.c */ - void st_foreach_safe _((struct st_table *, int (*)(ANYARGS), unsigned long)); - void rb_hash_foreach _((VALUE, int (*)(ANYARGS), VALUE)); -diff --git a/process.c b/process.c -index 8f6285d..ea28cb8 100644 ---- a/process.c -+++ b/process.c -@@ -1330,6 +1330,8 @@ rb_f_fork(obj) - fflush(stderr); - #endif - -+ rb_gc_before_fork(); -+ - before_exec(); - pid = fork(); - after_exec(); -@@ -1339,6 +1341,7 @@ rb_f_fork(obj) - #ifdef linux - after_exec(); - #endif -+ rb_gc_after_fork(); - rb_thread_atfork(); - if (rb_block_given_p()) { - int status; -@@ -1574,10 +1577,12 @@ rb_f_system(argc, argv) - - chfunc = signal(SIGCHLD, SIG_DFL); - retry: -+ rb_gc_before_fork(); - before_exec(); - pid = fork(); - if (pid == 0) { - /* child process */ -+ rb_gc_after_fork(); - rb_thread_atfork(); - rb_protect(proc_exec_args, (VALUE)&earg, NULL); - _exit(127); diff --git a/patches/ruby/1.8.7/head/railsexpress/09-track-malloc-size.patch b/patches/ruby/1.8.7/head/railsexpress/09-track-malloc-size.patch deleted file mode 100644 index d078748a44..0000000000 --- a/patches/ruby/1.8.7/head/railsexpress/09-track-malloc-size.patch +++ /dev/null @@ -1,120 +0,0 @@ -diff --git a/gc.c b/gc.c -index a3cbe91..30a1219 100644 ---- a/gc.c -+++ b/gc.c -@@ -79,6 +79,17 @@ void *alloca (); - - static unsigned long malloc_increase = 0; - static unsigned long malloc_limit = GC_MALLOC_LIMIT; -+ -+#ifdef HAVE_LONG_LONG -+static unsigned LONG_LONG gc_allocated_size = 0; -+static unsigned LONG_LONG gc_num_allocations = 0; -+#else -+static unsigned long gc_allocated_size = 0; -+static unsigned long gc_num_allocations = 0; -+#endif -+static int gc_statistics = 0; -+ -+ - static void run_final(); - static VALUE nomem_error; - static void garbage_collect(); -@@ -163,6 +174,11 @@ ruby_xmalloc(size) - } - malloc_increase += size; - -+ if (gc_statistics) { -+ gc_allocated_size += size; -+ gc_num_allocations += 1; -+ } -+ - return mem; - } - -@@ -220,7 +236,6 @@ ruby_xfree(x) - - extern int ruby_in_compile; - static int dont_gc; --static int gc_statistics = 0; - static GC_TIME_TYPE gc_time = 0; - static int gc_collections = 0; - static int verbose_gc_stats = Qfalse; -@@ -329,11 +344,55 @@ rb_gc_clear_stats() - { - gc_collections = 0; - gc_time = 0; -+ gc_allocated_size = 0; -+ gc_num_allocations = 0; - return Qnil; - } - - /* - * call-seq: -+ * GC.allocated_size => Integer -+ * -+ * Returns the size of memory (in bytes) allocated since GC statistics collection -+ * was enabled. -+ * -+ * GC.allocated_size #=> 35 -+ * -+ */ -+VALUE -+rb_gc_allocated_size() -+{ -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_allocated_size); -+#else -+ return ULONG2NUM(gc_allocated_size); -+#endif -+} -+ -+/* -+ * call-seq: -+ * GC.num_allocations => Integer -+ * -+ * Returns the number of memory allocations since GC statistics collection -+ * was enabled. -+ * -+ * GC.num_allocations #=> 150 -+ * -+ */ -+VALUE -+rb_gc_num_allocations() -+{ -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_num_allocations); -+#else -+ return ULONG2NUM(gc_num_allocations); -+#endif -+} -+ -+/* -+ -+/* -+ * call-seq: - * GC.collections => Integer - * - * Returns the number of garbage collections performed while GC statistics collection -@@ -2753,6 +2812,8 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "enable_stats", rb_gc_enable_stats, 0); - rb_define_singleton_method(rb_mGC, "disable_stats", rb_gc_disable_stats, 0); - rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0); -+ rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); -+ rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); - rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); - rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); - rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); -diff --git a/intern.h b/intern.h -index 99696f1..1117614 100644 ---- a/intern.h -+++ b/intern.h -@@ -272,6 +272,8 @@ VALUE rb_gc_disable _((void)); - VALUE rb_gc_start _((void)); - void rb_gc_before_fork _((void)); - void rb_gc_after_fork _((void)); -+VALUE rb_gc_allocated_size _((void)); -+VALUE rb_gc_num_allocations _((void)); - /* hash.c */ - void st_foreach_safe _((struct st_table *, int (*)(ANYARGS), unsigned long)); - void rb_hash_foreach _((VALUE, int (*)(ANYARGS), VALUE)); diff --git a/patches/ruby/1.8.7/head/railsexpress/10-track-object-allocation.patch b/patches/ruby/1.8.7/head/railsexpress/10-track-object-allocation.patch deleted file mode 100644 index 0eef717a24..0000000000 --- a/patches/ruby/1.8.7/head/railsexpress/10-track-object-allocation.patch +++ /dev/null @@ -1,111 +0,0 @@ -diff --git a/gc.c b/gc.c -index 30a1219..5b42b90 100644 ---- a/gc.c -+++ b/gc.c -@@ -96,6 +96,26 @@ static void garbage_collect(); - - int ruby_gc_stress = 0; - -+static unsigned long live_objects = 0; -+unsigned long rb_os_live_objects() -+{ -+ return live_objects; -+} -+ -+#if defined(HAVE_LONG_LONG) -+static unsigned LONG_LONG allocated_objects = 0; -+unsigned LONG_LONG rb_os_allocated_objects() -+{ -+ return allocated_objects; -+} -+#else -+static unsigned long allocated_objects = 0; -+unsigned long rb_os_allocated_objects() -+{ -+ return allocated_objects; -+} -+#endif -+ - NORETURN(void rb_exc_jump _((VALUE))); - - void -@@ -987,6 +1007,8 @@ rb_newobj() - RANY(obj)->file = ruby_sourcefile; - RANY(obj)->line = ruby_sourceline; - #endif -+ live_objects++; -+ allocated_objects++; - return obj; - } - -@@ -1825,6 +1847,7 @@ gc_sweep() - add_heap(); - } - during_gc = 0; -+ live_objects = live; - - if (do_gc_stats) { - fprintf(gc_data_file, "objects processed: %.7d\n", live+freed); -@@ -2790,6 +2813,35 @@ rb_obj_id(VALUE obj) - return (VALUE)((long)obj|FIXNUM_FLAG); - } - -+/* call-seq: -+ * ObjectSpace.live_objects => number -+ * -+ * Returns the count of objects currently allocated in the system. This goes -+ * down after the garbage collector runs. -+ */ -+static -+VALUE os_live_objects(VALUE self) -+{ -+ return ULONG2NUM(live_objects); -+} -+ -+/* call-seq: -+ * ObjectSpace.allocated_objects => number -+ * -+ * Returns the count of objects allocated since the Ruby interpreter has -+ * started. This number can only increase. To know how many objects are -+ * currently allocated, use ObjectSpace::live_objects -+ */ -+static -+VALUE os_allocated_objects(VALUE self) -+{ -+#if defined(HAVE_LONG_LONG) -+ return ULL2NUM(allocated_objects); -+#else -+ return ULONG2NUM(allocated_objects); -+#endif -+} -+ - /* - * The GC module provides an interface to Ruby's mark and - * sweep garbage collection mechanism. Some of the underlying methods -@@ -2833,6 +2885,9 @@ Init_GC() - rb_define_module_function(rb_mObSpace, "finalizers", finals, 0); - rb_define_module_function(rb_mObSpace, "call_finalizer", call_final, 1); - -+ rb_define_module_function(rb_mObSpace, "live_objects", os_live_objects, 0); -+ rb_define_module_function(rb_mObSpace, "allocated_objects", os_allocated_objects, 0); -+ - rb_define_module_function(rb_mObSpace, "define_finalizer", define_final, -1); - rb_define_module_function(rb_mObSpace, "undefine_finalizer", undefine_final, 1); - -diff --git a/intern.h b/intern.h -index 1117614..a87661d 100644 ---- a/intern.h -+++ b/intern.h -@@ -274,6 +274,12 @@ void rb_gc_before_fork _((void)); - void rb_gc_after_fork _((void)); - VALUE rb_gc_allocated_size _((void)); - VALUE rb_gc_num_allocations _((void)); -+unsigned long rb_os_live_objects _((void)); -+#ifdef HAVE_LONG_LONG -+unsigned LONG_LONG rb_os_allocated_objects _((void)); -+#else -+unsigned long rb_os_allocated_objects _((void)); -+#endif - /* hash.c */ - void st_foreach_safe _((struct st_table *, int (*)(ANYARGS), unsigned long)); - void rb_hash_foreach _((VALUE, int (*)(ANYARGS), VALUE)); diff --git a/patches/ruby/1.8.7/head/railsexpress/11-expose-heap-slots.patch b/patches/ruby/1.8.7/head/railsexpress/11-expose-heap-slots.patch deleted file mode 100644 index 3ce846c6a0..0000000000 --- a/patches/ruby/1.8.7/head/railsexpress/11-expose-heap-slots.patch +++ /dev/null @@ -1,70 +0,0 @@ -diff --git a/gc.c b/gc.c -index 5b42b90..21b3f6b 100644 ---- a/gc.c -+++ b/gc.c -@@ -690,6 +690,7 @@ static int heaps_used = 0; - - static int heap_min_slots = 10000; - static int heap_slots = 10000; -+static int heap_size = 0; - - static int heap_free_min = 4096; - static int heap_slots_increment = 10000; -@@ -800,6 +801,21 @@ static void set_gc_parameters() - - /* - * call-seq: -+ * GC.heap_slots => Integer -+ * -+ * Returns the number of heap slots available for object allocations. -+ * -+ * GC.heap_slots #=> 10000 -+ * -+ */ -+VALUE -+rb_gc_heap_slots() -+{ -+ return INT2NUM(heap_size); -+} -+ -+/* -+ * call-seq: - * GC.dump => nil - * - * dumps information about the current GC data structures to the GC log file -@@ -967,6 +983,7 @@ add_heap() - heaps[heaps_used].limit = heap_slots; - break; - } -+ heap_size += heap_slots; - pend = p + heap_slots; - if (lomem == 0 || lomem > p) lomem = p; - if (himem < pend) himem = pend; -@@ -1828,6 +1845,7 @@ gc_sweep() - if (n == heaps[i].limit && freed > free_min) { - RVALUE *pp; - -+ heap_size -= n; - heaps[i].limit = 0; - for (pp = final_list; pp != final; pp = pp->as.free.next) { - pp->as.free.flags |= FL_SINGLETON; /* freeing page mark */ -@@ -2866,6 +2884,7 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0); - rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); - rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); - rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); - rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); - rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); -diff --git a/intern.h b/intern.h -index a87661d..e8f3209 100644 ---- a/intern.h -+++ b/intern.h -@@ -274,6 +274,7 @@ void rb_gc_before_fork _((void)); - void rb_gc_after_fork _((void)); - VALUE rb_gc_allocated_size _((void)); - VALUE rb_gc_num_allocations _((void)); -+VALUE rb_gc_heap_slots _((void)); - unsigned long rb_os_live_objects _((void)); - #ifdef HAVE_LONG_LONG - unsigned LONG_LONG rb_os_allocated_objects _((void)); diff --git a/patches/ruby/1.8.7/head/railsexpress/12-fix-heap-size-growth-logic.patch b/patches/ruby/1.8.7/head/railsexpress/12-fix-heap-size-growth-logic.patch deleted file mode 100644 index 1db93f224d..0000000000 --- a/patches/ruby/1.8.7/head/railsexpress/12-fix-heap-size-growth-logic.patch +++ /dev/null @@ -1,54 +0,0 @@ -diff --git a/gc.c b/gc.c -index 21b3f6b..7db1ef6 100644 ---- a/gc.c -+++ b/gc.c -@@ -694,6 +694,7 @@ static int heap_size = 0; - - static int heap_free_min = 4096; - static int heap_slots_increment = 10000; -+static int initial_heap_slots_increment = 10000; - static double heap_slots_growth_factor = 1.8; - - static long initial_malloc_limit = GC_MALLOC_LIMIT; -@@ -771,14 +772,13 @@ static void set_gc_parameters() - if (verbose_gc_stats) { - fprintf(gc_data_file, "RUBY_HEAP_SLOTS_INCREMENT=%s\n", heap_slots_incr_ptr); - } -- if (heap_slots_incr_i > 0) { -- heap_slots_increment = heap_slots_incr_i; -- } -+ heap_slots_increment = heap_slots_incr_i; -+ initial_heap_slots_increment = heap_slots_increment; - } - - heap_slots_growth_factor_ptr = getenv("RUBY_HEAP_SLOTS_GROWTH_FACTOR"); - if (heap_slots_growth_factor_ptr != NULL) { -- double heap_slots_growth_factor_d = atoi(heap_slots_growth_factor_ptr); -+ double heap_slots_growth_factor_d = atof(heap_slots_growth_factor_ptr); - if (verbose_gc_stats) { - fprintf(gc_data_file, "RUBY_HEAP_SLOTS_GROWTH_FACTOR=%s\n", heap_slots_growth_factor_ptr); - } -@@ -988,8 +988,13 @@ add_heap() - if (lomem == 0 || lomem > p) lomem = p; - if (himem < pend) himem = pend; - heaps_used++; -- heap_slots += heap_slots_increment; -- heap_slots_increment *= heap_slots_growth_factor; -+ if (heaps_used == 1) -+ heap_slots = initial_heap_slots_increment; -+ else { -+ heap_slots_increment *= heap_slots_growth_factor; -+ heap_slots += heap_slots_increment; -+ } -+ - if (heap_slots <= 0) heap_slots = heap_min_slots; - - while (p < pend) { -@@ -1879,6 +1884,7 @@ gc_sweep() - live_counts[i], free_counts[i], obj_type(i)); - } - } -+ rb_gc_dump(); - fflush(gc_data_file); - } - diff --git a/patches/ruby/1.8.7/head/railsexpress/13-heap-slot-size.patch b/patches/ruby/1.8.7/head/railsexpress/13-heap-slot-size.patch deleted file mode 100644 index 45091c14ae..0000000000 --- a/patches/ruby/1.8.7/head/railsexpress/13-heap-slot-size.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/gc.c b/gc.c -index 7db1ef6..57740d2 100644 ---- a/gc.c -+++ b/gc.c -@@ -2891,6 +2891,7 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); - rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); - rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); - rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); - rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); - rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); diff --git a/patches/ruby/1.8.7/head/railsexpress/14-add-trace-stats-enabled-methods.patch b/patches/ruby/1.8.7/head/railsexpress/14-add-trace-stats-enabled-methods.patch deleted file mode 100644 index 4e3c4f2132..0000000000 --- a/patches/ruby/1.8.7/head/railsexpress/14-add-trace-stats-enabled-methods.patch +++ /dev/null @@ -1,66 +0,0 @@ -diff --git a/gc.c b/gc.c -index 57740d2..2c34932 100644 ---- a/gc.c -+++ b/gc.c -@@ -350,6 +350,22 @@ rb_gc_disable_stats() - - /* - * call-seq: -+ * GC.stats_enabled? => true or false -+ * -+ * Check whether GC stats have been enabled. -+ * -+ * GC.stats_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_stats_enabled() -+{ -+ return gc_statistics ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: - * GC.clear_stats => nil - * - * Clears garbage collection statistics, returning nil. This resets the number -@@ -491,6 +507,22 @@ rb_gc_disable_trace() - return old; - } - -+/* -+ * call-seq: -+ * GC.trace_enabled? => true or false -+ * -+ * Check whether GC tracing has been enabled. -+ * -+ * GC.trace_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_trace_enabled() -+{ -+ return verbose_gc_stats ? Qtrue : Qfalse; -+} -+ - char* GC_LOGFILE_IVAR = "@gc_logfile_name"; - - /* -@@ -2887,6 +2919,7 @@ Init_GC() - - rb_define_singleton_method(rb_mGC, "enable_stats", rb_gc_enable_stats, 0); - rb_define_singleton_method(rb_mGC, "disable_stats", rb_gc_disable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "stats_enabled?", rb_gc_stats_enabled, 0); - rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0); - rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); - rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); -@@ -2902,6 +2935,7 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "log_file", rb_gc_log_file, -1); - rb_define_singleton_method(rb_mGC, "enable_trace", rb_gc_enable_trace, 0); - rb_define_singleton_method(rb_mGC, "disable_trace", rb_gc_disable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "trace_enabled?", rb_gc_trace_enabled, 0); - - rb_mObSpace = rb_define_module("ObjectSpace"); - rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1); diff --git a/patches/ruby/1.8.7/head/railsexpress/15-track-live-dataset-size.patch b/patches/ruby/1.8.7/head/railsexpress/15-track-live-dataset-size.patch deleted file mode 100644 index de44e6b365..0000000000 --- a/patches/ruby/1.8.7/head/railsexpress/15-track-live-dataset-size.patch +++ /dev/null @@ -1,52 +0,0 @@ -diff --git a/gc.c b/gc.c -index 2c34932..0ce7e68 100644 ---- a/gc.c -+++ b/gc.c -@@ -89,6 +89,7 @@ static unsigned long gc_num_allocations = 0; - #endif - static int gc_statistics = 0; - -+static unsigned long heap_slots_live_after_last_gc = 0; - - static void run_final(); - static VALUE nomem_error; -@@ -465,6 +466,23 @@ rb_gc_time() - #endif - } - -+/* -+ * call-seq: -+ * GC.heap_slots_live_after_last_gc => Integer -+ * -+ * Returns the number of heap slots which were live after the last garbage collection. -+ * -+ * GC.heap_slots_live_after_last_gc #=> 231223 -+ * -+ */ -+VALUE -+rb_gc_heap_slots_live_after_last_gc() -+{ -+ return ULONG2NUM(heap_slots_live_after_last_gc); -+} -+ -+ -+ - VALUE rb_mGC; - - /* -@@ -1903,6 +1921,7 @@ gc_sweep() - } - during_gc = 0; - live_objects = live; -+ heap_slots_live_after_last_gc = live; - - if (do_gc_stats) { - fprintf(gc_data_file, "objects processed: %.7d\n", live+freed); -@@ -2924,6 +2943,7 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); - rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); - rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots_live_after_last_gc", rb_gc_heap_slots_live_after_last_gc, 0); - rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); - rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); - rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); diff --git a/patches/ruby/1.8.7/head/railsexpress/16-add-object-size-information-to-heap-dump.patch b/patches/ruby/1.8.7/head/railsexpress/16-add-object-size-information-to-heap-dump.patch deleted file mode 100644 index e974cdb63a..0000000000 --- a/patches/ruby/1.8.7/head/railsexpress/16-add-object-size-information-to-heap-dump.patch +++ /dev/null @@ -1,51 +0,0 @@ -diff --git a/gc.c b/gc.c -index 0ce7e68..53450bf 100644 ---- a/gc.c -+++ b/gc.c -@@ -953,9 +953,21 @@ rb_gc_dump_file_and_line_info(int argc, VALUE *argv) - if (!p->as.basic.klass) { - fprintf(f, "__unknown__"); - } else { -- fprintf(f, rb_obj_classname((VALUE)p)); -+ fprintf(f, "%s", rb_obj_classname((VALUE)p)); - } - } -+ /* print object size for some known object types */ -+ switch (TYPE(p)) { -+ case T_STRING: -+ fprintf(f, ":%lu", RSTRING(p)->len); -+ break; -+ case T_ARRAY: -+ fprintf(f, ":%lu", RARRAY(p)->len); -+ break; -+ case T_HASH: -+ fprintf(f, ":%d", RHASH(p)->tbl->num_entries); -+ break; -+ } - } - fprintf(f, "\n"); - } -@@ -1924,10 +1936,10 @@ gc_sweep() - heap_slots_live_after_last_gc = live; - - if (do_gc_stats) { -- fprintf(gc_data_file, "objects processed: %.7d\n", live+freed); -- fprintf(gc_data_file, "live objects : %.7d\n", live); -- fprintf(gc_data_file, "freelist objects : %.7d\n", freed - really_freed); -- fprintf(gc_data_file, "freed objects : %.7d\n", really_freed); -+ fprintf(gc_data_file, "objects processed: %.7lu\n", live+freed); -+ fprintf(gc_data_file, "live objects : %.7lu\n", live); -+ fprintf(gc_data_file, "freelist objects : %.7lu\n", freed - really_freed); -+ fprintf(gc_data_file, "freed objects : %.7lu\n", really_freed); - for(i=0; i<256; i++) { - if (free_counts[i]>0 || live_counts[i]>0) { - fprintf(gc_data_file, -@@ -2258,7 +2270,7 @@ garbage_collect() - gc_time += musecs_used; - - if (verbose_gc_stats) { -- fprintf(gc_data_file, "GC time: %d msec\n", musecs_used / 1000); -+ fprintf(gc_data_file, "GC time: %ld msec\n", (long)(musecs_used / 1000)); - fflush(gc_data_file); - } - } diff --git a/patches/ruby/1.8.7/head/railsexpress/17-caller-for-all-threads.patch b/patches/ruby/1.8.7/head/railsexpress/17-caller-for-all-threads.patch deleted file mode 100644 index aa79d1602c..0000000000 --- a/patches/ruby/1.8.7/head/railsexpress/17-caller-for-all-threads.patch +++ /dev/null @@ -1,230 +0,0 @@ -diff --git a/eval.c b/eval.c -index 356226e..a0fdc55 100644 ---- a/eval.c -+++ b/eval.c -@@ -8199,6 +8199,17 @@ rb_f_method_name() - } - } - -+/* Hash (Thread => Backtrace) used to collect backtrace for each threads. */ -+static VALUE backtrace_for_each_thread; -+ -+static int backtrace_level_for_each_thread; -+ -+static VALUE -+switch_thread_context_to_collect_backtrace(rb_thread_t next); -+ -+static VALUE -+rb_f_caller_for_all_threads(); -+ - void - Init_eval() - { -@@ -8244,6 +8255,7 @@ Init_eval() - rb_define_global_function("fail", rb_f_raise, -1); - - rb_define_global_function("caller", rb_f_caller, -1); -+ rb_define_global_function("caller_for_all_threads", rb_f_caller_for_all_threads, -1); - - rb_define_global_function("exit", rb_f_exit, -1); - rb_define_global_function("abort", rb_f_abort, -1); -@@ -10599,6 +10611,7 @@ static int th_sig, th_safe; - #define RESTORE_RAISE 5 - #define RESTORE_SIGNAL 6 - #define RESTORE_EXIT 7 -+#define RESTORE_BACKTRACE 8 - - extern VALUE *rb_gc_stack_start; - #ifdef __ia64 -@@ -10705,6 +10718,15 @@ rb_thread_switch(n) - } - rb_exc_raise(th_raise_exception); - break; -+ case RESTORE_BACKTRACE: -+ rb_hash_aset(backtrace_for_each_thread, curr_thread->thread, -+ backtrace(backtrace_level_for_each_thread)); -+ if (curr_thread != main_thread) { -+ switch_thread_context_to_collect_backtrace(curr_thread->next); -+ } else { -+ /* Circled back to main thread, cycle is complete. */ -+ } -+ break; - case RESTORE_NORMAL: - default: - break; -@@ -13875,3 +13897,74 @@ rb_throw(tag, val) - argv[1] = val; - rb_f_throw(2, argv); - } -+ -+static VALUE -+switch_thread_context_to_collect_backtrace(rb_thread_t next) -+{ -+ if (THREAD_SAVE_CONTEXT(curr_thread)) { -+ return Qnil; -+ } -+ curr_thread = next; -+ rb_thread_restore_context(next, RESTORE_BACKTRACE); -+ return Qnil; -+} -+ -+ -+/* -+ * call-seq: -+ * caller_for_all_threads(start=1) => array -+ * -+ * Returns the current execution stack for all threads -+ * ---a hash whose keys are thread instances and values -+ * the thread caller backtrace. -+ * -+ * Backtraces are array of hashes indicating location on the -+ * stack. Hash keys include ``:line'' or ``:file'' -+ * and ``:method'''. -+ * -+ * The optional _start_ parameter -+ * determines the number of initial stack entries to omit from the -+ * result. -+ * -+ * def a(skip) -+ * caller_for_all_threads(skip) -+ * end -+ * def b(skip) -+ * a(skip) -+ * end -+ * def c(skip) -+ * b(skip) -+ * end -+ * c(0) #=> ["prog:2:in `a'", "prog:5:in `b'", "prog:8:in `c'", "prog:10"] -+ * c(1) #=> ["prog:5:in `b'", "prog:8:in `c'", "prog:11"] -+ * c(2) #=> ["prog:8:in `c'", "prog:12"] -+ * c(3) #=> ["prog:13"] -+ */ -+static VALUE -+rb_f_caller_for_all_threads(argc, argv) -+ int argc; -+ VALUE *argv; -+{ -+ volatile int critical; -+ VALUE level; -+ VALUE result; -+ -+ rb_scan_args(argc, argv, "01", &level); -+ backtrace_level_for_each_thread = NIL_P(level) ? 0 : NUM2INT(level); -+ if (backtrace_level_for_each_thread < 0) { -+ rb_raise(rb_eArgError, "negative level (%d)", backtrace_level_for_each_thread); -+ } -+ -+ critical = rb_thread_critical; -+ rb_thread_critical = Qtrue; -+ -+ backtrace_for_each_thread = rb_hash_new(); -+ switch_thread_context_to_collect_backtrace(main_thread->next); -+ -+ result = backtrace_for_each_thread; -+ backtrace_for_each_thread = Qnil; -+ backtrace_for_each_thread = 0; -+ -+ rb_thread_critical = critical; -+ return result; -+} -diff --git a/test/callerforallthreads/test_caller_for_each_thread.rb b/test/callerforallthreads/test_caller_for_each_thread.rb -new file mode 100644 -index 0000000..6aebaed ---- /dev/null -+++ b/test/callerforallthreads/test_caller_for_each_thread.rb -@@ -0,0 +1,95 @@ -+# -*- ruby-indent-level: 4 -*- -+require 'thread' -+require 'test/unit' -+ -+class AClassWithNestedmethods -+ -+ def an_ultra_nested_method(skip) -+ caller_for_all_threads skip -+ end -+ -+ def a_nested_method(skip) -+ an_ultra_nested_method skip -+ end -+ -+ def a_method(skip=0) -+ a_nested_method skip -+ end -+ -+end -+ -+class CallerForEachThreadTest < Test::Unit::TestCase -+ -+ def testCollectMeaningfulBacktraceForASingleThread -+ backtraces = AClassWithNestedmethods.new.a_method -+ backtrace = backtraces[Thread.current] -+ assert_not_nil backtrace -+ assert_equal __FILE__ + ":8:in `an_ultra_nested_method'", backtrace[0] -+ assert_equal __FILE__ + ":12:in `a_nested_method'", backtrace[1] -+ assert_equal __FILE__ + ":16:in `a_method'", backtrace[2] -+ assert_equal __FILE__ + ":24:in `testCollectMeaningfulBacktraceForASingleThread'", -+ backtrace[3] -+ end -+ -+ def testCanSkipFirstStackEntries -+ backtraces = AClassWithNestedmethods.new.a_method 2 -+ backtrace = backtraces[Thread.current] -+ assert_not_nil backtrace -+ assert_equal __FILE__ + ":16:in `a_method'", backtrace[0] -+ assert_equal __FILE__ + ":35:in `testCanSkipFirstStackEntries'", -+ backtrace[1] -+ end -+ -+ def testCollectMeaningfulBacktraceForMultipleThreads -+ first_thread = Thread.new do -+ loop do -+ Thread.pass -+ sleep 1 -+ end -+ end -+ -+ second_thread = Thread.new do -+ loop do -+ Thread.pass -+ sleep 1 -+ end -+ end -+ -+ backtraces = AClassWithNestedmethods.new.a_method -+ -+ backtrace = backtraces[Thread.current] -+ assert_not_nil backtrace -+ assert_match __FILE__ + ":8:in `an_ultra_nested_method'", backtrace[0] -+ assert_match __FILE__ + ":12:in `a_nested_method'", backtrace[1] -+ assert_equal __FILE__ + ":16:in `a_method'", backtrace[2] -+ assert_equal __FILE__ + ":58:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[3] -+ -+ backtrace = backtraces[first_thread] -+ assert_not_nil backtrace -+ assert_equal __FILE__ + ":47:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[0] -+ assert_equal __FILE__ + ":45:in `loop'", -+ backtrace[1] -+ assert_equal __FILE__ + ":45:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[2] -+ assert_equal __FILE__ + ":44:in `initialize'",backtrace[3] -+ assert_equal __FILE__ + ":44:in `new'", backtrace[4] -+ assert_equal __FILE__ + ":44:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[5] -+ -+ backtrace = backtraces[second_thread] -+ assert_not_nil backtrace -+ assert_equal __FILE__ + ":53:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[0] -+ assert_equal __FILE__ + ":52:in `loop'", backtrace[1] -+ assert_equal __FILE__ + ":52:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[2] -+ assert_equal __FILE__ + ":51:in `initialize'",backtrace[3] -+ assert_equal __FILE__ + ":51:in `new'", backtrace[4] -+ assert_equal __FILE__ + ":51:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[5] -+ end -+ -+end -+ diff --git a/patches/ruby/1.8.7/p334/railsexpress/01-ignore-generated-files.patch b/patches/ruby/1.8.7/p334/railsexpress/01-ignore-generated-files.patch deleted file mode 100644 index b669ad44bd..0000000000 --- a/patches/ruby/1.8.7/p334/railsexpress/01-ignore-generated-files.patch +++ /dev/null @@ -1,101 +0,0 @@ -diff --git a/.gitignore b/.gitignore -new file mode 100644 -index 0000000..00c347a ---- /dev/null -+++ b/.gitignore -@@ -0,0 +1,95 @@ -+.ext -+.installed.list -+.rbconfig.time -+Makefile -+autom4te.cache/ -+config.h -+config.status -+configure -+ext/Win32API/Makefile -+ext/bigdecimal/Makefile -+ext/curses/Makefile -+ext/dbm/Makefile -+ext/digest/Makefile -+ext/digest/bubblebabble/Makefile -+ext/digest/md5/Makefile -+ext/digest/rmd160/Makefile -+ext/digest/sha1/Makefile -+ext/digest/sha2/Makefile -+ext/dl/Makefile -+ext/dl/call.func -+ext/dl/callback.func -+ext/dl/cbtable.func -+ext/dl/dlconfig.h -+ext/dl/dlconfig.rb -+ext/enumerator/Makefile -+ext/etc/Makefile -+ext/fcntl/Makefile -+ext/gdbm/Makefile -+ext/iconv/Makefile -+ext/io/wait/Makefile -+ext/nkf/Makefile -+ext/openssl/Makefile -+ext/openssl/extconf.h -+ext/pty/Makefile -+ext/racc/cparse/Makefile -+ext/readline/Makefile -+ext/sdbm/Makefile -+ext/socket/Makefile -+ext/stringio/Makefile -+ext/strscan/Makefile -+ext/syck/Makefile -+ext/syslog/Makefile -+ext/thread/Makefile -+ext/tk/Makefile -+ext/tk/tkutil/Makefile -+ext/win32ole/Makefile -+ext/win32ole/.document -+ext/zlib/Makefile -+largefile.h -+miniruby -+parse.c -+rbconfig.rb -+ruby -+enc.mk -+ext/bigdecimal/extconf.h -+ext/continuation/ -+ext/coverage/ -+ext/curses/extconf.h -+ext/dbm/extconf.h -+ext/digest/bubblebabble/extconf.h -+ext/digest/extconf.h -+ext/digest/md5/extconf.h -+ext/digest/rmd160/extconf.h -+ext/digest/sha1/extconf.h -+ext/digest/sha2/extconf.h -+ext/dl/callback.h -+ext/dl/extconf.h -+ext/etc/extconf.h -+ext/fcntl/extconf.h -+ext/fiber/ -+ext/iconv/extconf.h -+ext/io/wait/extconf.h -+ext/json/ -+ext/nkf/extconf.h -+ext/pty/extconf.h -+ext/racc/cparse/extconf.h -+ext/readline/extconf.h -+ext/ripper/ -+ext/sdbm/extconf.h -+ext/socket/constants.h -+ext/socket/extconf.h -+ext/stringio/extconf.h -+ext/strscan/extconf.h -+ext/syck/extconf.h -+ext/syslog/extconf.h -+ext/tk/extconf.h -+ext/tk/tkutil/extconf.h -+ext/zlib/extconf.h -+miniprelude.c -+prelude.c -+revision.h -+*.dylib -+*.log -+*.dSYM -+patches-ruby* diff --git a/patches/ruby/1.8.7/p334/railsexpress/02-fix-rcs-keyword-idiom.patch b/patches/ruby/1.8.7/p334/railsexpress/02-fix-rcs-keyword-idiom.patch deleted file mode 100644 index 09a5ea0634..0000000000 --- a/patches/ruby/1.8.7/p334/railsexpress/02-fix-rcs-keyword-idiom.patch +++ /dev/null @@ -1,19 +0,0 @@ -diff --git a/lib/logger.rb b/lib/logger.rb -index 15d95fc..69f0d7b 100644 ---- a/lib/logger.rb -+++ b/lib/logger.rb -@@ -171,7 +171,13 @@ require 'monitor' - class Logger - VERSION = "1.2.6" - id, name, rev = %w$Id$ -- ProgName = "#{name.chomp(",v")}/#{rev}" -+ if name -+ name = name.chomp(",v") -+ else -+ name = File.basename(__FILE__) -+ end -+ rev ||= "v#{VERSION}" -+ ProgName = "#{name}/#{rev}" - - class Error < RuntimeError; end - class ShiftingError < Error; end diff --git a/patches/ruby/1.8.7/p334/railsexpress/03-sigvtalrm-fix.patch b/patches/ruby/1.8.7/p334/railsexpress/03-sigvtalrm-fix.patch deleted file mode 100644 index b118b02051..0000000000 --- a/patches/ruby/1.8.7/p334/railsexpress/03-sigvtalrm-fix.patch +++ /dev/null @@ -1,27 +0,0 @@ -diff --git a/eval.c b/eval.c -index 284e486..00bcd36 100644 ---- a/eval.c -+++ b/eval.c -@@ -12461,6 +12461,11 @@ rb_thread_start_0(fn, arg, th) - curr_thread->next = th; - th->priority = curr_thread->priority; - th->thgroup = curr_thread->thgroup; -+#if defined(HAVE_SETITIMER) || defined(_THREAD_SAFE) -+ if (!thread_init) { -+ rb_thread_start_timer(); -+ } -+#endif - } - START_TIMER(); - -@@ -13188,7 +13193,9 @@ rb_thread_atfork() - main_thread = curr_thread; - curr_thread->next = curr_thread; - curr_thread->prev = curr_thread; -- STOP_TIMER(); -+#if defined(HAVE_SETITIMER) || defined(_THREAD_SAFE) -+ rb_thread_stop_timer(); -+#endif - } - - diff --git a/patches/ruby/1.8.7/p334/railsexpress/04-railsbench-gc-patch.patch b/patches/ruby/1.8.7/p334/railsexpress/04-railsbench-gc-patch.patch deleted file mode 100644 index 7b6c0e251a..0000000000 --- a/patches/ruby/1.8.7/p334/railsexpress/04-railsbench-gc-patch.patch +++ /dev/null @@ -1,1876 +0,0 @@ -diff --git a/gc.c b/gc.c -index fa45cd1..ab71d22 100644 ---- a/gc.c -+++ b/gc.c -@@ -22,8 +22,16 @@ - #include - #include - -+#ifdef _WIN32 -+#include -+#else -+#include -+#endif -+ - #ifdef HAVE_SYS_TIME_H - #include -+#elif defined(_WIN32) -+#include - #endif - - #ifdef HAVE_SYS_RESOURCE_H -@@ -42,7 +50,6 @@ void rb_io_fptr_finalize _((struct rb_io_t*)); - #ifdef __CYGWIN__ - int _setjmp(), _longjmp(); - #endif -- - /* Make alloca work the best possible way. */ - #ifdef __GNUC__ - # ifndef atarist -@@ -86,12 +93,12 @@ rb_memerror() - rb_thread_t th = rb_curr_thread; - - if (!nomem_error || -- (rb_thread_raised_p(th, RAISED_NOMEMORY) && rb_safe_level() < 4)) { -- fprintf(stderr, "[FATAL] failed to allocate memory\n"); -- exit(1); -+ (rb_thread_raised_p(th, RAISED_NOMEMORY) && rb_safe_level() < 4)) { -+ fprintf(stderr, "[FATAL] failed to allocate memory\n"); -+ exit(1); - } - if (rb_thread_raised_p(th, RAISED_NOMEMORY)) { -- rb_exc_jump(nomem_error); -+ rb_exc_jump(nomem_error); - } - rb_thread_raised_set(th, RAISED_NOMEMORY); - rb_exc_raise(nomem_error); -@@ -139,7 +146,7 @@ ruby_xmalloc(size) - void *mem; - - if (size < 0) { -- rb_raise(rb_eNoMemError, "negative allocation size (or too big)"); -+ rb_raise(rb_eNoMemError, "negative allocation size (or too big)"); - } - if (size == 0) size = 1; - -@@ -148,11 +155,11 @@ ruby_xmalloc(size) - } - RUBY_CRITICAL(mem = malloc(size)); - if (!mem) { -- garbage_collect(); -- RUBY_CRITICAL(mem = malloc(size)); -- if (!mem) { -- rb_memerror(); -- } -+ garbage_collect(); -+ RUBY_CRITICAL(mem = malloc(size)); -+ if (!mem) { -+ rb_memerror(); -+ } - } - malloc_increase += size; - -@@ -179,17 +186,17 @@ ruby_xrealloc(ptr, size) - void *mem; - - if (size < 0) { -- rb_raise(rb_eArgError, "negative re-allocation size"); -+ rb_raise(rb_eArgError, "negative re-allocation size"); - } - if (!ptr) return xmalloc(size); - if (size == 0) size = 1; - if (ruby_gc_stress) garbage_collect(); - RUBY_CRITICAL(mem = realloc(ptr, size)); - if (!mem) { -- garbage_collect(); -- RUBY_CRITICAL(mem = realloc(ptr, size)); -- if (!mem) { -- rb_memerror(); -+ garbage_collect(); -+ RUBY_CRITICAL(mem = realloc(ptr, size)); -+ if (!mem) { -+ rb_memerror(); - } - } - malloc_increase += size; -@@ -202,11 +209,20 @@ ruby_xfree(x) - void *x; - { - if (x) -- RUBY_CRITICAL(free(x)); -+ RUBY_CRITICAL(free(x)); - } - -+#if HAVE_LONG_LONG -+#define GC_TIME_TYPE LONG_LONG -+#else -+#define GC_TIME_TYPE long -+#endif -+ - extern int ruby_in_compile; - static int dont_gc; -+static int gc_statistics = 0; -+static GC_TIME_TYPE gc_time = 0; -+static int gc_collections = 0; - static int during_gc; - static int need_call_final = 0; - static st_table *finalizer_table = 0; -@@ -241,7 +257,7 @@ rb_gc_enable() - * Disables garbage collection, returning true if garbage - * collection was already disabled. - * -- * GC.disable #=> false -+ * GC.disable #=> false or true - * GC.disable #=> true - * - */ -@@ -255,6 +271,104 @@ rb_gc_disable() - return old; - } - -+/* -+ * call-seq: -+ * GC.enable_stats => true or false -+ * -+ * Enables garbage collection statistics, returning true if garbage -+ * collection statistics was already enabled. -+ * -+ * GC.enable_stats #=> false or true -+ * GC.enable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_stats() -+{ -+ int old = gc_statistics; -+ gc_statistics = Qtrue; -+ return old; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_stats => true or false -+ * -+ * Disables garbage collection statistics, returning true if garbage -+ * collection statistics was already disabled. -+ * -+ * GC.disable_stats #=> false or true -+ * GC.disable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_stats() -+{ -+ int old = gc_statistics; -+ gc_statistics = Qfalse; -+ return old; -+} -+ -+/* -+ * call-seq: -+ * GC.clear_stats => nil -+ * -+ * Clears garbage collection statistics, returning nil. This resets the number -+ * of collections (GC.collections) and the time used (GC.time) to 0. -+ * -+ * GC.clear_stats #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_clear_stats() -+{ -+ gc_collections = 0; -+ gc_time = 0; -+ return Qnil; -+} -+ -+/* -+ * call-seq: -+ * GC.collections => Integer -+ * -+ * Returns the number of garbage collections performed while GC statistics collection -+ * was enabled. -+ * -+ * GC.collections #=> 35 -+ * -+ */ -+ -+VALUE -+rb_gc_collections() -+{ -+ return INT2NUM(gc_collections); -+} -+ -+/* -+ * call-seq: -+ * GC.time => Integer -+ * -+ * Returns the time spent during garbage collection while GC statistics collection -+ * was enabled (in micro seconds). -+ * -+ * GC.time #=> 20000 -+ * -+ */ -+ -+VALUE -+rb_gc_time() -+{ -+#if HAVE_LONG_LONG -+ return LL2NUM(gc_time); -+#else -+ return LONG2NUM(gc_time); -+#endif -+} -+ -+ - VALUE rb_mGC; - - static struct gc_list { -@@ -281,19 +395,19 @@ rb_gc_unregister_address(addr) - struct gc_list *tmp = global_List; - - if (tmp->varptr == addr) { -- global_List = tmp->next; -- RUBY_CRITICAL(free(tmp)); -- return; -+ global_List = tmp->next; -+ RUBY_CRITICAL(free(tmp)); -+ return; - } - while (tmp->next) { -- if (tmp->next->varptr == addr) { -- struct gc_list *t = tmp->next; -+ if (tmp->next->varptr == addr) { -+ struct gc_list *t = tmp->next; - -- tmp->next = tmp->next->next; -- RUBY_CRITICAL(free(t)); -- break; -- } -- tmp = tmp->next; -+ tmp->next = tmp->next->next; -+ RUBY_CRITICAL(free(t)); -+ break; -+ } -+ tmp = tmp->next; - } - } - -@@ -312,26 +426,26 @@ rb_global_variable(var) - - typedef struct RVALUE { - union { -- struct { -- unsigned long flags; /* always 0 for freed obj */ -- 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; -- struct RStruct rstruct; -- struct RBignum bignum; -- struct RFile file; -- struct RNode node; -- struct RMatch match; -- struct RVarmap varmap; -- struct SCOPE scope; -+ struct { -+ unsigned long flags; /* always 0 for freed obj */ -+ 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; -+ struct RStruct rstruct; -+ struct RBignum bignum; -+ struct RFile file; -+ struct RNode node; -+ struct RMatch match; -+ struct RVarmap varmap; -+ struct SCOPE scope; - } as; - #ifdef GC_DEBUG - char *file; -@@ -346,7 +460,7 @@ typedef struct RVALUE { - static RVALUE *freelist = 0; - static RVALUE *deferred_final_list = 0; - --#define HEAPS_INCREMENT 10 -+static int heaps_increment = 10; - static struct heaps_slot { - void *membase; - RVALUE *slot; -@@ -355,45 +469,197 @@ static struct heaps_slot { - static int heaps_length = 0; - static int heaps_used = 0; - --#define HEAP_MIN_SLOTS 10000 --static int heap_slots = HEAP_MIN_SLOTS; -+static int heap_min_slots = 10000; -+static int heap_slots = 10000; - --#define FREE_MIN 4096 -+static int heap_free_min = 4096; -+static int heap_slots_increment = 10000; -+static double heap_slots_growth_factor = 1.8; -+ -+static long initial_malloc_limit = GC_MALLOC_LIMIT; -+ -+static int verbose_gc_stats = Qfalse; -+ -+static FILE* gc_data_file = NULL; - - static RVALUE *himem, *lomem; - -+static void set_gc_parameters() -+{ -+ char *gc_stats_ptr, *min_slots_ptr, *free_min_ptr, *heap_slots_incr_ptr, -+ *heap_incr_ptr, *malloc_limit_ptr, *gc_heap_file_ptr, *heap_slots_growth_factor_ptr; -+ -+ gc_data_file = stderr; -+ -+ gc_stats_ptr = getenv("RUBY_GC_STATS"); -+ if (gc_stats_ptr != NULL) { -+ int gc_stats_i = atoi(gc_stats_ptr); -+ if (gc_stats_i > 0) { -+ verbose_gc_stats = Qtrue; -+ } -+ } -+ -+ gc_heap_file_ptr = getenv("RUBY_GC_DATA_FILE"); -+ if (gc_heap_file_ptr != NULL) { -+ FILE* data_file = fopen(gc_heap_file_ptr, "w"); -+ if (data_file != NULL) { -+ gc_data_file = data_file; -+ } -+ else { -+ fprintf(stderr, -+ "can't open gc log file %s for writing, using default\n", gc_heap_file_ptr); -+ } -+ } -+ -+ min_slots_ptr = getenv("RUBY_HEAP_MIN_SLOTS"); -+ if (min_slots_ptr != NULL) { -+ int min_slots_i = atoi(min_slots_ptr); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_MIN_SLOTS=%s\n", min_slots_ptr); -+ } -+ if (min_slots_i > 0) { -+ heap_slots = min_slots_i; -+ heap_min_slots = min_slots_i; -+ } -+ } -+ -+ free_min_ptr = getenv("RUBY_HEAP_FREE_MIN"); -+ if (free_min_ptr != NULL) { -+ int free_min_i = atoi(free_min_ptr); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_FREE_MIN=%s\n", free_min_ptr); -+ } -+ if (free_min_i > 0) { -+ heap_free_min = free_min_i; -+ } -+ } -+ -+ heap_incr_ptr = getenv("RUBY_HEAP_INCREMENT"); -+ if (heap_incr_ptr != NULL) { -+ int heap_incr_i = atoi(heap_incr_ptr); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_INCREMENT=%s\n", heap_incr_ptr); -+ } -+ if (heap_incr_i > 0) { -+ heaps_increment = heap_incr_i; -+ } -+ } -+ -+ heap_slots_incr_ptr = getenv("RUBY_HEAP_SLOTS_INCREMENT"); -+ if (heap_slots_incr_ptr != NULL) { -+ int heap_slots_incr_i = atoi(heap_slots_incr_ptr); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_INCREMENT=%s\n", heap_slots_incr_ptr); -+ } -+ if (heap_slots_incr_i > 0) { -+ heap_slots_increment = heap_slots_incr_i; -+ } -+ } -+ -+ heap_slots_growth_factor_ptr = getenv("RUBY_HEAP_SLOTS_GROWTH_FACTOR"); -+ if (heap_slots_growth_factor_ptr != NULL) { -+ double heap_slots_growth_factor_d = atoi(heap_slots_growth_factor_ptr); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_GROWTH_FACTOR=%s\n", heap_slots_growth_factor_ptr); -+ } -+ if (heap_slots_growth_factor_d > 0) { -+ heap_slots_growth_factor = heap_slots_growth_factor_d; -+ } -+ } -+ -+ malloc_limit_ptr = getenv("RUBY_GC_MALLOC_LIMIT"); -+ if (malloc_limit_ptr != NULL) { -+ int malloc_limit_i = atol(malloc_limit_ptr); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_GC_MALLOC_LIMIT=%s\n", malloc_limit_ptr); -+ } -+ if (malloc_limit_i > 0) { -+ initial_malloc_limit = malloc_limit_i; -+ } -+ } -+} -+ -+/* -+ * call-seq: -+ * GC.dump => nil -+ * -+ * dumps information about the current GC data structures to the GC log file -+ * -+ * GC.dump #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_dump() -+{ -+ int i; -+ -+ for (i = 0; i < heaps_used; i++) { -+ int heap_size = heaps[i].limit; -+ fprintf(gc_data_file, "HEAP[%2d]: size=%7d\n", i, heap_size); -+ } -+ -+ return Qnil; -+} -+ -+/* -+ * call-seq: -+ * GC.log String => String -+ * -+ * Logs string to the GC data file and returns it. -+ * -+ * GC.log "manual GC call" #=> "manual GC call" -+ * -+ */ -+ -+VALUE -+rb_gc_log(self, original_str) -+ VALUE self, original_str; -+{ -+ if (original_str == Qnil) { -+ fprintf(gc_data_file, "\n"); -+ } -+ else { -+ VALUE str = StringValue(original_str); -+ char *p = RSTRING(str)->ptr; -+ fprintf(gc_data_file, "%s\n", p); -+ } -+ return original_str; -+} -+ -+ - static void - add_heap() - { - RVALUE *p, *pend; - - if (heaps_used == heaps_length) { -- /* Realloc heaps */ -- struct heaps_slot *p; -- int length; -- -- heaps_length += HEAPS_INCREMENT; -- length = heaps_length*sizeof(struct heaps_slot); -- RUBY_CRITICAL( -- if (heaps_used > 0) { -- p = (struct heaps_slot *)realloc(heaps, length); -- if (p) heaps = p; -- } -- else { -- p = heaps = (struct heaps_slot *)malloc(length); -- }); -- if (p == 0) rb_memerror(); -+ /* Realloc heaps */ -+ struct heaps_slot *p; -+ int length; -+ -+ heaps_length += heaps_increment; -+ length = heaps_length*sizeof(struct heaps_slot); -+ RUBY_CRITICAL( -+ if (heaps_used > 0) { -+ p = (struct heaps_slot *)realloc(heaps, length); -+ if (p) heaps = p; -+ } -+ else { -+ p = heaps = (struct heaps_slot *)malloc(length); -+ }); -+ if (p == 0) rb_memerror(); - } - - for (;;) { -- RUBY_CRITICAL(p = (RVALUE*)malloc(sizeof(RVALUE)*(heap_slots+1))); -- if (p == 0) { -- if (heap_slots == HEAP_MIN_SLOTS) { -- rb_memerror(); -- } -- heap_slots = HEAP_MIN_SLOTS; -- continue; -- } -+ RUBY_CRITICAL(p = (RVALUE*)malloc(sizeof(RVALUE)*(heap_slots+1))); -+ if (p == 0) { -+ if (heap_slots == heap_min_slots) { -+ rb_memerror(); -+ } -+ heap_slots = heap_min_slots; -+ continue; -+ } - heaps[heaps_used].membase = p; - if ((VALUE)p % sizeof(RVALUE) == 0) - heap_slots += 1; -@@ -401,25 +667,26 @@ add_heap() - p = (RVALUE*)((VALUE)p + sizeof(RVALUE) - ((VALUE)p % sizeof(RVALUE))); - heaps[heaps_used].slot = p; - heaps[heaps_used].limit = heap_slots; -- break; -+ break; - } - pend = p + heap_slots; - if (lomem == 0 || lomem > p) lomem = p; - if (himem < pend) himem = pend; - heaps_used++; -- heap_slots *= 1.8; -- if (heap_slots <= 0) heap_slots = HEAP_MIN_SLOTS; -+ heap_slots += heap_slots_increment; -+ heap_slots_increment *= heap_slots_growth_factor; -+ if (heap_slots <= 0) heap_slots = heap_min_slots; - - while (p < pend) { -- p->as.free.flags = 0; -- p->as.free.next = freelist; -- freelist = p; -- p++; -+ p->as.free.flags = 0; -+ p->as.free.next = freelist; -+ freelist = p; -+ p++; - } - } - #define RANY(o) ((RVALUE*)(o)) - --int -+int - rb_during_gc() - { - return during_gc; -@@ -431,7 +698,7 @@ rb_newobj() - VALUE obj; - - if (during_gc) -- rb_bug("object allocation during garbage collection phase"); -+ rb_bug("object allocation during garbage collection phase"); - - if (ruby_gc_stress || !freelist) garbage_collect(); - -@@ -580,13 +847,13 @@ rb_source_filename(f) - st_data_t name; - - if (!st_lookup(source_filenames, (st_data_t)f, &name)) { -- long len = strlen(f) + 1; -- char *ptr = ALLOC_N(char, len + 1); -- name = (st_data_t)ptr; -- *ptr++ = 0; -- MEMCPY(ptr, f, char, len); -- st_add_direct(source_filenames, (st_data_t)ptr, name); -- return ptr; -+ long len = strlen(f) + 1; -+ char *ptr = ALLOC_N(char, len + 1); -+ name = (st_data_t)ptr; -+ *ptr++ = 0; -+ MEMCPY(ptr, f, char, len); -+ st_add_direct(source_filenames, (st_data_t)ptr, name); -+ return ptr; - } - return (char *)name + 1; - } -@@ -596,7 +863,7 @@ mark_source_filename(f) - char *f; - { - if (f) { -- f[-1] = 1; -+ f[-1] = 1; - } - } - -@@ -605,12 +872,12 @@ sweep_source_filename(key, value) - char *key, *value; - { - if (*value) { -- *value = 0; -- return ST_CONTINUE; -+ *value = 0; -+ return ST_CONTINUE; - } - else { -- free(value); -- return ST_DELETE; -+ free(value); -+ return ST_DELETE; - } - } - -@@ -625,14 +892,14 @@ gc_mark_all() - - init_mark_stack(); - for (i = 0; i < heaps_used; i++) { -- p = heaps[i].slot; pend = p + heaps[i].limit; -- while (p < pend) { -- if ((p->as.basic.flags & FL_MARK) && -- (p->as.basic.flags != FL_MARK)) { -- gc_mark_children((VALUE)p, 0); -- } -- p++; -- } -+ p = heaps[i].slot; pend = p + heaps[i].limit; -+ while (p < pend) { -+ if ((p->as.basic.flags & FL_MARK) && -+ (p->as.basic.flags != FL_MARK)) { -+ gc_mark_children((VALUE)p, 0); -+ } -+ p++; -+ } - } - } - -@@ -647,8 +914,8 @@ gc_mark_rest() - - init_mark_stack(); - while(p != tmp_arry){ -- p--; -- gc_mark_children(*p, 0); -+ p--; -+ gc_mark_children(*p, 0); - } - } - -@@ -665,9 +932,9 @@ is_pointer_to_heap(ptr) - - /* check if p looks like a pointer */ - for (i=0; i < heaps_used; i++) { -- heap_org = heaps[i].slot; -- if (heap_org <= p && p < heap_org + heaps[i].limit) -- return Qtrue; -+ heap_org = heaps[i].slot; -+ if (heap_org <= p && p < heap_org + heaps[i].limit) -+ return Qtrue; - } - return Qfalse; - } -@@ -680,10 +947,10 @@ mark_locations_array(x, n) - VALUE v; - while (n--) { - v = *x; -- if (is_pointer_to_heap((void *)v)) { -- gc_mark(v, 0); -- } -- x++; -+ if (is_pointer_to_heap((void *)v)) { -+ gc_mark(v, 0); -+ } -+ x++; - } - } - -@@ -780,7 +1047,7 @@ rb_gc_mark_maybe(obj) - VALUE obj; - { - if (is_pointer_to_heap((void *)obj)) { -- gc_mark(obj, 0); -+ gc_mark(obj, 0); - } - } - -@@ -828,7 +1095,7 @@ gc_mark_children(ptr, lev) - { - register RVALUE *obj = RANY(ptr); - -- goto marking; /* skip */ -+ goto marking; /* skip */ - - again: - obj = RANY(ptr); -@@ -839,148 +1106,148 @@ gc_mark_children(ptr, lev) - - marking: - if (FL_TEST(obj, FL_EXIVAR)) { -- rb_mark_generic_ivar(ptr); -+ rb_mark_generic_ivar(ptr); - } - - switch (obj->as.basic.flags & T_MASK) { - case T_NIL: - case T_FIXNUM: -- rb_bug("rb_gc_mark() called for broken object"); -- break; -+ rb_bug("rb_gc_mark() called for broken object"); -+ break; - - case T_NODE: -- mark_source_filename(obj->as.node.nd_file); -- switch (nd_type(obj)) { -- case NODE_IF: /* 1,2,3 */ -- case NODE_FOR: -- case NODE_ITER: -- case NODE_CREF: -- case NODE_WHEN: -- case NODE_MASGN: -- case NODE_RESCUE: -- case NODE_RESBODY: -- case NODE_CLASS: -- gc_mark((VALUE)obj->as.node.u2.node, lev); -- /* 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_FBODY: -- case NODE_ENSURE: -- case NODE_CALL: -- case NODE_DEFS: -- case NODE_OP_ASGN1: -- gc_mark((VALUE)obj->as.node.u1.node, lev); -- /* fall through */ -- case NODE_SUPER: /* 3 */ -- case NODE_FCALL: -- case NODE_DEFN: -- case NODE_NEWLINE: -- ptr = (VALUE)obj->as.node.u3.node; -- goto again; -- -- 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_ARGS: -- gc_mark((VALUE)obj->as.node.u1.node, lev); -- /* fall through */ -- case NODE_METHOD: /* 2 */ -- case NODE_NOT: -- case NODE_GASGN: -- case NODE_LASGN: -- case NODE_DASGN: -- case NODE_DASGN_CURR: -- case NODE_IASGN: -- case NODE_CVDECL: -- case NODE_CVASGN: -- case NODE_COLON3: -- case NODE_OPT_N: -- case NODE_EVSTR: -- case NODE_UNDEF: -- ptr = (VALUE)obj->as.node.u2.node; -- goto again; -- -- 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: -- case NODE_SVALUE: -- ptr = (VALUE)obj->as.node.u1.node; -- goto again; -- -- case NODE_SCOPE: /* 2,3 */ -- case NODE_BLOCK_PASS: -- case NODE_CDECL: -- gc_mark((VALUE)obj->as.node.u3.node, lev); -- ptr = (VALUE)obj->as.node.u2.node; -- goto again; -- -- case NODE_ZARRAY: /* - */ -- case NODE_ZSUPER: -- case NODE_CFUNC: -- 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_ATTRSET: -- case NODE_BLOCK_ARG: -- case NODE_POSTEXE: -- break; -- case NODE_ALLOCA: -- mark_locations_array((VALUE*)obj->as.node.u1.value, -- obj->as.node.u3.cnt); -- ptr = (VALUE)obj->as.node.u2.node; -- goto again; -- -- default: /* unlisted NODE */ -- if (is_pointer_to_heap(obj->as.node.u1.node)) { -- gc_mark((VALUE)obj->as.node.u1.node, lev); -- } -- if (is_pointer_to_heap(obj->as.node.u2.node)) { -- gc_mark((VALUE)obj->as.node.u2.node, lev); -- } -- if (is_pointer_to_heap(obj->as.node.u3.node)) { -- gc_mark((VALUE)obj->as.node.u3.node, lev); -- } -- } -- return; /* no need to mark class. */ -+ mark_source_filename(obj->as.node.nd_file); -+ switch (nd_type(obj)) { -+ case NODE_IF: /* 1,2,3 */ -+ case NODE_FOR: -+ case NODE_ITER: -+ case NODE_CREF: -+ case NODE_WHEN: -+ case NODE_MASGN: -+ case NODE_RESCUE: -+ case NODE_RESBODY: -+ case NODE_CLASS: -+ gc_mark((VALUE)obj->as.node.u2.node, lev); -+ /* 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_FBODY: -+ case NODE_ENSURE: -+ case NODE_CALL: -+ case NODE_DEFS: -+ case NODE_OP_ASGN1: -+ gc_mark((VALUE)obj->as.node.u1.node, lev); -+ /* fall through */ -+ case NODE_SUPER: /* 3 */ -+ case NODE_FCALL: -+ case NODE_DEFN: -+ case NODE_NEWLINE: -+ ptr = (VALUE)obj->as.node.u3.node; -+ goto again; -+ -+ 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_ARGS: -+ gc_mark((VALUE)obj->as.node.u1.node, lev); -+ /* fall through */ -+ case NODE_METHOD: /* 2 */ -+ case NODE_NOT: -+ case NODE_GASGN: -+ case NODE_LASGN: -+ case NODE_DASGN: -+ case NODE_DASGN_CURR: -+ case NODE_IASGN: -+ case NODE_CVDECL: -+ case NODE_CVASGN: -+ case NODE_COLON3: -+ case NODE_OPT_N: -+ case NODE_EVSTR: -+ case NODE_UNDEF: -+ ptr = (VALUE)obj->as.node.u2.node; -+ goto again; -+ -+ 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: -+ case NODE_SVALUE: -+ ptr = (VALUE)obj->as.node.u1.node; -+ goto again; -+ -+ case NODE_SCOPE: /* 2,3 */ -+ case NODE_BLOCK_PASS: -+ case NODE_CDECL: -+ gc_mark((VALUE)obj->as.node.u3.node, lev); -+ ptr = (VALUE)obj->as.node.u2.node; -+ goto again; -+ -+ case NODE_ZARRAY: /* - */ -+ case NODE_ZSUPER: -+ case NODE_CFUNC: -+ 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_ATTRSET: -+ case NODE_BLOCK_ARG: -+ case NODE_POSTEXE: -+ break; -+ case NODE_ALLOCA: -+ mark_locations_array((VALUE*)obj->as.node.u1.value, -+ obj->as.node.u3.cnt); -+ ptr = (VALUE)obj->as.node.u2.node; -+ goto again; -+ -+ default: /* unlisted NODE */ -+ if (is_pointer_to_heap(obj->as.node.u1.node)) { -+ gc_mark((VALUE)obj->as.node.u1.node, lev); -+ } -+ if (is_pointer_to_heap(obj->as.node.u2.node)) { -+ gc_mark((VALUE)obj->as.node.u2.node, lev); -+ } -+ if (is_pointer_to_heap(obj->as.node.u3.node)) { -+ gc_mark((VALUE)obj->as.node.u3.node, lev); -+ } -+ } -+ return; /* no need to mark class. */ - } - - gc_mark(obj->as.basic.klass, lev); -@@ -988,92 +1255,92 @@ gc_mark_children(ptr, lev) - case T_ICLASS: - case T_CLASS: - case T_MODULE: -- mark_tbl(obj->as.klass.m_tbl, lev); -- mark_tbl(obj->as.klass.iv_tbl, lev); -- ptr = obj->as.klass.super; -- goto again; -+ mark_tbl(obj->as.klass.m_tbl, lev); -+ mark_tbl(obj->as.klass.iv_tbl, lev); -+ ptr = obj->as.klass.super; -+ goto again; - - case T_ARRAY: -- if (FL_TEST(obj, ELTS_SHARED)) { -- ptr = obj->as.array.aux.shared; -- goto again; -- } -- else { -- long i, len = obj->as.array.len; -- VALUE *ptr = obj->as.array.ptr; -+ if (FL_TEST(obj, ELTS_SHARED)) { -+ ptr = obj->as.array.aux.shared; -+ goto again; -+ } -+ else { -+ long i, len = obj->as.array.len; -+ VALUE *ptr = obj->as.array.ptr; - -- for (i=0; i < len; i++) { -- gc_mark(*ptr++, lev); -- } -- } -- break; -+ for (i=0; i < len; i++) { -+ gc_mark(*ptr++, lev); -+ } -+ } -+ break; - - case T_HASH: -- mark_hash(obj->as.hash.tbl, lev); -- ptr = obj->as.hash.ifnone; -- goto again; -+ mark_hash(obj->as.hash.tbl, lev); -+ ptr = obj->as.hash.ifnone; -+ goto again; - - case T_STRING: - #define STR_ASSOC FL_USER3 /* copied from string.c */ -- if (FL_TEST(obj, ELTS_SHARED|STR_ASSOC)) { -- ptr = obj->as.string.aux.shared; -- goto again; -- } -- break; -+ if (FL_TEST(obj, ELTS_SHARED|STR_ASSOC)) { -+ ptr = obj->as.string.aux.shared; -+ goto again; -+ } -+ break; - - case T_DATA: -- if (obj->as.data.dmark) (*obj->as.data.dmark)(DATA_PTR(obj)); -- break; -+ if (obj->as.data.dmark) (*obj->as.data.dmark)(DATA_PTR(obj)); -+ break; - - case T_OBJECT: -- mark_tbl(obj->as.object.iv_tbl, lev); -- break; -+ mark_tbl(obj->as.object.iv_tbl, lev); -+ break; - - case T_FILE: - case T_REGEXP: - case T_FLOAT: - case T_BIGNUM: - case T_BLKTAG: -- break; -+ break; - - case T_MATCH: -- if (obj->as.match.str) { -- ptr = obj->as.match.str; -- goto again; -- } -- break; -+ if (obj->as.match.str) { -+ ptr = obj->as.match.str; -+ goto again; -+ } -+ break; - - case T_VARMAP: -- gc_mark(obj->as.varmap.val, lev); -- ptr = (VALUE)obj->as.varmap.next; -- goto again; -+ gc_mark(obj->as.varmap.val, lev); -+ ptr = (VALUE)obj->as.varmap.next; -+ goto again; - - case T_SCOPE: -- if (obj->as.scope.local_vars && (obj->as.scope.flags & SCOPE_MALLOC)) { -- int n = obj->as.scope.local_tbl[0]+1; -- VALUE *vars = &obj->as.scope.local_vars[-1]; -+ if (obj->as.scope.local_vars && (obj->as.scope.flags & SCOPE_MALLOC)) { -+ int n = obj->as.scope.local_tbl[0]+1; -+ VALUE *vars = &obj->as.scope.local_vars[-1]; - -- while (n--) { -- gc_mark(*vars++, lev); -- } -- } -- break; -+ while (n--) { -+ gc_mark(*vars++, lev); -+ } -+ } -+ break; - - case T_STRUCT: -- { -- long len = obj->as.rstruct.len; -- VALUE *ptr = obj->as.rstruct.ptr; -+ { -+ long len = obj->as.rstruct.len; -+ VALUE *ptr = obj->as.rstruct.ptr; - -- while (len--) { -- gc_mark(*ptr++, lev); -- } -- } -- break; -+ while (len--) { -+ gc_mark(*ptr++, lev); -+ } -+ } -+ break; - - default: -- rb_bug("rb_gc_mark(): unknown data type 0x%lx(0x%lx) %s", -- obj->as.basic.flags & T_MASK, obj, -- is_pointer_to_heap(obj) ? "corrupted object" : "non object"); -+ rb_bug("rb_gc_mark(): unknown data type 0x%lx(0x%lx) %s", -+ obj->as.basic.flags & T_MASK, obj, -+ is_pointer_to_heap(obj) ? "corrupted object" : "non object"); - } - } - -@@ -1102,22 +1369,55 @@ finalize_list(p) - } - } - -+static char* obj_type(int tp) -+{ -+ switch (tp) { -+ case T_NIL : return "NIL"; -+ case T_OBJECT : return "OBJECT"; -+ case T_CLASS : return "CLASS"; -+ case T_ICLASS : return "ICLASS"; -+ case T_MODULE : return "MODULE"; -+ case T_FLOAT : return "FLOAT"; -+ case T_STRING : return "STRING"; -+ case T_REGEXP : return "REGEXP"; -+ case T_ARRAY : return "ARRAY"; -+ case T_FIXNUM : return "FIXNUM"; -+ case T_HASH : return "HASH"; -+ case T_STRUCT : return "STRUCT"; -+ case T_BIGNUM : return "BIGNUM"; -+ case T_FILE : return "FILE"; -+ -+ case T_TRUE : return "TRUE"; -+ case T_FALSE : return "FALSE"; -+ case T_DATA : return "DATA"; -+ case T_MATCH : return "MATCH"; -+ case T_SYMBOL : return "SYMBOL"; -+ -+ case T_BLKTAG : return "BLKTAG"; -+ case T_UNDEF : return "UNDEF"; -+ case T_VARMAP : return "VARMAP"; -+ case T_SCOPE : return "SCOPE"; -+ case T_NODE : return "NODE"; -+ default: return "____"; -+ } -+} -+ - static void - free_unused_heaps() - { - int i, j; - - for (i = j = 1; j < heaps_used; i++) { -- if (heaps[i].limit == 0) { -- free(heaps[i].membase); -- heaps_used--; -- } -- else { -- if (i != j) { -- heaps[j] = heaps[i]; -- } -- j++; -- } -+ if (heaps[i].limit == 0) { -+ free(heaps[i].membase); -+ heaps_used--; -+ } -+ else { -+ if (i != j) { -+ heaps[j] = heaps[i]; -+ } -+ j++; -+ } - } - } - -@@ -1134,24 +1434,33 @@ gc_sweep() - unsigned long live = 0; - unsigned long free_min = 0; - -+ unsigned long really_freed = 0; -+ int free_counts[256]; -+ int live_counts[256]; -+ int do_gc_stats = gc_statistics & verbose_gc_stats; -+ - for (i = 0; i < heaps_used; i++) { - free_min += heaps[i].limit; - } - free_min = free_min * 0.2; -- if (free_min < FREE_MIN) -- free_min = FREE_MIN; -+ if (free_min < heap_free_min) -+ free_min = heap_free_min; -+ -+ if (do_gc_stats) { -+ for (i = 0 ; i< 256; i++) { free_counts[i] = live_counts[i] = 0; } -+ } - - if (ruby_in_compile && ruby_parser_stack_on_heap()) { -- /* should not reclaim nodes during compilation -+ /* should not reclaim nodes during compilation - if yacc's semantic stack is not allocated on machine stack */ -- for (i = 0; i < heaps_used; i++) { -- p = heaps[i].slot; pend = p + heaps[i].limit; -- while (p < pend) { -- if (!(p->as.basic.flags&FL_MARK) && BUILTIN_TYPE(p) == T_NODE) -- gc_mark((VALUE)p, 0); -- p++; -- } -- } -+ for (i = 0; i < heaps_used; i++) { -+ p = heaps[i].slot; pend = p + heaps[i].limit; -+ while (p < pend) { -+ if (!(p->as.basic.flags&FL_MARK) && BUILTIN_TYPE(p) == T_NODE) -+ gc_mark((VALUE)p, 0); -+ p++; -+ } -+ } - } - - mark_source_filename(ruby_sourcefile); -@@ -1172,7 +1481,7 @@ gc_sweep() - while (p < pend) { - if (!(p->as.basic.flags & FL_MARK)) { - if (p->as.basic.flags && -- ((deferred = obj_free((VALUE)p)) || -+ (((do_gc_stats && really_freed++), deferred = obj_free((VALUE)p)) || - ((FL_TEST(p, FL_FINALIZE)) && need_call_final))) { - if (!deferred) { - p->as.free.flags = T_DEFERRED; -@@ -1183,6 +1492,12 @@ gc_sweep() - final_list = p; - } - else { -+ if (do_gc_stats) { -+ int obt = p->as.basic.flags & T_MASK; -+ if (obt) { -+ free_counts[obt]++; -+ } -+ } - add_freelist(p); - } - n++; -@@ -1194,6 +1509,9 @@ gc_sweep() - else { - RBASIC(p)->flags &= ~FL_MARK; - live++; -+ if (do_gc_stats) { -+ live_counts[RANY((VALUE)p)->as.basic.flags & T_MASK]++; -+ } - } - p++; - } -@@ -1211,15 +1529,29 @@ gc_sweep() - } - } - if (malloc_increase > malloc_limit) { -- malloc_limit += (malloc_increase - malloc_limit) * (double)live / (live + freed); -- if (malloc_limit < GC_MALLOC_LIMIT) malloc_limit = GC_MALLOC_LIMIT; -+ malloc_limit += (malloc_increase - malloc_limit) * (double)live / (live + freed); -+ if (malloc_limit < initial_malloc_limit) malloc_limit = initial_malloc_limit; - } - malloc_increase = 0; - if (freed < free_min) { -- add_heap(); -+ add_heap(); - } - during_gc = 0; - -+ if (do_gc_stats) { -+ fprintf(gc_data_file, "objects processed: %.7d\n", live+freed); -+ fprintf(gc_data_file, "live objects : %.7d\n", live); -+ fprintf(gc_data_file, "freelist objects : %.7d\n", freed - really_freed); -+ fprintf(gc_data_file, "freed objects : %.7d\n", really_freed); -+ for(i=0; i<256; i++) { -+ if (free_counts[i]>0 || live_counts[i]>0) { -+ fprintf(gc_data_file, -+ "kept %.7d / freed %.7d objects of type %s\n", -+ live_counts[i], free_counts[i], obj_type(i)); -+ } -+ } -+ } -+ - /* clear finalization list */ - if (final_list) { - deferred_final_list = final_list; -@@ -1260,51 +1592,51 @@ obj_free(obj) - case T_FIXNUM: - case T_TRUE: - case T_FALSE: -- rb_bug("obj_free() called for broken object"); -- break; -+ rb_bug("obj_free() called for broken object"); -+ break; - } - - if (FL_TEST(obj, FL_EXIVAR)) { -- rb_free_generic_ivar((VALUE)obj); -+ rb_free_generic_ivar((VALUE)obj); - } - - switch (BUILTIN_TYPE(obj)) { - case T_OBJECT: -- if (RANY(obj)->as.object.iv_tbl) { -- st_free_table(RANY(obj)->as.object.iv_tbl); -- } -- break; -+ if (RANY(obj)->as.object.iv_tbl) { -+ st_free_table(RANY(obj)->as.object.iv_tbl); -+ } -+ break; - case T_MODULE: - case T_CLASS: -- rb_clear_cache_by_class((VALUE)obj); -- st_free_table(RANY(obj)->as.klass.m_tbl); -- if (RANY(obj)->as.object.iv_tbl) { -- st_free_table(RANY(obj)->as.object.iv_tbl); -- } -- break; -+ rb_clear_cache_by_class((VALUE)obj); -+ st_free_table(RANY(obj)->as.klass.m_tbl); -+ if (RANY(obj)->as.object.iv_tbl) { -+ st_free_table(RANY(obj)->as.object.iv_tbl); -+ } -+ break; - case T_STRING: -- if (RANY(obj)->as.string.ptr && !FL_TEST(obj, ELTS_SHARED)) { -- RUBY_CRITICAL(free(RANY(obj)->as.string.ptr)); -- } -- break; -+ if (RANY(obj)->as.string.ptr && !FL_TEST(obj, ELTS_SHARED)) { -+ RUBY_CRITICAL(free(RANY(obj)->as.string.ptr)); -+ } -+ break; - case T_ARRAY: -- if (RANY(obj)->as.array.ptr && !FL_TEST(obj, ELTS_SHARED)) { -- RUBY_CRITICAL(free(RANY(obj)->as.array.ptr)); -- } -- break; -+ if (RANY(obj)->as.array.ptr && !FL_TEST(obj, ELTS_SHARED)) { -+ RUBY_CRITICAL(free(RANY(obj)->as.array.ptr)); -+ } -+ break; - case T_HASH: -- if (RANY(obj)->as.hash.tbl) { -- st_free_table(RANY(obj)->as.hash.tbl); -- } -- break; -+ if (RANY(obj)->as.hash.tbl) { -+ st_free_table(RANY(obj)->as.hash.tbl); -+ } -+ break; - case T_REGEXP: -- if (RANY(obj)->as.regexp.ptr) { -- re_free_pattern(RANY(obj)->as.regexp.ptr); -- } -- if (RANY(obj)->as.regexp.str) { -- RUBY_CRITICAL(free(RANY(obj)->as.regexp.str)); -- } -- break; -+ if (RANY(obj)->as.regexp.ptr) { -+ re_free_pattern(RANY(obj)->as.regexp.ptr); -+ } -+ if (RANY(obj)->as.regexp.str) { -+ RUBY_CRITICAL(free(RANY(obj)->as.regexp.str)); -+ } -+ break; - case T_DATA: - if (DATA_PTR(obj)) { - if ((long)RANY(obj)->as.data.dfree == -1) { -@@ -1317,11 +1649,11 @@ obj_free(obj) - } - break; - case T_MATCH: -- if (RANY(obj)->as.match.regs) { -- re_free_registers(RANY(obj)->as.match.regs); -- RUBY_CRITICAL(free(RANY(obj)->as.match.regs)); -- } -- break; -+ if (RANY(obj)->as.match.regs) { -+ re_free_registers(RANY(obj)->as.match.regs); -+ RUBY_CRITICAL(free(RANY(obj)->as.match.regs)); -+ } -+ break; - case T_FILE: - if (RANY(obj)->as.file.fptr) { - struct rb_io_t *fptr = RANY(obj)->as.file.fptr; -@@ -1332,19 +1664,19 @@ obj_free(obj) - } - break; - case T_ICLASS: -- /* iClass shares table with the module */ -- break; -+ /* iClass shares table with the module */ -+ break; - - case T_FLOAT: - case T_VARMAP: - case T_BLKTAG: -- break; -+ break; - - case T_BIGNUM: -- if (RANY(obj)->as.bignum.digits) { -- RUBY_CRITICAL(free(RANY(obj)->as.bignum.digits)); -- } -- break; -+ if (RANY(obj)->as.bignum.digits) { -+ RUBY_CRITICAL(free(RANY(obj)->as.bignum.digits)); -+ } -+ break; - case T_NODE: - switch (nd_type(obj)) { - case NODE_SCOPE: -@@ -1359,7 +1691,7 @@ obj_free(obj) - break; /* no need to free iv_tbl */ - - case T_SCOPE: -- if (RANY(obj)->as.scope.local_vars && -+ if (RANY(obj)->as.scope.local_vars && - RANY(obj)->as.scope.flags != SCOPE_ALLOCA) { - VALUE *vars = RANY(obj)->as.scope.local_vars-1; - if (!(RANY(obj)->as.scope.flags & SCOPE_CLONE) && vars[0] == 0) -@@ -1370,14 +1702,14 @@ obj_free(obj) - break; - - case T_STRUCT: -- if (RANY(obj)->as.rstruct.ptr) { -- RUBY_CRITICAL(free(RANY(obj)->as.rstruct.ptr)); -- } -- break; -+ if (RANY(obj)->as.rstruct.ptr) { -+ RUBY_CRITICAL(free(RANY(obj)->as.rstruct.ptr)); -+ } -+ break; - - default: -- rb_bug("gc_sweep(): unknown data type 0x%lx(0x%lx)", -- RANY(obj)->as.basic.flags & T_MASK, obj); -+ rb_bug("gc_sweep(): unknown data type 0x%lx(0x%lx)", -+ RANY(obj)->as.basic.flags & T_MASK, obj); - } - - return 0; -@@ -1407,18 +1739,18 @@ _rb_setjmp:\n\ - typedef unsigned long rb_jmp_buf[6]; - __asm__ (".align 4\n\ - _rb_setjmp:\n\ -- pushl %ebp\n\ -- movl %esp,%ebp\n\ -- movl 8(%ebp),%ebp\n\ -- movl %eax,(%ebp)\n\ -- movl %ebx,4(%ebp)\n\ -- movl %ecx,8(%ebp)\n\ -- movl %edx,12(%ebp)\n\ -- movl %esi,16(%ebp)\n\ -- movl %edi,20(%ebp)\n\ -- popl %ebp\n\ -- xorl %eax,%eax\n\ -- ret"); -+ pushl %ebp\n\ -+ movl %esp,%ebp\n\ -+ movl 8(%ebp),%ebp\n\ -+ movl %eax,(%ebp)\n\ -+ movl %ebx,4(%ebp)\n\ -+ movl %ecx,8(%ebp)\n\ -+ movl %edx,12(%ebp)\n\ -+ movl %esi,16(%ebp)\n\ -+ movl %edi,20(%ebp)\n\ -+ popl %ebp\n\ -+ xorl %eax,%eax\n\ -+ ret"); - #endif - #endif - int rb_setjmp (rb_jmp_buf); -@@ -1431,41 +1763,50 @@ garbage_collect() - struct gc_list *list; - struct FRAME * volatile frame; /* gcc 2.7.2.3 -O2 bug?? */ - jmp_buf save_regs_gc_mark; -+ struct timeval gctv1, gctv2; - SET_STACK_END; - - #ifdef HAVE_NATIVETHREAD - if (!is_ruby_native_thread()) { -- rb_bug("cross-thread violation on rb_gc()"); -+ rb_bug("cross-thread violation on rb_gc()"); - } - #endif - if (dont_gc || during_gc) { -- if (!freelist) { -- add_heap(); -- } -- return; -+ if (!freelist) { -+ add_heap(); -+ } -+ return; - } - if (during_gc) return; - during_gc++; - -+ if (gc_statistics) { -+ gc_collections++; -+ gettimeofday(&gctv1, NULL); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "Garbage collection started\n"); -+ } -+ } -+ - init_mark_stack(); - - gc_mark((VALUE)ruby_current_node, 0); - - /* mark frame stack */ - for (frame = ruby_frame; frame; frame = frame->prev) { -- rb_gc_mark_frame(frame); -- if (frame->tmp) { -- struct FRAME *tmp = frame->tmp; -- while (tmp) { -- rb_gc_mark_frame(tmp); -- tmp = tmp->prev; -- } -- } -+ rb_gc_mark_frame(frame); -+ if (frame->tmp) { -+ struct FRAME *tmp = frame->tmp; -+ while (tmp) { -+ rb_gc_mark_frame(tmp); -+ tmp = tmp->prev; -+ } -+ } - } - gc_mark((VALUE)ruby_scope, 0); - gc_mark((VALUE)ruby_dyna_vars, 0); - if (finalizer_table) { -- mark_tbl(finalizer_table, 0); -+ mark_tbl(finalizer_table, 0); - } - - FLUSH_REGISTER_WINDOWS; -@@ -1478,9 +1819,9 @@ garbage_collect() - rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)STACK_END + 1); - #else - if ((VALUE*)STACK_END < rb_gc_stack_start) -- rb_gc_mark_locations((VALUE*)STACK_END, rb_gc_stack_start); -+ rb_gc_mark_locations((VALUE*)STACK_END, rb_gc_stack_start); - else -- rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)STACK_END + 1); -+ rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)STACK_END + 1); - #endif - #ifdef __ia64 - /* mark backing store (flushed register window on the stack) */ -@@ -1489,13 +1830,13 @@ garbage_collect() - #endif - #if defined(__human68k__) || defined(__mc68000__) - rb_gc_mark_locations((VALUE*)((char*)STACK_END + 2), -- (VALUE*)((char*)rb_gc_stack_start + 2)); -+ (VALUE*)((char*)rb_gc_stack_start + 2)); - #endif - rb_gc_mark_threads(); - - /* mark protected global variables */ - for (list = global_List; list; list = list->next) { -- rb_gc_mark_maybe(*list->varptr); -+ rb_gc_mark_maybe(*list->varptr); - } - rb_mark_end_proc(); - rb_gc_mark_global_tbl(); -@@ -1510,18 +1851,30 @@ garbage_collect() - - /* gc_mark objects whose marking are not completed*/ - do { -- while (!MARK_STACK_EMPTY) { -- if (mark_stack_overflow){ -- gc_mark_all(); -- } -- else { -- gc_mark_rest(); -- } -- } -- rb_gc_abort_threads(); -+ while (!MARK_STACK_EMPTY) { -+ if (mark_stack_overflow){ -+ gc_mark_all(); -+ } -+ else { -+ gc_mark_rest(); -+ } -+ } -+ rb_gc_abort_threads(); - } while (!MARK_STACK_EMPTY); - - gc_sweep(); -+ -+ if (gc_statistics) { -+ GC_TIME_TYPE musecs_used; -+ gettimeofday(&gctv2, NULL); -+ musecs_used = ((GC_TIME_TYPE)(gctv2.tv_sec - gctv1.tv_sec) * 1000000) + (gctv2.tv_usec - gctv1.tv_usec); -+ gc_time += musecs_used; -+ -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "GC time: %d msec\n", musecs_used / 1000); -+ fflush(gc_data_file); -+ } -+ } - } - - void -@@ -1588,8 +1941,8 @@ Init_stack(addr) - memset(&m, 0, sizeof(m)); - VirtualQuery(&m, &m, sizeof(m)); - rb_gc_stack_start = -- STACK_UPPER((VALUE *)&m, (VALUE *)m.BaseAddress, -- (VALUE *)((char *)m.BaseAddress + m.RegionSize) - 1); -+ STACK_UPPER((VALUE *)&m, (VALUE *)m.BaseAddress, -+ (VALUE *)((char *)m.BaseAddress + m.RegionSize) - 1); - #elif defined(STACK_END_ADDRESS) - { - extern void *STACK_END_ADDRESS; -@@ -1599,24 +1952,24 @@ Init_stack(addr) - if (!addr) addr = (void *)&addr; - STACK_UPPER(&addr, addr, ++addr); - if (rb_gc_stack_start) { -- if (STACK_UPPER(&addr, -- rb_gc_stack_start > addr, -- rb_gc_stack_start < addr)) -- rb_gc_stack_start = addr; -- return; -+ if (STACK_UPPER(&addr, -+ rb_gc_stack_start > addr, -+ rb_gc_stack_start < addr)) -+ rb_gc_stack_start = addr; -+ return; - } - rb_gc_stack_start = addr; - #endif - #ifdef HAVE_GETRLIMIT - { -- struct rlimit rlim; -+ struct rlimit rlim; - -- if (getrlimit(RLIMIT_STACK, &rlim) == 0) { -- unsigned int space = rlim.rlim_cur/5; -+ if (getrlimit(RLIMIT_STACK, &rlim) == 0) { -+ unsigned int space = rlim.rlim_cur/5; - -- if (space > 1024*1024) space = 1024*1024; -- STACK_LEVEL_MAX = (rlim.rlim_cur - space) / sizeof(VALUE); -- } -+ if (space > 1024*1024) space = 1024*1024; -+ STACK_LEVEL_MAX = (rlim.rlim_cur - space) / sizeof(VALUE); -+ } - } - #endif - } -@@ -1652,16 +2005,16 @@ void ruby_init_stack(VALUE *addr - } - #elif defined _WIN32 - { -- MEMORY_BASIC_INFORMATION mi; -- DWORD size; -- DWORD space; -- -- if (VirtualQuery(&mi, &mi, sizeof(mi))) { -- size = (char *)mi.BaseAddress - (char *)mi.AllocationBase; -- space = size / 5; -- if (space > 1024*1024) space = 1024*1024; -- STACK_LEVEL_MAX = (size - space) / sizeof(VALUE); -- } -+ MEMORY_BASIC_INFORMATION mi; -+ DWORD size; -+ DWORD space; -+ -+ if (VirtualQuery(&mi, &mi, sizeof(mi))) { -+ size = (char *)mi.BaseAddress - (char *)mi.AllocationBase; -+ space = size / 5; -+ if (space > 1024*1024) space = 1024*1024; -+ STACK_LEVEL_MAX = (size - space) / sizeof(VALUE); -+ } - } - #endif - } -@@ -1701,8 +2054,9 @@ void - Init_heap() - { - if (!rb_gc_stack_start) { -- Init_stack(0); -+ Init_stack(0); - } -+ set_gc_parameters(); - add_heap(); - } - -@@ -1715,7 +2069,7 @@ os_obj_of(of) - volatile VALUE v; - - for (i = 0; i < heaps_used; i++) { -- RVALUE *p, *pend; -+ RVALUE *p, *pend; - - p = heaps[i].slot; pend = p + heaps[i].limit; - for (;p < pend; p++) { -@@ -1808,8 +2162,8 @@ add_final(os, block) - { - rb_warn("ObjectSpace::add_finalizer is deprecated; use define_finalizer"); - if (!rb_respond_to(block, rb_intern("call"))) { -- rb_raise(rb_eArgError, "wrong type argument %s (should be callable)", -- rb_obj_classname(block)); -+ rb_raise(rb_eArgError, "wrong type argument %s (should be callable)", -+ rb_obj_classname(block)); - } - rb_ary_push(finalizers, block); - return block; -@@ -1864,7 +2218,7 @@ undefine_final(os, obj) - VALUE os, obj; - { - if (finalizer_table) { -- st_delete(finalizer_table, (st_data_t*)&obj, 0); -+ st_delete(finalizer_table, (st_data_t*)&obj, 0); - } - return obj; - } -@@ -1888,11 +2242,11 @@ define_final(argc, argv, os) - - rb_scan_args(argc, argv, "11", &obj, &block); - if (argc == 1) { -- block = rb_block_proc(); -+ block = rb_block_proc(); - } - else if (!rb_respond_to(block, rb_intern("call"))) { -- rb_raise(rb_eArgError, "wrong type argument %s (should be callable)", -- rb_obj_classname(block)); -+ rb_raise(rb_eArgError, "wrong type argument %s (should be callable)", -+ rb_obj_classname(block)); - } - need_call_final = 1; - if (!FL_ABLE(obj)) { -@@ -1905,10 +2259,10 @@ define_final(argc, argv, os) - OBJ_FREEZE(block); - - if (!finalizer_table) { -- finalizer_table = st_init_numtable(); -+ finalizer_table = st_init_numtable(); - } - if (st_lookup(finalizer_table, obj, &table)) { -- rb_ary_push(table, block); -+ rb_ary_push(table, block); - } - else { - table = rb_ary_new3(1, block); -@@ -1927,7 +2281,7 @@ rb_gc_copy_finalizer(dest, obj) - if (!finalizer_table) return; - if (!FL_TEST(obj, FL_FINALIZE)) return; - if (st_lookup(finalizer_table, obj, &table)) { -- st_insert(finalizer_table, dest, table); -+ st_insert(finalizer_table, dest, table); - } - RBASIC(dest)->flags |= FL_FINALIZE; - } -@@ -1957,18 +2311,18 @@ run_final(obj) - args[1] = 0; - args[2] = (VALUE)ruby_safe_level; - for (i=0; ilen; i++) { -- args[0] = RARRAY(finalizers)->ptr[i]; -- if (!args[1]) args[1] = rb_ary_new3(1, objid); -- rb_protect((VALUE(*)_((VALUE)))run_single_final, (VALUE)args, &status); -+ args[0] = RARRAY(finalizers)->ptr[i]; -+ if (!args[1]) args[1] = rb_ary_new3(1, objid); -+ rb_protect((VALUE(*)_((VALUE)))run_single_final, (VALUE)args, &status); - } - if (finalizer_table && st_delete(finalizer_table, (st_data_t*)&obj, &table)) { -- for (i=0; ilen; i++) { -- VALUE final = RARRAY(table)->ptr[i]; -- args[0] = RARRAY(final)->ptr[1]; -- if (!args[1]) args[1] = rb_ary_new3(1, objid); -- args[2] = FIX2INT(RARRAY(final)->ptr[0]); -- rb_protect((VALUE(*)_((VALUE)))run_single_final, (VALUE)args, &status); -- } -+ for (i=0; ilen; i++) { -+ VALUE final = RARRAY(table)->ptr[i]; -+ args[0] = RARRAY(final)->ptr[1]; -+ if (!args[1]) args[1] = rb_ary_new3(1, objid); -+ args[2] = FIX2INT(RARRAY(final)->ptr[0]); -+ rb_protect((VALUE(*)_((VALUE)))run_single_final, (VALUE)args, &status); -+ } - } - rb_thread_critical = critical_save; - } -@@ -1980,8 +2334,8 @@ rb_gc_finalize_deferred() - - deferred_final_list = 0; - if (p) { -- finalize_list(p); -- free_unused_heaps(); -+ finalize_list(p); -+ free_unused_heaps(); - } - } - -@@ -2061,7 +2415,7 @@ id2ref(obj, objid) - if (ptr == Qfalse) return Qfalse; - if (ptr == Qnil) return Qnil; - if (FIXNUM_P(ptr)) return (VALUE)ptr; -- ptr = objid ^ FIXNUM_FLAG; /* unset FIXNUM_FLAG */ -+ ptr = objid ^ FIXNUM_FLAG; /* unset FIXNUM_FLAG */ - - if ((ptr % sizeof(RVALUE)) == (4 << 2)) { - ID symid = ptr / sizeof(RVALUE); -@@ -2075,7 +2429,7 @@ id2ref(obj, objid) - rb_raise(rb_eRangeError, "0x%lx is not id value", p0); - } - if (BUILTIN_TYPE(ptr) == 0 || RBASIC(ptr)->klass == 0) { -- rb_raise(rb_eRangeError, "0x%lx is recycled object", p0); -+ rb_raise(rb_eRangeError, "0x%lx is recycled object", p0); - } - return (VALUE)ptr; - } -@@ -2166,6 +2520,14 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "stress=", gc_stress_set, 1); - rb_define_method(rb_mGC, "garbage_collect", rb_gc_start, 0); - -+ rb_define_singleton_method(rb_mGC, "enable_stats", rb_gc_enable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "disable_stats", rb_gc_disable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0); -+ rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); -+ rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); -+ rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); -+ rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); -+ - rb_mObSpace = rb_define_module("ObjectSpace"); - rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1); - rb_define_module_function(rb_mObSpace, "garbage_collect", rb_gc_start, 0); -@@ -2188,7 +2550,7 @@ Init_GC() - - rb_global_variable(&nomem_error); - nomem_error = rb_exc_new3(rb_eNoMemError, -- rb_obj_freeze(rb_str_new2("failed to allocate memory"))); -+ rb_obj_freeze(rb_str_new2("failed to allocate memory"))); - OBJ_TAINT(nomem_error); - OBJ_FREEZE(nomem_error); - diff --git a/patches/ruby/1.8.7/p334/railsexpress/05-display-full-stack-trace.patch b/patches/ruby/1.8.7/p334/railsexpress/05-display-full-stack-trace.patch deleted file mode 100644 index fbfcccf859..0000000000 --- a/patches/ruby/1.8.7/p334/railsexpress/05-display-full-stack-trace.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/eval.c b/eval.c -index 00bcd36..5ee11a0 100644 ---- a/eval.c -+++ b/eval.c -@@ -1325,8 +1325,8 @@ error_print() - int truncate = eclass == rb_eSysStackError; - - #define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5) --#define TRACE_HEAD 8 --#define TRACE_TAIL 5 -+#define TRACE_HEAD 100 -+#define TRACE_TAIL 100 - - ep = RARRAY(errat); - for (i=1; ilen; i++) { diff --git a/patches/ruby/1.8.7/p334/railsexpress/06-better-source-file-tracing.patch b/patches/ruby/1.8.7/p334/railsexpress/06-better-source-file-tracing.patch deleted file mode 100644 index b35d2e3bc7..0000000000 --- a/patches/ruby/1.8.7/p334/railsexpress/06-better-source-file-tracing.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/eval.c b/eval.c -index 5ee11a0..8a2f492 100644 ---- a/eval.c -+++ b/eval.c -@@ -1161,7 +1161,7 @@ static VALUE trace_func = 0; - static int tracing = 0; - static void call_trace_func _((rb_event_t,NODE*,VALUE,ID,VALUE)); - --#if 0 -+#if 1 - #define SET_CURRENT_SOURCE() (ruby_sourcefile = ruby_current_node->nd_file, \ - ruby_sourceline = nd_line(ruby_current_node)) - #else diff --git a/patches/ruby/1.8.7/p334/railsexpress/07-heap-dump-support.patch b/patches/ruby/1.8.7/p334/railsexpress/07-heap-dump-support.patch deleted file mode 100644 index e88b2d8f95..0000000000 --- a/patches/ruby/1.8.7/p334/railsexpress/07-heap-dump-support.patch +++ /dev/null @@ -1,159 +0,0 @@ -diff --git a/configure.in b/configure.in -index 7368808..ffe0649 100644 ---- a/configure.in -+++ b/configure.in -@@ -1609,6 +1609,14 @@ fi - LDFLAGS="-L. $LDFLAGS" - AC_SUBST(ARCHFILE) - -+dnl enable gc debugging -+AC_ARG_ENABLE(gcdebug, -+ [ --enable-gcdebug build garbage collector with debugging enabled. ], -+ [enable_gcdebug=$enableval]) -+if test "$enable_gcdebug" = 'yes'; then -+ AC_DEFINE(GC_DEBUG, 1) -+fi -+ - dnl build rdoc index if requested - RDOCTARGET="" - AC_ARG_ENABLE(install-doc, -diff --git a/gc.c b/gc.c -index ab71d22..9ad716f 100644 ---- a/gc.c -+++ b/gc.c -@@ -411,7 +411,6 @@ rb_gc_unregister_address(addr) - } - } - --#undef GC_DEBUG - - void - rb_global_variable(var) -@@ -602,6 +601,85 @@ rb_gc_dump() - return Qnil; - } - -+ -+static char* obj_type(int tp); -+ -+#ifdef GC_DEBUG -+/* -+ * call-seq: -+ * GC.dump_file_and_line_info(String, boolean) => nil -+ * -+ * dumps information on which currently allocated object was created by which file and on which line -+ * -+ * GC.dump_file_and_line_info(String, boolean) #=> nil -+ * -+ * The second parameter specifies whether class names should be included in the dump. -+ * Note that including class names will allocate additional string objects on the heap. -+ * -+ */ -+ -+VALUE -+rb_gc_dump_file_and_line_info(int argc, VALUE *argv) -+{ -+ VALUE filename, str, include_classnames = Qnil; -+ char *fname = NULL; -+ char *klass = NULL; -+ FILE* f = NULL; -+ int i,n = 0; -+ -+ rb_scan_args(argc, argv, "11", &filename, &include_classnames); -+ -+ str = StringValue(filename); -+ fname = RSTRING(str)->ptr; -+ f = fopen(fname, "w"); -+ -+ for (i = 0; i < heaps_used; i++) { -+ RVALUE *p, *pend; -+ -+ p = heaps[i].slot; pend = p + heaps[i].limit; -+ for (;p < pend; p++) { -+ if (p->as.basic.flags) { -+ fprintf(f, "%s:%s:%d", obj_type(p->as.basic.flags & T_MASK), p->file, p->line); -+ // rb_obj_classname will create objects on the heap, we need a better solution -+ if (include_classnames == Qtrue) { -+ /* write the class */ -+ fprintf(f, ":"); -+ switch (TYPE(p)) { -+ case T_NONE: -+ fprintf(f, "__none__"); -+ break; -+ case T_BLKTAG: -+ fprintf(f, "__blktag__"); -+ break; -+ case T_UNDEF: -+ fprintf(f, "__undef__"); -+ break; -+ case T_VARMAP: -+ fprintf(f, "__varmap__"); -+ break; -+ case T_SCOPE: -+ fprintf(f, "__scope__"); -+ break; -+ case T_NODE: -+ fprintf(f, "__node__"); -+ break; -+ default: -+ if (!p->as.basic.klass) { -+ fprintf(f, "__unknown__"); -+ } else { -+ fprintf(f, rb_obj_classname((VALUE)p)); -+ } -+ } -+ } -+ fprintf(f, "\n"); -+ } -+ } -+ } -+ fclose(f); -+ return Qnil; -+} -+#endif -+ - /* - * call-seq: - * GC.log String => String -@@ -1066,6 +1144,11 @@ gc_mark(ptr, lev) - if (obj->as.basic.flags & FL_MARK) return; /* already marked */ - obj->as.basic.flags |= FL_MARK; - -+#ifdef GC_DEBUG -+ /* mark our new reference point for sourcefile objects */ -+ mark_source_filename(RANY(obj)->file); -+#endif -+ - if (lev > GC_LEVEL_MAX || (lev == 0 && ruby_stack_check())) { - if (!mark_stack_overflow) { - if (mark_stack_ptr - mark_stack < MARK_STACK_MAX) { -@@ -1104,6 +1187,11 @@ gc_mark_children(ptr, lev) - if (obj->as.basic.flags & FL_MARK) return; /* already marked */ - obj->as.basic.flags |= FL_MARK; - -+#ifdef GC_DEBUG -+ /* mark our new reference point for sourcefile objects */ -+ mark_source_filename(RANY(obj)->file); -+#endif -+ - marking: - if (FL_TEST(obj, FL_EXIVAR)) { - rb_mark_generic_ivar(ptr); -@@ -1550,6 +1638,7 @@ gc_sweep() - live_counts[i], free_counts[i], obj_type(i)); - } - } -+ fflush(gc_data_file); - } - - /* clear finalization list */ -@@ -2526,6 +2615,9 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); - rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); - rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); -+#ifdef GC_DEBUG -+ rb_define_singleton_method(rb_mGC, "dump_file_and_line_info", rb_gc_dump_file_and_line_info, -1); -+#endif - rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); - - rb_mObSpace = rb_define_module("ObjectSpace"); diff --git a/patches/ruby/1.8.7/p334/railsexpress/08-fork-support-for-gc-logging.patch b/patches/ruby/1.8.7/p334/railsexpress/08-fork-support-for-gc-logging.patch deleted file mode 100644 index 894701b87e..0000000000 --- a/patches/ruby/1.8.7/p334/railsexpress/08-fork-support-for-gc-logging.patch +++ /dev/null @@ -1,249 +0,0 @@ -diff --git a/gc.c b/gc.c -index 9ad716f..a3cbe91 100644 ---- a/gc.c -+++ b/gc.c -@@ -223,6 +223,8 @@ static int dont_gc; - static int gc_statistics = 0; - static GC_TIME_TYPE gc_time = 0; - static int gc_collections = 0; -+static int verbose_gc_stats = Qfalse; -+static FILE* gc_data_file = NULL; - static int during_gc; - static int need_call_final = 0; - static st_table *finalizer_table = 0; -@@ -368,9 +370,148 @@ rb_gc_time() - #endif - } - -- - VALUE rb_mGC; - -+/* -+ * call-seq: -+ * GC.enable_trace => true or false -+ * -+ * Enables garbage collection tracing, returning true if garbage -+ * collection tracing was already enabled. -+ * -+ * GC.enable_trace #=> false or true -+ * GC.enable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_trace() -+{ -+ int old = verbose_gc_stats; -+ verbose_gc_stats = Qtrue; -+ return old; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_trace => true or false -+ * -+ * Disables garbage collection tracing, returning true if garbage -+ * collection tracing was already disabled. -+ * -+ * GC.disable_trace #=> false or true -+ * GC.disable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_trace() -+{ -+ int old = verbose_gc_stats; -+ verbose_gc_stats = Qfalse; -+ return old; -+} -+ -+char* GC_LOGFILE_IVAR = "@gc_logfile_name"; -+ -+/* -+ * call-seq: -+ * GC.log_file(filename=nil, mode="w") => boolean -+ * -+ * Changes the GC data log file. Closes the currently open logfile. -+ * Returns true if the file was successfully opened for -+ * writing. Returns false if the file could not be opened for -+ * writing. Returns the name of the current logfile (or nil) if no -+ * parameter is given. Restores logging to stderr when given nil as -+ * an argument. -+ * -+ * GC.log_file #=> nil -+ * GC.log_file "/tmp/gc.log" #=> true -+ * GC.log_file #=> "/tmp/gc.log" -+ * GC.log_file nil #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_log_file(int argc, VALUE *argv, VALUE self) -+{ -+ VALUE filename = Qnil; -+ VALUE mode_str = Qnil; -+ FILE* f = NULL; -+ char* mode = "w"; -+ -+ VALUE current_logfile_name = rb_iv_get(rb_mGC, GC_LOGFILE_IVAR); -+ -+ if (argc==0) -+ return current_logfile_name; -+ -+ rb_scan_args(argc, argv, "02", &filename, &mode_str); -+ -+ if (filename == Qnil) { -+ /* close current logfile and reset logfile to stderr */ -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+ } -+ return Qtrue; -+ } -+ -+ /* we have a real logfile name */ -+ filename = StringValue(filename); -+ -+ if (rb_equal(current_logfile_name, filename) == Qtrue) { -+ /* do nothing if we get the file name we're already logging to */ -+ return Qtrue; -+ } -+ -+ /* get mode for file opening */ -+ if (mode_str != Qnil) -+ { -+ mode = RSTRING(StringValue(mode_str))->ptr; -+ } -+ -+ /* try to open file in given mode */ -+ if (f = fopen(RSTRING(filename)->ptr, mode)) { -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ } -+ gc_data_file = f; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, filename); -+ } else { -+ return Qfalse; -+ } -+ return Qtrue; -+} -+ -+ -+/* -+ * Called from process.c before a fork. Flushes the gc log file to -+ * avoid writing the buffered output twice (once in the parent, and -+ * once in the child). -+ */ -+void -+rb_gc_before_fork() -+{ -+ /* flush gc log file */ -+ fflush(gc_data_file); -+} -+ -+/* -+ * Called from process.c after a fork in the child process. Turns off -+ * logging, disables GC stats and resets all gc counters and timing -+ * information. -+ */ -+void -+rb_gc_after_fork() -+{ -+ rb_gc_disable_stats(); -+ rb_gc_clear_stats(); -+ rb_gc_disable_trace(); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+} -+ - static struct gc_list { - VALUE *varptr; - struct gc_list *next; -@@ -477,10 +618,6 @@ static double heap_slots_growth_factor = 1.8; - - static long initial_malloc_limit = GC_MALLOC_LIMIT; - --static int verbose_gc_stats = Qfalse; -- --static FILE* gc_data_file = NULL; -- - static RVALUE *himem, *lomem; - - static void set_gc_parameters() -@@ -496,6 +633,8 @@ static void set_gc_parameters() - if (gc_stats_i > 0) { - verbose_gc_stats = Qtrue; - } -+ /* child processes should not inherit RUBY_GC_STATS */ -+ unsetenv("RUBY_GC_STATS"); - } - - gc_heap_file_ptr = getenv("RUBY_GC_DATA_FILE"); -@@ -508,6 +647,8 @@ static void set_gc_parameters() - fprintf(stderr, - "can't open gc log file %s for writing, using default\n", gc_heap_file_ptr); - } -+ /* child processes should not inherit RUBY_GC_DATA_FILE to avoid clobbering */ -+ unsetenv("RUBY_GC_DATA_FILE"); - } - - min_slots_ptr = getenv("RUBY_HEAP_MIN_SLOTS"); -@@ -2619,6 +2760,9 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "dump_file_and_line_info", rb_gc_dump_file_and_line_info, -1); - #endif - rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); -+ rb_define_singleton_method(rb_mGC, "log_file", rb_gc_log_file, -1); -+ rb_define_singleton_method(rb_mGC, "enable_trace", rb_gc_enable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "disable_trace", rb_gc_disable_trace, 0); - - rb_mObSpace = rb_define_module("ObjectSpace"); - rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1); -diff --git a/intern.h b/intern.h -index acae58d..49e1827 100644 ---- a/intern.h -+++ b/intern.h -@@ -270,6 +270,8 @@ void rb_gc_call_finalizer_at_exit _((void)); - VALUE rb_gc_enable _((void)); - VALUE rb_gc_disable _((void)); - VALUE rb_gc_start _((void)); -+void rb_gc_before_fork _((void)); -+void rb_gc_after_fork _((void)); - /* hash.c */ - void st_foreach_safe _((struct st_table *, int (*)(ANYARGS), unsigned long)); - void rb_hash_foreach _((VALUE, int (*)(ANYARGS), VALUE)); -diff --git a/process.c b/process.c -index 8f6285d..ea28cb8 100644 ---- a/process.c -+++ b/process.c -@@ -1330,6 +1330,8 @@ rb_f_fork(obj) - fflush(stderr); - #endif - -+ rb_gc_before_fork(); -+ - before_exec(); - pid = fork(); - after_exec(); -@@ -1339,6 +1341,7 @@ rb_f_fork(obj) - #ifdef linux - after_exec(); - #endif -+ rb_gc_after_fork(); - rb_thread_atfork(); - if (rb_block_given_p()) { - int status; -@@ -1574,10 +1577,12 @@ rb_f_system(argc, argv) - - chfunc = signal(SIGCHLD, SIG_DFL); - retry: -+ rb_gc_before_fork(); - before_exec(); - pid = fork(); - if (pid == 0) { - /* child process */ -+ rb_gc_after_fork(); - rb_thread_atfork(); - rb_protect(proc_exec_args, (VALUE)&earg, NULL); - _exit(127); diff --git a/patches/ruby/1.8.7/p334/railsexpress/09-track-malloc-size.patch b/patches/ruby/1.8.7/p334/railsexpress/09-track-malloc-size.patch deleted file mode 100644 index 3717fe4518..0000000000 --- a/patches/ruby/1.8.7/p334/railsexpress/09-track-malloc-size.patch +++ /dev/null @@ -1,120 +0,0 @@ -diff --git a/gc.c b/gc.c -index a3cbe91..30a1219 100644 ---- a/gc.c -+++ b/gc.c -@@ -79,6 +79,17 @@ void *alloca (); - - static unsigned long malloc_increase = 0; - static unsigned long malloc_limit = GC_MALLOC_LIMIT; -+ -+#ifdef HAVE_LONG_LONG -+static unsigned LONG_LONG gc_allocated_size = 0; -+static unsigned LONG_LONG gc_num_allocations = 0; -+#else -+static unsigned long gc_allocated_size = 0; -+static unsigned long gc_num_allocations = 0; -+#endif -+static int gc_statistics = 0; -+ -+ - static void run_final(); - static VALUE nomem_error; - static void garbage_collect(); -@@ -163,6 +174,11 @@ ruby_xmalloc(size) - } - malloc_increase += size; - -+ if (gc_statistics) { -+ gc_allocated_size += size; -+ gc_num_allocations += 1; -+ } -+ - return mem; - } - -@@ -220,7 +236,6 @@ ruby_xfree(x) - - extern int ruby_in_compile; - static int dont_gc; --static int gc_statistics = 0; - static GC_TIME_TYPE gc_time = 0; - static int gc_collections = 0; - static int verbose_gc_stats = Qfalse; -@@ -329,11 +344,55 @@ rb_gc_clear_stats() - { - gc_collections = 0; - gc_time = 0; -+ gc_allocated_size = 0; -+ gc_num_allocations = 0; - return Qnil; - } - - /* - * call-seq: -+ * GC.allocated_size => Integer -+ * -+ * Returns the size of memory (in bytes) allocated since GC statistics collection -+ * was enabled. -+ * -+ * GC.allocated_size #=> 35 -+ * -+ */ -+VALUE -+rb_gc_allocated_size() -+{ -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_allocated_size); -+#else -+ return ULONG2NUM(gc_allocated_size); -+#endif -+} -+ -+/* -+ * call-seq: -+ * GC.num_allocations => Integer -+ * -+ * Returns the number of memory allocations since GC statistics collection -+ * was enabled. -+ * -+ * GC.num_allocations #=> 150 -+ * -+ */ -+VALUE -+rb_gc_num_allocations() -+{ -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_num_allocations); -+#else -+ return ULONG2NUM(gc_num_allocations); -+#endif -+} -+ -+/* -+ -+/* -+ * call-seq: - * GC.collections => Integer - * - * Returns the number of garbage collections performed while GC statistics collection -@@ -2753,6 +2812,8 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "enable_stats", rb_gc_enable_stats, 0); - rb_define_singleton_method(rb_mGC, "disable_stats", rb_gc_disable_stats, 0); - rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0); -+ rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); -+ rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); - rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); - rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); - rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); -diff --git a/intern.h b/intern.h -index 49e1827..78bf699 100644 ---- a/intern.h -+++ b/intern.h -@@ -272,6 +272,8 @@ VALUE rb_gc_disable _((void)); - VALUE rb_gc_start _((void)); - void rb_gc_before_fork _((void)); - void rb_gc_after_fork _((void)); -+VALUE rb_gc_allocated_size _((void)); -+VALUE rb_gc_num_allocations _((void)); - /* hash.c */ - void st_foreach_safe _((struct st_table *, int (*)(ANYARGS), unsigned long)); - void rb_hash_foreach _((VALUE, int (*)(ANYARGS), VALUE)); diff --git a/patches/ruby/1.8.7/p334/railsexpress/10-track-object-allocation.patch b/patches/ruby/1.8.7/p334/railsexpress/10-track-object-allocation.patch deleted file mode 100644 index 0763da4430..0000000000 --- a/patches/ruby/1.8.7/p334/railsexpress/10-track-object-allocation.patch +++ /dev/null @@ -1,111 +0,0 @@ -diff --git a/gc.c b/gc.c -index 30a1219..5b42b90 100644 ---- a/gc.c -+++ b/gc.c -@@ -96,6 +96,26 @@ static void garbage_collect(); - - int ruby_gc_stress = 0; - -+static unsigned long live_objects = 0; -+unsigned long rb_os_live_objects() -+{ -+ return live_objects; -+} -+ -+#if defined(HAVE_LONG_LONG) -+static unsigned LONG_LONG allocated_objects = 0; -+unsigned LONG_LONG rb_os_allocated_objects() -+{ -+ return allocated_objects; -+} -+#else -+static unsigned long allocated_objects = 0; -+unsigned long rb_os_allocated_objects() -+{ -+ return allocated_objects; -+} -+#endif -+ - NORETURN(void rb_exc_jump _((VALUE))); - - void -@@ -987,6 +1007,8 @@ rb_newobj() - RANY(obj)->file = ruby_sourcefile; - RANY(obj)->line = ruby_sourceline; - #endif -+ live_objects++; -+ allocated_objects++; - return obj; - } - -@@ -1825,6 +1847,7 @@ gc_sweep() - add_heap(); - } - during_gc = 0; -+ live_objects = live; - - if (do_gc_stats) { - fprintf(gc_data_file, "objects processed: %.7d\n", live+freed); -@@ -2790,6 +2813,35 @@ rb_obj_id(VALUE obj) - return (VALUE)((long)obj|FIXNUM_FLAG); - } - -+/* call-seq: -+ * ObjectSpace.live_objects => number -+ * -+ * Returns the count of objects currently allocated in the system. This goes -+ * down after the garbage collector runs. -+ */ -+static -+VALUE os_live_objects(VALUE self) -+{ -+ return ULONG2NUM(live_objects); -+} -+ -+/* call-seq: -+ * ObjectSpace.allocated_objects => number -+ * -+ * Returns the count of objects allocated since the Ruby interpreter has -+ * started. This number can only increase. To know how many objects are -+ * currently allocated, use ObjectSpace::live_objects -+ */ -+static -+VALUE os_allocated_objects(VALUE self) -+{ -+#if defined(HAVE_LONG_LONG) -+ return ULL2NUM(allocated_objects); -+#else -+ return ULONG2NUM(allocated_objects); -+#endif -+} -+ - /* - * The GC module provides an interface to Ruby's mark and - * sweep garbage collection mechanism. Some of the underlying methods -@@ -2833,6 +2885,9 @@ Init_GC() - rb_define_module_function(rb_mObSpace, "finalizers", finals, 0); - rb_define_module_function(rb_mObSpace, "call_finalizer", call_final, 1); - -+ rb_define_module_function(rb_mObSpace, "live_objects", os_live_objects, 0); -+ rb_define_module_function(rb_mObSpace, "allocated_objects", os_allocated_objects, 0); -+ - rb_define_module_function(rb_mObSpace, "define_finalizer", define_final, -1); - rb_define_module_function(rb_mObSpace, "undefine_finalizer", undefine_final, 1); - -diff --git a/intern.h b/intern.h -index 78bf699..86b4395 100644 ---- a/intern.h -+++ b/intern.h -@@ -274,6 +274,12 @@ void rb_gc_before_fork _((void)); - void rb_gc_after_fork _((void)); - VALUE rb_gc_allocated_size _((void)); - VALUE rb_gc_num_allocations _((void)); -+unsigned long rb_os_live_objects _((void)); -+#ifdef HAVE_LONG_LONG -+unsigned LONG_LONG rb_os_allocated_objects _((void)); -+#else -+unsigned long rb_os_allocated_objects _((void)); -+#endif - /* hash.c */ - void st_foreach_safe _((struct st_table *, int (*)(ANYARGS), unsigned long)); - void rb_hash_foreach _((VALUE, int (*)(ANYARGS), VALUE)); diff --git a/patches/ruby/1.8.7/p334/railsexpress/11-expose-heap-slots.patch b/patches/ruby/1.8.7/p334/railsexpress/11-expose-heap-slots.patch deleted file mode 100644 index 5761315623..0000000000 --- a/patches/ruby/1.8.7/p334/railsexpress/11-expose-heap-slots.patch +++ /dev/null @@ -1,70 +0,0 @@ -diff --git a/gc.c b/gc.c -index 5b42b90..21b3f6b 100644 ---- a/gc.c -+++ b/gc.c -@@ -690,6 +690,7 @@ static int heaps_used = 0; - - static int heap_min_slots = 10000; - static int heap_slots = 10000; -+static int heap_size = 0; - - static int heap_free_min = 4096; - static int heap_slots_increment = 10000; -@@ -800,6 +801,21 @@ static void set_gc_parameters() - - /* - * call-seq: -+ * GC.heap_slots => Integer -+ * -+ * Returns the number of heap slots available for object allocations. -+ * -+ * GC.heap_slots #=> 10000 -+ * -+ */ -+VALUE -+rb_gc_heap_slots() -+{ -+ return INT2NUM(heap_size); -+} -+ -+/* -+ * call-seq: - * GC.dump => nil - * - * dumps information about the current GC data structures to the GC log file -@@ -967,6 +983,7 @@ add_heap() - heaps[heaps_used].limit = heap_slots; - break; - } -+ heap_size += heap_slots; - pend = p + heap_slots; - if (lomem == 0 || lomem > p) lomem = p; - if (himem < pend) himem = pend; -@@ -1828,6 +1845,7 @@ gc_sweep() - if (n == heaps[i].limit && freed > free_min) { - RVALUE *pp; - -+ heap_size -= n; - heaps[i].limit = 0; - for (pp = final_list; pp != final; pp = pp->as.free.next) { - pp->as.free.flags |= FL_SINGLETON; /* freeing page mark */ -@@ -2866,6 +2884,7 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0); - rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); - rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); - rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); - rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); - rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); -diff --git a/intern.h b/intern.h -index 86b4395..e23d2d7 100644 ---- a/intern.h -+++ b/intern.h -@@ -274,6 +274,7 @@ void rb_gc_before_fork _((void)); - void rb_gc_after_fork _((void)); - VALUE rb_gc_allocated_size _((void)); - VALUE rb_gc_num_allocations _((void)); -+VALUE rb_gc_heap_slots _((void)); - unsigned long rb_os_live_objects _((void)); - #ifdef HAVE_LONG_LONG - unsigned LONG_LONG rb_os_allocated_objects _((void)); diff --git a/patches/ruby/1.8.7/p334/railsexpress/12-fix-heap-size-growth-logic.patch b/patches/ruby/1.8.7/p334/railsexpress/12-fix-heap-size-growth-logic.patch deleted file mode 100644 index 1db93f224d..0000000000 --- a/patches/ruby/1.8.7/p334/railsexpress/12-fix-heap-size-growth-logic.patch +++ /dev/null @@ -1,54 +0,0 @@ -diff --git a/gc.c b/gc.c -index 21b3f6b..7db1ef6 100644 ---- a/gc.c -+++ b/gc.c -@@ -694,6 +694,7 @@ static int heap_size = 0; - - static int heap_free_min = 4096; - static int heap_slots_increment = 10000; -+static int initial_heap_slots_increment = 10000; - static double heap_slots_growth_factor = 1.8; - - static long initial_malloc_limit = GC_MALLOC_LIMIT; -@@ -771,14 +772,13 @@ static void set_gc_parameters() - if (verbose_gc_stats) { - fprintf(gc_data_file, "RUBY_HEAP_SLOTS_INCREMENT=%s\n", heap_slots_incr_ptr); - } -- if (heap_slots_incr_i > 0) { -- heap_slots_increment = heap_slots_incr_i; -- } -+ heap_slots_increment = heap_slots_incr_i; -+ initial_heap_slots_increment = heap_slots_increment; - } - - heap_slots_growth_factor_ptr = getenv("RUBY_HEAP_SLOTS_GROWTH_FACTOR"); - if (heap_slots_growth_factor_ptr != NULL) { -- double heap_slots_growth_factor_d = atoi(heap_slots_growth_factor_ptr); -+ double heap_slots_growth_factor_d = atof(heap_slots_growth_factor_ptr); - if (verbose_gc_stats) { - fprintf(gc_data_file, "RUBY_HEAP_SLOTS_GROWTH_FACTOR=%s\n", heap_slots_growth_factor_ptr); - } -@@ -988,8 +988,13 @@ add_heap() - if (lomem == 0 || lomem > p) lomem = p; - if (himem < pend) himem = pend; - heaps_used++; -- heap_slots += heap_slots_increment; -- heap_slots_increment *= heap_slots_growth_factor; -+ if (heaps_used == 1) -+ heap_slots = initial_heap_slots_increment; -+ else { -+ heap_slots_increment *= heap_slots_growth_factor; -+ heap_slots += heap_slots_increment; -+ } -+ - if (heap_slots <= 0) heap_slots = heap_min_slots; - - while (p < pend) { -@@ -1879,6 +1884,7 @@ gc_sweep() - live_counts[i], free_counts[i], obj_type(i)); - } - } -+ rb_gc_dump(); - fflush(gc_data_file); - } - diff --git a/patches/ruby/1.8.7/p334/railsexpress/13-heap-slot-size.patch b/patches/ruby/1.8.7/p334/railsexpress/13-heap-slot-size.patch deleted file mode 100644 index 45091c14ae..0000000000 --- a/patches/ruby/1.8.7/p334/railsexpress/13-heap-slot-size.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/gc.c b/gc.c -index 7db1ef6..57740d2 100644 ---- a/gc.c -+++ b/gc.c -@@ -2891,6 +2891,7 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); - rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); - rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); - rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); - rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); - rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); diff --git a/patches/ruby/1.8.7/p334/railsexpress/14-add-trace-stats-enabled-methods.patch b/patches/ruby/1.8.7/p334/railsexpress/14-add-trace-stats-enabled-methods.patch deleted file mode 100644 index 4e3c4f2132..0000000000 --- a/patches/ruby/1.8.7/p334/railsexpress/14-add-trace-stats-enabled-methods.patch +++ /dev/null @@ -1,66 +0,0 @@ -diff --git a/gc.c b/gc.c -index 57740d2..2c34932 100644 ---- a/gc.c -+++ b/gc.c -@@ -350,6 +350,22 @@ rb_gc_disable_stats() - - /* - * call-seq: -+ * GC.stats_enabled? => true or false -+ * -+ * Check whether GC stats have been enabled. -+ * -+ * GC.stats_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_stats_enabled() -+{ -+ return gc_statistics ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: - * GC.clear_stats => nil - * - * Clears garbage collection statistics, returning nil. This resets the number -@@ -491,6 +507,22 @@ rb_gc_disable_trace() - return old; - } - -+/* -+ * call-seq: -+ * GC.trace_enabled? => true or false -+ * -+ * Check whether GC tracing has been enabled. -+ * -+ * GC.trace_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_trace_enabled() -+{ -+ return verbose_gc_stats ? Qtrue : Qfalse; -+} -+ - char* GC_LOGFILE_IVAR = "@gc_logfile_name"; - - /* -@@ -2887,6 +2919,7 @@ Init_GC() - - rb_define_singleton_method(rb_mGC, "enable_stats", rb_gc_enable_stats, 0); - rb_define_singleton_method(rb_mGC, "disable_stats", rb_gc_disable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "stats_enabled?", rb_gc_stats_enabled, 0); - rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0); - rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); - rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); -@@ -2902,6 +2935,7 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "log_file", rb_gc_log_file, -1); - rb_define_singleton_method(rb_mGC, "enable_trace", rb_gc_enable_trace, 0); - rb_define_singleton_method(rb_mGC, "disable_trace", rb_gc_disable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "trace_enabled?", rb_gc_trace_enabled, 0); - - rb_mObSpace = rb_define_module("ObjectSpace"); - rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1); diff --git a/patches/ruby/1.8.7/p334/railsexpress/15-track-live-dataset-size.patch b/patches/ruby/1.8.7/p334/railsexpress/15-track-live-dataset-size.patch deleted file mode 100644 index de44e6b365..0000000000 --- a/patches/ruby/1.8.7/p334/railsexpress/15-track-live-dataset-size.patch +++ /dev/null @@ -1,52 +0,0 @@ -diff --git a/gc.c b/gc.c -index 2c34932..0ce7e68 100644 ---- a/gc.c -+++ b/gc.c -@@ -89,6 +89,7 @@ static unsigned long gc_num_allocations = 0; - #endif - static int gc_statistics = 0; - -+static unsigned long heap_slots_live_after_last_gc = 0; - - static void run_final(); - static VALUE nomem_error; -@@ -465,6 +466,23 @@ rb_gc_time() - #endif - } - -+/* -+ * call-seq: -+ * GC.heap_slots_live_after_last_gc => Integer -+ * -+ * Returns the number of heap slots which were live after the last garbage collection. -+ * -+ * GC.heap_slots_live_after_last_gc #=> 231223 -+ * -+ */ -+VALUE -+rb_gc_heap_slots_live_after_last_gc() -+{ -+ return ULONG2NUM(heap_slots_live_after_last_gc); -+} -+ -+ -+ - VALUE rb_mGC; - - /* -@@ -1903,6 +1921,7 @@ gc_sweep() - } - during_gc = 0; - live_objects = live; -+ heap_slots_live_after_last_gc = live; - - if (do_gc_stats) { - fprintf(gc_data_file, "objects processed: %.7d\n", live+freed); -@@ -2924,6 +2943,7 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); - rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); - rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots_live_after_last_gc", rb_gc_heap_slots_live_after_last_gc, 0); - rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); - rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); - rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); diff --git a/patches/ruby/1.8.7/p334/railsexpress/16-add-object-size-information-to-heap-dump.patch b/patches/ruby/1.8.7/p334/railsexpress/16-add-object-size-information-to-heap-dump.patch deleted file mode 100644 index e974cdb63a..0000000000 --- a/patches/ruby/1.8.7/p334/railsexpress/16-add-object-size-information-to-heap-dump.patch +++ /dev/null @@ -1,51 +0,0 @@ -diff --git a/gc.c b/gc.c -index 0ce7e68..53450bf 100644 ---- a/gc.c -+++ b/gc.c -@@ -953,9 +953,21 @@ rb_gc_dump_file_and_line_info(int argc, VALUE *argv) - if (!p->as.basic.klass) { - fprintf(f, "__unknown__"); - } else { -- fprintf(f, rb_obj_classname((VALUE)p)); -+ fprintf(f, "%s", rb_obj_classname((VALUE)p)); - } - } -+ /* print object size for some known object types */ -+ switch (TYPE(p)) { -+ case T_STRING: -+ fprintf(f, ":%lu", RSTRING(p)->len); -+ break; -+ case T_ARRAY: -+ fprintf(f, ":%lu", RARRAY(p)->len); -+ break; -+ case T_HASH: -+ fprintf(f, ":%d", RHASH(p)->tbl->num_entries); -+ break; -+ } - } - fprintf(f, "\n"); - } -@@ -1924,10 +1936,10 @@ gc_sweep() - heap_slots_live_after_last_gc = live; - - if (do_gc_stats) { -- fprintf(gc_data_file, "objects processed: %.7d\n", live+freed); -- fprintf(gc_data_file, "live objects : %.7d\n", live); -- fprintf(gc_data_file, "freelist objects : %.7d\n", freed - really_freed); -- fprintf(gc_data_file, "freed objects : %.7d\n", really_freed); -+ fprintf(gc_data_file, "objects processed: %.7lu\n", live+freed); -+ fprintf(gc_data_file, "live objects : %.7lu\n", live); -+ fprintf(gc_data_file, "freelist objects : %.7lu\n", freed - really_freed); -+ fprintf(gc_data_file, "freed objects : %.7lu\n", really_freed); - for(i=0; i<256; i++) { - if (free_counts[i]>0 || live_counts[i]>0) { - fprintf(gc_data_file, -@@ -2258,7 +2270,7 @@ garbage_collect() - gc_time += musecs_used; - - if (verbose_gc_stats) { -- fprintf(gc_data_file, "GC time: %d msec\n", musecs_used / 1000); -+ fprintf(gc_data_file, "GC time: %ld msec\n", (long)(musecs_used / 1000)); - fflush(gc_data_file); - } - } diff --git a/patches/ruby/1.8.7/p334/railsexpress/17-caller-for-all-threads.patch b/patches/ruby/1.8.7/p334/railsexpress/17-caller-for-all-threads.patch deleted file mode 100644 index 84601db4ba..0000000000 --- a/patches/ruby/1.8.7/p334/railsexpress/17-caller-for-all-threads.patch +++ /dev/null @@ -1,230 +0,0 @@ -diff --git a/eval.c b/eval.c -index 8a2f492..b34b60d 100644 ---- a/eval.c -+++ b/eval.c -@@ -8199,6 +8199,17 @@ rb_f_method_name() - } - } - -+/* Hash (Thread => Backtrace) used to collect backtrace for each threads. */ -+static VALUE backtrace_for_each_thread; -+ -+static int backtrace_level_for_each_thread; -+ -+static VALUE -+switch_thread_context_to_collect_backtrace(rb_thread_t next); -+ -+static VALUE -+rb_f_caller_for_all_threads(); -+ - void - Init_eval() - { -@@ -8244,6 +8255,7 @@ Init_eval() - rb_define_global_function("fail", rb_f_raise, -1); - - rb_define_global_function("caller", rb_f_caller, -1); -+ rb_define_global_function("caller_for_all_threads", rb_f_caller_for_all_threads, -1); - - rb_define_global_function("exit", rb_f_exit, -1); - rb_define_global_function("abort", rb_f_abort, -1); -@@ -10599,6 +10611,7 @@ static int th_sig, th_safe; - #define RESTORE_RAISE 5 - #define RESTORE_SIGNAL 6 - #define RESTORE_EXIT 7 -+#define RESTORE_BACKTRACE 8 - - extern VALUE *rb_gc_stack_start; - #ifdef __ia64 -@@ -10705,6 +10718,15 @@ rb_thread_switch(n) - } - rb_exc_raise(th_raise_exception); - break; -+ case RESTORE_BACKTRACE: -+ rb_hash_aset(backtrace_for_each_thread, curr_thread->thread, -+ backtrace(backtrace_level_for_each_thread)); -+ if (curr_thread != main_thread) { -+ switch_thread_context_to_collect_backtrace(curr_thread->next); -+ } else { -+ /* Circled back to main thread, cycle is complete. */ -+ } -+ break; - case RESTORE_NORMAL: - default: - break; -@@ -13874,3 +13896,74 @@ rb_throw(tag, val) - argv[1] = val; - rb_f_throw(2, argv); - } -+ -+static VALUE -+switch_thread_context_to_collect_backtrace(rb_thread_t next) -+{ -+ if (THREAD_SAVE_CONTEXT(curr_thread)) { -+ return Qnil; -+ } -+ curr_thread = next; -+ rb_thread_restore_context(next, RESTORE_BACKTRACE); -+ return Qnil; -+} -+ -+ -+/* -+ * call-seq: -+ * caller_for_all_threads(start=1) => array -+ * -+ * Returns the current execution stack for all threads -+ * ---a hash whose keys are thread instances and values -+ * the thread caller backtrace. -+ * -+ * Backtraces are array of hashes indicating location on the -+ * stack. Hash keys include ``:line'' or ``:file'' -+ * and ``:method'''. -+ * -+ * The optional _start_ parameter -+ * determines the number of initial stack entries to omit from the -+ * result. -+ * -+ * def a(skip) -+ * caller_for_all_threads(skip) -+ * end -+ * def b(skip) -+ * a(skip) -+ * end -+ * def c(skip) -+ * b(skip) -+ * end -+ * c(0) #=> ["prog:2:in `a'", "prog:5:in `b'", "prog:8:in `c'", "prog:10"] -+ * c(1) #=> ["prog:5:in `b'", "prog:8:in `c'", "prog:11"] -+ * c(2) #=> ["prog:8:in `c'", "prog:12"] -+ * c(3) #=> ["prog:13"] -+ */ -+static VALUE -+rb_f_caller_for_all_threads(argc, argv) -+ int argc; -+ VALUE *argv; -+{ -+ volatile int critical; -+ VALUE level; -+ VALUE result; -+ -+ rb_scan_args(argc, argv, "01", &level); -+ backtrace_level_for_each_thread = NIL_P(level) ? 0 : NUM2INT(level); -+ if (backtrace_level_for_each_thread < 0) { -+ rb_raise(rb_eArgError, "negative level (%d)", backtrace_level_for_each_thread); -+ } -+ -+ critical = rb_thread_critical; -+ rb_thread_critical = Qtrue; -+ -+ backtrace_for_each_thread = rb_hash_new(); -+ switch_thread_context_to_collect_backtrace(main_thread->next); -+ -+ result = backtrace_for_each_thread; -+ backtrace_for_each_thread = Qnil; -+ backtrace_for_each_thread = 0; -+ -+ rb_thread_critical = critical; -+ return result; -+} -diff --git a/test/callerforallthreads/test_caller_for_each_thread.rb b/test/callerforallthreads/test_caller_for_each_thread.rb -new file mode 100644 -index 0000000..6aebaed ---- /dev/null -+++ b/test/callerforallthreads/test_caller_for_each_thread.rb -@@ -0,0 +1,95 @@ -+# -*- ruby-indent-level: 4 -*- -+require 'thread' -+require 'test/unit' -+ -+class AClassWithNestedmethods -+ -+ def an_ultra_nested_method(skip) -+ caller_for_all_threads skip -+ end -+ -+ def a_nested_method(skip) -+ an_ultra_nested_method skip -+ end -+ -+ def a_method(skip=0) -+ a_nested_method skip -+ end -+ -+end -+ -+class CallerForEachThreadTest < Test::Unit::TestCase -+ -+ def testCollectMeaningfulBacktraceForASingleThread -+ backtraces = AClassWithNestedmethods.new.a_method -+ backtrace = backtraces[Thread.current] -+ assert_not_nil backtrace -+ assert_equal __FILE__ + ":8:in `an_ultra_nested_method'", backtrace[0] -+ assert_equal __FILE__ + ":12:in `a_nested_method'", backtrace[1] -+ assert_equal __FILE__ + ":16:in `a_method'", backtrace[2] -+ assert_equal __FILE__ + ":24:in `testCollectMeaningfulBacktraceForASingleThread'", -+ backtrace[3] -+ end -+ -+ def testCanSkipFirstStackEntries -+ backtraces = AClassWithNestedmethods.new.a_method 2 -+ backtrace = backtraces[Thread.current] -+ assert_not_nil backtrace -+ assert_equal __FILE__ + ":16:in `a_method'", backtrace[0] -+ assert_equal __FILE__ + ":35:in `testCanSkipFirstStackEntries'", -+ backtrace[1] -+ end -+ -+ def testCollectMeaningfulBacktraceForMultipleThreads -+ first_thread = Thread.new do -+ loop do -+ Thread.pass -+ sleep 1 -+ end -+ end -+ -+ second_thread = Thread.new do -+ loop do -+ Thread.pass -+ sleep 1 -+ end -+ end -+ -+ backtraces = AClassWithNestedmethods.new.a_method -+ -+ backtrace = backtraces[Thread.current] -+ assert_not_nil backtrace -+ assert_match __FILE__ + ":8:in `an_ultra_nested_method'", backtrace[0] -+ assert_match __FILE__ + ":12:in `a_nested_method'", backtrace[1] -+ assert_equal __FILE__ + ":16:in `a_method'", backtrace[2] -+ assert_equal __FILE__ + ":58:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[3] -+ -+ backtrace = backtraces[first_thread] -+ assert_not_nil backtrace -+ assert_equal __FILE__ + ":47:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[0] -+ assert_equal __FILE__ + ":45:in `loop'", -+ backtrace[1] -+ assert_equal __FILE__ + ":45:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[2] -+ assert_equal __FILE__ + ":44:in `initialize'",backtrace[3] -+ assert_equal __FILE__ + ":44:in `new'", backtrace[4] -+ assert_equal __FILE__ + ":44:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[5] -+ -+ backtrace = backtraces[second_thread] -+ assert_not_nil backtrace -+ assert_equal __FILE__ + ":53:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[0] -+ assert_equal __FILE__ + ":52:in `loop'", backtrace[1] -+ assert_equal __FILE__ + ":52:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[2] -+ assert_equal __FILE__ + ":51:in `initialize'",backtrace[3] -+ assert_equal __FILE__ + ":51:in `new'", backtrace[4] -+ assert_equal __FILE__ + ":51:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[5] -+ end -+ -+end -+ diff --git a/patches/ruby/1.8.7/p352/railsexpress/01-ignore-generated-files.patch b/patches/ruby/1.8.7/p352/railsexpress/01-ignore-generated-files.patch deleted file mode 100644 index b669ad44bd..0000000000 --- a/patches/ruby/1.8.7/p352/railsexpress/01-ignore-generated-files.patch +++ /dev/null @@ -1,101 +0,0 @@ -diff --git a/.gitignore b/.gitignore -new file mode 100644 -index 0000000..00c347a ---- /dev/null -+++ b/.gitignore -@@ -0,0 +1,95 @@ -+.ext -+.installed.list -+.rbconfig.time -+Makefile -+autom4te.cache/ -+config.h -+config.status -+configure -+ext/Win32API/Makefile -+ext/bigdecimal/Makefile -+ext/curses/Makefile -+ext/dbm/Makefile -+ext/digest/Makefile -+ext/digest/bubblebabble/Makefile -+ext/digest/md5/Makefile -+ext/digest/rmd160/Makefile -+ext/digest/sha1/Makefile -+ext/digest/sha2/Makefile -+ext/dl/Makefile -+ext/dl/call.func -+ext/dl/callback.func -+ext/dl/cbtable.func -+ext/dl/dlconfig.h -+ext/dl/dlconfig.rb -+ext/enumerator/Makefile -+ext/etc/Makefile -+ext/fcntl/Makefile -+ext/gdbm/Makefile -+ext/iconv/Makefile -+ext/io/wait/Makefile -+ext/nkf/Makefile -+ext/openssl/Makefile -+ext/openssl/extconf.h -+ext/pty/Makefile -+ext/racc/cparse/Makefile -+ext/readline/Makefile -+ext/sdbm/Makefile -+ext/socket/Makefile -+ext/stringio/Makefile -+ext/strscan/Makefile -+ext/syck/Makefile -+ext/syslog/Makefile -+ext/thread/Makefile -+ext/tk/Makefile -+ext/tk/tkutil/Makefile -+ext/win32ole/Makefile -+ext/win32ole/.document -+ext/zlib/Makefile -+largefile.h -+miniruby -+parse.c -+rbconfig.rb -+ruby -+enc.mk -+ext/bigdecimal/extconf.h -+ext/continuation/ -+ext/coverage/ -+ext/curses/extconf.h -+ext/dbm/extconf.h -+ext/digest/bubblebabble/extconf.h -+ext/digest/extconf.h -+ext/digest/md5/extconf.h -+ext/digest/rmd160/extconf.h -+ext/digest/sha1/extconf.h -+ext/digest/sha2/extconf.h -+ext/dl/callback.h -+ext/dl/extconf.h -+ext/etc/extconf.h -+ext/fcntl/extconf.h -+ext/fiber/ -+ext/iconv/extconf.h -+ext/io/wait/extconf.h -+ext/json/ -+ext/nkf/extconf.h -+ext/pty/extconf.h -+ext/racc/cparse/extconf.h -+ext/readline/extconf.h -+ext/ripper/ -+ext/sdbm/extconf.h -+ext/socket/constants.h -+ext/socket/extconf.h -+ext/stringio/extconf.h -+ext/strscan/extconf.h -+ext/syck/extconf.h -+ext/syslog/extconf.h -+ext/tk/extconf.h -+ext/tk/tkutil/extconf.h -+ext/zlib/extconf.h -+miniprelude.c -+prelude.c -+revision.h -+*.dylib -+*.log -+*.dSYM -+patches-ruby* diff --git a/patches/ruby/1.8.7/p352/railsexpress/02-sigvtalrm-fix.patch b/patches/ruby/1.8.7/p352/railsexpress/02-sigvtalrm-fix.patch deleted file mode 100644 index fe99f6eed6..0000000000 --- a/patches/ruby/1.8.7/p352/railsexpress/02-sigvtalrm-fix.patch +++ /dev/null @@ -1,27 +0,0 @@ -diff --git a/eval.c b/eval.c -index 7886e17..6ff2560 100644 ---- a/eval.c -+++ b/eval.c -@@ -12461,6 +12461,11 @@ rb_thread_start_0(fn, arg, th) - curr_thread->next = th; - th->priority = curr_thread->priority; - th->thgroup = curr_thread->thgroup; -+#if defined(HAVE_SETITIMER) || defined(_THREAD_SAFE) -+ if (!thread_init) { -+ rb_thread_start_timer(); -+ } -+#endif - } - START_TIMER(); - -@@ -13189,7 +13194,9 @@ rb_thread_atfork() - main_thread = curr_thread; - curr_thread->next = curr_thread; - curr_thread->prev = curr_thread; -- STOP_TIMER(); -+#if defined(HAVE_SETITIMER) || defined(_THREAD_SAFE) -+ rb_thread_stop_timer(); -+#endif - } - - diff --git a/patches/ruby/1.8.7/p352/railsexpress/03-railsbench-gc-patch.patch b/patches/ruby/1.8.7/p352/railsexpress/03-railsbench-gc-patch.patch deleted file mode 100644 index 7b6c0e251a..0000000000 --- a/patches/ruby/1.8.7/p352/railsexpress/03-railsbench-gc-patch.patch +++ /dev/null @@ -1,1876 +0,0 @@ -diff --git a/gc.c b/gc.c -index fa45cd1..ab71d22 100644 ---- a/gc.c -+++ b/gc.c -@@ -22,8 +22,16 @@ - #include - #include - -+#ifdef _WIN32 -+#include -+#else -+#include -+#endif -+ - #ifdef HAVE_SYS_TIME_H - #include -+#elif defined(_WIN32) -+#include - #endif - - #ifdef HAVE_SYS_RESOURCE_H -@@ -42,7 +50,6 @@ void rb_io_fptr_finalize _((struct rb_io_t*)); - #ifdef __CYGWIN__ - int _setjmp(), _longjmp(); - #endif -- - /* Make alloca work the best possible way. */ - #ifdef __GNUC__ - # ifndef atarist -@@ -86,12 +93,12 @@ rb_memerror() - rb_thread_t th = rb_curr_thread; - - if (!nomem_error || -- (rb_thread_raised_p(th, RAISED_NOMEMORY) && rb_safe_level() < 4)) { -- fprintf(stderr, "[FATAL] failed to allocate memory\n"); -- exit(1); -+ (rb_thread_raised_p(th, RAISED_NOMEMORY) && rb_safe_level() < 4)) { -+ fprintf(stderr, "[FATAL] failed to allocate memory\n"); -+ exit(1); - } - if (rb_thread_raised_p(th, RAISED_NOMEMORY)) { -- rb_exc_jump(nomem_error); -+ rb_exc_jump(nomem_error); - } - rb_thread_raised_set(th, RAISED_NOMEMORY); - rb_exc_raise(nomem_error); -@@ -139,7 +146,7 @@ ruby_xmalloc(size) - void *mem; - - if (size < 0) { -- rb_raise(rb_eNoMemError, "negative allocation size (or too big)"); -+ rb_raise(rb_eNoMemError, "negative allocation size (or too big)"); - } - if (size == 0) size = 1; - -@@ -148,11 +155,11 @@ ruby_xmalloc(size) - } - RUBY_CRITICAL(mem = malloc(size)); - if (!mem) { -- garbage_collect(); -- RUBY_CRITICAL(mem = malloc(size)); -- if (!mem) { -- rb_memerror(); -- } -+ garbage_collect(); -+ RUBY_CRITICAL(mem = malloc(size)); -+ if (!mem) { -+ rb_memerror(); -+ } - } - malloc_increase += size; - -@@ -179,17 +186,17 @@ ruby_xrealloc(ptr, size) - void *mem; - - if (size < 0) { -- rb_raise(rb_eArgError, "negative re-allocation size"); -+ rb_raise(rb_eArgError, "negative re-allocation size"); - } - if (!ptr) return xmalloc(size); - if (size == 0) size = 1; - if (ruby_gc_stress) garbage_collect(); - RUBY_CRITICAL(mem = realloc(ptr, size)); - if (!mem) { -- garbage_collect(); -- RUBY_CRITICAL(mem = realloc(ptr, size)); -- if (!mem) { -- rb_memerror(); -+ garbage_collect(); -+ RUBY_CRITICAL(mem = realloc(ptr, size)); -+ if (!mem) { -+ rb_memerror(); - } - } - malloc_increase += size; -@@ -202,11 +209,20 @@ ruby_xfree(x) - void *x; - { - if (x) -- RUBY_CRITICAL(free(x)); -+ RUBY_CRITICAL(free(x)); - } - -+#if HAVE_LONG_LONG -+#define GC_TIME_TYPE LONG_LONG -+#else -+#define GC_TIME_TYPE long -+#endif -+ - extern int ruby_in_compile; - static int dont_gc; -+static int gc_statistics = 0; -+static GC_TIME_TYPE gc_time = 0; -+static int gc_collections = 0; - static int during_gc; - static int need_call_final = 0; - static st_table *finalizer_table = 0; -@@ -241,7 +257,7 @@ rb_gc_enable() - * Disables garbage collection, returning true if garbage - * collection was already disabled. - * -- * GC.disable #=> false -+ * GC.disable #=> false or true - * GC.disable #=> true - * - */ -@@ -255,6 +271,104 @@ rb_gc_disable() - return old; - } - -+/* -+ * call-seq: -+ * GC.enable_stats => true or false -+ * -+ * Enables garbage collection statistics, returning true if garbage -+ * collection statistics was already enabled. -+ * -+ * GC.enable_stats #=> false or true -+ * GC.enable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_stats() -+{ -+ int old = gc_statistics; -+ gc_statistics = Qtrue; -+ return old; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_stats => true or false -+ * -+ * Disables garbage collection statistics, returning true if garbage -+ * collection statistics was already disabled. -+ * -+ * GC.disable_stats #=> false or true -+ * GC.disable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_stats() -+{ -+ int old = gc_statistics; -+ gc_statistics = Qfalse; -+ return old; -+} -+ -+/* -+ * call-seq: -+ * GC.clear_stats => nil -+ * -+ * Clears garbage collection statistics, returning nil. This resets the number -+ * of collections (GC.collections) and the time used (GC.time) to 0. -+ * -+ * GC.clear_stats #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_clear_stats() -+{ -+ gc_collections = 0; -+ gc_time = 0; -+ return Qnil; -+} -+ -+/* -+ * call-seq: -+ * GC.collections => Integer -+ * -+ * Returns the number of garbage collections performed while GC statistics collection -+ * was enabled. -+ * -+ * GC.collections #=> 35 -+ * -+ */ -+ -+VALUE -+rb_gc_collections() -+{ -+ return INT2NUM(gc_collections); -+} -+ -+/* -+ * call-seq: -+ * GC.time => Integer -+ * -+ * Returns the time spent during garbage collection while GC statistics collection -+ * was enabled (in micro seconds). -+ * -+ * GC.time #=> 20000 -+ * -+ */ -+ -+VALUE -+rb_gc_time() -+{ -+#if HAVE_LONG_LONG -+ return LL2NUM(gc_time); -+#else -+ return LONG2NUM(gc_time); -+#endif -+} -+ -+ - VALUE rb_mGC; - - static struct gc_list { -@@ -281,19 +395,19 @@ rb_gc_unregister_address(addr) - struct gc_list *tmp = global_List; - - if (tmp->varptr == addr) { -- global_List = tmp->next; -- RUBY_CRITICAL(free(tmp)); -- return; -+ global_List = tmp->next; -+ RUBY_CRITICAL(free(tmp)); -+ return; - } - while (tmp->next) { -- if (tmp->next->varptr == addr) { -- struct gc_list *t = tmp->next; -+ if (tmp->next->varptr == addr) { -+ struct gc_list *t = tmp->next; - -- tmp->next = tmp->next->next; -- RUBY_CRITICAL(free(t)); -- break; -- } -- tmp = tmp->next; -+ tmp->next = tmp->next->next; -+ RUBY_CRITICAL(free(t)); -+ break; -+ } -+ tmp = tmp->next; - } - } - -@@ -312,26 +426,26 @@ rb_global_variable(var) - - typedef struct RVALUE { - union { -- struct { -- unsigned long flags; /* always 0 for freed obj */ -- 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; -- struct RStruct rstruct; -- struct RBignum bignum; -- struct RFile file; -- struct RNode node; -- struct RMatch match; -- struct RVarmap varmap; -- struct SCOPE scope; -+ struct { -+ unsigned long flags; /* always 0 for freed obj */ -+ 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; -+ struct RStruct rstruct; -+ struct RBignum bignum; -+ struct RFile file; -+ struct RNode node; -+ struct RMatch match; -+ struct RVarmap varmap; -+ struct SCOPE scope; - } as; - #ifdef GC_DEBUG - char *file; -@@ -346,7 +460,7 @@ typedef struct RVALUE { - static RVALUE *freelist = 0; - static RVALUE *deferred_final_list = 0; - --#define HEAPS_INCREMENT 10 -+static int heaps_increment = 10; - static struct heaps_slot { - void *membase; - RVALUE *slot; -@@ -355,45 +469,197 @@ static struct heaps_slot { - static int heaps_length = 0; - static int heaps_used = 0; - --#define HEAP_MIN_SLOTS 10000 --static int heap_slots = HEAP_MIN_SLOTS; -+static int heap_min_slots = 10000; -+static int heap_slots = 10000; - --#define FREE_MIN 4096 -+static int heap_free_min = 4096; -+static int heap_slots_increment = 10000; -+static double heap_slots_growth_factor = 1.8; -+ -+static long initial_malloc_limit = GC_MALLOC_LIMIT; -+ -+static int verbose_gc_stats = Qfalse; -+ -+static FILE* gc_data_file = NULL; - - static RVALUE *himem, *lomem; - -+static void set_gc_parameters() -+{ -+ char *gc_stats_ptr, *min_slots_ptr, *free_min_ptr, *heap_slots_incr_ptr, -+ *heap_incr_ptr, *malloc_limit_ptr, *gc_heap_file_ptr, *heap_slots_growth_factor_ptr; -+ -+ gc_data_file = stderr; -+ -+ gc_stats_ptr = getenv("RUBY_GC_STATS"); -+ if (gc_stats_ptr != NULL) { -+ int gc_stats_i = atoi(gc_stats_ptr); -+ if (gc_stats_i > 0) { -+ verbose_gc_stats = Qtrue; -+ } -+ } -+ -+ gc_heap_file_ptr = getenv("RUBY_GC_DATA_FILE"); -+ if (gc_heap_file_ptr != NULL) { -+ FILE* data_file = fopen(gc_heap_file_ptr, "w"); -+ if (data_file != NULL) { -+ gc_data_file = data_file; -+ } -+ else { -+ fprintf(stderr, -+ "can't open gc log file %s for writing, using default\n", gc_heap_file_ptr); -+ } -+ } -+ -+ min_slots_ptr = getenv("RUBY_HEAP_MIN_SLOTS"); -+ if (min_slots_ptr != NULL) { -+ int min_slots_i = atoi(min_slots_ptr); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_MIN_SLOTS=%s\n", min_slots_ptr); -+ } -+ if (min_slots_i > 0) { -+ heap_slots = min_slots_i; -+ heap_min_slots = min_slots_i; -+ } -+ } -+ -+ free_min_ptr = getenv("RUBY_HEAP_FREE_MIN"); -+ if (free_min_ptr != NULL) { -+ int free_min_i = atoi(free_min_ptr); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_FREE_MIN=%s\n", free_min_ptr); -+ } -+ if (free_min_i > 0) { -+ heap_free_min = free_min_i; -+ } -+ } -+ -+ heap_incr_ptr = getenv("RUBY_HEAP_INCREMENT"); -+ if (heap_incr_ptr != NULL) { -+ int heap_incr_i = atoi(heap_incr_ptr); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_INCREMENT=%s\n", heap_incr_ptr); -+ } -+ if (heap_incr_i > 0) { -+ heaps_increment = heap_incr_i; -+ } -+ } -+ -+ heap_slots_incr_ptr = getenv("RUBY_HEAP_SLOTS_INCREMENT"); -+ if (heap_slots_incr_ptr != NULL) { -+ int heap_slots_incr_i = atoi(heap_slots_incr_ptr); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_INCREMENT=%s\n", heap_slots_incr_ptr); -+ } -+ if (heap_slots_incr_i > 0) { -+ heap_slots_increment = heap_slots_incr_i; -+ } -+ } -+ -+ heap_slots_growth_factor_ptr = getenv("RUBY_HEAP_SLOTS_GROWTH_FACTOR"); -+ if (heap_slots_growth_factor_ptr != NULL) { -+ double heap_slots_growth_factor_d = atoi(heap_slots_growth_factor_ptr); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_GROWTH_FACTOR=%s\n", heap_slots_growth_factor_ptr); -+ } -+ if (heap_slots_growth_factor_d > 0) { -+ heap_slots_growth_factor = heap_slots_growth_factor_d; -+ } -+ } -+ -+ malloc_limit_ptr = getenv("RUBY_GC_MALLOC_LIMIT"); -+ if (malloc_limit_ptr != NULL) { -+ int malloc_limit_i = atol(malloc_limit_ptr); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_GC_MALLOC_LIMIT=%s\n", malloc_limit_ptr); -+ } -+ if (malloc_limit_i > 0) { -+ initial_malloc_limit = malloc_limit_i; -+ } -+ } -+} -+ -+/* -+ * call-seq: -+ * GC.dump => nil -+ * -+ * dumps information about the current GC data structures to the GC log file -+ * -+ * GC.dump #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_dump() -+{ -+ int i; -+ -+ for (i = 0; i < heaps_used; i++) { -+ int heap_size = heaps[i].limit; -+ fprintf(gc_data_file, "HEAP[%2d]: size=%7d\n", i, heap_size); -+ } -+ -+ return Qnil; -+} -+ -+/* -+ * call-seq: -+ * GC.log String => String -+ * -+ * Logs string to the GC data file and returns it. -+ * -+ * GC.log "manual GC call" #=> "manual GC call" -+ * -+ */ -+ -+VALUE -+rb_gc_log(self, original_str) -+ VALUE self, original_str; -+{ -+ if (original_str == Qnil) { -+ fprintf(gc_data_file, "\n"); -+ } -+ else { -+ VALUE str = StringValue(original_str); -+ char *p = RSTRING(str)->ptr; -+ fprintf(gc_data_file, "%s\n", p); -+ } -+ return original_str; -+} -+ -+ - static void - add_heap() - { - RVALUE *p, *pend; - - if (heaps_used == heaps_length) { -- /* Realloc heaps */ -- struct heaps_slot *p; -- int length; -- -- heaps_length += HEAPS_INCREMENT; -- length = heaps_length*sizeof(struct heaps_slot); -- RUBY_CRITICAL( -- if (heaps_used > 0) { -- p = (struct heaps_slot *)realloc(heaps, length); -- if (p) heaps = p; -- } -- else { -- p = heaps = (struct heaps_slot *)malloc(length); -- }); -- if (p == 0) rb_memerror(); -+ /* Realloc heaps */ -+ struct heaps_slot *p; -+ int length; -+ -+ heaps_length += heaps_increment; -+ length = heaps_length*sizeof(struct heaps_slot); -+ RUBY_CRITICAL( -+ if (heaps_used > 0) { -+ p = (struct heaps_slot *)realloc(heaps, length); -+ if (p) heaps = p; -+ } -+ else { -+ p = heaps = (struct heaps_slot *)malloc(length); -+ }); -+ if (p == 0) rb_memerror(); - } - - for (;;) { -- RUBY_CRITICAL(p = (RVALUE*)malloc(sizeof(RVALUE)*(heap_slots+1))); -- if (p == 0) { -- if (heap_slots == HEAP_MIN_SLOTS) { -- rb_memerror(); -- } -- heap_slots = HEAP_MIN_SLOTS; -- continue; -- } -+ RUBY_CRITICAL(p = (RVALUE*)malloc(sizeof(RVALUE)*(heap_slots+1))); -+ if (p == 0) { -+ if (heap_slots == heap_min_slots) { -+ rb_memerror(); -+ } -+ heap_slots = heap_min_slots; -+ continue; -+ } - heaps[heaps_used].membase = p; - if ((VALUE)p % sizeof(RVALUE) == 0) - heap_slots += 1; -@@ -401,25 +667,26 @@ add_heap() - p = (RVALUE*)((VALUE)p + sizeof(RVALUE) - ((VALUE)p % sizeof(RVALUE))); - heaps[heaps_used].slot = p; - heaps[heaps_used].limit = heap_slots; -- break; -+ break; - } - pend = p + heap_slots; - if (lomem == 0 || lomem > p) lomem = p; - if (himem < pend) himem = pend; - heaps_used++; -- heap_slots *= 1.8; -- if (heap_slots <= 0) heap_slots = HEAP_MIN_SLOTS; -+ heap_slots += heap_slots_increment; -+ heap_slots_increment *= heap_slots_growth_factor; -+ if (heap_slots <= 0) heap_slots = heap_min_slots; - - while (p < pend) { -- p->as.free.flags = 0; -- p->as.free.next = freelist; -- freelist = p; -- p++; -+ p->as.free.flags = 0; -+ p->as.free.next = freelist; -+ freelist = p; -+ p++; - } - } - #define RANY(o) ((RVALUE*)(o)) - --int -+int - rb_during_gc() - { - return during_gc; -@@ -431,7 +698,7 @@ rb_newobj() - VALUE obj; - - if (during_gc) -- rb_bug("object allocation during garbage collection phase"); -+ rb_bug("object allocation during garbage collection phase"); - - if (ruby_gc_stress || !freelist) garbage_collect(); - -@@ -580,13 +847,13 @@ rb_source_filename(f) - st_data_t name; - - if (!st_lookup(source_filenames, (st_data_t)f, &name)) { -- long len = strlen(f) + 1; -- char *ptr = ALLOC_N(char, len + 1); -- name = (st_data_t)ptr; -- *ptr++ = 0; -- MEMCPY(ptr, f, char, len); -- st_add_direct(source_filenames, (st_data_t)ptr, name); -- return ptr; -+ long len = strlen(f) + 1; -+ char *ptr = ALLOC_N(char, len + 1); -+ name = (st_data_t)ptr; -+ *ptr++ = 0; -+ MEMCPY(ptr, f, char, len); -+ st_add_direct(source_filenames, (st_data_t)ptr, name); -+ return ptr; - } - return (char *)name + 1; - } -@@ -596,7 +863,7 @@ mark_source_filename(f) - char *f; - { - if (f) { -- f[-1] = 1; -+ f[-1] = 1; - } - } - -@@ -605,12 +872,12 @@ sweep_source_filename(key, value) - char *key, *value; - { - if (*value) { -- *value = 0; -- return ST_CONTINUE; -+ *value = 0; -+ return ST_CONTINUE; - } - else { -- free(value); -- return ST_DELETE; -+ free(value); -+ return ST_DELETE; - } - } - -@@ -625,14 +892,14 @@ gc_mark_all() - - init_mark_stack(); - for (i = 0; i < heaps_used; i++) { -- p = heaps[i].slot; pend = p + heaps[i].limit; -- while (p < pend) { -- if ((p->as.basic.flags & FL_MARK) && -- (p->as.basic.flags != FL_MARK)) { -- gc_mark_children((VALUE)p, 0); -- } -- p++; -- } -+ p = heaps[i].slot; pend = p + heaps[i].limit; -+ while (p < pend) { -+ if ((p->as.basic.flags & FL_MARK) && -+ (p->as.basic.flags != FL_MARK)) { -+ gc_mark_children((VALUE)p, 0); -+ } -+ p++; -+ } - } - } - -@@ -647,8 +914,8 @@ gc_mark_rest() - - init_mark_stack(); - while(p != tmp_arry){ -- p--; -- gc_mark_children(*p, 0); -+ p--; -+ gc_mark_children(*p, 0); - } - } - -@@ -665,9 +932,9 @@ is_pointer_to_heap(ptr) - - /* check if p looks like a pointer */ - for (i=0; i < heaps_used; i++) { -- heap_org = heaps[i].slot; -- if (heap_org <= p && p < heap_org + heaps[i].limit) -- return Qtrue; -+ heap_org = heaps[i].slot; -+ if (heap_org <= p && p < heap_org + heaps[i].limit) -+ return Qtrue; - } - return Qfalse; - } -@@ -680,10 +947,10 @@ mark_locations_array(x, n) - VALUE v; - while (n--) { - v = *x; -- if (is_pointer_to_heap((void *)v)) { -- gc_mark(v, 0); -- } -- x++; -+ if (is_pointer_to_heap((void *)v)) { -+ gc_mark(v, 0); -+ } -+ x++; - } - } - -@@ -780,7 +1047,7 @@ rb_gc_mark_maybe(obj) - VALUE obj; - { - if (is_pointer_to_heap((void *)obj)) { -- gc_mark(obj, 0); -+ gc_mark(obj, 0); - } - } - -@@ -828,7 +1095,7 @@ gc_mark_children(ptr, lev) - { - register RVALUE *obj = RANY(ptr); - -- goto marking; /* skip */ -+ goto marking; /* skip */ - - again: - obj = RANY(ptr); -@@ -839,148 +1106,148 @@ gc_mark_children(ptr, lev) - - marking: - if (FL_TEST(obj, FL_EXIVAR)) { -- rb_mark_generic_ivar(ptr); -+ rb_mark_generic_ivar(ptr); - } - - switch (obj->as.basic.flags & T_MASK) { - case T_NIL: - case T_FIXNUM: -- rb_bug("rb_gc_mark() called for broken object"); -- break; -+ rb_bug("rb_gc_mark() called for broken object"); -+ break; - - case T_NODE: -- mark_source_filename(obj->as.node.nd_file); -- switch (nd_type(obj)) { -- case NODE_IF: /* 1,2,3 */ -- case NODE_FOR: -- case NODE_ITER: -- case NODE_CREF: -- case NODE_WHEN: -- case NODE_MASGN: -- case NODE_RESCUE: -- case NODE_RESBODY: -- case NODE_CLASS: -- gc_mark((VALUE)obj->as.node.u2.node, lev); -- /* 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_FBODY: -- case NODE_ENSURE: -- case NODE_CALL: -- case NODE_DEFS: -- case NODE_OP_ASGN1: -- gc_mark((VALUE)obj->as.node.u1.node, lev); -- /* fall through */ -- case NODE_SUPER: /* 3 */ -- case NODE_FCALL: -- case NODE_DEFN: -- case NODE_NEWLINE: -- ptr = (VALUE)obj->as.node.u3.node; -- goto again; -- -- 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_ARGS: -- gc_mark((VALUE)obj->as.node.u1.node, lev); -- /* fall through */ -- case NODE_METHOD: /* 2 */ -- case NODE_NOT: -- case NODE_GASGN: -- case NODE_LASGN: -- case NODE_DASGN: -- case NODE_DASGN_CURR: -- case NODE_IASGN: -- case NODE_CVDECL: -- case NODE_CVASGN: -- case NODE_COLON3: -- case NODE_OPT_N: -- case NODE_EVSTR: -- case NODE_UNDEF: -- ptr = (VALUE)obj->as.node.u2.node; -- goto again; -- -- 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: -- case NODE_SVALUE: -- ptr = (VALUE)obj->as.node.u1.node; -- goto again; -- -- case NODE_SCOPE: /* 2,3 */ -- case NODE_BLOCK_PASS: -- case NODE_CDECL: -- gc_mark((VALUE)obj->as.node.u3.node, lev); -- ptr = (VALUE)obj->as.node.u2.node; -- goto again; -- -- case NODE_ZARRAY: /* - */ -- case NODE_ZSUPER: -- case NODE_CFUNC: -- 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_ATTRSET: -- case NODE_BLOCK_ARG: -- case NODE_POSTEXE: -- break; -- case NODE_ALLOCA: -- mark_locations_array((VALUE*)obj->as.node.u1.value, -- obj->as.node.u3.cnt); -- ptr = (VALUE)obj->as.node.u2.node; -- goto again; -- -- default: /* unlisted NODE */ -- if (is_pointer_to_heap(obj->as.node.u1.node)) { -- gc_mark((VALUE)obj->as.node.u1.node, lev); -- } -- if (is_pointer_to_heap(obj->as.node.u2.node)) { -- gc_mark((VALUE)obj->as.node.u2.node, lev); -- } -- if (is_pointer_to_heap(obj->as.node.u3.node)) { -- gc_mark((VALUE)obj->as.node.u3.node, lev); -- } -- } -- return; /* no need to mark class. */ -+ mark_source_filename(obj->as.node.nd_file); -+ switch (nd_type(obj)) { -+ case NODE_IF: /* 1,2,3 */ -+ case NODE_FOR: -+ case NODE_ITER: -+ case NODE_CREF: -+ case NODE_WHEN: -+ case NODE_MASGN: -+ case NODE_RESCUE: -+ case NODE_RESBODY: -+ case NODE_CLASS: -+ gc_mark((VALUE)obj->as.node.u2.node, lev); -+ /* 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_FBODY: -+ case NODE_ENSURE: -+ case NODE_CALL: -+ case NODE_DEFS: -+ case NODE_OP_ASGN1: -+ gc_mark((VALUE)obj->as.node.u1.node, lev); -+ /* fall through */ -+ case NODE_SUPER: /* 3 */ -+ case NODE_FCALL: -+ case NODE_DEFN: -+ case NODE_NEWLINE: -+ ptr = (VALUE)obj->as.node.u3.node; -+ goto again; -+ -+ 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_ARGS: -+ gc_mark((VALUE)obj->as.node.u1.node, lev); -+ /* fall through */ -+ case NODE_METHOD: /* 2 */ -+ case NODE_NOT: -+ case NODE_GASGN: -+ case NODE_LASGN: -+ case NODE_DASGN: -+ case NODE_DASGN_CURR: -+ case NODE_IASGN: -+ case NODE_CVDECL: -+ case NODE_CVASGN: -+ case NODE_COLON3: -+ case NODE_OPT_N: -+ case NODE_EVSTR: -+ case NODE_UNDEF: -+ ptr = (VALUE)obj->as.node.u2.node; -+ goto again; -+ -+ 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: -+ case NODE_SVALUE: -+ ptr = (VALUE)obj->as.node.u1.node; -+ goto again; -+ -+ case NODE_SCOPE: /* 2,3 */ -+ case NODE_BLOCK_PASS: -+ case NODE_CDECL: -+ gc_mark((VALUE)obj->as.node.u3.node, lev); -+ ptr = (VALUE)obj->as.node.u2.node; -+ goto again; -+ -+ case NODE_ZARRAY: /* - */ -+ case NODE_ZSUPER: -+ case NODE_CFUNC: -+ 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_ATTRSET: -+ case NODE_BLOCK_ARG: -+ case NODE_POSTEXE: -+ break; -+ case NODE_ALLOCA: -+ mark_locations_array((VALUE*)obj->as.node.u1.value, -+ obj->as.node.u3.cnt); -+ ptr = (VALUE)obj->as.node.u2.node; -+ goto again; -+ -+ default: /* unlisted NODE */ -+ if (is_pointer_to_heap(obj->as.node.u1.node)) { -+ gc_mark((VALUE)obj->as.node.u1.node, lev); -+ } -+ if (is_pointer_to_heap(obj->as.node.u2.node)) { -+ gc_mark((VALUE)obj->as.node.u2.node, lev); -+ } -+ if (is_pointer_to_heap(obj->as.node.u3.node)) { -+ gc_mark((VALUE)obj->as.node.u3.node, lev); -+ } -+ } -+ return; /* no need to mark class. */ - } - - gc_mark(obj->as.basic.klass, lev); -@@ -988,92 +1255,92 @@ gc_mark_children(ptr, lev) - case T_ICLASS: - case T_CLASS: - case T_MODULE: -- mark_tbl(obj->as.klass.m_tbl, lev); -- mark_tbl(obj->as.klass.iv_tbl, lev); -- ptr = obj->as.klass.super; -- goto again; -+ mark_tbl(obj->as.klass.m_tbl, lev); -+ mark_tbl(obj->as.klass.iv_tbl, lev); -+ ptr = obj->as.klass.super; -+ goto again; - - case T_ARRAY: -- if (FL_TEST(obj, ELTS_SHARED)) { -- ptr = obj->as.array.aux.shared; -- goto again; -- } -- else { -- long i, len = obj->as.array.len; -- VALUE *ptr = obj->as.array.ptr; -+ if (FL_TEST(obj, ELTS_SHARED)) { -+ ptr = obj->as.array.aux.shared; -+ goto again; -+ } -+ else { -+ long i, len = obj->as.array.len; -+ VALUE *ptr = obj->as.array.ptr; - -- for (i=0; i < len; i++) { -- gc_mark(*ptr++, lev); -- } -- } -- break; -+ for (i=0; i < len; i++) { -+ gc_mark(*ptr++, lev); -+ } -+ } -+ break; - - case T_HASH: -- mark_hash(obj->as.hash.tbl, lev); -- ptr = obj->as.hash.ifnone; -- goto again; -+ mark_hash(obj->as.hash.tbl, lev); -+ ptr = obj->as.hash.ifnone; -+ goto again; - - case T_STRING: - #define STR_ASSOC FL_USER3 /* copied from string.c */ -- if (FL_TEST(obj, ELTS_SHARED|STR_ASSOC)) { -- ptr = obj->as.string.aux.shared; -- goto again; -- } -- break; -+ if (FL_TEST(obj, ELTS_SHARED|STR_ASSOC)) { -+ ptr = obj->as.string.aux.shared; -+ goto again; -+ } -+ break; - - case T_DATA: -- if (obj->as.data.dmark) (*obj->as.data.dmark)(DATA_PTR(obj)); -- break; -+ if (obj->as.data.dmark) (*obj->as.data.dmark)(DATA_PTR(obj)); -+ break; - - case T_OBJECT: -- mark_tbl(obj->as.object.iv_tbl, lev); -- break; -+ mark_tbl(obj->as.object.iv_tbl, lev); -+ break; - - case T_FILE: - case T_REGEXP: - case T_FLOAT: - case T_BIGNUM: - case T_BLKTAG: -- break; -+ break; - - case T_MATCH: -- if (obj->as.match.str) { -- ptr = obj->as.match.str; -- goto again; -- } -- break; -+ if (obj->as.match.str) { -+ ptr = obj->as.match.str; -+ goto again; -+ } -+ break; - - case T_VARMAP: -- gc_mark(obj->as.varmap.val, lev); -- ptr = (VALUE)obj->as.varmap.next; -- goto again; -+ gc_mark(obj->as.varmap.val, lev); -+ ptr = (VALUE)obj->as.varmap.next; -+ goto again; - - case T_SCOPE: -- if (obj->as.scope.local_vars && (obj->as.scope.flags & SCOPE_MALLOC)) { -- int n = obj->as.scope.local_tbl[0]+1; -- VALUE *vars = &obj->as.scope.local_vars[-1]; -+ if (obj->as.scope.local_vars && (obj->as.scope.flags & SCOPE_MALLOC)) { -+ int n = obj->as.scope.local_tbl[0]+1; -+ VALUE *vars = &obj->as.scope.local_vars[-1]; - -- while (n--) { -- gc_mark(*vars++, lev); -- } -- } -- break; -+ while (n--) { -+ gc_mark(*vars++, lev); -+ } -+ } -+ break; - - case T_STRUCT: -- { -- long len = obj->as.rstruct.len; -- VALUE *ptr = obj->as.rstruct.ptr; -+ { -+ long len = obj->as.rstruct.len; -+ VALUE *ptr = obj->as.rstruct.ptr; - -- while (len--) { -- gc_mark(*ptr++, lev); -- } -- } -- break; -+ while (len--) { -+ gc_mark(*ptr++, lev); -+ } -+ } -+ break; - - default: -- rb_bug("rb_gc_mark(): unknown data type 0x%lx(0x%lx) %s", -- obj->as.basic.flags & T_MASK, obj, -- is_pointer_to_heap(obj) ? "corrupted object" : "non object"); -+ rb_bug("rb_gc_mark(): unknown data type 0x%lx(0x%lx) %s", -+ obj->as.basic.flags & T_MASK, obj, -+ is_pointer_to_heap(obj) ? "corrupted object" : "non object"); - } - } - -@@ -1102,22 +1369,55 @@ finalize_list(p) - } - } - -+static char* obj_type(int tp) -+{ -+ switch (tp) { -+ case T_NIL : return "NIL"; -+ case T_OBJECT : return "OBJECT"; -+ case T_CLASS : return "CLASS"; -+ case T_ICLASS : return "ICLASS"; -+ case T_MODULE : return "MODULE"; -+ case T_FLOAT : return "FLOAT"; -+ case T_STRING : return "STRING"; -+ case T_REGEXP : return "REGEXP"; -+ case T_ARRAY : return "ARRAY"; -+ case T_FIXNUM : return "FIXNUM"; -+ case T_HASH : return "HASH"; -+ case T_STRUCT : return "STRUCT"; -+ case T_BIGNUM : return "BIGNUM"; -+ case T_FILE : return "FILE"; -+ -+ case T_TRUE : return "TRUE"; -+ case T_FALSE : return "FALSE"; -+ case T_DATA : return "DATA"; -+ case T_MATCH : return "MATCH"; -+ case T_SYMBOL : return "SYMBOL"; -+ -+ case T_BLKTAG : return "BLKTAG"; -+ case T_UNDEF : return "UNDEF"; -+ case T_VARMAP : return "VARMAP"; -+ case T_SCOPE : return "SCOPE"; -+ case T_NODE : return "NODE"; -+ default: return "____"; -+ } -+} -+ - static void - free_unused_heaps() - { - int i, j; - - for (i = j = 1; j < heaps_used; i++) { -- if (heaps[i].limit == 0) { -- free(heaps[i].membase); -- heaps_used--; -- } -- else { -- if (i != j) { -- heaps[j] = heaps[i]; -- } -- j++; -- } -+ if (heaps[i].limit == 0) { -+ free(heaps[i].membase); -+ heaps_used--; -+ } -+ else { -+ if (i != j) { -+ heaps[j] = heaps[i]; -+ } -+ j++; -+ } - } - } - -@@ -1134,24 +1434,33 @@ gc_sweep() - unsigned long live = 0; - unsigned long free_min = 0; - -+ unsigned long really_freed = 0; -+ int free_counts[256]; -+ int live_counts[256]; -+ int do_gc_stats = gc_statistics & verbose_gc_stats; -+ - for (i = 0; i < heaps_used; i++) { - free_min += heaps[i].limit; - } - free_min = free_min * 0.2; -- if (free_min < FREE_MIN) -- free_min = FREE_MIN; -+ if (free_min < heap_free_min) -+ free_min = heap_free_min; -+ -+ if (do_gc_stats) { -+ for (i = 0 ; i< 256; i++) { free_counts[i] = live_counts[i] = 0; } -+ } - - if (ruby_in_compile && ruby_parser_stack_on_heap()) { -- /* should not reclaim nodes during compilation -+ /* should not reclaim nodes during compilation - if yacc's semantic stack is not allocated on machine stack */ -- for (i = 0; i < heaps_used; i++) { -- p = heaps[i].slot; pend = p + heaps[i].limit; -- while (p < pend) { -- if (!(p->as.basic.flags&FL_MARK) && BUILTIN_TYPE(p) == T_NODE) -- gc_mark((VALUE)p, 0); -- p++; -- } -- } -+ for (i = 0; i < heaps_used; i++) { -+ p = heaps[i].slot; pend = p + heaps[i].limit; -+ while (p < pend) { -+ if (!(p->as.basic.flags&FL_MARK) && BUILTIN_TYPE(p) == T_NODE) -+ gc_mark((VALUE)p, 0); -+ p++; -+ } -+ } - } - - mark_source_filename(ruby_sourcefile); -@@ -1172,7 +1481,7 @@ gc_sweep() - while (p < pend) { - if (!(p->as.basic.flags & FL_MARK)) { - if (p->as.basic.flags && -- ((deferred = obj_free((VALUE)p)) || -+ (((do_gc_stats && really_freed++), deferred = obj_free((VALUE)p)) || - ((FL_TEST(p, FL_FINALIZE)) && need_call_final))) { - if (!deferred) { - p->as.free.flags = T_DEFERRED; -@@ -1183,6 +1492,12 @@ gc_sweep() - final_list = p; - } - else { -+ if (do_gc_stats) { -+ int obt = p->as.basic.flags & T_MASK; -+ if (obt) { -+ free_counts[obt]++; -+ } -+ } - add_freelist(p); - } - n++; -@@ -1194,6 +1509,9 @@ gc_sweep() - else { - RBASIC(p)->flags &= ~FL_MARK; - live++; -+ if (do_gc_stats) { -+ live_counts[RANY((VALUE)p)->as.basic.flags & T_MASK]++; -+ } - } - p++; - } -@@ -1211,15 +1529,29 @@ gc_sweep() - } - } - if (malloc_increase > malloc_limit) { -- malloc_limit += (malloc_increase - malloc_limit) * (double)live / (live + freed); -- if (malloc_limit < GC_MALLOC_LIMIT) malloc_limit = GC_MALLOC_LIMIT; -+ malloc_limit += (malloc_increase - malloc_limit) * (double)live / (live + freed); -+ if (malloc_limit < initial_malloc_limit) malloc_limit = initial_malloc_limit; - } - malloc_increase = 0; - if (freed < free_min) { -- add_heap(); -+ add_heap(); - } - during_gc = 0; - -+ if (do_gc_stats) { -+ fprintf(gc_data_file, "objects processed: %.7d\n", live+freed); -+ fprintf(gc_data_file, "live objects : %.7d\n", live); -+ fprintf(gc_data_file, "freelist objects : %.7d\n", freed - really_freed); -+ fprintf(gc_data_file, "freed objects : %.7d\n", really_freed); -+ for(i=0; i<256; i++) { -+ if (free_counts[i]>0 || live_counts[i]>0) { -+ fprintf(gc_data_file, -+ "kept %.7d / freed %.7d objects of type %s\n", -+ live_counts[i], free_counts[i], obj_type(i)); -+ } -+ } -+ } -+ - /* clear finalization list */ - if (final_list) { - deferred_final_list = final_list; -@@ -1260,51 +1592,51 @@ obj_free(obj) - case T_FIXNUM: - case T_TRUE: - case T_FALSE: -- rb_bug("obj_free() called for broken object"); -- break; -+ rb_bug("obj_free() called for broken object"); -+ break; - } - - if (FL_TEST(obj, FL_EXIVAR)) { -- rb_free_generic_ivar((VALUE)obj); -+ rb_free_generic_ivar((VALUE)obj); - } - - switch (BUILTIN_TYPE(obj)) { - case T_OBJECT: -- if (RANY(obj)->as.object.iv_tbl) { -- st_free_table(RANY(obj)->as.object.iv_tbl); -- } -- break; -+ if (RANY(obj)->as.object.iv_tbl) { -+ st_free_table(RANY(obj)->as.object.iv_tbl); -+ } -+ break; - case T_MODULE: - case T_CLASS: -- rb_clear_cache_by_class((VALUE)obj); -- st_free_table(RANY(obj)->as.klass.m_tbl); -- if (RANY(obj)->as.object.iv_tbl) { -- st_free_table(RANY(obj)->as.object.iv_tbl); -- } -- break; -+ rb_clear_cache_by_class((VALUE)obj); -+ st_free_table(RANY(obj)->as.klass.m_tbl); -+ if (RANY(obj)->as.object.iv_tbl) { -+ st_free_table(RANY(obj)->as.object.iv_tbl); -+ } -+ break; - case T_STRING: -- if (RANY(obj)->as.string.ptr && !FL_TEST(obj, ELTS_SHARED)) { -- RUBY_CRITICAL(free(RANY(obj)->as.string.ptr)); -- } -- break; -+ if (RANY(obj)->as.string.ptr && !FL_TEST(obj, ELTS_SHARED)) { -+ RUBY_CRITICAL(free(RANY(obj)->as.string.ptr)); -+ } -+ break; - case T_ARRAY: -- if (RANY(obj)->as.array.ptr && !FL_TEST(obj, ELTS_SHARED)) { -- RUBY_CRITICAL(free(RANY(obj)->as.array.ptr)); -- } -- break; -+ if (RANY(obj)->as.array.ptr && !FL_TEST(obj, ELTS_SHARED)) { -+ RUBY_CRITICAL(free(RANY(obj)->as.array.ptr)); -+ } -+ break; - case T_HASH: -- if (RANY(obj)->as.hash.tbl) { -- st_free_table(RANY(obj)->as.hash.tbl); -- } -- break; -+ if (RANY(obj)->as.hash.tbl) { -+ st_free_table(RANY(obj)->as.hash.tbl); -+ } -+ break; - case T_REGEXP: -- if (RANY(obj)->as.regexp.ptr) { -- re_free_pattern(RANY(obj)->as.regexp.ptr); -- } -- if (RANY(obj)->as.regexp.str) { -- RUBY_CRITICAL(free(RANY(obj)->as.regexp.str)); -- } -- break; -+ if (RANY(obj)->as.regexp.ptr) { -+ re_free_pattern(RANY(obj)->as.regexp.ptr); -+ } -+ if (RANY(obj)->as.regexp.str) { -+ RUBY_CRITICAL(free(RANY(obj)->as.regexp.str)); -+ } -+ break; - case T_DATA: - if (DATA_PTR(obj)) { - if ((long)RANY(obj)->as.data.dfree == -1) { -@@ -1317,11 +1649,11 @@ obj_free(obj) - } - break; - case T_MATCH: -- if (RANY(obj)->as.match.regs) { -- re_free_registers(RANY(obj)->as.match.regs); -- RUBY_CRITICAL(free(RANY(obj)->as.match.regs)); -- } -- break; -+ if (RANY(obj)->as.match.regs) { -+ re_free_registers(RANY(obj)->as.match.regs); -+ RUBY_CRITICAL(free(RANY(obj)->as.match.regs)); -+ } -+ break; - case T_FILE: - if (RANY(obj)->as.file.fptr) { - struct rb_io_t *fptr = RANY(obj)->as.file.fptr; -@@ -1332,19 +1664,19 @@ obj_free(obj) - } - break; - case T_ICLASS: -- /* iClass shares table with the module */ -- break; -+ /* iClass shares table with the module */ -+ break; - - case T_FLOAT: - case T_VARMAP: - case T_BLKTAG: -- break; -+ break; - - case T_BIGNUM: -- if (RANY(obj)->as.bignum.digits) { -- RUBY_CRITICAL(free(RANY(obj)->as.bignum.digits)); -- } -- break; -+ if (RANY(obj)->as.bignum.digits) { -+ RUBY_CRITICAL(free(RANY(obj)->as.bignum.digits)); -+ } -+ break; - case T_NODE: - switch (nd_type(obj)) { - case NODE_SCOPE: -@@ -1359,7 +1691,7 @@ obj_free(obj) - break; /* no need to free iv_tbl */ - - case T_SCOPE: -- if (RANY(obj)->as.scope.local_vars && -+ if (RANY(obj)->as.scope.local_vars && - RANY(obj)->as.scope.flags != SCOPE_ALLOCA) { - VALUE *vars = RANY(obj)->as.scope.local_vars-1; - if (!(RANY(obj)->as.scope.flags & SCOPE_CLONE) && vars[0] == 0) -@@ -1370,14 +1702,14 @@ obj_free(obj) - break; - - case T_STRUCT: -- if (RANY(obj)->as.rstruct.ptr) { -- RUBY_CRITICAL(free(RANY(obj)->as.rstruct.ptr)); -- } -- break; -+ if (RANY(obj)->as.rstruct.ptr) { -+ RUBY_CRITICAL(free(RANY(obj)->as.rstruct.ptr)); -+ } -+ break; - - default: -- rb_bug("gc_sweep(): unknown data type 0x%lx(0x%lx)", -- RANY(obj)->as.basic.flags & T_MASK, obj); -+ rb_bug("gc_sweep(): unknown data type 0x%lx(0x%lx)", -+ RANY(obj)->as.basic.flags & T_MASK, obj); - } - - return 0; -@@ -1407,18 +1739,18 @@ _rb_setjmp:\n\ - typedef unsigned long rb_jmp_buf[6]; - __asm__ (".align 4\n\ - _rb_setjmp:\n\ -- pushl %ebp\n\ -- movl %esp,%ebp\n\ -- movl 8(%ebp),%ebp\n\ -- movl %eax,(%ebp)\n\ -- movl %ebx,4(%ebp)\n\ -- movl %ecx,8(%ebp)\n\ -- movl %edx,12(%ebp)\n\ -- movl %esi,16(%ebp)\n\ -- movl %edi,20(%ebp)\n\ -- popl %ebp\n\ -- xorl %eax,%eax\n\ -- ret"); -+ pushl %ebp\n\ -+ movl %esp,%ebp\n\ -+ movl 8(%ebp),%ebp\n\ -+ movl %eax,(%ebp)\n\ -+ movl %ebx,4(%ebp)\n\ -+ movl %ecx,8(%ebp)\n\ -+ movl %edx,12(%ebp)\n\ -+ movl %esi,16(%ebp)\n\ -+ movl %edi,20(%ebp)\n\ -+ popl %ebp\n\ -+ xorl %eax,%eax\n\ -+ ret"); - #endif - #endif - int rb_setjmp (rb_jmp_buf); -@@ -1431,41 +1763,50 @@ garbage_collect() - struct gc_list *list; - struct FRAME * volatile frame; /* gcc 2.7.2.3 -O2 bug?? */ - jmp_buf save_regs_gc_mark; -+ struct timeval gctv1, gctv2; - SET_STACK_END; - - #ifdef HAVE_NATIVETHREAD - if (!is_ruby_native_thread()) { -- rb_bug("cross-thread violation on rb_gc()"); -+ rb_bug("cross-thread violation on rb_gc()"); - } - #endif - if (dont_gc || during_gc) { -- if (!freelist) { -- add_heap(); -- } -- return; -+ if (!freelist) { -+ add_heap(); -+ } -+ return; - } - if (during_gc) return; - during_gc++; - -+ if (gc_statistics) { -+ gc_collections++; -+ gettimeofday(&gctv1, NULL); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "Garbage collection started\n"); -+ } -+ } -+ - init_mark_stack(); - - gc_mark((VALUE)ruby_current_node, 0); - - /* mark frame stack */ - for (frame = ruby_frame; frame; frame = frame->prev) { -- rb_gc_mark_frame(frame); -- if (frame->tmp) { -- struct FRAME *tmp = frame->tmp; -- while (tmp) { -- rb_gc_mark_frame(tmp); -- tmp = tmp->prev; -- } -- } -+ rb_gc_mark_frame(frame); -+ if (frame->tmp) { -+ struct FRAME *tmp = frame->tmp; -+ while (tmp) { -+ rb_gc_mark_frame(tmp); -+ tmp = tmp->prev; -+ } -+ } - } - gc_mark((VALUE)ruby_scope, 0); - gc_mark((VALUE)ruby_dyna_vars, 0); - if (finalizer_table) { -- mark_tbl(finalizer_table, 0); -+ mark_tbl(finalizer_table, 0); - } - - FLUSH_REGISTER_WINDOWS; -@@ -1478,9 +1819,9 @@ garbage_collect() - rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)STACK_END + 1); - #else - if ((VALUE*)STACK_END < rb_gc_stack_start) -- rb_gc_mark_locations((VALUE*)STACK_END, rb_gc_stack_start); -+ rb_gc_mark_locations((VALUE*)STACK_END, rb_gc_stack_start); - else -- rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)STACK_END + 1); -+ rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)STACK_END + 1); - #endif - #ifdef __ia64 - /* mark backing store (flushed register window on the stack) */ -@@ -1489,13 +1830,13 @@ garbage_collect() - #endif - #if defined(__human68k__) || defined(__mc68000__) - rb_gc_mark_locations((VALUE*)((char*)STACK_END + 2), -- (VALUE*)((char*)rb_gc_stack_start + 2)); -+ (VALUE*)((char*)rb_gc_stack_start + 2)); - #endif - rb_gc_mark_threads(); - - /* mark protected global variables */ - for (list = global_List; list; list = list->next) { -- rb_gc_mark_maybe(*list->varptr); -+ rb_gc_mark_maybe(*list->varptr); - } - rb_mark_end_proc(); - rb_gc_mark_global_tbl(); -@@ -1510,18 +1851,30 @@ garbage_collect() - - /* gc_mark objects whose marking are not completed*/ - do { -- while (!MARK_STACK_EMPTY) { -- if (mark_stack_overflow){ -- gc_mark_all(); -- } -- else { -- gc_mark_rest(); -- } -- } -- rb_gc_abort_threads(); -+ while (!MARK_STACK_EMPTY) { -+ if (mark_stack_overflow){ -+ gc_mark_all(); -+ } -+ else { -+ gc_mark_rest(); -+ } -+ } -+ rb_gc_abort_threads(); - } while (!MARK_STACK_EMPTY); - - gc_sweep(); -+ -+ if (gc_statistics) { -+ GC_TIME_TYPE musecs_used; -+ gettimeofday(&gctv2, NULL); -+ musecs_used = ((GC_TIME_TYPE)(gctv2.tv_sec - gctv1.tv_sec) * 1000000) + (gctv2.tv_usec - gctv1.tv_usec); -+ gc_time += musecs_used; -+ -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "GC time: %d msec\n", musecs_used / 1000); -+ fflush(gc_data_file); -+ } -+ } - } - - void -@@ -1588,8 +1941,8 @@ Init_stack(addr) - memset(&m, 0, sizeof(m)); - VirtualQuery(&m, &m, sizeof(m)); - rb_gc_stack_start = -- STACK_UPPER((VALUE *)&m, (VALUE *)m.BaseAddress, -- (VALUE *)((char *)m.BaseAddress + m.RegionSize) - 1); -+ STACK_UPPER((VALUE *)&m, (VALUE *)m.BaseAddress, -+ (VALUE *)((char *)m.BaseAddress + m.RegionSize) - 1); - #elif defined(STACK_END_ADDRESS) - { - extern void *STACK_END_ADDRESS; -@@ -1599,24 +1952,24 @@ Init_stack(addr) - if (!addr) addr = (void *)&addr; - STACK_UPPER(&addr, addr, ++addr); - if (rb_gc_stack_start) { -- if (STACK_UPPER(&addr, -- rb_gc_stack_start > addr, -- rb_gc_stack_start < addr)) -- rb_gc_stack_start = addr; -- return; -+ if (STACK_UPPER(&addr, -+ rb_gc_stack_start > addr, -+ rb_gc_stack_start < addr)) -+ rb_gc_stack_start = addr; -+ return; - } - rb_gc_stack_start = addr; - #endif - #ifdef HAVE_GETRLIMIT - { -- struct rlimit rlim; -+ struct rlimit rlim; - -- if (getrlimit(RLIMIT_STACK, &rlim) == 0) { -- unsigned int space = rlim.rlim_cur/5; -+ if (getrlimit(RLIMIT_STACK, &rlim) == 0) { -+ unsigned int space = rlim.rlim_cur/5; - -- if (space > 1024*1024) space = 1024*1024; -- STACK_LEVEL_MAX = (rlim.rlim_cur - space) / sizeof(VALUE); -- } -+ if (space > 1024*1024) space = 1024*1024; -+ STACK_LEVEL_MAX = (rlim.rlim_cur - space) / sizeof(VALUE); -+ } - } - #endif - } -@@ -1652,16 +2005,16 @@ void ruby_init_stack(VALUE *addr - } - #elif defined _WIN32 - { -- MEMORY_BASIC_INFORMATION mi; -- DWORD size; -- DWORD space; -- -- if (VirtualQuery(&mi, &mi, sizeof(mi))) { -- size = (char *)mi.BaseAddress - (char *)mi.AllocationBase; -- space = size / 5; -- if (space > 1024*1024) space = 1024*1024; -- STACK_LEVEL_MAX = (size - space) / sizeof(VALUE); -- } -+ MEMORY_BASIC_INFORMATION mi; -+ DWORD size; -+ DWORD space; -+ -+ if (VirtualQuery(&mi, &mi, sizeof(mi))) { -+ size = (char *)mi.BaseAddress - (char *)mi.AllocationBase; -+ space = size / 5; -+ if (space > 1024*1024) space = 1024*1024; -+ STACK_LEVEL_MAX = (size - space) / sizeof(VALUE); -+ } - } - #endif - } -@@ -1701,8 +2054,9 @@ void - Init_heap() - { - if (!rb_gc_stack_start) { -- Init_stack(0); -+ Init_stack(0); - } -+ set_gc_parameters(); - add_heap(); - } - -@@ -1715,7 +2069,7 @@ os_obj_of(of) - volatile VALUE v; - - for (i = 0; i < heaps_used; i++) { -- RVALUE *p, *pend; -+ RVALUE *p, *pend; - - p = heaps[i].slot; pend = p + heaps[i].limit; - for (;p < pend; p++) { -@@ -1808,8 +2162,8 @@ add_final(os, block) - { - rb_warn("ObjectSpace::add_finalizer is deprecated; use define_finalizer"); - if (!rb_respond_to(block, rb_intern("call"))) { -- rb_raise(rb_eArgError, "wrong type argument %s (should be callable)", -- rb_obj_classname(block)); -+ rb_raise(rb_eArgError, "wrong type argument %s (should be callable)", -+ rb_obj_classname(block)); - } - rb_ary_push(finalizers, block); - return block; -@@ -1864,7 +2218,7 @@ undefine_final(os, obj) - VALUE os, obj; - { - if (finalizer_table) { -- st_delete(finalizer_table, (st_data_t*)&obj, 0); -+ st_delete(finalizer_table, (st_data_t*)&obj, 0); - } - return obj; - } -@@ -1888,11 +2242,11 @@ define_final(argc, argv, os) - - rb_scan_args(argc, argv, "11", &obj, &block); - if (argc == 1) { -- block = rb_block_proc(); -+ block = rb_block_proc(); - } - else if (!rb_respond_to(block, rb_intern("call"))) { -- rb_raise(rb_eArgError, "wrong type argument %s (should be callable)", -- rb_obj_classname(block)); -+ rb_raise(rb_eArgError, "wrong type argument %s (should be callable)", -+ rb_obj_classname(block)); - } - need_call_final = 1; - if (!FL_ABLE(obj)) { -@@ -1905,10 +2259,10 @@ define_final(argc, argv, os) - OBJ_FREEZE(block); - - if (!finalizer_table) { -- finalizer_table = st_init_numtable(); -+ finalizer_table = st_init_numtable(); - } - if (st_lookup(finalizer_table, obj, &table)) { -- rb_ary_push(table, block); -+ rb_ary_push(table, block); - } - else { - table = rb_ary_new3(1, block); -@@ -1927,7 +2281,7 @@ rb_gc_copy_finalizer(dest, obj) - if (!finalizer_table) return; - if (!FL_TEST(obj, FL_FINALIZE)) return; - if (st_lookup(finalizer_table, obj, &table)) { -- st_insert(finalizer_table, dest, table); -+ st_insert(finalizer_table, dest, table); - } - RBASIC(dest)->flags |= FL_FINALIZE; - } -@@ -1957,18 +2311,18 @@ run_final(obj) - args[1] = 0; - args[2] = (VALUE)ruby_safe_level; - for (i=0; ilen; i++) { -- args[0] = RARRAY(finalizers)->ptr[i]; -- if (!args[1]) args[1] = rb_ary_new3(1, objid); -- rb_protect((VALUE(*)_((VALUE)))run_single_final, (VALUE)args, &status); -+ args[0] = RARRAY(finalizers)->ptr[i]; -+ if (!args[1]) args[1] = rb_ary_new3(1, objid); -+ rb_protect((VALUE(*)_((VALUE)))run_single_final, (VALUE)args, &status); - } - if (finalizer_table && st_delete(finalizer_table, (st_data_t*)&obj, &table)) { -- for (i=0; ilen; i++) { -- VALUE final = RARRAY(table)->ptr[i]; -- args[0] = RARRAY(final)->ptr[1]; -- if (!args[1]) args[1] = rb_ary_new3(1, objid); -- args[2] = FIX2INT(RARRAY(final)->ptr[0]); -- rb_protect((VALUE(*)_((VALUE)))run_single_final, (VALUE)args, &status); -- } -+ for (i=0; ilen; i++) { -+ VALUE final = RARRAY(table)->ptr[i]; -+ args[0] = RARRAY(final)->ptr[1]; -+ if (!args[1]) args[1] = rb_ary_new3(1, objid); -+ args[2] = FIX2INT(RARRAY(final)->ptr[0]); -+ rb_protect((VALUE(*)_((VALUE)))run_single_final, (VALUE)args, &status); -+ } - } - rb_thread_critical = critical_save; - } -@@ -1980,8 +2334,8 @@ rb_gc_finalize_deferred() - - deferred_final_list = 0; - if (p) { -- finalize_list(p); -- free_unused_heaps(); -+ finalize_list(p); -+ free_unused_heaps(); - } - } - -@@ -2061,7 +2415,7 @@ id2ref(obj, objid) - if (ptr == Qfalse) return Qfalse; - if (ptr == Qnil) return Qnil; - if (FIXNUM_P(ptr)) return (VALUE)ptr; -- ptr = objid ^ FIXNUM_FLAG; /* unset FIXNUM_FLAG */ -+ ptr = objid ^ FIXNUM_FLAG; /* unset FIXNUM_FLAG */ - - if ((ptr % sizeof(RVALUE)) == (4 << 2)) { - ID symid = ptr / sizeof(RVALUE); -@@ -2075,7 +2429,7 @@ id2ref(obj, objid) - rb_raise(rb_eRangeError, "0x%lx is not id value", p0); - } - if (BUILTIN_TYPE(ptr) == 0 || RBASIC(ptr)->klass == 0) { -- rb_raise(rb_eRangeError, "0x%lx is recycled object", p0); -+ rb_raise(rb_eRangeError, "0x%lx is recycled object", p0); - } - return (VALUE)ptr; - } -@@ -2166,6 +2520,14 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "stress=", gc_stress_set, 1); - rb_define_method(rb_mGC, "garbage_collect", rb_gc_start, 0); - -+ rb_define_singleton_method(rb_mGC, "enable_stats", rb_gc_enable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "disable_stats", rb_gc_disable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0); -+ rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); -+ rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); -+ rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); -+ rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); -+ - rb_mObSpace = rb_define_module("ObjectSpace"); - rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1); - rb_define_module_function(rb_mObSpace, "garbage_collect", rb_gc_start, 0); -@@ -2188,7 +2550,7 @@ Init_GC() - - rb_global_variable(&nomem_error); - nomem_error = rb_exc_new3(rb_eNoMemError, -- rb_obj_freeze(rb_str_new2("failed to allocate memory"))); -+ rb_obj_freeze(rb_str_new2("failed to allocate memory"))); - OBJ_TAINT(nomem_error); - OBJ_FREEZE(nomem_error); - diff --git a/patches/ruby/1.8.7/p352/railsexpress/04-display-full-stack-trace.patch b/patches/ruby/1.8.7/p352/railsexpress/04-display-full-stack-trace.patch deleted file mode 100644 index a927a80ba6..0000000000 --- a/patches/ruby/1.8.7/p352/railsexpress/04-display-full-stack-trace.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/eval.c b/eval.c -index 6ff2560..fb3307c 100644 ---- a/eval.c -+++ b/eval.c -@@ -1325,8 +1325,8 @@ error_print() - int truncate = eclass == rb_eSysStackError; - - #define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5) --#define TRACE_HEAD 8 --#define TRACE_TAIL 5 -+#define TRACE_HEAD 100 -+#define TRACE_TAIL 100 - - ep = RARRAY(errat); - for (i=1; ilen; i++) { diff --git a/patches/ruby/1.8.7/p352/railsexpress/05-better-source-file-tracing.patch b/patches/ruby/1.8.7/p352/railsexpress/05-better-source-file-tracing.patch deleted file mode 100644 index f7a4d4f24f..0000000000 --- a/patches/ruby/1.8.7/p352/railsexpress/05-better-source-file-tracing.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/eval.c b/eval.c -index fb3307c..356226e 100644 ---- a/eval.c -+++ b/eval.c -@@ -1161,7 +1161,7 @@ static VALUE trace_func = 0; - static int tracing = 0; - static void call_trace_func _((rb_event_t,NODE*,VALUE,ID,VALUE)); - --#if 0 -+#if 1 - #define SET_CURRENT_SOURCE() (ruby_sourcefile = ruby_current_node->nd_file, \ - ruby_sourceline = nd_line(ruby_current_node)) - #else diff --git a/patches/ruby/1.8.7/p352/railsexpress/06-heap-dump-support.patch b/patches/ruby/1.8.7/p352/railsexpress/06-heap-dump-support.patch deleted file mode 100644 index 5235be6bcc..0000000000 --- a/patches/ruby/1.8.7/p352/railsexpress/06-heap-dump-support.patch +++ /dev/null @@ -1,159 +0,0 @@ -diff --git a/configure.in b/configure.in -index 62b34a8..4be088c 100644 ---- a/configure.in -+++ b/configure.in -@@ -1595,6 +1595,14 @@ fi - LDFLAGS="-L. $LDFLAGS" - AC_SUBST(ARCHFILE) - -+dnl enable gc debugging -+AC_ARG_ENABLE(gcdebug, -+ [ --enable-gcdebug build garbage collector with debugging enabled. ], -+ [enable_gcdebug=$enableval]) -+if test "$enable_gcdebug" = 'yes'; then -+ AC_DEFINE(GC_DEBUG, 1) -+fi -+ - dnl build rdoc index if requested - RDOCTARGET="" - AC_ARG_ENABLE(install-doc, -diff --git a/gc.c b/gc.c -index ab71d22..9ad716f 100644 ---- a/gc.c -+++ b/gc.c -@@ -411,7 +411,6 @@ rb_gc_unregister_address(addr) - } - } - --#undef GC_DEBUG - - void - rb_global_variable(var) -@@ -602,6 +601,85 @@ rb_gc_dump() - return Qnil; - } - -+ -+static char* obj_type(int tp); -+ -+#ifdef GC_DEBUG -+/* -+ * call-seq: -+ * GC.dump_file_and_line_info(String, boolean) => nil -+ * -+ * dumps information on which currently allocated object was created by which file and on which line -+ * -+ * GC.dump_file_and_line_info(String, boolean) #=> nil -+ * -+ * The second parameter specifies whether class names should be included in the dump. -+ * Note that including class names will allocate additional string objects on the heap. -+ * -+ */ -+ -+VALUE -+rb_gc_dump_file_and_line_info(int argc, VALUE *argv) -+{ -+ VALUE filename, str, include_classnames = Qnil; -+ char *fname = NULL; -+ char *klass = NULL; -+ FILE* f = NULL; -+ int i,n = 0; -+ -+ rb_scan_args(argc, argv, "11", &filename, &include_classnames); -+ -+ str = StringValue(filename); -+ fname = RSTRING(str)->ptr; -+ f = fopen(fname, "w"); -+ -+ for (i = 0; i < heaps_used; i++) { -+ RVALUE *p, *pend; -+ -+ p = heaps[i].slot; pend = p + heaps[i].limit; -+ for (;p < pend; p++) { -+ if (p->as.basic.flags) { -+ fprintf(f, "%s:%s:%d", obj_type(p->as.basic.flags & T_MASK), p->file, p->line); -+ // rb_obj_classname will create objects on the heap, we need a better solution -+ if (include_classnames == Qtrue) { -+ /* write the class */ -+ fprintf(f, ":"); -+ switch (TYPE(p)) { -+ case T_NONE: -+ fprintf(f, "__none__"); -+ break; -+ case T_BLKTAG: -+ fprintf(f, "__blktag__"); -+ break; -+ case T_UNDEF: -+ fprintf(f, "__undef__"); -+ break; -+ case T_VARMAP: -+ fprintf(f, "__varmap__"); -+ break; -+ case T_SCOPE: -+ fprintf(f, "__scope__"); -+ break; -+ case T_NODE: -+ fprintf(f, "__node__"); -+ break; -+ default: -+ if (!p->as.basic.klass) { -+ fprintf(f, "__unknown__"); -+ } else { -+ fprintf(f, rb_obj_classname((VALUE)p)); -+ } -+ } -+ } -+ fprintf(f, "\n"); -+ } -+ } -+ } -+ fclose(f); -+ return Qnil; -+} -+#endif -+ - /* - * call-seq: - * GC.log String => String -@@ -1066,6 +1144,11 @@ gc_mark(ptr, lev) - if (obj->as.basic.flags & FL_MARK) return; /* already marked */ - obj->as.basic.flags |= FL_MARK; - -+#ifdef GC_DEBUG -+ /* mark our new reference point for sourcefile objects */ -+ mark_source_filename(RANY(obj)->file); -+#endif -+ - if (lev > GC_LEVEL_MAX || (lev == 0 && ruby_stack_check())) { - if (!mark_stack_overflow) { - if (mark_stack_ptr - mark_stack < MARK_STACK_MAX) { -@@ -1104,6 +1187,11 @@ gc_mark_children(ptr, lev) - if (obj->as.basic.flags & FL_MARK) return; /* already marked */ - obj->as.basic.flags |= FL_MARK; - -+#ifdef GC_DEBUG -+ /* mark our new reference point for sourcefile objects */ -+ mark_source_filename(RANY(obj)->file); -+#endif -+ - marking: - if (FL_TEST(obj, FL_EXIVAR)) { - rb_mark_generic_ivar(ptr); -@@ -1550,6 +1638,7 @@ gc_sweep() - live_counts[i], free_counts[i], obj_type(i)); - } - } -+ fflush(gc_data_file); - } - - /* clear finalization list */ -@@ -2526,6 +2615,9 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); - rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); - rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); -+#ifdef GC_DEBUG -+ rb_define_singleton_method(rb_mGC, "dump_file_and_line_info", rb_gc_dump_file_and_line_info, -1); -+#endif - rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); - - rb_mObSpace = rb_define_module("ObjectSpace"); diff --git a/patches/ruby/1.8.7/p352/railsexpress/07-fork-support-for-gc-logging.patch b/patches/ruby/1.8.7/p352/railsexpress/07-fork-support-for-gc-logging.patch deleted file mode 100644 index 0f01a75db0..0000000000 --- a/patches/ruby/1.8.7/p352/railsexpress/07-fork-support-for-gc-logging.patch +++ /dev/null @@ -1,249 +0,0 @@ -diff --git a/gc.c b/gc.c -index 9ad716f..a3cbe91 100644 ---- a/gc.c -+++ b/gc.c -@@ -223,6 +223,8 @@ static int dont_gc; - static int gc_statistics = 0; - static GC_TIME_TYPE gc_time = 0; - static int gc_collections = 0; -+static int verbose_gc_stats = Qfalse; -+static FILE* gc_data_file = NULL; - static int during_gc; - static int need_call_final = 0; - static st_table *finalizer_table = 0; -@@ -368,9 +370,148 @@ rb_gc_time() - #endif - } - -- - VALUE rb_mGC; - -+/* -+ * call-seq: -+ * GC.enable_trace => true or false -+ * -+ * Enables garbage collection tracing, returning true if garbage -+ * collection tracing was already enabled. -+ * -+ * GC.enable_trace #=> false or true -+ * GC.enable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_trace() -+{ -+ int old = verbose_gc_stats; -+ verbose_gc_stats = Qtrue; -+ return old; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_trace => true or false -+ * -+ * Disables garbage collection tracing, returning true if garbage -+ * collection tracing was already disabled. -+ * -+ * GC.disable_trace #=> false or true -+ * GC.disable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_trace() -+{ -+ int old = verbose_gc_stats; -+ verbose_gc_stats = Qfalse; -+ return old; -+} -+ -+char* GC_LOGFILE_IVAR = "@gc_logfile_name"; -+ -+/* -+ * call-seq: -+ * GC.log_file(filename=nil, mode="w") => boolean -+ * -+ * Changes the GC data log file. Closes the currently open logfile. -+ * Returns true if the file was successfully opened for -+ * writing. Returns false if the file could not be opened for -+ * writing. Returns the name of the current logfile (or nil) if no -+ * parameter is given. Restores logging to stderr when given nil as -+ * an argument. -+ * -+ * GC.log_file #=> nil -+ * GC.log_file "/tmp/gc.log" #=> true -+ * GC.log_file #=> "/tmp/gc.log" -+ * GC.log_file nil #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_log_file(int argc, VALUE *argv, VALUE self) -+{ -+ VALUE filename = Qnil; -+ VALUE mode_str = Qnil; -+ FILE* f = NULL; -+ char* mode = "w"; -+ -+ VALUE current_logfile_name = rb_iv_get(rb_mGC, GC_LOGFILE_IVAR); -+ -+ if (argc==0) -+ return current_logfile_name; -+ -+ rb_scan_args(argc, argv, "02", &filename, &mode_str); -+ -+ if (filename == Qnil) { -+ /* close current logfile and reset logfile to stderr */ -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+ } -+ return Qtrue; -+ } -+ -+ /* we have a real logfile name */ -+ filename = StringValue(filename); -+ -+ if (rb_equal(current_logfile_name, filename) == Qtrue) { -+ /* do nothing if we get the file name we're already logging to */ -+ return Qtrue; -+ } -+ -+ /* get mode for file opening */ -+ if (mode_str != Qnil) -+ { -+ mode = RSTRING(StringValue(mode_str))->ptr; -+ } -+ -+ /* try to open file in given mode */ -+ if (f = fopen(RSTRING(filename)->ptr, mode)) { -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ } -+ gc_data_file = f; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, filename); -+ } else { -+ return Qfalse; -+ } -+ return Qtrue; -+} -+ -+ -+/* -+ * Called from process.c before a fork. Flushes the gc log file to -+ * avoid writing the buffered output twice (once in the parent, and -+ * once in the child). -+ */ -+void -+rb_gc_before_fork() -+{ -+ /* flush gc log file */ -+ fflush(gc_data_file); -+} -+ -+/* -+ * Called from process.c after a fork in the child process. Turns off -+ * logging, disables GC stats and resets all gc counters and timing -+ * information. -+ */ -+void -+rb_gc_after_fork() -+{ -+ rb_gc_disable_stats(); -+ rb_gc_clear_stats(); -+ rb_gc_disable_trace(); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+} -+ - static struct gc_list { - VALUE *varptr; - struct gc_list *next; -@@ -477,10 +618,6 @@ static double heap_slots_growth_factor = 1.8; - - static long initial_malloc_limit = GC_MALLOC_LIMIT; - --static int verbose_gc_stats = Qfalse; -- --static FILE* gc_data_file = NULL; -- - static RVALUE *himem, *lomem; - - static void set_gc_parameters() -@@ -496,6 +633,8 @@ static void set_gc_parameters() - if (gc_stats_i > 0) { - verbose_gc_stats = Qtrue; - } -+ /* child processes should not inherit RUBY_GC_STATS */ -+ unsetenv("RUBY_GC_STATS"); - } - - gc_heap_file_ptr = getenv("RUBY_GC_DATA_FILE"); -@@ -508,6 +647,8 @@ static void set_gc_parameters() - fprintf(stderr, - "can't open gc log file %s for writing, using default\n", gc_heap_file_ptr); - } -+ /* child processes should not inherit RUBY_GC_DATA_FILE to avoid clobbering */ -+ unsetenv("RUBY_GC_DATA_FILE"); - } - - min_slots_ptr = getenv("RUBY_HEAP_MIN_SLOTS"); -@@ -2619,6 +2760,9 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "dump_file_and_line_info", rb_gc_dump_file_and_line_info, -1); - #endif - rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); -+ rb_define_singleton_method(rb_mGC, "log_file", rb_gc_log_file, -1); -+ rb_define_singleton_method(rb_mGC, "enable_trace", rb_gc_enable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "disable_trace", rb_gc_disable_trace, 0); - - rb_mObSpace = rb_define_module("ObjectSpace"); - rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1); -diff --git a/intern.h b/intern.h -index 950ae9d..99696f1 100644 ---- a/intern.h -+++ b/intern.h -@@ -270,6 +270,8 @@ void rb_gc_call_finalizer_at_exit _((void)); - VALUE rb_gc_enable _((void)); - VALUE rb_gc_disable _((void)); - VALUE rb_gc_start _((void)); -+void rb_gc_before_fork _((void)); -+void rb_gc_after_fork _((void)); - /* hash.c */ - void st_foreach_safe _((struct st_table *, int (*)(ANYARGS), unsigned long)); - void rb_hash_foreach _((VALUE, int (*)(ANYARGS), VALUE)); -diff --git a/process.c b/process.c -index 8f6285d..ea28cb8 100644 ---- a/process.c -+++ b/process.c -@@ -1330,6 +1330,8 @@ rb_f_fork(obj) - fflush(stderr); - #endif - -+ rb_gc_before_fork(); -+ - before_exec(); - pid = fork(); - after_exec(); -@@ -1339,6 +1341,7 @@ rb_f_fork(obj) - #ifdef linux - after_exec(); - #endif -+ rb_gc_after_fork(); - rb_thread_atfork(); - if (rb_block_given_p()) { - int status; -@@ -1574,10 +1577,12 @@ rb_f_system(argc, argv) - - chfunc = signal(SIGCHLD, SIG_DFL); - retry: -+ rb_gc_before_fork(); - before_exec(); - pid = fork(); - if (pid == 0) { - /* child process */ -+ rb_gc_after_fork(); - rb_thread_atfork(); - rb_protect(proc_exec_args, (VALUE)&earg, NULL); - _exit(127); diff --git a/patches/ruby/1.8.7/p352/railsexpress/08-track-malloc-size.patch b/patches/ruby/1.8.7/p352/railsexpress/08-track-malloc-size.patch deleted file mode 100644 index d078748a44..0000000000 --- a/patches/ruby/1.8.7/p352/railsexpress/08-track-malloc-size.patch +++ /dev/null @@ -1,120 +0,0 @@ -diff --git a/gc.c b/gc.c -index a3cbe91..30a1219 100644 ---- a/gc.c -+++ b/gc.c -@@ -79,6 +79,17 @@ void *alloca (); - - static unsigned long malloc_increase = 0; - static unsigned long malloc_limit = GC_MALLOC_LIMIT; -+ -+#ifdef HAVE_LONG_LONG -+static unsigned LONG_LONG gc_allocated_size = 0; -+static unsigned LONG_LONG gc_num_allocations = 0; -+#else -+static unsigned long gc_allocated_size = 0; -+static unsigned long gc_num_allocations = 0; -+#endif -+static int gc_statistics = 0; -+ -+ - static void run_final(); - static VALUE nomem_error; - static void garbage_collect(); -@@ -163,6 +174,11 @@ ruby_xmalloc(size) - } - malloc_increase += size; - -+ if (gc_statistics) { -+ gc_allocated_size += size; -+ gc_num_allocations += 1; -+ } -+ - return mem; - } - -@@ -220,7 +236,6 @@ ruby_xfree(x) - - extern int ruby_in_compile; - static int dont_gc; --static int gc_statistics = 0; - static GC_TIME_TYPE gc_time = 0; - static int gc_collections = 0; - static int verbose_gc_stats = Qfalse; -@@ -329,11 +344,55 @@ rb_gc_clear_stats() - { - gc_collections = 0; - gc_time = 0; -+ gc_allocated_size = 0; -+ gc_num_allocations = 0; - return Qnil; - } - - /* - * call-seq: -+ * GC.allocated_size => Integer -+ * -+ * Returns the size of memory (in bytes) allocated since GC statistics collection -+ * was enabled. -+ * -+ * GC.allocated_size #=> 35 -+ * -+ */ -+VALUE -+rb_gc_allocated_size() -+{ -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_allocated_size); -+#else -+ return ULONG2NUM(gc_allocated_size); -+#endif -+} -+ -+/* -+ * call-seq: -+ * GC.num_allocations => Integer -+ * -+ * Returns the number of memory allocations since GC statistics collection -+ * was enabled. -+ * -+ * GC.num_allocations #=> 150 -+ * -+ */ -+VALUE -+rb_gc_num_allocations() -+{ -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_num_allocations); -+#else -+ return ULONG2NUM(gc_num_allocations); -+#endif -+} -+ -+/* -+ -+/* -+ * call-seq: - * GC.collections => Integer - * - * Returns the number of garbage collections performed while GC statistics collection -@@ -2753,6 +2812,8 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "enable_stats", rb_gc_enable_stats, 0); - rb_define_singleton_method(rb_mGC, "disable_stats", rb_gc_disable_stats, 0); - rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0); -+ rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); -+ rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); - rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); - rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); - rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); -diff --git a/intern.h b/intern.h -index 99696f1..1117614 100644 ---- a/intern.h -+++ b/intern.h -@@ -272,6 +272,8 @@ VALUE rb_gc_disable _((void)); - VALUE rb_gc_start _((void)); - void rb_gc_before_fork _((void)); - void rb_gc_after_fork _((void)); -+VALUE rb_gc_allocated_size _((void)); -+VALUE rb_gc_num_allocations _((void)); - /* hash.c */ - void st_foreach_safe _((struct st_table *, int (*)(ANYARGS), unsigned long)); - void rb_hash_foreach _((VALUE, int (*)(ANYARGS), VALUE)); diff --git a/patches/ruby/1.8.7/p352/railsexpress/09-track-object-allocation.patch b/patches/ruby/1.8.7/p352/railsexpress/09-track-object-allocation.patch deleted file mode 100644 index 0eef717a24..0000000000 --- a/patches/ruby/1.8.7/p352/railsexpress/09-track-object-allocation.patch +++ /dev/null @@ -1,111 +0,0 @@ -diff --git a/gc.c b/gc.c -index 30a1219..5b42b90 100644 ---- a/gc.c -+++ b/gc.c -@@ -96,6 +96,26 @@ static void garbage_collect(); - - int ruby_gc_stress = 0; - -+static unsigned long live_objects = 0; -+unsigned long rb_os_live_objects() -+{ -+ return live_objects; -+} -+ -+#if defined(HAVE_LONG_LONG) -+static unsigned LONG_LONG allocated_objects = 0; -+unsigned LONG_LONG rb_os_allocated_objects() -+{ -+ return allocated_objects; -+} -+#else -+static unsigned long allocated_objects = 0; -+unsigned long rb_os_allocated_objects() -+{ -+ return allocated_objects; -+} -+#endif -+ - NORETURN(void rb_exc_jump _((VALUE))); - - void -@@ -987,6 +1007,8 @@ rb_newobj() - RANY(obj)->file = ruby_sourcefile; - RANY(obj)->line = ruby_sourceline; - #endif -+ live_objects++; -+ allocated_objects++; - return obj; - } - -@@ -1825,6 +1847,7 @@ gc_sweep() - add_heap(); - } - during_gc = 0; -+ live_objects = live; - - if (do_gc_stats) { - fprintf(gc_data_file, "objects processed: %.7d\n", live+freed); -@@ -2790,6 +2813,35 @@ rb_obj_id(VALUE obj) - return (VALUE)((long)obj|FIXNUM_FLAG); - } - -+/* call-seq: -+ * ObjectSpace.live_objects => number -+ * -+ * Returns the count of objects currently allocated in the system. This goes -+ * down after the garbage collector runs. -+ */ -+static -+VALUE os_live_objects(VALUE self) -+{ -+ return ULONG2NUM(live_objects); -+} -+ -+/* call-seq: -+ * ObjectSpace.allocated_objects => number -+ * -+ * Returns the count of objects allocated since the Ruby interpreter has -+ * started. This number can only increase. To know how many objects are -+ * currently allocated, use ObjectSpace::live_objects -+ */ -+static -+VALUE os_allocated_objects(VALUE self) -+{ -+#if defined(HAVE_LONG_LONG) -+ return ULL2NUM(allocated_objects); -+#else -+ return ULONG2NUM(allocated_objects); -+#endif -+} -+ - /* - * The GC module provides an interface to Ruby's mark and - * sweep garbage collection mechanism. Some of the underlying methods -@@ -2833,6 +2885,9 @@ Init_GC() - rb_define_module_function(rb_mObSpace, "finalizers", finals, 0); - rb_define_module_function(rb_mObSpace, "call_finalizer", call_final, 1); - -+ rb_define_module_function(rb_mObSpace, "live_objects", os_live_objects, 0); -+ rb_define_module_function(rb_mObSpace, "allocated_objects", os_allocated_objects, 0); -+ - rb_define_module_function(rb_mObSpace, "define_finalizer", define_final, -1); - rb_define_module_function(rb_mObSpace, "undefine_finalizer", undefine_final, 1); - -diff --git a/intern.h b/intern.h -index 1117614..a87661d 100644 ---- a/intern.h -+++ b/intern.h -@@ -274,6 +274,12 @@ void rb_gc_before_fork _((void)); - void rb_gc_after_fork _((void)); - VALUE rb_gc_allocated_size _((void)); - VALUE rb_gc_num_allocations _((void)); -+unsigned long rb_os_live_objects _((void)); -+#ifdef HAVE_LONG_LONG -+unsigned LONG_LONG rb_os_allocated_objects _((void)); -+#else -+unsigned long rb_os_allocated_objects _((void)); -+#endif - /* hash.c */ - void st_foreach_safe _((struct st_table *, int (*)(ANYARGS), unsigned long)); - void rb_hash_foreach _((VALUE, int (*)(ANYARGS), VALUE)); diff --git a/patches/ruby/1.8.7/p352/railsexpress/10-expose-heap-slots.patch b/patches/ruby/1.8.7/p352/railsexpress/10-expose-heap-slots.patch deleted file mode 100644 index 3ce846c6a0..0000000000 --- a/patches/ruby/1.8.7/p352/railsexpress/10-expose-heap-slots.patch +++ /dev/null @@ -1,70 +0,0 @@ -diff --git a/gc.c b/gc.c -index 5b42b90..21b3f6b 100644 ---- a/gc.c -+++ b/gc.c -@@ -690,6 +690,7 @@ static int heaps_used = 0; - - static int heap_min_slots = 10000; - static int heap_slots = 10000; -+static int heap_size = 0; - - static int heap_free_min = 4096; - static int heap_slots_increment = 10000; -@@ -800,6 +801,21 @@ static void set_gc_parameters() - - /* - * call-seq: -+ * GC.heap_slots => Integer -+ * -+ * Returns the number of heap slots available for object allocations. -+ * -+ * GC.heap_slots #=> 10000 -+ * -+ */ -+VALUE -+rb_gc_heap_slots() -+{ -+ return INT2NUM(heap_size); -+} -+ -+/* -+ * call-seq: - * GC.dump => nil - * - * dumps information about the current GC data structures to the GC log file -@@ -967,6 +983,7 @@ add_heap() - heaps[heaps_used].limit = heap_slots; - break; - } -+ heap_size += heap_slots; - pend = p + heap_slots; - if (lomem == 0 || lomem > p) lomem = p; - if (himem < pend) himem = pend; -@@ -1828,6 +1845,7 @@ gc_sweep() - if (n == heaps[i].limit && freed > free_min) { - RVALUE *pp; - -+ heap_size -= n; - heaps[i].limit = 0; - for (pp = final_list; pp != final; pp = pp->as.free.next) { - pp->as.free.flags |= FL_SINGLETON; /* freeing page mark */ -@@ -2866,6 +2884,7 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0); - rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); - rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); - rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); - rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); - rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); -diff --git a/intern.h b/intern.h -index a87661d..e8f3209 100644 ---- a/intern.h -+++ b/intern.h -@@ -274,6 +274,7 @@ void rb_gc_before_fork _((void)); - void rb_gc_after_fork _((void)); - VALUE rb_gc_allocated_size _((void)); - VALUE rb_gc_num_allocations _((void)); -+VALUE rb_gc_heap_slots _((void)); - unsigned long rb_os_live_objects _((void)); - #ifdef HAVE_LONG_LONG - unsigned LONG_LONG rb_os_allocated_objects _((void)); diff --git a/patches/ruby/1.8.7/p352/railsexpress/11-fix-heap-size-growth-logic.patch b/patches/ruby/1.8.7/p352/railsexpress/11-fix-heap-size-growth-logic.patch deleted file mode 100644 index 1db93f224d..0000000000 --- a/patches/ruby/1.8.7/p352/railsexpress/11-fix-heap-size-growth-logic.patch +++ /dev/null @@ -1,54 +0,0 @@ -diff --git a/gc.c b/gc.c -index 21b3f6b..7db1ef6 100644 ---- a/gc.c -+++ b/gc.c -@@ -694,6 +694,7 @@ static int heap_size = 0; - - static int heap_free_min = 4096; - static int heap_slots_increment = 10000; -+static int initial_heap_slots_increment = 10000; - static double heap_slots_growth_factor = 1.8; - - static long initial_malloc_limit = GC_MALLOC_LIMIT; -@@ -771,14 +772,13 @@ static void set_gc_parameters() - if (verbose_gc_stats) { - fprintf(gc_data_file, "RUBY_HEAP_SLOTS_INCREMENT=%s\n", heap_slots_incr_ptr); - } -- if (heap_slots_incr_i > 0) { -- heap_slots_increment = heap_slots_incr_i; -- } -+ heap_slots_increment = heap_slots_incr_i; -+ initial_heap_slots_increment = heap_slots_increment; - } - - heap_slots_growth_factor_ptr = getenv("RUBY_HEAP_SLOTS_GROWTH_FACTOR"); - if (heap_slots_growth_factor_ptr != NULL) { -- double heap_slots_growth_factor_d = atoi(heap_slots_growth_factor_ptr); -+ double heap_slots_growth_factor_d = atof(heap_slots_growth_factor_ptr); - if (verbose_gc_stats) { - fprintf(gc_data_file, "RUBY_HEAP_SLOTS_GROWTH_FACTOR=%s\n", heap_slots_growth_factor_ptr); - } -@@ -988,8 +988,13 @@ add_heap() - if (lomem == 0 || lomem > p) lomem = p; - if (himem < pend) himem = pend; - heaps_used++; -- heap_slots += heap_slots_increment; -- heap_slots_increment *= heap_slots_growth_factor; -+ if (heaps_used == 1) -+ heap_slots = initial_heap_slots_increment; -+ else { -+ heap_slots_increment *= heap_slots_growth_factor; -+ heap_slots += heap_slots_increment; -+ } -+ - if (heap_slots <= 0) heap_slots = heap_min_slots; - - while (p < pend) { -@@ -1879,6 +1884,7 @@ gc_sweep() - live_counts[i], free_counts[i], obj_type(i)); - } - } -+ rb_gc_dump(); - fflush(gc_data_file); - } - diff --git a/patches/ruby/1.8.7/p352/railsexpress/12-heap-slot-size.patch b/patches/ruby/1.8.7/p352/railsexpress/12-heap-slot-size.patch deleted file mode 100644 index 45091c14ae..0000000000 --- a/patches/ruby/1.8.7/p352/railsexpress/12-heap-slot-size.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/gc.c b/gc.c -index 7db1ef6..57740d2 100644 ---- a/gc.c -+++ b/gc.c -@@ -2891,6 +2891,7 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); - rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); - rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); - rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); - rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); - rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); diff --git a/patches/ruby/1.8.7/p352/railsexpress/13-add-trace-stats-enabled-methods.patch b/patches/ruby/1.8.7/p352/railsexpress/13-add-trace-stats-enabled-methods.patch deleted file mode 100644 index 4e3c4f2132..0000000000 --- a/patches/ruby/1.8.7/p352/railsexpress/13-add-trace-stats-enabled-methods.patch +++ /dev/null @@ -1,66 +0,0 @@ -diff --git a/gc.c b/gc.c -index 57740d2..2c34932 100644 ---- a/gc.c -+++ b/gc.c -@@ -350,6 +350,22 @@ rb_gc_disable_stats() - - /* - * call-seq: -+ * GC.stats_enabled? => true or false -+ * -+ * Check whether GC stats have been enabled. -+ * -+ * GC.stats_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_stats_enabled() -+{ -+ return gc_statistics ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: - * GC.clear_stats => nil - * - * Clears garbage collection statistics, returning nil. This resets the number -@@ -491,6 +507,22 @@ rb_gc_disable_trace() - return old; - } - -+/* -+ * call-seq: -+ * GC.trace_enabled? => true or false -+ * -+ * Check whether GC tracing has been enabled. -+ * -+ * GC.trace_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_trace_enabled() -+{ -+ return verbose_gc_stats ? Qtrue : Qfalse; -+} -+ - char* GC_LOGFILE_IVAR = "@gc_logfile_name"; - - /* -@@ -2887,6 +2919,7 @@ Init_GC() - - rb_define_singleton_method(rb_mGC, "enable_stats", rb_gc_enable_stats, 0); - rb_define_singleton_method(rb_mGC, "disable_stats", rb_gc_disable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "stats_enabled?", rb_gc_stats_enabled, 0); - rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0); - rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); - rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); -@@ -2902,6 +2935,7 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "log_file", rb_gc_log_file, -1); - rb_define_singleton_method(rb_mGC, "enable_trace", rb_gc_enable_trace, 0); - rb_define_singleton_method(rb_mGC, "disable_trace", rb_gc_disable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "trace_enabled?", rb_gc_trace_enabled, 0); - - rb_mObSpace = rb_define_module("ObjectSpace"); - rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1); diff --git a/patches/ruby/1.8.7/p352/railsexpress/14-track-live-dataset-size.patch b/patches/ruby/1.8.7/p352/railsexpress/14-track-live-dataset-size.patch deleted file mode 100644 index de44e6b365..0000000000 --- a/patches/ruby/1.8.7/p352/railsexpress/14-track-live-dataset-size.patch +++ /dev/null @@ -1,52 +0,0 @@ -diff --git a/gc.c b/gc.c -index 2c34932..0ce7e68 100644 ---- a/gc.c -+++ b/gc.c -@@ -89,6 +89,7 @@ static unsigned long gc_num_allocations = 0; - #endif - static int gc_statistics = 0; - -+static unsigned long heap_slots_live_after_last_gc = 0; - - static void run_final(); - static VALUE nomem_error; -@@ -465,6 +466,23 @@ rb_gc_time() - #endif - } - -+/* -+ * call-seq: -+ * GC.heap_slots_live_after_last_gc => Integer -+ * -+ * Returns the number of heap slots which were live after the last garbage collection. -+ * -+ * GC.heap_slots_live_after_last_gc #=> 231223 -+ * -+ */ -+VALUE -+rb_gc_heap_slots_live_after_last_gc() -+{ -+ return ULONG2NUM(heap_slots_live_after_last_gc); -+} -+ -+ -+ - VALUE rb_mGC; - - /* -@@ -1903,6 +1921,7 @@ gc_sweep() - } - during_gc = 0; - live_objects = live; -+ heap_slots_live_after_last_gc = live; - - if (do_gc_stats) { - fprintf(gc_data_file, "objects processed: %.7d\n", live+freed); -@@ -2924,6 +2943,7 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); - rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); - rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots_live_after_last_gc", rb_gc_heap_slots_live_after_last_gc, 0); - rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); - rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); - rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); diff --git a/patches/ruby/1.8.7/p352/railsexpress/15-add-object-size-information-to-heap-dump.patch b/patches/ruby/1.8.7/p352/railsexpress/15-add-object-size-information-to-heap-dump.patch deleted file mode 100644 index e974cdb63a..0000000000 --- a/patches/ruby/1.8.7/p352/railsexpress/15-add-object-size-information-to-heap-dump.patch +++ /dev/null @@ -1,51 +0,0 @@ -diff --git a/gc.c b/gc.c -index 0ce7e68..53450bf 100644 ---- a/gc.c -+++ b/gc.c -@@ -953,9 +953,21 @@ rb_gc_dump_file_and_line_info(int argc, VALUE *argv) - if (!p->as.basic.klass) { - fprintf(f, "__unknown__"); - } else { -- fprintf(f, rb_obj_classname((VALUE)p)); -+ fprintf(f, "%s", rb_obj_classname((VALUE)p)); - } - } -+ /* print object size for some known object types */ -+ switch (TYPE(p)) { -+ case T_STRING: -+ fprintf(f, ":%lu", RSTRING(p)->len); -+ break; -+ case T_ARRAY: -+ fprintf(f, ":%lu", RARRAY(p)->len); -+ break; -+ case T_HASH: -+ fprintf(f, ":%d", RHASH(p)->tbl->num_entries); -+ break; -+ } - } - fprintf(f, "\n"); - } -@@ -1924,10 +1936,10 @@ gc_sweep() - heap_slots_live_after_last_gc = live; - - if (do_gc_stats) { -- fprintf(gc_data_file, "objects processed: %.7d\n", live+freed); -- fprintf(gc_data_file, "live objects : %.7d\n", live); -- fprintf(gc_data_file, "freelist objects : %.7d\n", freed - really_freed); -- fprintf(gc_data_file, "freed objects : %.7d\n", really_freed); -+ fprintf(gc_data_file, "objects processed: %.7lu\n", live+freed); -+ fprintf(gc_data_file, "live objects : %.7lu\n", live); -+ fprintf(gc_data_file, "freelist objects : %.7lu\n", freed - really_freed); -+ fprintf(gc_data_file, "freed objects : %.7lu\n", really_freed); - for(i=0; i<256; i++) { - if (free_counts[i]>0 || live_counts[i]>0) { - fprintf(gc_data_file, -@@ -2258,7 +2270,7 @@ garbage_collect() - gc_time += musecs_used; - - if (verbose_gc_stats) { -- fprintf(gc_data_file, "GC time: %d msec\n", musecs_used / 1000); -+ fprintf(gc_data_file, "GC time: %ld msec\n", (long)(musecs_used / 1000)); - fflush(gc_data_file); - } - } diff --git a/patches/ruby/1.8.7/p352/railsexpress/16-caller-for-all-threads.patch b/patches/ruby/1.8.7/p352/railsexpress/16-caller-for-all-threads.patch deleted file mode 100644 index aa79d1602c..0000000000 --- a/patches/ruby/1.8.7/p352/railsexpress/16-caller-for-all-threads.patch +++ /dev/null @@ -1,230 +0,0 @@ -diff --git a/eval.c b/eval.c -index 356226e..a0fdc55 100644 ---- a/eval.c -+++ b/eval.c -@@ -8199,6 +8199,17 @@ rb_f_method_name() - } - } - -+/* Hash (Thread => Backtrace) used to collect backtrace for each threads. */ -+static VALUE backtrace_for_each_thread; -+ -+static int backtrace_level_for_each_thread; -+ -+static VALUE -+switch_thread_context_to_collect_backtrace(rb_thread_t next); -+ -+static VALUE -+rb_f_caller_for_all_threads(); -+ - void - Init_eval() - { -@@ -8244,6 +8255,7 @@ Init_eval() - rb_define_global_function("fail", rb_f_raise, -1); - - rb_define_global_function("caller", rb_f_caller, -1); -+ rb_define_global_function("caller_for_all_threads", rb_f_caller_for_all_threads, -1); - - rb_define_global_function("exit", rb_f_exit, -1); - rb_define_global_function("abort", rb_f_abort, -1); -@@ -10599,6 +10611,7 @@ static int th_sig, th_safe; - #define RESTORE_RAISE 5 - #define RESTORE_SIGNAL 6 - #define RESTORE_EXIT 7 -+#define RESTORE_BACKTRACE 8 - - extern VALUE *rb_gc_stack_start; - #ifdef __ia64 -@@ -10705,6 +10718,15 @@ rb_thread_switch(n) - } - rb_exc_raise(th_raise_exception); - break; -+ case RESTORE_BACKTRACE: -+ rb_hash_aset(backtrace_for_each_thread, curr_thread->thread, -+ backtrace(backtrace_level_for_each_thread)); -+ if (curr_thread != main_thread) { -+ switch_thread_context_to_collect_backtrace(curr_thread->next); -+ } else { -+ /* Circled back to main thread, cycle is complete. */ -+ } -+ break; - case RESTORE_NORMAL: - default: - break; -@@ -13875,3 +13897,74 @@ rb_throw(tag, val) - argv[1] = val; - rb_f_throw(2, argv); - } -+ -+static VALUE -+switch_thread_context_to_collect_backtrace(rb_thread_t next) -+{ -+ if (THREAD_SAVE_CONTEXT(curr_thread)) { -+ return Qnil; -+ } -+ curr_thread = next; -+ rb_thread_restore_context(next, RESTORE_BACKTRACE); -+ return Qnil; -+} -+ -+ -+/* -+ * call-seq: -+ * caller_for_all_threads(start=1) => array -+ * -+ * Returns the current execution stack for all threads -+ * ---a hash whose keys are thread instances and values -+ * the thread caller backtrace. -+ * -+ * Backtraces are array of hashes indicating location on the -+ * stack. Hash keys include ``:line'' or ``:file'' -+ * and ``:method'''. -+ * -+ * The optional _start_ parameter -+ * determines the number of initial stack entries to omit from the -+ * result. -+ * -+ * def a(skip) -+ * caller_for_all_threads(skip) -+ * end -+ * def b(skip) -+ * a(skip) -+ * end -+ * def c(skip) -+ * b(skip) -+ * end -+ * c(0) #=> ["prog:2:in `a'", "prog:5:in `b'", "prog:8:in `c'", "prog:10"] -+ * c(1) #=> ["prog:5:in `b'", "prog:8:in `c'", "prog:11"] -+ * c(2) #=> ["prog:8:in `c'", "prog:12"] -+ * c(3) #=> ["prog:13"] -+ */ -+static VALUE -+rb_f_caller_for_all_threads(argc, argv) -+ int argc; -+ VALUE *argv; -+{ -+ volatile int critical; -+ VALUE level; -+ VALUE result; -+ -+ rb_scan_args(argc, argv, "01", &level); -+ backtrace_level_for_each_thread = NIL_P(level) ? 0 : NUM2INT(level); -+ if (backtrace_level_for_each_thread < 0) { -+ rb_raise(rb_eArgError, "negative level (%d)", backtrace_level_for_each_thread); -+ } -+ -+ critical = rb_thread_critical; -+ rb_thread_critical = Qtrue; -+ -+ backtrace_for_each_thread = rb_hash_new(); -+ switch_thread_context_to_collect_backtrace(main_thread->next); -+ -+ result = backtrace_for_each_thread; -+ backtrace_for_each_thread = Qnil; -+ backtrace_for_each_thread = 0; -+ -+ rb_thread_critical = critical; -+ return result; -+} -diff --git a/test/callerforallthreads/test_caller_for_each_thread.rb b/test/callerforallthreads/test_caller_for_each_thread.rb -new file mode 100644 -index 0000000..6aebaed ---- /dev/null -+++ b/test/callerforallthreads/test_caller_for_each_thread.rb -@@ -0,0 +1,95 @@ -+# -*- ruby-indent-level: 4 -*- -+require 'thread' -+require 'test/unit' -+ -+class AClassWithNestedmethods -+ -+ def an_ultra_nested_method(skip) -+ caller_for_all_threads skip -+ end -+ -+ def a_nested_method(skip) -+ an_ultra_nested_method skip -+ end -+ -+ def a_method(skip=0) -+ a_nested_method skip -+ end -+ -+end -+ -+class CallerForEachThreadTest < Test::Unit::TestCase -+ -+ def testCollectMeaningfulBacktraceForASingleThread -+ backtraces = AClassWithNestedmethods.new.a_method -+ backtrace = backtraces[Thread.current] -+ assert_not_nil backtrace -+ assert_equal __FILE__ + ":8:in `an_ultra_nested_method'", backtrace[0] -+ assert_equal __FILE__ + ":12:in `a_nested_method'", backtrace[1] -+ assert_equal __FILE__ + ":16:in `a_method'", backtrace[2] -+ assert_equal __FILE__ + ":24:in `testCollectMeaningfulBacktraceForASingleThread'", -+ backtrace[3] -+ end -+ -+ def testCanSkipFirstStackEntries -+ backtraces = AClassWithNestedmethods.new.a_method 2 -+ backtrace = backtraces[Thread.current] -+ assert_not_nil backtrace -+ assert_equal __FILE__ + ":16:in `a_method'", backtrace[0] -+ assert_equal __FILE__ + ":35:in `testCanSkipFirstStackEntries'", -+ backtrace[1] -+ end -+ -+ def testCollectMeaningfulBacktraceForMultipleThreads -+ first_thread = Thread.new do -+ loop do -+ Thread.pass -+ sleep 1 -+ end -+ end -+ -+ second_thread = Thread.new do -+ loop do -+ Thread.pass -+ sleep 1 -+ end -+ end -+ -+ backtraces = AClassWithNestedmethods.new.a_method -+ -+ backtrace = backtraces[Thread.current] -+ assert_not_nil backtrace -+ assert_match __FILE__ + ":8:in `an_ultra_nested_method'", backtrace[0] -+ assert_match __FILE__ + ":12:in `a_nested_method'", backtrace[1] -+ assert_equal __FILE__ + ":16:in `a_method'", backtrace[2] -+ assert_equal __FILE__ + ":58:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[3] -+ -+ backtrace = backtraces[first_thread] -+ assert_not_nil backtrace -+ assert_equal __FILE__ + ":47:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[0] -+ assert_equal __FILE__ + ":45:in `loop'", -+ backtrace[1] -+ assert_equal __FILE__ + ":45:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[2] -+ assert_equal __FILE__ + ":44:in `initialize'",backtrace[3] -+ assert_equal __FILE__ + ":44:in `new'", backtrace[4] -+ assert_equal __FILE__ + ":44:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[5] -+ -+ backtrace = backtraces[second_thread] -+ assert_not_nil backtrace -+ assert_equal __FILE__ + ":53:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[0] -+ assert_equal __FILE__ + ":52:in `loop'", backtrace[1] -+ assert_equal __FILE__ + ":52:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[2] -+ assert_equal __FILE__ + ":51:in `initialize'",backtrace[3] -+ assert_equal __FILE__ + ":51:in `new'", backtrace[4] -+ assert_equal __FILE__ + ":51:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[5] -+ end -+ -+end -+ diff --git a/patches/ruby/1.8.7/p357/railsexpress/01-ignore-generated-files.patch b/patches/ruby/1.8.7/p357/railsexpress/01-ignore-generated-files.patch deleted file mode 100644 index b669ad44bd..0000000000 --- a/patches/ruby/1.8.7/p357/railsexpress/01-ignore-generated-files.patch +++ /dev/null @@ -1,101 +0,0 @@ -diff --git a/.gitignore b/.gitignore -new file mode 100644 -index 0000000..00c347a ---- /dev/null -+++ b/.gitignore -@@ -0,0 +1,95 @@ -+.ext -+.installed.list -+.rbconfig.time -+Makefile -+autom4te.cache/ -+config.h -+config.status -+configure -+ext/Win32API/Makefile -+ext/bigdecimal/Makefile -+ext/curses/Makefile -+ext/dbm/Makefile -+ext/digest/Makefile -+ext/digest/bubblebabble/Makefile -+ext/digest/md5/Makefile -+ext/digest/rmd160/Makefile -+ext/digest/sha1/Makefile -+ext/digest/sha2/Makefile -+ext/dl/Makefile -+ext/dl/call.func -+ext/dl/callback.func -+ext/dl/cbtable.func -+ext/dl/dlconfig.h -+ext/dl/dlconfig.rb -+ext/enumerator/Makefile -+ext/etc/Makefile -+ext/fcntl/Makefile -+ext/gdbm/Makefile -+ext/iconv/Makefile -+ext/io/wait/Makefile -+ext/nkf/Makefile -+ext/openssl/Makefile -+ext/openssl/extconf.h -+ext/pty/Makefile -+ext/racc/cparse/Makefile -+ext/readline/Makefile -+ext/sdbm/Makefile -+ext/socket/Makefile -+ext/stringio/Makefile -+ext/strscan/Makefile -+ext/syck/Makefile -+ext/syslog/Makefile -+ext/thread/Makefile -+ext/tk/Makefile -+ext/tk/tkutil/Makefile -+ext/win32ole/Makefile -+ext/win32ole/.document -+ext/zlib/Makefile -+largefile.h -+miniruby -+parse.c -+rbconfig.rb -+ruby -+enc.mk -+ext/bigdecimal/extconf.h -+ext/continuation/ -+ext/coverage/ -+ext/curses/extconf.h -+ext/dbm/extconf.h -+ext/digest/bubblebabble/extconf.h -+ext/digest/extconf.h -+ext/digest/md5/extconf.h -+ext/digest/rmd160/extconf.h -+ext/digest/sha1/extconf.h -+ext/digest/sha2/extconf.h -+ext/dl/callback.h -+ext/dl/extconf.h -+ext/etc/extconf.h -+ext/fcntl/extconf.h -+ext/fiber/ -+ext/iconv/extconf.h -+ext/io/wait/extconf.h -+ext/json/ -+ext/nkf/extconf.h -+ext/pty/extconf.h -+ext/racc/cparse/extconf.h -+ext/readline/extconf.h -+ext/ripper/ -+ext/sdbm/extconf.h -+ext/socket/constants.h -+ext/socket/extconf.h -+ext/stringio/extconf.h -+ext/strscan/extconf.h -+ext/syck/extconf.h -+ext/syslog/extconf.h -+ext/tk/extconf.h -+ext/tk/tkutil/extconf.h -+ext/zlib/extconf.h -+miniprelude.c -+prelude.c -+revision.h -+*.dylib -+*.log -+*.dSYM -+patches-ruby* diff --git a/patches/ruby/1.8.7/p357/railsexpress/02-sigvtalrm-fix.patch b/patches/ruby/1.8.7/p357/railsexpress/02-sigvtalrm-fix.patch deleted file mode 100644 index fe99f6eed6..0000000000 --- a/patches/ruby/1.8.7/p357/railsexpress/02-sigvtalrm-fix.patch +++ /dev/null @@ -1,27 +0,0 @@ -diff --git a/eval.c b/eval.c -index 7886e17..6ff2560 100644 ---- a/eval.c -+++ b/eval.c -@@ -12461,6 +12461,11 @@ rb_thread_start_0(fn, arg, th) - curr_thread->next = th; - th->priority = curr_thread->priority; - th->thgroup = curr_thread->thgroup; -+#if defined(HAVE_SETITIMER) || defined(_THREAD_SAFE) -+ if (!thread_init) { -+ rb_thread_start_timer(); -+ } -+#endif - } - START_TIMER(); - -@@ -13189,7 +13194,9 @@ rb_thread_atfork() - main_thread = curr_thread; - curr_thread->next = curr_thread; - curr_thread->prev = curr_thread; -- STOP_TIMER(); -+#if defined(HAVE_SETITIMER) || defined(_THREAD_SAFE) -+ rb_thread_stop_timer(); -+#endif - } - - diff --git a/patches/ruby/1.8.7/p357/railsexpress/03-railsbench-gc-patch.patch b/patches/ruby/1.8.7/p357/railsexpress/03-railsbench-gc-patch.patch deleted file mode 100644 index 7b6c0e251a..0000000000 --- a/patches/ruby/1.8.7/p357/railsexpress/03-railsbench-gc-patch.patch +++ /dev/null @@ -1,1876 +0,0 @@ -diff --git a/gc.c b/gc.c -index fa45cd1..ab71d22 100644 ---- a/gc.c -+++ b/gc.c -@@ -22,8 +22,16 @@ - #include - #include - -+#ifdef _WIN32 -+#include -+#else -+#include -+#endif -+ - #ifdef HAVE_SYS_TIME_H - #include -+#elif defined(_WIN32) -+#include - #endif - - #ifdef HAVE_SYS_RESOURCE_H -@@ -42,7 +50,6 @@ void rb_io_fptr_finalize _((struct rb_io_t*)); - #ifdef __CYGWIN__ - int _setjmp(), _longjmp(); - #endif -- - /* Make alloca work the best possible way. */ - #ifdef __GNUC__ - # ifndef atarist -@@ -86,12 +93,12 @@ rb_memerror() - rb_thread_t th = rb_curr_thread; - - if (!nomem_error || -- (rb_thread_raised_p(th, RAISED_NOMEMORY) && rb_safe_level() < 4)) { -- fprintf(stderr, "[FATAL] failed to allocate memory\n"); -- exit(1); -+ (rb_thread_raised_p(th, RAISED_NOMEMORY) && rb_safe_level() < 4)) { -+ fprintf(stderr, "[FATAL] failed to allocate memory\n"); -+ exit(1); - } - if (rb_thread_raised_p(th, RAISED_NOMEMORY)) { -- rb_exc_jump(nomem_error); -+ rb_exc_jump(nomem_error); - } - rb_thread_raised_set(th, RAISED_NOMEMORY); - rb_exc_raise(nomem_error); -@@ -139,7 +146,7 @@ ruby_xmalloc(size) - void *mem; - - if (size < 0) { -- rb_raise(rb_eNoMemError, "negative allocation size (or too big)"); -+ rb_raise(rb_eNoMemError, "negative allocation size (or too big)"); - } - if (size == 0) size = 1; - -@@ -148,11 +155,11 @@ ruby_xmalloc(size) - } - RUBY_CRITICAL(mem = malloc(size)); - if (!mem) { -- garbage_collect(); -- RUBY_CRITICAL(mem = malloc(size)); -- if (!mem) { -- rb_memerror(); -- } -+ garbage_collect(); -+ RUBY_CRITICAL(mem = malloc(size)); -+ if (!mem) { -+ rb_memerror(); -+ } - } - malloc_increase += size; - -@@ -179,17 +186,17 @@ ruby_xrealloc(ptr, size) - void *mem; - - if (size < 0) { -- rb_raise(rb_eArgError, "negative re-allocation size"); -+ rb_raise(rb_eArgError, "negative re-allocation size"); - } - if (!ptr) return xmalloc(size); - if (size == 0) size = 1; - if (ruby_gc_stress) garbage_collect(); - RUBY_CRITICAL(mem = realloc(ptr, size)); - if (!mem) { -- garbage_collect(); -- RUBY_CRITICAL(mem = realloc(ptr, size)); -- if (!mem) { -- rb_memerror(); -+ garbage_collect(); -+ RUBY_CRITICAL(mem = realloc(ptr, size)); -+ if (!mem) { -+ rb_memerror(); - } - } - malloc_increase += size; -@@ -202,11 +209,20 @@ ruby_xfree(x) - void *x; - { - if (x) -- RUBY_CRITICAL(free(x)); -+ RUBY_CRITICAL(free(x)); - } - -+#if HAVE_LONG_LONG -+#define GC_TIME_TYPE LONG_LONG -+#else -+#define GC_TIME_TYPE long -+#endif -+ - extern int ruby_in_compile; - static int dont_gc; -+static int gc_statistics = 0; -+static GC_TIME_TYPE gc_time = 0; -+static int gc_collections = 0; - static int during_gc; - static int need_call_final = 0; - static st_table *finalizer_table = 0; -@@ -241,7 +257,7 @@ rb_gc_enable() - * Disables garbage collection, returning true if garbage - * collection was already disabled. - * -- * GC.disable #=> false -+ * GC.disable #=> false or true - * GC.disable #=> true - * - */ -@@ -255,6 +271,104 @@ rb_gc_disable() - return old; - } - -+/* -+ * call-seq: -+ * GC.enable_stats => true or false -+ * -+ * Enables garbage collection statistics, returning true if garbage -+ * collection statistics was already enabled. -+ * -+ * GC.enable_stats #=> false or true -+ * GC.enable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_stats() -+{ -+ int old = gc_statistics; -+ gc_statistics = Qtrue; -+ return old; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_stats => true or false -+ * -+ * Disables garbage collection statistics, returning true if garbage -+ * collection statistics was already disabled. -+ * -+ * GC.disable_stats #=> false or true -+ * GC.disable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_stats() -+{ -+ int old = gc_statistics; -+ gc_statistics = Qfalse; -+ return old; -+} -+ -+/* -+ * call-seq: -+ * GC.clear_stats => nil -+ * -+ * Clears garbage collection statistics, returning nil. This resets the number -+ * of collections (GC.collections) and the time used (GC.time) to 0. -+ * -+ * GC.clear_stats #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_clear_stats() -+{ -+ gc_collections = 0; -+ gc_time = 0; -+ return Qnil; -+} -+ -+/* -+ * call-seq: -+ * GC.collections => Integer -+ * -+ * Returns the number of garbage collections performed while GC statistics collection -+ * was enabled. -+ * -+ * GC.collections #=> 35 -+ * -+ */ -+ -+VALUE -+rb_gc_collections() -+{ -+ return INT2NUM(gc_collections); -+} -+ -+/* -+ * call-seq: -+ * GC.time => Integer -+ * -+ * Returns the time spent during garbage collection while GC statistics collection -+ * was enabled (in micro seconds). -+ * -+ * GC.time #=> 20000 -+ * -+ */ -+ -+VALUE -+rb_gc_time() -+{ -+#if HAVE_LONG_LONG -+ return LL2NUM(gc_time); -+#else -+ return LONG2NUM(gc_time); -+#endif -+} -+ -+ - VALUE rb_mGC; - - static struct gc_list { -@@ -281,19 +395,19 @@ rb_gc_unregister_address(addr) - struct gc_list *tmp = global_List; - - if (tmp->varptr == addr) { -- global_List = tmp->next; -- RUBY_CRITICAL(free(tmp)); -- return; -+ global_List = tmp->next; -+ RUBY_CRITICAL(free(tmp)); -+ return; - } - while (tmp->next) { -- if (tmp->next->varptr == addr) { -- struct gc_list *t = tmp->next; -+ if (tmp->next->varptr == addr) { -+ struct gc_list *t = tmp->next; - -- tmp->next = tmp->next->next; -- RUBY_CRITICAL(free(t)); -- break; -- } -- tmp = tmp->next; -+ tmp->next = tmp->next->next; -+ RUBY_CRITICAL(free(t)); -+ break; -+ } -+ tmp = tmp->next; - } - } - -@@ -312,26 +426,26 @@ rb_global_variable(var) - - typedef struct RVALUE { - union { -- struct { -- unsigned long flags; /* always 0 for freed obj */ -- 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; -- struct RStruct rstruct; -- struct RBignum bignum; -- struct RFile file; -- struct RNode node; -- struct RMatch match; -- struct RVarmap varmap; -- struct SCOPE scope; -+ struct { -+ unsigned long flags; /* always 0 for freed obj */ -+ 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; -+ struct RStruct rstruct; -+ struct RBignum bignum; -+ struct RFile file; -+ struct RNode node; -+ struct RMatch match; -+ struct RVarmap varmap; -+ struct SCOPE scope; - } as; - #ifdef GC_DEBUG - char *file; -@@ -346,7 +460,7 @@ typedef struct RVALUE { - static RVALUE *freelist = 0; - static RVALUE *deferred_final_list = 0; - --#define HEAPS_INCREMENT 10 -+static int heaps_increment = 10; - static struct heaps_slot { - void *membase; - RVALUE *slot; -@@ -355,45 +469,197 @@ static struct heaps_slot { - static int heaps_length = 0; - static int heaps_used = 0; - --#define HEAP_MIN_SLOTS 10000 --static int heap_slots = HEAP_MIN_SLOTS; -+static int heap_min_slots = 10000; -+static int heap_slots = 10000; - --#define FREE_MIN 4096 -+static int heap_free_min = 4096; -+static int heap_slots_increment = 10000; -+static double heap_slots_growth_factor = 1.8; -+ -+static long initial_malloc_limit = GC_MALLOC_LIMIT; -+ -+static int verbose_gc_stats = Qfalse; -+ -+static FILE* gc_data_file = NULL; - - static RVALUE *himem, *lomem; - -+static void set_gc_parameters() -+{ -+ char *gc_stats_ptr, *min_slots_ptr, *free_min_ptr, *heap_slots_incr_ptr, -+ *heap_incr_ptr, *malloc_limit_ptr, *gc_heap_file_ptr, *heap_slots_growth_factor_ptr; -+ -+ gc_data_file = stderr; -+ -+ gc_stats_ptr = getenv("RUBY_GC_STATS"); -+ if (gc_stats_ptr != NULL) { -+ int gc_stats_i = atoi(gc_stats_ptr); -+ if (gc_stats_i > 0) { -+ verbose_gc_stats = Qtrue; -+ } -+ } -+ -+ gc_heap_file_ptr = getenv("RUBY_GC_DATA_FILE"); -+ if (gc_heap_file_ptr != NULL) { -+ FILE* data_file = fopen(gc_heap_file_ptr, "w"); -+ if (data_file != NULL) { -+ gc_data_file = data_file; -+ } -+ else { -+ fprintf(stderr, -+ "can't open gc log file %s for writing, using default\n", gc_heap_file_ptr); -+ } -+ } -+ -+ min_slots_ptr = getenv("RUBY_HEAP_MIN_SLOTS"); -+ if (min_slots_ptr != NULL) { -+ int min_slots_i = atoi(min_slots_ptr); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_MIN_SLOTS=%s\n", min_slots_ptr); -+ } -+ if (min_slots_i > 0) { -+ heap_slots = min_slots_i; -+ heap_min_slots = min_slots_i; -+ } -+ } -+ -+ free_min_ptr = getenv("RUBY_HEAP_FREE_MIN"); -+ if (free_min_ptr != NULL) { -+ int free_min_i = atoi(free_min_ptr); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_FREE_MIN=%s\n", free_min_ptr); -+ } -+ if (free_min_i > 0) { -+ heap_free_min = free_min_i; -+ } -+ } -+ -+ heap_incr_ptr = getenv("RUBY_HEAP_INCREMENT"); -+ if (heap_incr_ptr != NULL) { -+ int heap_incr_i = atoi(heap_incr_ptr); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_INCREMENT=%s\n", heap_incr_ptr); -+ } -+ if (heap_incr_i > 0) { -+ heaps_increment = heap_incr_i; -+ } -+ } -+ -+ heap_slots_incr_ptr = getenv("RUBY_HEAP_SLOTS_INCREMENT"); -+ if (heap_slots_incr_ptr != NULL) { -+ int heap_slots_incr_i = atoi(heap_slots_incr_ptr); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_INCREMENT=%s\n", heap_slots_incr_ptr); -+ } -+ if (heap_slots_incr_i > 0) { -+ heap_slots_increment = heap_slots_incr_i; -+ } -+ } -+ -+ heap_slots_growth_factor_ptr = getenv("RUBY_HEAP_SLOTS_GROWTH_FACTOR"); -+ if (heap_slots_growth_factor_ptr != NULL) { -+ double heap_slots_growth_factor_d = atoi(heap_slots_growth_factor_ptr); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_GROWTH_FACTOR=%s\n", heap_slots_growth_factor_ptr); -+ } -+ if (heap_slots_growth_factor_d > 0) { -+ heap_slots_growth_factor = heap_slots_growth_factor_d; -+ } -+ } -+ -+ malloc_limit_ptr = getenv("RUBY_GC_MALLOC_LIMIT"); -+ if (malloc_limit_ptr != NULL) { -+ int malloc_limit_i = atol(malloc_limit_ptr); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_GC_MALLOC_LIMIT=%s\n", malloc_limit_ptr); -+ } -+ if (malloc_limit_i > 0) { -+ initial_malloc_limit = malloc_limit_i; -+ } -+ } -+} -+ -+/* -+ * call-seq: -+ * GC.dump => nil -+ * -+ * dumps information about the current GC data structures to the GC log file -+ * -+ * GC.dump #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_dump() -+{ -+ int i; -+ -+ for (i = 0; i < heaps_used; i++) { -+ int heap_size = heaps[i].limit; -+ fprintf(gc_data_file, "HEAP[%2d]: size=%7d\n", i, heap_size); -+ } -+ -+ return Qnil; -+} -+ -+/* -+ * call-seq: -+ * GC.log String => String -+ * -+ * Logs string to the GC data file and returns it. -+ * -+ * GC.log "manual GC call" #=> "manual GC call" -+ * -+ */ -+ -+VALUE -+rb_gc_log(self, original_str) -+ VALUE self, original_str; -+{ -+ if (original_str == Qnil) { -+ fprintf(gc_data_file, "\n"); -+ } -+ else { -+ VALUE str = StringValue(original_str); -+ char *p = RSTRING(str)->ptr; -+ fprintf(gc_data_file, "%s\n", p); -+ } -+ return original_str; -+} -+ -+ - static void - add_heap() - { - RVALUE *p, *pend; - - if (heaps_used == heaps_length) { -- /* Realloc heaps */ -- struct heaps_slot *p; -- int length; -- -- heaps_length += HEAPS_INCREMENT; -- length = heaps_length*sizeof(struct heaps_slot); -- RUBY_CRITICAL( -- if (heaps_used > 0) { -- p = (struct heaps_slot *)realloc(heaps, length); -- if (p) heaps = p; -- } -- else { -- p = heaps = (struct heaps_slot *)malloc(length); -- }); -- if (p == 0) rb_memerror(); -+ /* Realloc heaps */ -+ struct heaps_slot *p; -+ int length; -+ -+ heaps_length += heaps_increment; -+ length = heaps_length*sizeof(struct heaps_slot); -+ RUBY_CRITICAL( -+ if (heaps_used > 0) { -+ p = (struct heaps_slot *)realloc(heaps, length); -+ if (p) heaps = p; -+ } -+ else { -+ p = heaps = (struct heaps_slot *)malloc(length); -+ }); -+ if (p == 0) rb_memerror(); - } - - for (;;) { -- RUBY_CRITICAL(p = (RVALUE*)malloc(sizeof(RVALUE)*(heap_slots+1))); -- if (p == 0) { -- if (heap_slots == HEAP_MIN_SLOTS) { -- rb_memerror(); -- } -- heap_slots = HEAP_MIN_SLOTS; -- continue; -- } -+ RUBY_CRITICAL(p = (RVALUE*)malloc(sizeof(RVALUE)*(heap_slots+1))); -+ if (p == 0) { -+ if (heap_slots == heap_min_slots) { -+ rb_memerror(); -+ } -+ heap_slots = heap_min_slots; -+ continue; -+ } - heaps[heaps_used].membase = p; - if ((VALUE)p % sizeof(RVALUE) == 0) - heap_slots += 1; -@@ -401,25 +667,26 @@ add_heap() - p = (RVALUE*)((VALUE)p + sizeof(RVALUE) - ((VALUE)p % sizeof(RVALUE))); - heaps[heaps_used].slot = p; - heaps[heaps_used].limit = heap_slots; -- break; -+ break; - } - pend = p + heap_slots; - if (lomem == 0 || lomem > p) lomem = p; - if (himem < pend) himem = pend; - heaps_used++; -- heap_slots *= 1.8; -- if (heap_slots <= 0) heap_slots = HEAP_MIN_SLOTS; -+ heap_slots += heap_slots_increment; -+ heap_slots_increment *= heap_slots_growth_factor; -+ if (heap_slots <= 0) heap_slots = heap_min_slots; - - while (p < pend) { -- p->as.free.flags = 0; -- p->as.free.next = freelist; -- freelist = p; -- p++; -+ p->as.free.flags = 0; -+ p->as.free.next = freelist; -+ freelist = p; -+ p++; - } - } - #define RANY(o) ((RVALUE*)(o)) - --int -+int - rb_during_gc() - { - return during_gc; -@@ -431,7 +698,7 @@ rb_newobj() - VALUE obj; - - if (during_gc) -- rb_bug("object allocation during garbage collection phase"); -+ rb_bug("object allocation during garbage collection phase"); - - if (ruby_gc_stress || !freelist) garbage_collect(); - -@@ -580,13 +847,13 @@ rb_source_filename(f) - st_data_t name; - - if (!st_lookup(source_filenames, (st_data_t)f, &name)) { -- long len = strlen(f) + 1; -- char *ptr = ALLOC_N(char, len + 1); -- name = (st_data_t)ptr; -- *ptr++ = 0; -- MEMCPY(ptr, f, char, len); -- st_add_direct(source_filenames, (st_data_t)ptr, name); -- return ptr; -+ long len = strlen(f) + 1; -+ char *ptr = ALLOC_N(char, len + 1); -+ name = (st_data_t)ptr; -+ *ptr++ = 0; -+ MEMCPY(ptr, f, char, len); -+ st_add_direct(source_filenames, (st_data_t)ptr, name); -+ return ptr; - } - return (char *)name + 1; - } -@@ -596,7 +863,7 @@ mark_source_filename(f) - char *f; - { - if (f) { -- f[-1] = 1; -+ f[-1] = 1; - } - } - -@@ -605,12 +872,12 @@ sweep_source_filename(key, value) - char *key, *value; - { - if (*value) { -- *value = 0; -- return ST_CONTINUE; -+ *value = 0; -+ return ST_CONTINUE; - } - else { -- free(value); -- return ST_DELETE; -+ free(value); -+ return ST_DELETE; - } - } - -@@ -625,14 +892,14 @@ gc_mark_all() - - init_mark_stack(); - for (i = 0; i < heaps_used; i++) { -- p = heaps[i].slot; pend = p + heaps[i].limit; -- while (p < pend) { -- if ((p->as.basic.flags & FL_MARK) && -- (p->as.basic.flags != FL_MARK)) { -- gc_mark_children((VALUE)p, 0); -- } -- p++; -- } -+ p = heaps[i].slot; pend = p + heaps[i].limit; -+ while (p < pend) { -+ if ((p->as.basic.flags & FL_MARK) && -+ (p->as.basic.flags != FL_MARK)) { -+ gc_mark_children((VALUE)p, 0); -+ } -+ p++; -+ } - } - } - -@@ -647,8 +914,8 @@ gc_mark_rest() - - init_mark_stack(); - while(p != tmp_arry){ -- p--; -- gc_mark_children(*p, 0); -+ p--; -+ gc_mark_children(*p, 0); - } - } - -@@ -665,9 +932,9 @@ is_pointer_to_heap(ptr) - - /* check if p looks like a pointer */ - for (i=0; i < heaps_used; i++) { -- heap_org = heaps[i].slot; -- if (heap_org <= p && p < heap_org + heaps[i].limit) -- return Qtrue; -+ heap_org = heaps[i].slot; -+ if (heap_org <= p && p < heap_org + heaps[i].limit) -+ return Qtrue; - } - return Qfalse; - } -@@ -680,10 +947,10 @@ mark_locations_array(x, n) - VALUE v; - while (n--) { - v = *x; -- if (is_pointer_to_heap((void *)v)) { -- gc_mark(v, 0); -- } -- x++; -+ if (is_pointer_to_heap((void *)v)) { -+ gc_mark(v, 0); -+ } -+ x++; - } - } - -@@ -780,7 +1047,7 @@ rb_gc_mark_maybe(obj) - VALUE obj; - { - if (is_pointer_to_heap((void *)obj)) { -- gc_mark(obj, 0); -+ gc_mark(obj, 0); - } - } - -@@ -828,7 +1095,7 @@ gc_mark_children(ptr, lev) - { - register RVALUE *obj = RANY(ptr); - -- goto marking; /* skip */ -+ goto marking; /* skip */ - - again: - obj = RANY(ptr); -@@ -839,148 +1106,148 @@ gc_mark_children(ptr, lev) - - marking: - if (FL_TEST(obj, FL_EXIVAR)) { -- rb_mark_generic_ivar(ptr); -+ rb_mark_generic_ivar(ptr); - } - - switch (obj->as.basic.flags & T_MASK) { - case T_NIL: - case T_FIXNUM: -- rb_bug("rb_gc_mark() called for broken object"); -- break; -+ rb_bug("rb_gc_mark() called for broken object"); -+ break; - - case T_NODE: -- mark_source_filename(obj->as.node.nd_file); -- switch (nd_type(obj)) { -- case NODE_IF: /* 1,2,3 */ -- case NODE_FOR: -- case NODE_ITER: -- case NODE_CREF: -- case NODE_WHEN: -- case NODE_MASGN: -- case NODE_RESCUE: -- case NODE_RESBODY: -- case NODE_CLASS: -- gc_mark((VALUE)obj->as.node.u2.node, lev); -- /* 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_FBODY: -- case NODE_ENSURE: -- case NODE_CALL: -- case NODE_DEFS: -- case NODE_OP_ASGN1: -- gc_mark((VALUE)obj->as.node.u1.node, lev); -- /* fall through */ -- case NODE_SUPER: /* 3 */ -- case NODE_FCALL: -- case NODE_DEFN: -- case NODE_NEWLINE: -- ptr = (VALUE)obj->as.node.u3.node; -- goto again; -- -- 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_ARGS: -- gc_mark((VALUE)obj->as.node.u1.node, lev); -- /* fall through */ -- case NODE_METHOD: /* 2 */ -- case NODE_NOT: -- case NODE_GASGN: -- case NODE_LASGN: -- case NODE_DASGN: -- case NODE_DASGN_CURR: -- case NODE_IASGN: -- case NODE_CVDECL: -- case NODE_CVASGN: -- case NODE_COLON3: -- case NODE_OPT_N: -- case NODE_EVSTR: -- case NODE_UNDEF: -- ptr = (VALUE)obj->as.node.u2.node; -- goto again; -- -- 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: -- case NODE_SVALUE: -- ptr = (VALUE)obj->as.node.u1.node; -- goto again; -- -- case NODE_SCOPE: /* 2,3 */ -- case NODE_BLOCK_PASS: -- case NODE_CDECL: -- gc_mark((VALUE)obj->as.node.u3.node, lev); -- ptr = (VALUE)obj->as.node.u2.node; -- goto again; -- -- case NODE_ZARRAY: /* - */ -- case NODE_ZSUPER: -- case NODE_CFUNC: -- 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_ATTRSET: -- case NODE_BLOCK_ARG: -- case NODE_POSTEXE: -- break; -- case NODE_ALLOCA: -- mark_locations_array((VALUE*)obj->as.node.u1.value, -- obj->as.node.u3.cnt); -- ptr = (VALUE)obj->as.node.u2.node; -- goto again; -- -- default: /* unlisted NODE */ -- if (is_pointer_to_heap(obj->as.node.u1.node)) { -- gc_mark((VALUE)obj->as.node.u1.node, lev); -- } -- if (is_pointer_to_heap(obj->as.node.u2.node)) { -- gc_mark((VALUE)obj->as.node.u2.node, lev); -- } -- if (is_pointer_to_heap(obj->as.node.u3.node)) { -- gc_mark((VALUE)obj->as.node.u3.node, lev); -- } -- } -- return; /* no need to mark class. */ -+ mark_source_filename(obj->as.node.nd_file); -+ switch (nd_type(obj)) { -+ case NODE_IF: /* 1,2,3 */ -+ case NODE_FOR: -+ case NODE_ITER: -+ case NODE_CREF: -+ case NODE_WHEN: -+ case NODE_MASGN: -+ case NODE_RESCUE: -+ case NODE_RESBODY: -+ case NODE_CLASS: -+ gc_mark((VALUE)obj->as.node.u2.node, lev); -+ /* 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_FBODY: -+ case NODE_ENSURE: -+ case NODE_CALL: -+ case NODE_DEFS: -+ case NODE_OP_ASGN1: -+ gc_mark((VALUE)obj->as.node.u1.node, lev); -+ /* fall through */ -+ case NODE_SUPER: /* 3 */ -+ case NODE_FCALL: -+ case NODE_DEFN: -+ case NODE_NEWLINE: -+ ptr = (VALUE)obj->as.node.u3.node; -+ goto again; -+ -+ 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_ARGS: -+ gc_mark((VALUE)obj->as.node.u1.node, lev); -+ /* fall through */ -+ case NODE_METHOD: /* 2 */ -+ case NODE_NOT: -+ case NODE_GASGN: -+ case NODE_LASGN: -+ case NODE_DASGN: -+ case NODE_DASGN_CURR: -+ case NODE_IASGN: -+ case NODE_CVDECL: -+ case NODE_CVASGN: -+ case NODE_COLON3: -+ case NODE_OPT_N: -+ case NODE_EVSTR: -+ case NODE_UNDEF: -+ ptr = (VALUE)obj->as.node.u2.node; -+ goto again; -+ -+ 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: -+ case NODE_SVALUE: -+ ptr = (VALUE)obj->as.node.u1.node; -+ goto again; -+ -+ case NODE_SCOPE: /* 2,3 */ -+ case NODE_BLOCK_PASS: -+ case NODE_CDECL: -+ gc_mark((VALUE)obj->as.node.u3.node, lev); -+ ptr = (VALUE)obj->as.node.u2.node; -+ goto again; -+ -+ case NODE_ZARRAY: /* - */ -+ case NODE_ZSUPER: -+ case NODE_CFUNC: -+ 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_ATTRSET: -+ case NODE_BLOCK_ARG: -+ case NODE_POSTEXE: -+ break; -+ case NODE_ALLOCA: -+ mark_locations_array((VALUE*)obj->as.node.u1.value, -+ obj->as.node.u3.cnt); -+ ptr = (VALUE)obj->as.node.u2.node; -+ goto again; -+ -+ default: /* unlisted NODE */ -+ if (is_pointer_to_heap(obj->as.node.u1.node)) { -+ gc_mark((VALUE)obj->as.node.u1.node, lev); -+ } -+ if (is_pointer_to_heap(obj->as.node.u2.node)) { -+ gc_mark((VALUE)obj->as.node.u2.node, lev); -+ } -+ if (is_pointer_to_heap(obj->as.node.u3.node)) { -+ gc_mark((VALUE)obj->as.node.u3.node, lev); -+ } -+ } -+ return; /* no need to mark class. */ - } - - gc_mark(obj->as.basic.klass, lev); -@@ -988,92 +1255,92 @@ gc_mark_children(ptr, lev) - case T_ICLASS: - case T_CLASS: - case T_MODULE: -- mark_tbl(obj->as.klass.m_tbl, lev); -- mark_tbl(obj->as.klass.iv_tbl, lev); -- ptr = obj->as.klass.super; -- goto again; -+ mark_tbl(obj->as.klass.m_tbl, lev); -+ mark_tbl(obj->as.klass.iv_tbl, lev); -+ ptr = obj->as.klass.super; -+ goto again; - - case T_ARRAY: -- if (FL_TEST(obj, ELTS_SHARED)) { -- ptr = obj->as.array.aux.shared; -- goto again; -- } -- else { -- long i, len = obj->as.array.len; -- VALUE *ptr = obj->as.array.ptr; -+ if (FL_TEST(obj, ELTS_SHARED)) { -+ ptr = obj->as.array.aux.shared; -+ goto again; -+ } -+ else { -+ long i, len = obj->as.array.len; -+ VALUE *ptr = obj->as.array.ptr; - -- for (i=0; i < len; i++) { -- gc_mark(*ptr++, lev); -- } -- } -- break; -+ for (i=0; i < len; i++) { -+ gc_mark(*ptr++, lev); -+ } -+ } -+ break; - - case T_HASH: -- mark_hash(obj->as.hash.tbl, lev); -- ptr = obj->as.hash.ifnone; -- goto again; -+ mark_hash(obj->as.hash.tbl, lev); -+ ptr = obj->as.hash.ifnone; -+ goto again; - - case T_STRING: - #define STR_ASSOC FL_USER3 /* copied from string.c */ -- if (FL_TEST(obj, ELTS_SHARED|STR_ASSOC)) { -- ptr = obj->as.string.aux.shared; -- goto again; -- } -- break; -+ if (FL_TEST(obj, ELTS_SHARED|STR_ASSOC)) { -+ ptr = obj->as.string.aux.shared; -+ goto again; -+ } -+ break; - - case T_DATA: -- if (obj->as.data.dmark) (*obj->as.data.dmark)(DATA_PTR(obj)); -- break; -+ if (obj->as.data.dmark) (*obj->as.data.dmark)(DATA_PTR(obj)); -+ break; - - case T_OBJECT: -- mark_tbl(obj->as.object.iv_tbl, lev); -- break; -+ mark_tbl(obj->as.object.iv_tbl, lev); -+ break; - - case T_FILE: - case T_REGEXP: - case T_FLOAT: - case T_BIGNUM: - case T_BLKTAG: -- break; -+ break; - - case T_MATCH: -- if (obj->as.match.str) { -- ptr = obj->as.match.str; -- goto again; -- } -- break; -+ if (obj->as.match.str) { -+ ptr = obj->as.match.str; -+ goto again; -+ } -+ break; - - case T_VARMAP: -- gc_mark(obj->as.varmap.val, lev); -- ptr = (VALUE)obj->as.varmap.next; -- goto again; -+ gc_mark(obj->as.varmap.val, lev); -+ ptr = (VALUE)obj->as.varmap.next; -+ goto again; - - case T_SCOPE: -- if (obj->as.scope.local_vars && (obj->as.scope.flags & SCOPE_MALLOC)) { -- int n = obj->as.scope.local_tbl[0]+1; -- VALUE *vars = &obj->as.scope.local_vars[-1]; -+ if (obj->as.scope.local_vars && (obj->as.scope.flags & SCOPE_MALLOC)) { -+ int n = obj->as.scope.local_tbl[0]+1; -+ VALUE *vars = &obj->as.scope.local_vars[-1]; - -- while (n--) { -- gc_mark(*vars++, lev); -- } -- } -- break; -+ while (n--) { -+ gc_mark(*vars++, lev); -+ } -+ } -+ break; - - case T_STRUCT: -- { -- long len = obj->as.rstruct.len; -- VALUE *ptr = obj->as.rstruct.ptr; -+ { -+ long len = obj->as.rstruct.len; -+ VALUE *ptr = obj->as.rstruct.ptr; - -- while (len--) { -- gc_mark(*ptr++, lev); -- } -- } -- break; -+ while (len--) { -+ gc_mark(*ptr++, lev); -+ } -+ } -+ break; - - default: -- rb_bug("rb_gc_mark(): unknown data type 0x%lx(0x%lx) %s", -- obj->as.basic.flags & T_MASK, obj, -- is_pointer_to_heap(obj) ? "corrupted object" : "non object"); -+ rb_bug("rb_gc_mark(): unknown data type 0x%lx(0x%lx) %s", -+ obj->as.basic.flags & T_MASK, obj, -+ is_pointer_to_heap(obj) ? "corrupted object" : "non object"); - } - } - -@@ -1102,22 +1369,55 @@ finalize_list(p) - } - } - -+static char* obj_type(int tp) -+{ -+ switch (tp) { -+ case T_NIL : return "NIL"; -+ case T_OBJECT : return "OBJECT"; -+ case T_CLASS : return "CLASS"; -+ case T_ICLASS : return "ICLASS"; -+ case T_MODULE : return "MODULE"; -+ case T_FLOAT : return "FLOAT"; -+ case T_STRING : return "STRING"; -+ case T_REGEXP : return "REGEXP"; -+ case T_ARRAY : return "ARRAY"; -+ case T_FIXNUM : return "FIXNUM"; -+ case T_HASH : return "HASH"; -+ case T_STRUCT : return "STRUCT"; -+ case T_BIGNUM : return "BIGNUM"; -+ case T_FILE : return "FILE"; -+ -+ case T_TRUE : return "TRUE"; -+ case T_FALSE : return "FALSE"; -+ case T_DATA : return "DATA"; -+ case T_MATCH : return "MATCH"; -+ case T_SYMBOL : return "SYMBOL"; -+ -+ case T_BLKTAG : return "BLKTAG"; -+ case T_UNDEF : return "UNDEF"; -+ case T_VARMAP : return "VARMAP"; -+ case T_SCOPE : return "SCOPE"; -+ case T_NODE : return "NODE"; -+ default: return "____"; -+ } -+} -+ - static void - free_unused_heaps() - { - int i, j; - - for (i = j = 1; j < heaps_used; i++) { -- if (heaps[i].limit == 0) { -- free(heaps[i].membase); -- heaps_used--; -- } -- else { -- if (i != j) { -- heaps[j] = heaps[i]; -- } -- j++; -- } -+ if (heaps[i].limit == 0) { -+ free(heaps[i].membase); -+ heaps_used--; -+ } -+ else { -+ if (i != j) { -+ heaps[j] = heaps[i]; -+ } -+ j++; -+ } - } - } - -@@ -1134,24 +1434,33 @@ gc_sweep() - unsigned long live = 0; - unsigned long free_min = 0; - -+ unsigned long really_freed = 0; -+ int free_counts[256]; -+ int live_counts[256]; -+ int do_gc_stats = gc_statistics & verbose_gc_stats; -+ - for (i = 0; i < heaps_used; i++) { - free_min += heaps[i].limit; - } - free_min = free_min * 0.2; -- if (free_min < FREE_MIN) -- free_min = FREE_MIN; -+ if (free_min < heap_free_min) -+ free_min = heap_free_min; -+ -+ if (do_gc_stats) { -+ for (i = 0 ; i< 256; i++) { free_counts[i] = live_counts[i] = 0; } -+ } - - if (ruby_in_compile && ruby_parser_stack_on_heap()) { -- /* should not reclaim nodes during compilation -+ /* should not reclaim nodes during compilation - if yacc's semantic stack is not allocated on machine stack */ -- for (i = 0; i < heaps_used; i++) { -- p = heaps[i].slot; pend = p + heaps[i].limit; -- while (p < pend) { -- if (!(p->as.basic.flags&FL_MARK) && BUILTIN_TYPE(p) == T_NODE) -- gc_mark((VALUE)p, 0); -- p++; -- } -- } -+ for (i = 0; i < heaps_used; i++) { -+ p = heaps[i].slot; pend = p + heaps[i].limit; -+ while (p < pend) { -+ if (!(p->as.basic.flags&FL_MARK) && BUILTIN_TYPE(p) == T_NODE) -+ gc_mark((VALUE)p, 0); -+ p++; -+ } -+ } - } - - mark_source_filename(ruby_sourcefile); -@@ -1172,7 +1481,7 @@ gc_sweep() - while (p < pend) { - if (!(p->as.basic.flags & FL_MARK)) { - if (p->as.basic.flags && -- ((deferred = obj_free((VALUE)p)) || -+ (((do_gc_stats && really_freed++), deferred = obj_free((VALUE)p)) || - ((FL_TEST(p, FL_FINALIZE)) && need_call_final))) { - if (!deferred) { - p->as.free.flags = T_DEFERRED; -@@ -1183,6 +1492,12 @@ gc_sweep() - final_list = p; - } - else { -+ if (do_gc_stats) { -+ int obt = p->as.basic.flags & T_MASK; -+ if (obt) { -+ free_counts[obt]++; -+ } -+ } - add_freelist(p); - } - n++; -@@ -1194,6 +1509,9 @@ gc_sweep() - else { - RBASIC(p)->flags &= ~FL_MARK; - live++; -+ if (do_gc_stats) { -+ live_counts[RANY((VALUE)p)->as.basic.flags & T_MASK]++; -+ } - } - p++; - } -@@ -1211,15 +1529,29 @@ gc_sweep() - } - } - if (malloc_increase > malloc_limit) { -- malloc_limit += (malloc_increase - malloc_limit) * (double)live / (live + freed); -- if (malloc_limit < GC_MALLOC_LIMIT) malloc_limit = GC_MALLOC_LIMIT; -+ malloc_limit += (malloc_increase - malloc_limit) * (double)live / (live + freed); -+ if (malloc_limit < initial_malloc_limit) malloc_limit = initial_malloc_limit; - } - malloc_increase = 0; - if (freed < free_min) { -- add_heap(); -+ add_heap(); - } - during_gc = 0; - -+ if (do_gc_stats) { -+ fprintf(gc_data_file, "objects processed: %.7d\n", live+freed); -+ fprintf(gc_data_file, "live objects : %.7d\n", live); -+ fprintf(gc_data_file, "freelist objects : %.7d\n", freed - really_freed); -+ fprintf(gc_data_file, "freed objects : %.7d\n", really_freed); -+ for(i=0; i<256; i++) { -+ if (free_counts[i]>0 || live_counts[i]>0) { -+ fprintf(gc_data_file, -+ "kept %.7d / freed %.7d objects of type %s\n", -+ live_counts[i], free_counts[i], obj_type(i)); -+ } -+ } -+ } -+ - /* clear finalization list */ - if (final_list) { - deferred_final_list = final_list; -@@ -1260,51 +1592,51 @@ obj_free(obj) - case T_FIXNUM: - case T_TRUE: - case T_FALSE: -- rb_bug("obj_free() called for broken object"); -- break; -+ rb_bug("obj_free() called for broken object"); -+ break; - } - - if (FL_TEST(obj, FL_EXIVAR)) { -- rb_free_generic_ivar((VALUE)obj); -+ rb_free_generic_ivar((VALUE)obj); - } - - switch (BUILTIN_TYPE(obj)) { - case T_OBJECT: -- if (RANY(obj)->as.object.iv_tbl) { -- st_free_table(RANY(obj)->as.object.iv_tbl); -- } -- break; -+ if (RANY(obj)->as.object.iv_tbl) { -+ st_free_table(RANY(obj)->as.object.iv_tbl); -+ } -+ break; - case T_MODULE: - case T_CLASS: -- rb_clear_cache_by_class((VALUE)obj); -- st_free_table(RANY(obj)->as.klass.m_tbl); -- if (RANY(obj)->as.object.iv_tbl) { -- st_free_table(RANY(obj)->as.object.iv_tbl); -- } -- break; -+ rb_clear_cache_by_class((VALUE)obj); -+ st_free_table(RANY(obj)->as.klass.m_tbl); -+ if (RANY(obj)->as.object.iv_tbl) { -+ st_free_table(RANY(obj)->as.object.iv_tbl); -+ } -+ break; - case T_STRING: -- if (RANY(obj)->as.string.ptr && !FL_TEST(obj, ELTS_SHARED)) { -- RUBY_CRITICAL(free(RANY(obj)->as.string.ptr)); -- } -- break; -+ if (RANY(obj)->as.string.ptr && !FL_TEST(obj, ELTS_SHARED)) { -+ RUBY_CRITICAL(free(RANY(obj)->as.string.ptr)); -+ } -+ break; - case T_ARRAY: -- if (RANY(obj)->as.array.ptr && !FL_TEST(obj, ELTS_SHARED)) { -- RUBY_CRITICAL(free(RANY(obj)->as.array.ptr)); -- } -- break; -+ if (RANY(obj)->as.array.ptr && !FL_TEST(obj, ELTS_SHARED)) { -+ RUBY_CRITICAL(free(RANY(obj)->as.array.ptr)); -+ } -+ break; - case T_HASH: -- if (RANY(obj)->as.hash.tbl) { -- st_free_table(RANY(obj)->as.hash.tbl); -- } -- break; -+ if (RANY(obj)->as.hash.tbl) { -+ st_free_table(RANY(obj)->as.hash.tbl); -+ } -+ break; - case T_REGEXP: -- if (RANY(obj)->as.regexp.ptr) { -- re_free_pattern(RANY(obj)->as.regexp.ptr); -- } -- if (RANY(obj)->as.regexp.str) { -- RUBY_CRITICAL(free(RANY(obj)->as.regexp.str)); -- } -- break; -+ if (RANY(obj)->as.regexp.ptr) { -+ re_free_pattern(RANY(obj)->as.regexp.ptr); -+ } -+ if (RANY(obj)->as.regexp.str) { -+ RUBY_CRITICAL(free(RANY(obj)->as.regexp.str)); -+ } -+ break; - case T_DATA: - if (DATA_PTR(obj)) { - if ((long)RANY(obj)->as.data.dfree == -1) { -@@ -1317,11 +1649,11 @@ obj_free(obj) - } - break; - case T_MATCH: -- if (RANY(obj)->as.match.regs) { -- re_free_registers(RANY(obj)->as.match.regs); -- RUBY_CRITICAL(free(RANY(obj)->as.match.regs)); -- } -- break; -+ if (RANY(obj)->as.match.regs) { -+ re_free_registers(RANY(obj)->as.match.regs); -+ RUBY_CRITICAL(free(RANY(obj)->as.match.regs)); -+ } -+ break; - case T_FILE: - if (RANY(obj)->as.file.fptr) { - struct rb_io_t *fptr = RANY(obj)->as.file.fptr; -@@ -1332,19 +1664,19 @@ obj_free(obj) - } - break; - case T_ICLASS: -- /* iClass shares table with the module */ -- break; -+ /* iClass shares table with the module */ -+ break; - - case T_FLOAT: - case T_VARMAP: - case T_BLKTAG: -- break; -+ break; - - case T_BIGNUM: -- if (RANY(obj)->as.bignum.digits) { -- RUBY_CRITICAL(free(RANY(obj)->as.bignum.digits)); -- } -- break; -+ if (RANY(obj)->as.bignum.digits) { -+ RUBY_CRITICAL(free(RANY(obj)->as.bignum.digits)); -+ } -+ break; - case T_NODE: - switch (nd_type(obj)) { - case NODE_SCOPE: -@@ -1359,7 +1691,7 @@ obj_free(obj) - break; /* no need to free iv_tbl */ - - case T_SCOPE: -- if (RANY(obj)->as.scope.local_vars && -+ if (RANY(obj)->as.scope.local_vars && - RANY(obj)->as.scope.flags != SCOPE_ALLOCA) { - VALUE *vars = RANY(obj)->as.scope.local_vars-1; - if (!(RANY(obj)->as.scope.flags & SCOPE_CLONE) && vars[0] == 0) -@@ -1370,14 +1702,14 @@ obj_free(obj) - break; - - case T_STRUCT: -- if (RANY(obj)->as.rstruct.ptr) { -- RUBY_CRITICAL(free(RANY(obj)->as.rstruct.ptr)); -- } -- break; -+ if (RANY(obj)->as.rstruct.ptr) { -+ RUBY_CRITICAL(free(RANY(obj)->as.rstruct.ptr)); -+ } -+ break; - - default: -- rb_bug("gc_sweep(): unknown data type 0x%lx(0x%lx)", -- RANY(obj)->as.basic.flags & T_MASK, obj); -+ rb_bug("gc_sweep(): unknown data type 0x%lx(0x%lx)", -+ RANY(obj)->as.basic.flags & T_MASK, obj); - } - - return 0; -@@ -1407,18 +1739,18 @@ _rb_setjmp:\n\ - typedef unsigned long rb_jmp_buf[6]; - __asm__ (".align 4\n\ - _rb_setjmp:\n\ -- pushl %ebp\n\ -- movl %esp,%ebp\n\ -- movl 8(%ebp),%ebp\n\ -- movl %eax,(%ebp)\n\ -- movl %ebx,4(%ebp)\n\ -- movl %ecx,8(%ebp)\n\ -- movl %edx,12(%ebp)\n\ -- movl %esi,16(%ebp)\n\ -- movl %edi,20(%ebp)\n\ -- popl %ebp\n\ -- xorl %eax,%eax\n\ -- ret"); -+ pushl %ebp\n\ -+ movl %esp,%ebp\n\ -+ movl 8(%ebp),%ebp\n\ -+ movl %eax,(%ebp)\n\ -+ movl %ebx,4(%ebp)\n\ -+ movl %ecx,8(%ebp)\n\ -+ movl %edx,12(%ebp)\n\ -+ movl %esi,16(%ebp)\n\ -+ movl %edi,20(%ebp)\n\ -+ popl %ebp\n\ -+ xorl %eax,%eax\n\ -+ ret"); - #endif - #endif - int rb_setjmp (rb_jmp_buf); -@@ -1431,41 +1763,50 @@ garbage_collect() - struct gc_list *list; - struct FRAME * volatile frame; /* gcc 2.7.2.3 -O2 bug?? */ - jmp_buf save_regs_gc_mark; -+ struct timeval gctv1, gctv2; - SET_STACK_END; - - #ifdef HAVE_NATIVETHREAD - if (!is_ruby_native_thread()) { -- rb_bug("cross-thread violation on rb_gc()"); -+ rb_bug("cross-thread violation on rb_gc()"); - } - #endif - if (dont_gc || during_gc) { -- if (!freelist) { -- add_heap(); -- } -- return; -+ if (!freelist) { -+ add_heap(); -+ } -+ return; - } - if (during_gc) return; - during_gc++; - -+ if (gc_statistics) { -+ gc_collections++; -+ gettimeofday(&gctv1, NULL); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "Garbage collection started\n"); -+ } -+ } -+ - init_mark_stack(); - - gc_mark((VALUE)ruby_current_node, 0); - - /* mark frame stack */ - for (frame = ruby_frame; frame; frame = frame->prev) { -- rb_gc_mark_frame(frame); -- if (frame->tmp) { -- struct FRAME *tmp = frame->tmp; -- while (tmp) { -- rb_gc_mark_frame(tmp); -- tmp = tmp->prev; -- } -- } -+ rb_gc_mark_frame(frame); -+ if (frame->tmp) { -+ struct FRAME *tmp = frame->tmp; -+ while (tmp) { -+ rb_gc_mark_frame(tmp); -+ tmp = tmp->prev; -+ } -+ } - } - gc_mark((VALUE)ruby_scope, 0); - gc_mark((VALUE)ruby_dyna_vars, 0); - if (finalizer_table) { -- mark_tbl(finalizer_table, 0); -+ mark_tbl(finalizer_table, 0); - } - - FLUSH_REGISTER_WINDOWS; -@@ -1478,9 +1819,9 @@ garbage_collect() - rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)STACK_END + 1); - #else - if ((VALUE*)STACK_END < rb_gc_stack_start) -- rb_gc_mark_locations((VALUE*)STACK_END, rb_gc_stack_start); -+ rb_gc_mark_locations((VALUE*)STACK_END, rb_gc_stack_start); - else -- rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)STACK_END + 1); -+ rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)STACK_END + 1); - #endif - #ifdef __ia64 - /* mark backing store (flushed register window on the stack) */ -@@ -1489,13 +1830,13 @@ garbage_collect() - #endif - #if defined(__human68k__) || defined(__mc68000__) - rb_gc_mark_locations((VALUE*)((char*)STACK_END + 2), -- (VALUE*)((char*)rb_gc_stack_start + 2)); -+ (VALUE*)((char*)rb_gc_stack_start + 2)); - #endif - rb_gc_mark_threads(); - - /* mark protected global variables */ - for (list = global_List; list; list = list->next) { -- rb_gc_mark_maybe(*list->varptr); -+ rb_gc_mark_maybe(*list->varptr); - } - rb_mark_end_proc(); - rb_gc_mark_global_tbl(); -@@ -1510,18 +1851,30 @@ garbage_collect() - - /* gc_mark objects whose marking are not completed*/ - do { -- while (!MARK_STACK_EMPTY) { -- if (mark_stack_overflow){ -- gc_mark_all(); -- } -- else { -- gc_mark_rest(); -- } -- } -- rb_gc_abort_threads(); -+ while (!MARK_STACK_EMPTY) { -+ if (mark_stack_overflow){ -+ gc_mark_all(); -+ } -+ else { -+ gc_mark_rest(); -+ } -+ } -+ rb_gc_abort_threads(); - } while (!MARK_STACK_EMPTY); - - gc_sweep(); -+ -+ if (gc_statistics) { -+ GC_TIME_TYPE musecs_used; -+ gettimeofday(&gctv2, NULL); -+ musecs_used = ((GC_TIME_TYPE)(gctv2.tv_sec - gctv1.tv_sec) * 1000000) + (gctv2.tv_usec - gctv1.tv_usec); -+ gc_time += musecs_used; -+ -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "GC time: %d msec\n", musecs_used / 1000); -+ fflush(gc_data_file); -+ } -+ } - } - - void -@@ -1588,8 +1941,8 @@ Init_stack(addr) - memset(&m, 0, sizeof(m)); - VirtualQuery(&m, &m, sizeof(m)); - rb_gc_stack_start = -- STACK_UPPER((VALUE *)&m, (VALUE *)m.BaseAddress, -- (VALUE *)((char *)m.BaseAddress + m.RegionSize) - 1); -+ STACK_UPPER((VALUE *)&m, (VALUE *)m.BaseAddress, -+ (VALUE *)((char *)m.BaseAddress + m.RegionSize) - 1); - #elif defined(STACK_END_ADDRESS) - { - extern void *STACK_END_ADDRESS; -@@ -1599,24 +1952,24 @@ Init_stack(addr) - if (!addr) addr = (void *)&addr; - STACK_UPPER(&addr, addr, ++addr); - if (rb_gc_stack_start) { -- if (STACK_UPPER(&addr, -- rb_gc_stack_start > addr, -- rb_gc_stack_start < addr)) -- rb_gc_stack_start = addr; -- return; -+ if (STACK_UPPER(&addr, -+ rb_gc_stack_start > addr, -+ rb_gc_stack_start < addr)) -+ rb_gc_stack_start = addr; -+ return; - } - rb_gc_stack_start = addr; - #endif - #ifdef HAVE_GETRLIMIT - { -- struct rlimit rlim; -+ struct rlimit rlim; - -- if (getrlimit(RLIMIT_STACK, &rlim) == 0) { -- unsigned int space = rlim.rlim_cur/5; -+ if (getrlimit(RLIMIT_STACK, &rlim) == 0) { -+ unsigned int space = rlim.rlim_cur/5; - -- if (space > 1024*1024) space = 1024*1024; -- STACK_LEVEL_MAX = (rlim.rlim_cur - space) / sizeof(VALUE); -- } -+ if (space > 1024*1024) space = 1024*1024; -+ STACK_LEVEL_MAX = (rlim.rlim_cur - space) / sizeof(VALUE); -+ } - } - #endif - } -@@ -1652,16 +2005,16 @@ void ruby_init_stack(VALUE *addr - } - #elif defined _WIN32 - { -- MEMORY_BASIC_INFORMATION mi; -- DWORD size; -- DWORD space; -- -- if (VirtualQuery(&mi, &mi, sizeof(mi))) { -- size = (char *)mi.BaseAddress - (char *)mi.AllocationBase; -- space = size / 5; -- if (space > 1024*1024) space = 1024*1024; -- STACK_LEVEL_MAX = (size - space) / sizeof(VALUE); -- } -+ MEMORY_BASIC_INFORMATION mi; -+ DWORD size; -+ DWORD space; -+ -+ if (VirtualQuery(&mi, &mi, sizeof(mi))) { -+ size = (char *)mi.BaseAddress - (char *)mi.AllocationBase; -+ space = size / 5; -+ if (space > 1024*1024) space = 1024*1024; -+ STACK_LEVEL_MAX = (size - space) / sizeof(VALUE); -+ } - } - #endif - } -@@ -1701,8 +2054,9 @@ void - Init_heap() - { - if (!rb_gc_stack_start) { -- Init_stack(0); -+ Init_stack(0); - } -+ set_gc_parameters(); - add_heap(); - } - -@@ -1715,7 +2069,7 @@ os_obj_of(of) - volatile VALUE v; - - for (i = 0; i < heaps_used; i++) { -- RVALUE *p, *pend; -+ RVALUE *p, *pend; - - p = heaps[i].slot; pend = p + heaps[i].limit; - for (;p < pend; p++) { -@@ -1808,8 +2162,8 @@ add_final(os, block) - { - rb_warn("ObjectSpace::add_finalizer is deprecated; use define_finalizer"); - if (!rb_respond_to(block, rb_intern("call"))) { -- rb_raise(rb_eArgError, "wrong type argument %s (should be callable)", -- rb_obj_classname(block)); -+ rb_raise(rb_eArgError, "wrong type argument %s (should be callable)", -+ rb_obj_classname(block)); - } - rb_ary_push(finalizers, block); - return block; -@@ -1864,7 +2218,7 @@ undefine_final(os, obj) - VALUE os, obj; - { - if (finalizer_table) { -- st_delete(finalizer_table, (st_data_t*)&obj, 0); -+ st_delete(finalizer_table, (st_data_t*)&obj, 0); - } - return obj; - } -@@ -1888,11 +2242,11 @@ define_final(argc, argv, os) - - rb_scan_args(argc, argv, "11", &obj, &block); - if (argc == 1) { -- block = rb_block_proc(); -+ block = rb_block_proc(); - } - else if (!rb_respond_to(block, rb_intern("call"))) { -- rb_raise(rb_eArgError, "wrong type argument %s (should be callable)", -- rb_obj_classname(block)); -+ rb_raise(rb_eArgError, "wrong type argument %s (should be callable)", -+ rb_obj_classname(block)); - } - need_call_final = 1; - if (!FL_ABLE(obj)) { -@@ -1905,10 +2259,10 @@ define_final(argc, argv, os) - OBJ_FREEZE(block); - - if (!finalizer_table) { -- finalizer_table = st_init_numtable(); -+ finalizer_table = st_init_numtable(); - } - if (st_lookup(finalizer_table, obj, &table)) { -- rb_ary_push(table, block); -+ rb_ary_push(table, block); - } - else { - table = rb_ary_new3(1, block); -@@ -1927,7 +2281,7 @@ rb_gc_copy_finalizer(dest, obj) - if (!finalizer_table) return; - if (!FL_TEST(obj, FL_FINALIZE)) return; - if (st_lookup(finalizer_table, obj, &table)) { -- st_insert(finalizer_table, dest, table); -+ st_insert(finalizer_table, dest, table); - } - RBASIC(dest)->flags |= FL_FINALIZE; - } -@@ -1957,18 +2311,18 @@ run_final(obj) - args[1] = 0; - args[2] = (VALUE)ruby_safe_level; - for (i=0; ilen; i++) { -- args[0] = RARRAY(finalizers)->ptr[i]; -- if (!args[1]) args[1] = rb_ary_new3(1, objid); -- rb_protect((VALUE(*)_((VALUE)))run_single_final, (VALUE)args, &status); -+ args[0] = RARRAY(finalizers)->ptr[i]; -+ if (!args[1]) args[1] = rb_ary_new3(1, objid); -+ rb_protect((VALUE(*)_((VALUE)))run_single_final, (VALUE)args, &status); - } - if (finalizer_table && st_delete(finalizer_table, (st_data_t*)&obj, &table)) { -- for (i=0; ilen; i++) { -- VALUE final = RARRAY(table)->ptr[i]; -- args[0] = RARRAY(final)->ptr[1]; -- if (!args[1]) args[1] = rb_ary_new3(1, objid); -- args[2] = FIX2INT(RARRAY(final)->ptr[0]); -- rb_protect((VALUE(*)_((VALUE)))run_single_final, (VALUE)args, &status); -- } -+ for (i=0; ilen; i++) { -+ VALUE final = RARRAY(table)->ptr[i]; -+ args[0] = RARRAY(final)->ptr[1]; -+ if (!args[1]) args[1] = rb_ary_new3(1, objid); -+ args[2] = FIX2INT(RARRAY(final)->ptr[0]); -+ rb_protect((VALUE(*)_((VALUE)))run_single_final, (VALUE)args, &status); -+ } - } - rb_thread_critical = critical_save; - } -@@ -1980,8 +2334,8 @@ rb_gc_finalize_deferred() - - deferred_final_list = 0; - if (p) { -- finalize_list(p); -- free_unused_heaps(); -+ finalize_list(p); -+ free_unused_heaps(); - } - } - -@@ -2061,7 +2415,7 @@ id2ref(obj, objid) - if (ptr == Qfalse) return Qfalse; - if (ptr == Qnil) return Qnil; - if (FIXNUM_P(ptr)) return (VALUE)ptr; -- ptr = objid ^ FIXNUM_FLAG; /* unset FIXNUM_FLAG */ -+ ptr = objid ^ FIXNUM_FLAG; /* unset FIXNUM_FLAG */ - - if ((ptr % sizeof(RVALUE)) == (4 << 2)) { - ID symid = ptr / sizeof(RVALUE); -@@ -2075,7 +2429,7 @@ id2ref(obj, objid) - rb_raise(rb_eRangeError, "0x%lx is not id value", p0); - } - if (BUILTIN_TYPE(ptr) == 0 || RBASIC(ptr)->klass == 0) { -- rb_raise(rb_eRangeError, "0x%lx is recycled object", p0); -+ rb_raise(rb_eRangeError, "0x%lx is recycled object", p0); - } - return (VALUE)ptr; - } -@@ -2166,6 +2520,14 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "stress=", gc_stress_set, 1); - rb_define_method(rb_mGC, "garbage_collect", rb_gc_start, 0); - -+ rb_define_singleton_method(rb_mGC, "enable_stats", rb_gc_enable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "disable_stats", rb_gc_disable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0); -+ rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); -+ rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); -+ rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); -+ rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); -+ - rb_mObSpace = rb_define_module("ObjectSpace"); - rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1); - rb_define_module_function(rb_mObSpace, "garbage_collect", rb_gc_start, 0); -@@ -2188,7 +2550,7 @@ Init_GC() - - rb_global_variable(&nomem_error); - nomem_error = rb_exc_new3(rb_eNoMemError, -- rb_obj_freeze(rb_str_new2("failed to allocate memory"))); -+ rb_obj_freeze(rb_str_new2("failed to allocate memory"))); - OBJ_TAINT(nomem_error); - OBJ_FREEZE(nomem_error); - diff --git a/patches/ruby/1.8.7/p357/railsexpress/04-display-full-stack-trace.patch b/patches/ruby/1.8.7/p357/railsexpress/04-display-full-stack-trace.patch deleted file mode 100644 index a927a80ba6..0000000000 --- a/patches/ruby/1.8.7/p357/railsexpress/04-display-full-stack-trace.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/eval.c b/eval.c -index 6ff2560..fb3307c 100644 ---- a/eval.c -+++ b/eval.c -@@ -1325,8 +1325,8 @@ error_print() - int truncate = eclass == rb_eSysStackError; - - #define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5) --#define TRACE_HEAD 8 --#define TRACE_TAIL 5 -+#define TRACE_HEAD 100 -+#define TRACE_TAIL 100 - - ep = RARRAY(errat); - for (i=1; ilen; i++) { diff --git a/patches/ruby/1.8.7/p357/railsexpress/05-better-source-file-tracing.patch b/patches/ruby/1.8.7/p357/railsexpress/05-better-source-file-tracing.patch deleted file mode 100644 index f7a4d4f24f..0000000000 --- a/patches/ruby/1.8.7/p357/railsexpress/05-better-source-file-tracing.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/eval.c b/eval.c -index fb3307c..356226e 100644 ---- a/eval.c -+++ b/eval.c -@@ -1161,7 +1161,7 @@ static VALUE trace_func = 0; - static int tracing = 0; - static void call_trace_func _((rb_event_t,NODE*,VALUE,ID,VALUE)); - --#if 0 -+#if 1 - #define SET_CURRENT_SOURCE() (ruby_sourcefile = ruby_current_node->nd_file, \ - ruby_sourceline = nd_line(ruby_current_node)) - #else diff --git a/patches/ruby/1.8.7/p357/railsexpress/06-heap-dump-support.patch b/patches/ruby/1.8.7/p357/railsexpress/06-heap-dump-support.patch deleted file mode 100644 index 5235be6bcc..0000000000 --- a/patches/ruby/1.8.7/p357/railsexpress/06-heap-dump-support.patch +++ /dev/null @@ -1,159 +0,0 @@ -diff --git a/configure.in b/configure.in -index 62b34a8..4be088c 100644 ---- a/configure.in -+++ b/configure.in -@@ -1595,6 +1595,14 @@ fi - LDFLAGS="-L. $LDFLAGS" - AC_SUBST(ARCHFILE) - -+dnl enable gc debugging -+AC_ARG_ENABLE(gcdebug, -+ [ --enable-gcdebug build garbage collector with debugging enabled. ], -+ [enable_gcdebug=$enableval]) -+if test "$enable_gcdebug" = 'yes'; then -+ AC_DEFINE(GC_DEBUG, 1) -+fi -+ - dnl build rdoc index if requested - RDOCTARGET="" - AC_ARG_ENABLE(install-doc, -diff --git a/gc.c b/gc.c -index ab71d22..9ad716f 100644 ---- a/gc.c -+++ b/gc.c -@@ -411,7 +411,6 @@ rb_gc_unregister_address(addr) - } - } - --#undef GC_DEBUG - - void - rb_global_variable(var) -@@ -602,6 +601,85 @@ rb_gc_dump() - return Qnil; - } - -+ -+static char* obj_type(int tp); -+ -+#ifdef GC_DEBUG -+/* -+ * call-seq: -+ * GC.dump_file_and_line_info(String, boolean) => nil -+ * -+ * dumps information on which currently allocated object was created by which file and on which line -+ * -+ * GC.dump_file_and_line_info(String, boolean) #=> nil -+ * -+ * The second parameter specifies whether class names should be included in the dump. -+ * Note that including class names will allocate additional string objects on the heap. -+ * -+ */ -+ -+VALUE -+rb_gc_dump_file_and_line_info(int argc, VALUE *argv) -+{ -+ VALUE filename, str, include_classnames = Qnil; -+ char *fname = NULL; -+ char *klass = NULL; -+ FILE* f = NULL; -+ int i,n = 0; -+ -+ rb_scan_args(argc, argv, "11", &filename, &include_classnames); -+ -+ str = StringValue(filename); -+ fname = RSTRING(str)->ptr; -+ f = fopen(fname, "w"); -+ -+ for (i = 0; i < heaps_used; i++) { -+ RVALUE *p, *pend; -+ -+ p = heaps[i].slot; pend = p + heaps[i].limit; -+ for (;p < pend; p++) { -+ if (p->as.basic.flags) { -+ fprintf(f, "%s:%s:%d", obj_type(p->as.basic.flags & T_MASK), p->file, p->line); -+ // rb_obj_classname will create objects on the heap, we need a better solution -+ if (include_classnames == Qtrue) { -+ /* write the class */ -+ fprintf(f, ":"); -+ switch (TYPE(p)) { -+ case T_NONE: -+ fprintf(f, "__none__"); -+ break; -+ case T_BLKTAG: -+ fprintf(f, "__blktag__"); -+ break; -+ case T_UNDEF: -+ fprintf(f, "__undef__"); -+ break; -+ case T_VARMAP: -+ fprintf(f, "__varmap__"); -+ break; -+ case T_SCOPE: -+ fprintf(f, "__scope__"); -+ break; -+ case T_NODE: -+ fprintf(f, "__node__"); -+ break; -+ default: -+ if (!p->as.basic.klass) { -+ fprintf(f, "__unknown__"); -+ } else { -+ fprintf(f, rb_obj_classname((VALUE)p)); -+ } -+ } -+ } -+ fprintf(f, "\n"); -+ } -+ } -+ } -+ fclose(f); -+ return Qnil; -+} -+#endif -+ - /* - * call-seq: - * GC.log String => String -@@ -1066,6 +1144,11 @@ gc_mark(ptr, lev) - if (obj->as.basic.flags & FL_MARK) return; /* already marked */ - obj->as.basic.flags |= FL_MARK; - -+#ifdef GC_DEBUG -+ /* mark our new reference point for sourcefile objects */ -+ mark_source_filename(RANY(obj)->file); -+#endif -+ - if (lev > GC_LEVEL_MAX || (lev == 0 && ruby_stack_check())) { - if (!mark_stack_overflow) { - if (mark_stack_ptr - mark_stack < MARK_STACK_MAX) { -@@ -1104,6 +1187,11 @@ gc_mark_children(ptr, lev) - if (obj->as.basic.flags & FL_MARK) return; /* already marked */ - obj->as.basic.flags |= FL_MARK; - -+#ifdef GC_DEBUG -+ /* mark our new reference point for sourcefile objects */ -+ mark_source_filename(RANY(obj)->file); -+#endif -+ - marking: - if (FL_TEST(obj, FL_EXIVAR)) { - rb_mark_generic_ivar(ptr); -@@ -1550,6 +1638,7 @@ gc_sweep() - live_counts[i], free_counts[i], obj_type(i)); - } - } -+ fflush(gc_data_file); - } - - /* clear finalization list */ -@@ -2526,6 +2615,9 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); - rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); - rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); -+#ifdef GC_DEBUG -+ rb_define_singleton_method(rb_mGC, "dump_file_and_line_info", rb_gc_dump_file_and_line_info, -1); -+#endif - rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); - - rb_mObSpace = rb_define_module("ObjectSpace"); diff --git a/patches/ruby/1.8.7/p357/railsexpress/07-fork-support-for-gc-logging.patch b/patches/ruby/1.8.7/p357/railsexpress/07-fork-support-for-gc-logging.patch deleted file mode 100644 index 0f01a75db0..0000000000 --- a/patches/ruby/1.8.7/p357/railsexpress/07-fork-support-for-gc-logging.patch +++ /dev/null @@ -1,249 +0,0 @@ -diff --git a/gc.c b/gc.c -index 9ad716f..a3cbe91 100644 ---- a/gc.c -+++ b/gc.c -@@ -223,6 +223,8 @@ static int dont_gc; - static int gc_statistics = 0; - static GC_TIME_TYPE gc_time = 0; - static int gc_collections = 0; -+static int verbose_gc_stats = Qfalse; -+static FILE* gc_data_file = NULL; - static int during_gc; - static int need_call_final = 0; - static st_table *finalizer_table = 0; -@@ -368,9 +370,148 @@ rb_gc_time() - #endif - } - -- - VALUE rb_mGC; - -+/* -+ * call-seq: -+ * GC.enable_trace => true or false -+ * -+ * Enables garbage collection tracing, returning true if garbage -+ * collection tracing was already enabled. -+ * -+ * GC.enable_trace #=> false or true -+ * GC.enable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_trace() -+{ -+ int old = verbose_gc_stats; -+ verbose_gc_stats = Qtrue; -+ return old; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_trace => true or false -+ * -+ * Disables garbage collection tracing, returning true if garbage -+ * collection tracing was already disabled. -+ * -+ * GC.disable_trace #=> false or true -+ * GC.disable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_trace() -+{ -+ int old = verbose_gc_stats; -+ verbose_gc_stats = Qfalse; -+ return old; -+} -+ -+char* GC_LOGFILE_IVAR = "@gc_logfile_name"; -+ -+/* -+ * call-seq: -+ * GC.log_file(filename=nil, mode="w") => boolean -+ * -+ * Changes the GC data log file. Closes the currently open logfile. -+ * Returns true if the file was successfully opened for -+ * writing. Returns false if the file could not be opened for -+ * writing. Returns the name of the current logfile (or nil) if no -+ * parameter is given. Restores logging to stderr when given nil as -+ * an argument. -+ * -+ * GC.log_file #=> nil -+ * GC.log_file "/tmp/gc.log" #=> true -+ * GC.log_file #=> "/tmp/gc.log" -+ * GC.log_file nil #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_log_file(int argc, VALUE *argv, VALUE self) -+{ -+ VALUE filename = Qnil; -+ VALUE mode_str = Qnil; -+ FILE* f = NULL; -+ char* mode = "w"; -+ -+ VALUE current_logfile_name = rb_iv_get(rb_mGC, GC_LOGFILE_IVAR); -+ -+ if (argc==0) -+ return current_logfile_name; -+ -+ rb_scan_args(argc, argv, "02", &filename, &mode_str); -+ -+ if (filename == Qnil) { -+ /* close current logfile and reset logfile to stderr */ -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+ } -+ return Qtrue; -+ } -+ -+ /* we have a real logfile name */ -+ filename = StringValue(filename); -+ -+ if (rb_equal(current_logfile_name, filename) == Qtrue) { -+ /* do nothing if we get the file name we're already logging to */ -+ return Qtrue; -+ } -+ -+ /* get mode for file opening */ -+ if (mode_str != Qnil) -+ { -+ mode = RSTRING(StringValue(mode_str))->ptr; -+ } -+ -+ /* try to open file in given mode */ -+ if (f = fopen(RSTRING(filename)->ptr, mode)) { -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ } -+ gc_data_file = f; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, filename); -+ } else { -+ return Qfalse; -+ } -+ return Qtrue; -+} -+ -+ -+/* -+ * Called from process.c before a fork. Flushes the gc log file to -+ * avoid writing the buffered output twice (once in the parent, and -+ * once in the child). -+ */ -+void -+rb_gc_before_fork() -+{ -+ /* flush gc log file */ -+ fflush(gc_data_file); -+} -+ -+/* -+ * Called from process.c after a fork in the child process. Turns off -+ * logging, disables GC stats and resets all gc counters and timing -+ * information. -+ */ -+void -+rb_gc_after_fork() -+{ -+ rb_gc_disable_stats(); -+ rb_gc_clear_stats(); -+ rb_gc_disable_trace(); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+} -+ - static struct gc_list { - VALUE *varptr; - struct gc_list *next; -@@ -477,10 +618,6 @@ static double heap_slots_growth_factor = 1.8; - - static long initial_malloc_limit = GC_MALLOC_LIMIT; - --static int verbose_gc_stats = Qfalse; -- --static FILE* gc_data_file = NULL; -- - static RVALUE *himem, *lomem; - - static void set_gc_parameters() -@@ -496,6 +633,8 @@ static void set_gc_parameters() - if (gc_stats_i > 0) { - verbose_gc_stats = Qtrue; - } -+ /* child processes should not inherit RUBY_GC_STATS */ -+ unsetenv("RUBY_GC_STATS"); - } - - gc_heap_file_ptr = getenv("RUBY_GC_DATA_FILE"); -@@ -508,6 +647,8 @@ static void set_gc_parameters() - fprintf(stderr, - "can't open gc log file %s for writing, using default\n", gc_heap_file_ptr); - } -+ /* child processes should not inherit RUBY_GC_DATA_FILE to avoid clobbering */ -+ unsetenv("RUBY_GC_DATA_FILE"); - } - - min_slots_ptr = getenv("RUBY_HEAP_MIN_SLOTS"); -@@ -2619,6 +2760,9 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "dump_file_and_line_info", rb_gc_dump_file_and_line_info, -1); - #endif - rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); -+ rb_define_singleton_method(rb_mGC, "log_file", rb_gc_log_file, -1); -+ rb_define_singleton_method(rb_mGC, "enable_trace", rb_gc_enable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "disable_trace", rb_gc_disable_trace, 0); - - rb_mObSpace = rb_define_module("ObjectSpace"); - rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1); -diff --git a/intern.h b/intern.h -index 950ae9d..99696f1 100644 ---- a/intern.h -+++ b/intern.h -@@ -270,6 +270,8 @@ void rb_gc_call_finalizer_at_exit _((void)); - VALUE rb_gc_enable _((void)); - VALUE rb_gc_disable _((void)); - VALUE rb_gc_start _((void)); -+void rb_gc_before_fork _((void)); -+void rb_gc_after_fork _((void)); - /* hash.c */ - void st_foreach_safe _((struct st_table *, int (*)(ANYARGS), unsigned long)); - void rb_hash_foreach _((VALUE, int (*)(ANYARGS), VALUE)); -diff --git a/process.c b/process.c -index 8f6285d..ea28cb8 100644 ---- a/process.c -+++ b/process.c -@@ -1330,6 +1330,8 @@ rb_f_fork(obj) - fflush(stderr); - #endif - -+ rb_gc_before_fork(); -+ - before_exec(); - pid = fork(); - after_exec(); -@@ -1339,6 +1341,7 @@ rb_f_fork(obj) - #ifdef linux - after_exec(); - #endif -+ rb_gc_after_fork(); - rb_thread_atfork(); - if (rb_block_given_p()) { - int status; -@@ -1574,10 +1577,12 @@ rb_f_system(argc, argv) - - chfunc = signal(SIGCHLD, SIG_DFL); - retry: -+ rb_gc_before_fork(); - before_exec(); - pid = fork(); - if (pid == 0) { - /* child process */ -+ rb_gc_after_fork(); - rb_thread_atfork(); - rb_protect(proc_exec_args, (VALUE)&earg, NULL); - _exit(127); diff --git a/patches/ruby/1.8.7/p357/railsexpress/08-track-malloc-size.patch b/patches/ruby/1.8.7/p357/railsexpress/08-track-malloc-size.patch deleted file mode 100644 index d078748a44..0000000000 --- a/patches/ruby/1.8.7/p357/railsexpress/08-track-malloc-size.patch +++ /dev/null @@ -1,120 +0,0 @@ -diff --git a/gc.c b/gc.c -index a3cbe91..30a1219 100644 ---- a/gc.c -+++ b/gc.c -@@ -79,6 +79,17 @@ void *alloca (); - - static unsigned long malloc_increase = 0; - static unsigned long malloc_limit = GC_MALLOC_LIMIT; -+ -+#ifdef HAVE_LONG_LONG -+static unsigned LONG_LONG gc_allocated_size = 0; -+static unsigned LONG_LONG gc_num_allocations = 0; -+#else -+static unsigned long gc_allocated_size = 0; -+static unsigned long gc_num_allocations = 0; -+#endif -+static int gc_statistics = 0; -+ -+ - static void run_final(); - static VALUE nomem_error; - static void garbage_collect(); -@@ -163,6 +174,11 @@ ruby_xmalloc(size) - } - malloc_increase += size; - -+ if (gc_statistics) { -+ gc_allocated_size += size; -+ gc_num_allocations += 1; -+ } -+ - return mem; - } - -@@ -220,7 +236,6 @@ ruby_xfree(x) - - extern int ruby_in_compile; - static int dont_gc; --static int gc_statistics = 0; - static GC_TIME_TYPE gc_time = 0; - static int gc_collections = 0; - static int verbose_gc_stats = Qfalse; -@@ -329,11 +344,55 @@ rb_gc_clear_stats() - { - gc_collections = 0; - gc_time = 0; -+ gc_allocated_size = 0; -+ gc_num_allocations = 0; - return Qnil; - } - - /* - * call-seq: -+ * GC.allocated_size => Integer -+ * -+ * Returns the size of memory (in bytes) allocated since GC statistics collection -+ * was enabled. -+ * -+ * GC.allocated_size #=> 35 -+ * -+ */ -+VALUE -+rb_gc_allocated_size() -+{ -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_allocated_size); -+#else -+ return ULONG2NUM(gc_allocated_size); -+#endif -+} -+ -+/* -+ * call-seq: -+ * GC.num_allocations => Integer -+ * -+ * Returns the number of memory allocations since GC statistics collection -+ * was enabled. -+ * -+ * GC.num_allocations #=> 150 -+ * -+ */ -+VALUE -+rb_gc_num_allocations() -+{ -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_num_allocations); -+#else -+ return ULONG2NUM(gc_num_allocations); -+#endif -+} -+ -+/* -+ -+/* -+ * call-seq: - * GC.collections => Integer - * - * Returns the number of garbage collections performed while GC statistics collection -@@ -2753,6 +2812,8 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "enable_stats", rb_gc_enable_stats, 0); - rb_define_singleton_method(rb_mGC, "disable_stats", rb_gc_disable_stats, 0); - rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0); -+ rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); -+ rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); - rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); - rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); - rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); -diff --git a/intern.h b/intern.h -index 99696f1..1117614 100644 ---- a/intern.h -+++ b/intern.h -@@ -272,6 +272,8 @@ VALUE rb_gc_disable _((void)); - VALUE rb_gc_start _((void)); - void rb_gc_before_fork _((void)); - void rb_gc_after_fork _((void)); -+VALUE rb_gc_allocated_size _((void)); -+VALUE rb_gc_num_allocations _((void)); - /* hash.c */ - void st_foreach_safe _((struct st_table *, int (*)(ANYARGS), unsigned long)); - void rb_hash_foreach _((VALUE, int (*)(ANYARGS), VALUE)); diff --git a/patches/ruby/1.8.7/p357/railsexpress/09-track-object-allocation.patch b/patches/ruby/1.8.7/p357/railsexpress/09-track-object-allocation.patch deleted file mode 100644 index 0eef717a24..0000000000 --- a/patches/ruby/1.8.7/p357/railsexpress/09-track-object-allocation.patch +++ /dev/null @@ -1,111 +0,0 @@ -diff --git a/gc.c b/gc.c -index 30a1219..5b42b90 100644 ---- a/gc.c -+++ b/gc.c -@@ -96,6 +96,26 @@ static void garbage_collect(); - - int ruby_gc_stress = 0; - -+static unsigned long live_objects = 0; -+unsigned long rb_os_live_objects() -+{ -+ return live_objects; -+} -+ -+#if defined(HAVE_LONG_LONG) -+static unsigned LONG_LONG allocated_objects = 0; -+unsigned LONG_LONG rb_os_allocated_objects() -+{ -+ return allocated_objects; -+} -+#else -+static unsigned long allocated_objects = 0; -+unsigned long rb_os_allocated_objects() -+{ -+ return allocated_objects; -+} -+#endif -+ - NORETURN(void rb_exc_jump _((VALUE))); - - void -@@ -987,6 +1007,8 @@ rb_newobj() - RANY(obj)->file = ruby_sourcefile; - RANY(obj)->line = ruby_sourceline; - #endif -+ live_objects++; -+ allocated_objects++; - return obj; - } - -@@ -1825,6 +1847,7 @@ gc_sweep() - add_heap(); - } - during_gc = 0; -+ live_objects = live; - - if (do_gc_stats) { - fprintf(gc_data_file, "objects processed: %.7d\n", live+freed); -@@ -2790,6 +2813,35 @@ rb_obj_id(VALUE obj) - return (VALUE)((long)obj|FIXNUM_FLAG); - } - -+/* call-seq: -+ * ObjectSpace.live_objects => number -+ * -+ * Returns the count of objects currently allocated in the system. This goes -+ * down after the garbage collector runs. -+ */ -+static -+VALUE os_live_objects(VALUE self) -+{ -+ return ULONG2NUM(live_objects); -+} -+ -+/* call-seq: -+ * ObjectSpace.allocated_objects => number -+ * -+ * Returns the count of objects allocated since the Ruby interpreter has -+ * started. This number can only increase. To know how many objects are -+ * currently allocated, use ObjectSpace::live_objects -+ */ -+static -+VALUE os_allocated_objects(VALUE self) -+{ -+#if defined(HAVE_LONG_LONG) -+ return ULL2NUM(allocated_objects); -+#else -+ return ULONG2NUM(allocated_objects); -+#endif -+} -+ - /* - * The GC module provides an interface to Ruby's mark and - * sweep garbage collection mechanism. Some of the underlying methods -@@ -2833,6 +2885,9 @@ Init_GC() - rb_define_module_function(rb_mObSpace, "finalizers", finals, 0); - rb_define_module_function(rb_mObSpace, "call_finalizer", call_final, 1); - -+ rb_define_module_function(rb_mObSpace, "live_objects", os_live_objects, 0); -+ rb_define_module_function(rb_mObSpace, "allocated_objects", os_allocated_objects, 0); -+ - rb_define_module_function(rb_mObSpace, "define_finalizer", define_final, -1); - rb_define_module_function(rb_mObSpace, "undefine_finalizer", undefine_final, 1); - -diff --git a/intern.h b/intern.h -index 1117614..a87661d 100644 ---- a/intern.h -+++ b/intern.h -@@ -274,6 +274,12 @@ void rb_gc_before_fork _((void)); - void rb_gc_after_fork _((void)); - VALUE rb_gc_allocated_size _((void)); - VALUE rb_gc_num_allocations _((void)); -+unsigned long rb_os_live_objects _((void)); -+#ifdef HAVE_LONG_LONG -+unsigned LONG_LONG rb_os_allocated_objects _((void)); -+#else -+unsigned long rb_os_allocated_objects _((void)); -+#endif - /* hash.c */ - void st_foreach_safe _((struct st_table *, int (*)(ANYARGS), unsigned long)); - void rb_hash_foreach _((VALUE, int (*)(ANYARGS), VALUE)); diff --git a/patches/ruby/1.8.7/p357/railsexpress/10-expose-heap-slots.patch b/patches/ruby/1.8.7/p357/railsexpress/10-expose-heap-slots.patch deleted file mode 100644 index 3ce846c6a0..0000000000 --- a/patches/ruby/1.8.7/p357/railsexpress/10-expose-heap-slots.patch +++ /dev/null @@ -1,70 +0,0 @@ -diff --git a/gc.c b/gc.c -index 5b42b90..21b3f6b 100644 ---- a/gc.c -+++ b/gc.c -@@ -690,6 +690,7 @@ static int heaps_used = 0; - - static int heap_min_slots = 10000; - static int heap_slots = 10000; -+static int heap_size = 0; - - static int heap_free_min = 4096; - static int heap_slots_increment = 10000; -@@ -800,6 +801,21 @@ static void set_gc_parameters() - - /* - * call-seq: -+ * GC.heap_slots => Integer -+ * -+ * Returns the number of heap slots available for object allocations. -+ * -+ * GC.heap_slots #=> 10000 -+ * -+ */ -+VALUE -+rb_gc_heap_slots() -+{ -+ return INT2NUM(heap_size); -+} -+ -+/* -+ * call-seq: - * GC.dump => nil - * - * dumps information about the current GC data structures to the GC log file -@@ -967,6 +983,7 @@ add_heap() - heaps[heaps_used].limit = heap_slots; - break; - } -+ heap_size += heap_slots; - pend = p + heap_slots; - if (lomem == 0 || lomem > p) lomem = p; - if (himem < pend) himem = pend; -@@ -1828,6 +1845,7 @@ gc_sweep() - if (n == heaps[i].limit && freed > free_min) { - RVALUE *pp; - -+ heap_size -= n; - heaps[i].limit = 0; - for (pp = final_list; pp != final; pp = pp->as.free.next) { - pp->as.free.flags |= FL_SINGLETON; /* freeing page mark */ -@@ -2866,6 +2884,7 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0); - rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); - rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); - rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); - rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); - rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); -diff --git a/intern.h b/intern.h -index a87661d..e8f3209 100644 ---- a/intern.h -+++ b/intern.h -@@ -274,6 +274,7 @@ void rb_gc_before_fork _((void)); - void rb_gc_after_fork _((void)); - VALUE rb_gc_allocated_size _((void)); - VALUE rb_gc_num_allocations _((void)); -+VALUE rb_gc_heap_slots _((void)); - unsigned long rb_os_live_objects _((void)); - #ifdef HAVE_LONG_LONG - unsigned LONG_LONG rb_os_allocated_objects _((void)); diff --git a/patches/ruby/1.8.7/p357/railsexpress/11-fix-heap-size-growth-logic.patch b/patches/ruby/1.8.7/p357/railsexpress/11-fix-heap-size-growth-logic.patch deleted file mode 100644 index 1db93f224d..0000000000 --- a/patches/ruby/1.8.7/p357/railsexpress/11-fix-heap-size-growth-logic.patch +++ /dev/null @@ -1,54 +0,0 @@ -diff --git a/gc.c b/gc.c -index 21b3f6b..7db1ef6 100644 ---- a/gc.c -+++ b/gc.c -@@ -694,6 +694,7 @@ static int heap_size = 0; - - static int heap_free_min = 4096; - static int heap_slots_increment = 10000; -+static int initial_heap_slots_increment = 10000; - static double heap_slots_growth_factor = 1.8; - - static long initial_malloc_limit = GC_MALLOC_LIMIT; -@@ -771,14 +772,13 @@ static void set_gc_parameters() - if (verbose_gc_stats) { - fprintf(gc_data_file, "RUBY_HEAP_SLOTS_INCREMENT=%s\n", heap_slots_incr_ptr); - } -- if (heap_slots_incr_i > 0) { -- heap_slots_increment = heap_slots_incr_i; -- } -+ heap_slots_increment = heap_slots_incr_i; -+ initial_heap_slots_increment = heap_slots_increment; - } - - heap_slots_growth_factor_ptr = getenv("RUBY_HEAP_SLOTS_GROWTH_FACTOR"); - if (heap_slots_growth_factor_ptr != NULL) { -- double heap_slots_growth_factor_d = atoi(heap_slots_growth_factor_ptr); -+ double heap_slots_growth_factor_d = atof(heap_slots_growth_factor_ptr); - if (verbose_gc_stats) { - fprintf(gc_data_file, "RUBY_HEAP_SLOTS_GROWTH_FACTOR=%s\n", heap_slots_growth_factor_ptr); - } -@@ -988,8 +988,13 @@ add_heap() - if (lomem == 0 || lomem > p) lomem = p; - if (himem < pend) himem = pend; - heaps_used++; -- heap_slots += heap_slots_increment; -- heap_slots_increment *= heap_slots_growth_factor; -+ if (heaps_used == 1) -+ heap_slots = initial_heap_slots_increment; -+ else { -+ heap_slots_increment *= heap_slots_growth_factor; -+ heap_slots += heap_slots_increment; -+ } -+ - if (heap_slots <= 0) heap_slots = heap_min_slots; - - while (p < pend) { -@@ -1879,6 +1884,7 @@ gc_sweep() - live_counts[i], free_counts[i], obj_type(i)); - } - } -+ rb_gc_dump(); - fflush(gc_data_file); - } - diff --git a/patches/ruby/1.8.7/p357/railsexpress/12-heap-slot-size.patch b/patches/ruby/1.8.7/p357/railsexpress/12-heap-slot-size.patch deleted file mode 100644 index 45091c14ae..0000000000 --- a/patches/ruby/1.8.7/p357/railsexpress/12-heap-slot-size.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/gc.c b/gc.c -index 7db1ef6..57740d2 100644 ---- a/gc.c -+++ b/gc.c -@@ -2891,6 +2891,7 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); - rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); - rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); - rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); - rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); - rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); diff --git a/patches/ruby/1.8.7/p357/railsexpress/13-add-trace-stats-enabled-methods.patch b/patches/ruby/1.8.7/p357/railsexpress/13-add-trace-stats-enabled-methods.patch deleted file mode 100644 index 4e3c4f2132..0000000000 --- a/patches/ruby/1.8.7/p357/railsexpress/13-add-trace-stats-enabled-methods.patch +++ /dev/null @@ -1,66 +0,0 @@ -diff --git a/gc.c b/gc.c -index 57740d2..2c34932 100644 ---- a/gc.c -+++ b/gc.c -@@ -350,6 +350,22 @@ rb_gc_disable_stats() - - /* - * call-seq: -+ * GC.stats_enabled? => true or false -+ * -+ * Check whether GC stats have been enabled. -+ * -+ * GC.stats_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_stats_enabled() -+{ -+ return gc_statistics ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: - * GC.clear_stats => nil - * - * Clears garbage collection statistics, returning nil. This resets the number -@@ -491,6 +507,22 @@ rb_gc_disable_trace() - return old; - } - -+/* -+ * call-seq: -+ * GC.trace_enabled? => true or false -+ * -+ * Check whether GC tracing has been enabled. -+ * -+ * GC.trace_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_trace_enabled() -+{ -+ return verbose_gc_stats ? Qtrue : Qfalse; -+} -+ - char* GC_LOGFILE_IVAR = "@gc_logfile_name"; - - /* -@@ -2887,6 +2919,7 @@ Init_GC() - - rb_define_singleton_method(rb_mGC, "enable_stats", rb_gc_enable_stats, 0); - rb_define_singleton_method(rb_mGC, "disable_stats", rb_gc_disable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "stats_enabled?", rb_gc_stats_enabled, 0); - rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0); - rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); - rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); -@@ -2902,6 +2935,7 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "log_file", rb_gc_log_file, -1); - rb_define_singleton_method(rb_mGC, "enable_trace", rb_gc_enable_trace, 0); - rb_define_singleton_method(rb_mGC, "disable_trace", rb_gc_disable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "trace_enabled?", rb_gc_trace_enabled, 0); - - rb_mObSpace = rb_define_module("ObjectSpace"); - rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1); diff --git a/patches/ruby/1.8.7/p357/railsexpress/14-track-live-dataset-size.patch b/patches/ruby/1.8.7/p357/railsexpress/14-track-live-dataset-size.patch deleted file mode 100644 index de44e6b365..0000000000 --- a/patches/ruby/1.8.7/p357/railsexpress/14-track-live-dataset-size.patch +++ /dev/null @@ -1,52 +0,0 @@ -diff --git a/gc.c b/gc.c -index 2c34932..0ce7e68 100644 ---- a/gc.c -+++ b/gc.c -@@ -89,6 +89,7 @@ static unsigned long gc_num_allocations = 0; - #endif - static int gc_statistics = 0; - -+static unsigned long heap_slots_live_after_last_gc = 0; - - static void run_final(); - static VALUE nomem_error; -@@ -465,6 +466,23 @@ rb_gc_time() - #endif - } - -+/* -+ * call-seq: -+ * GC.heap_slots_live_after_last_gc => Integer -+ * -+ * Returns the number of heap slots which were live after the last garbage collection. -+ * -+ * GC.heap_slots_live_after_last_gc #=> 231223 -+ * -+ */ -+VALUE -+rb_gc_heap_slots_live_after_last_gc() -+{ -+ return ULONG2NUM(heap_slots_live_after_last_gc); -+} -+ -+ -+ - VALUE rb_mGC; - - /* -@@ -1903,6 +1921,7 @@ gc_sweep() - } - during_gc = 0; - live_objects = live; -+ heap_slots_live_after_last_gc = live; - - if (do_gc_stats) { - fprintf(gc_data_file, "objects processed: %.7d\n", live+freed); -@@ -2924,6 +2943,7 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); - rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); - rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots_live_after_last_gc", rb_gc_heap_slots_live_after_last_gc, 0); - rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); - rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); - rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); diff --git a/patches/ruby/1.8.7/p357/railsexpress/15-add-object-size-information-to-heap-dump.patch b/patches/ruby/1.8.7/p357/railsexpress/15-add-object-size-information-to-heap-dump.patch deleted file mode 100644 index e974cdb63a..0000000000 --- a/patches/ruby/1.8.7/p357/railsexpress/15-add-object-size-information-to-heap-dump.patch +++ /dev/null @@ -1,51 +0,0 @@ -diff --git a/gc.c b/gc.c -index 0ce7e68..53450bf 100644 ---- a/gc.c -+++ b/gc.c -@@ -953,9 +953,21 @@ rb_gc_dump_file_and_line_info(int argc, VALUE *argv) - if (!p->as.basic.klass) { - fprintf(f, "__unknown__"); - } else { -- fprintf(f, rb_obj_classname((VALUE)p)); -+ fprintf(f, "%s", rb_obj_classname((VALUE)p)); - } - } -+ /* print object size for some known object types */ -+ switch (TYPE(p)) { -+ case T_STRING: -+ fprintf(f, ":%lu", RSTRING(p)->len); -+ break; -+ case T_ARRAY: -+ fprintf(f, ":%lu", RARRAY(p)->len); -+ break; -+ case T_HASH: -+ fprintf(f, ":%d", RHASH(p)->tbl->num_entries); -+ break; -+ } - } - fprintf(f, "\n"); - } -@@ -1924,10 +1936,10 @@ gc_sweep() - heap_slots_live_after_last_gc = live; - - if (do_gc_stats) { -- fprintf(gc_data_file, "objects processed: %.7d\n", live+freed); -- fprintf(gc_data_file, "live objects : %.7d\n", live); -- fprintf(gc_data_file, "freelist objects : %.7d\n", freed - really_freed); -- fprintf(gc_data_file, "freed objects : %.7d\n", really_freed); -+ fprintf(gc_data_file, "objects processed: %.7lu\n", live+freed); -+ fprintf(gc_data_file, "live objects : %.7lu\n", live); -+ fprintf(gc_data_file, "freelist objects : %.7lu\n", freed - really_freed); -+ fprintf(gc_data_file, "freed objects : %.7lu\n", really_freed); - for(i=0; i<256; i++) { - if (free_counts[i]>0 || live_counts[i]>0) { - fprintf(gc_data_file, -@@ -2258,7 +2270,7 @@ garbage_collect() - gc_time += musecs_used; - - if (verbose_gc_stats) { -- fprintf(gc_data_file, "GC time: %d msec\n", musecs_used / 1000); -+ fprintf(gc_data_file, "GC time: %ld msec\n", (long)(musecs_used / 1000)); - fflush(gc_data_file); - } - } diff --git a/patches/ruby/1.8.7/p357/railsexpress/16-caller-for-all-threads.patch b/patches/ruby/1.8.7/p357/railsexpress/16-caller-for-all-threads.patch deleted file mode 100644 index aa79d1602c..0000000000 --- a/patches/ruby/1.8.7/p357/railsexpress/16-caller-for-all-threads.patch +++ /dev/null @@ -1,230 +0,0 @@ -diff --git a/eval.c b/eval.c -index 356226e..a0fdc55 100644 ---- a/eval.c -+++ b/eval.c -@@ -8199,6 +8199,17 @@ rb_f_method_name() - } - } - -+/* Hash (Thread => Backtrace) used to collect backtrace for each threads. */ -+static VALUE backtrace_for_each_thread; -+ -+static int backtrace_level_for_each_thread; -+ -+static VALUE -+switch_thread_context_to_collect_backtrace(rb_thread_t next); -+ -+static VALUE -+rb_f_caller_for_all_threads(); -+ - void - Init_eval() - { -@@ -8244,6 +8255,7 @@ Init_eval() - rb_define_global_function("fail", rb_f_raise, -1); - - rb_define_global_function("caller", rb_f_caller, -1); -+ rb_define_global_function("caller_for_all_threads", rb_f_caller_for_all_threads, -1); - - rb_define_global_function("exit", rb_f_exit, -1); - rb_define_global_function("abort", rb_f_abort, -1); -@@ -10599,6 +10611,7 @@ static int th_sig, th_safe; - #define RESTORE_RAISE 5 - #define RESTORE_SIGNAL 6 - #define RESTORE_EXIT 7 -+#define RESTORE_BACKTRACE 8 - - extern VALUE *rb_gc_stack_start; - #ifdef __ia64 -@@ -10705,6 +10718,15 @@ rb_thread_switch(n) - } - rb_exc_raise(th_raise_exception); - break; -+ case RESTORE_BACKTRACE: -+ rb_hash_aset(backtrace_for_each_thread, curr_thread->thread, -+ backtrace(backtrace_level_for_each_thread)); -+ if (curr_thread != main_thread) { -+ switch_thread_context_to_collect_backtrace(curr_thread->next); -+ } else { -+ /* Circled back to main thread, cycle is complete. */ -+ } -+ break; - case RESTORE_NORMAL: - default: - break; -@@ -13875,3 +13897,74 @@ rb_throw(tag, val) - argv[1] = val; - rb_f_throw(2, argv); - } -+ -+static VALUE -+switch_thread_context_to_collect_backtrace(rb_thread_t next) -+{ -+ if (THREAD_SAVE_CONTEXT(curr_thread)) { -+ return Qnil; -+ } -+ curr_thread = next; -+ rb_thread_restore_context(next, RESTORE_BACKTRACE); -+ return Qnil; -+} -+ -+ -+/* -+ * call-seq: -+ * caller_for_all_threads(start=1) => array -+ * -+ * Returns the current execution stack for all threads -+ * ---a hash whose keys are thread instances and values -+ * the thread caller backtrace. -+ * -+ * Backtraces are array of hashes indicating location on the -+ * stack. Hash keys include ``:line'' or ``:file'' -+ * and ``:method'''. -+ * -+ * The optional _start_ parameter -+ * determines the number of initial stack entries to omit from the -+ * result. -+ * -+ * def a(skip) -+ * caller_for_all_threads(skip) -+ * end -+ * def b(skip) -+ * a(skip) -+ * end -+ * def c(skip) -+ * b(skip) -+ * end -+ * c(0) #=> ["prog:2:in `a'", "prog:5:in `b'", "prog:8:in `c'", "prog:10"] -+ * c(1) #=> ["prog:5:in `b'", "prog:8:in `c'", "prog:11"] -+ * c(2) #=> ["prog:8:in `c'", "prog:12"] -+ * c(3) #=> ["prog:13"] -+ */ -+static VALUE -+rb_f_caller_for_all_threads(argc, argv) -+ int argc; -+ VALUE *argv; -+{ -+ volatile int critical; -+ VALUE level; -+ VALUE result; -+ -+ rb_scan_args(argc, argv, "01", &level); -+ backtrace_level_for_each_thread = NIL_P(level) ? 0 : NUM2INT(level); -+ if (backtrace_level_for_each_thread < 0) { -+ rb_raise(rb_eArgError, "negative level (%d)", backtrace_level_for_each_thread); -+ } -+ -+ critical = rb_thread_critical; -+ rb_thread_critical = Qtrue; -+ -+ backtrace_for_each_thread = rb_hash_new(); -+ switch_thread_context_to_collect_backtrace(main_thread->next); -+ -+ result = backtrace_for_each_thread; -+ backtrace_for_each_thread = Qnil; -+ backtrace_for_each_thread = 0; -+ -+ rb_thread_critical = critical; -+ return result; -+} -diff --git a/test/callerforallthreads/test_caller_for_each_thread.rb b/test/callerforallthreads/test_caller_for_each_thread.rb -new file mode 100644 -index 0000000..6aebaed ---- /dev/null -+++ b/test/callerforallthreads/test_caller_for_each_thread.rb -@@ -0,0 +1,95 @@ -+# -*- ruby-indent-level: 4 -*- -+require 'thread' -+require 'test/unit' -+ -+class AClassWithNestedmethods -+ -+ def an_ultra_nested_method(skip) -+ caller_for_all_threads skip -+ end -+ -+ def a_nested_method(skip) -+ an_ultra_nested_method skip -+ end -+ -+ def a_method(skip=0) -+ a_nested_method skip -+ end -+ -+end -+ -+class CallerForEachThreadTest < Test::Unit::TestCase -+ -+ def testCollectMeaningfulBacktraceForASingleThread -+ backtraces = AClassWithNestedmethods.new.a_method -+ backtrace = backtraces[Thread.current] -+ assert_not_nil backtrace -+ assert_equal __FILE__ + ":8:in `an_ultra_nested_method'", backtrace[0] -+ assert_equal __FILE__ + ":12:in `a_nested_method'", backtrace[1] -+ assert_equal __FILE__ + ":16:in `a_method'", backtrace[2] -+ assert_equal __FILE__ + ":24:in `testCollectMeaningfulBacktraceForASingleThread'", -+ backtrace[3] -+ end -+ -+ def testCanSkipFirstStackEntries -+ backtraces = AClassWithNestedmethods.new.a_method 2 -+ backtrace = backtraces[Thread.current] -+ assert_not_nil backtrace -+ assert_equal __FILE__ + ":16:in `a_method'", backtrace[0] -+ assert_equal __FILE__ + ":35:in `testCanSkipFirstStackEntries'", -+ backtrace[1] -+ end -+ -+ def testCollectMeaningfulBacktraceForMultipleThreads -+ first_thread = Thread.new do -+ loop do -+ Thread.pass -+ sleep 1 -+ end -+ end -+ -+ second_thread = Thread.new do -+ loop do -+ Thread.pass -+ sleep 1 -+ end -+ end -+ -+ backtraces = AClassWithNestedmethods.new.a_method -+ -+ backtrace = backtraces[Thread.current] -+ assert_not_nil backtrace -+ assert_match __FILE__ + ":8:in `an_ultra_nested_method'", backtrace[0] -+ assert_match __FILE__ + ":12:in `a_nested_method'", backtrace[1] -+ assert_equal __FILE__ + ":16:in `a_method'", backtrace[2] -+ assert_equal __FILE__ + ":58:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[3] -+ -+ backtrace = backtraces[first_thread] -+ assert_not_nil backtrace -+ assert_equal __FILE__ + ":47:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[0] -+ assert_equal __FILE__ + ":45:in `loop'", -+ backtrace[1] -+ assert_equal __FILE__ + ":45:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[2] -+ assert_equal __FILE__ + ":44:in `initialize'",backtrace[3] -+ assert_equal __FILE__ + ":44:in `new'", backtrace[4] -+ assert_equal __FILE__ + ":44:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[5] -+ -+ backtrace = backtraces[second_thread] -+ assert_not_nil backtrace -+ assert_equal __FILE__ + ":53:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[0] -+ assert_equal __FILE__ + ":52:in `loop'", backtrace[1] -+ assert_equal __FILE__ + ":52:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[2] -+ assert_equal __FILE__ + ":51:in `initialize'",backtrace[3] -+ assert_equal __FILE__ + ":51:in `new'", backtrace[4] -+ assert_equal __FILE__ + ":51:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[5] -+ end -+ -+end -+ diff --git a/patches/ruby/1.8.7/p358/railsexpress/01-ignore-generated-files.patch b/patches/ruby/1.8.7/p358/railsexpress/01-ignore-generated-files.patch deleted file mode 100644 index b669ad44bd..0000000000 --- a/patches/ruby/1.8.7/p358/railsexpress/01-ignore-generated-files.patch +++ /dev/null @@ -1,101 +0,0 @@ -diff --git a/.gitignore b/.gitignore -new file mode 100644 -index 0000000..00c347a ---- /dev/null -+++ b/.gitignore -@@ -0,0 +1,95 @@ -+.ext -+.installed.list -+.rbconfig.time -+Makefile -+autom4te.cache/ -+config.h -+config.status -+configure -+ext/Win32API/Makefile -+ext/bigdecimal/Makefile -+ext/curses/Makefile -+ext/dbm/Makefile -+ext/digest/Makefile -+ext/digest/bubblebabble/Makefile -+ext/digest/md5/Makefile -+ext/digest/rmd160/Makefile -+ext/digest/sha1/Makefile -+ext/digest/sha2/Makefile -+ext/dl/Makefile -+ext/dl/call.func -+ext/dl/callback.func -+ext/dl/cbtable.func -+ext/dl/dlconfig.h -+ext/dl/dlconfig.rb -+ext/enumerator/Makefile -+ext/etc/Makefile -+ext/fcntl/Makefile -+ext/gdbm/Makefile -+ext/iconv/Makefile -+ext/io/wait/Makefile -+ext/nkf/Makefile -+ext/openssl/Makefile -+ext/openssl/extconf.h -+ext/pty/Makefile -+ext/racc/cparse/Makefile -+ext/readline/Makefile -+ext/sdbm/Makefile -+ext/socket/Makefile -+ext/stringio/Makefile -+ext/strscan/Makefile -+ext/syck/Makefile -+ext/syslog/Makefile -+ext/thread/Makefile -+ext/tk/Makefile -+ext/tk/tkutil/Makefile -+ext/win32ole/Makefile -+ext/win32ole/.document -+ext/zlib/Makefile -+largefile.h -+miniruby -+parse.c -+rbconfig.rb -+ruby -+enc.mk -+ext/bigdecimal/extconf.h -+ext/continuation/ -+ext/coverage/ -+ext/curses/extconf.h -+ext/dbm/extconf.h -+ext/digest/bubblebabble/extconf.h -+ext/digest/extconf.h -+ext/digest/md5/extconf.h -+ext/digest/rmd160/extconf.h -+ext/digest/sha1/extconf.h -+ext/digest/sha2/extconf.h -+ext/dl/callback.h -+ext/dl/extconf.h -+ext/etc/extconf.h -+ext/fcntl/extconf.h -+ext/fiber/ -+ext/iconv/extconf.h -+ext/io/wait/extconf.h -+ext/json/ -+ext/nkf/extconf.h -+ext/pty/extconf.h -+ext/racc/cparse/extconf.h -+ext/readline/extconf.h -+ext/ripper/ -+ext/sdbm/extconf.h -+ext/socket/constants.h -+ext/socket/extconf.h -+ext/stringio/extconf.h -+ext/strscan/extconf.h -+ext/syck/extconf.h -+ext/syslog/extconf.h -+ext/tk/extconf.h -+ext/tk/tkutil/extconf.h -+ext/zlib/extconf.h -+miniprelude.c -+prelude.c -+revision.h -+*.dylib -+*.log -+*.dSYM -+patches-ruby* diff --git a/patches/ruby/1.8.7/p358/railsexpress/02-fix-tests-for-osx.patch b/patches/ruby/1.8.7/p358/railsexpress/02-fix-tests-for-osx.patch deleted file mode 100644 index 6250e97f36..0000000000 --- a/patches/ruby/1.8.7/p358/railsexpress/02-fix-tests-for-osx.patch +++ /dev/null @@ -1,139 +0,0 @@ -diff --git a/test/drb/drbtest.rb b/test/drb/drbtest.rb -index bc16ab1..c12b168 100644 ---- a/test/drb/drbtest.rb -+++ b/test/drb/drbtest.rb -@@ -22,7 +22,7 @@ class DRbService - %w(ut_drb.rb ut_array.rb ut_port.rb ut_large.rb ut_safe1.rb ut_eval.rb).each do |nm| - add_service_command(nm) - end -- @server = @@server = DRb::DRbServer.new('druby://localhost:0', @@manager, {}) -+ @server = @@server = DRb::DRbServer.new('druby://127.0.0.1:0', @@manager, {}) - @@manager.uri = @@server.uri - def self.manager - @@manager -@@ -79,16 +79,16 @@ module DRbCore - end - - def test_00_DRbObject -- ro = DRbObject.new(nil, 'druby://localhost:12345') -- assert_equal('druby://localhost:12345', ro.__drburi) -+ ro = DRbObject.new(nil, 'druby://127.0.0.1:12345') -+ assert_equal('druby://127.0.0.1:12345', ro.__drburi) - assert_equal(nil, ro.__drbref) - -- ro = DRbObject.new_with_uri('druby://localhost:12345') -- assert_equal('druby://localhost:12345', ro.__drburi) -+ ro = DRbObject.new_with_uri('druby://127.0.0.1:12345') -+ assert_equal('druby://127.0.0.1:12345', ro.__drburi) - assert_equal(nil, ro.__drbref) - -- ro = DRbObject.new_with_uri('druby://localhost:12345?foobar') -- assert_equal('druby://localhost:12345', ro.__drburi) -+ ro = DRbObject.new_with_uri('druby://127.0.0.1:12345?foobar') -+ assert_equal('druby://127.0.0.1:12345', ro.__drburi) - assert_equal(DRb::DRbURIOption.new('foobar'), ro.__drbref) - end - -diff --git a/test/drb/ut_drb.rb b/test/drb/ut_drb.rb -index f5720cf..265713d 100644 ---- a/test/drb/ut_drb.rb -+++ b/test/drb/ut_drb.rb -@@ -154,7 +154,7 @@ if __FILE__ == $0 - - DRb::DRbServer.default_argc_limit(8) - DRb::DRbServer.default_load_limit(4096) -- DRb.start_service('druby://localhost:0', DRbEx.new) -+ DRb.start_service('druby://127.0.0.1:0', DRbEx.new) - es = DRb::ExtServ.new(ARGV.shift, ARGV.shift) - DRb.thread.join - end -diff --git a/test/drb/ut_drb_drbssl.rb b/test/drb/ut_drb_drbssl.rb -index 0a2191e..bca3012 100644 ---- a/test/drb/ut_drb_drbssl.rb -+++ b/test/drb/ut_drb_drbssl.rb -@@ -18,7 +18,7 @@ if __FILE__ == $0 - - DRb::DRbServer.default_argc_limit(8) - DRb::DRbServer.default_load_limit(4096) -- DRb.start_service('drbssl://localhost:0', DRbEx.new, config) -+ DRb.start_service('drbssl://127.0.0.1:0', DRbEx.new, config) - es = DRb::ExtServ.new(ARGV.shift, ARGV.shift) - DRb.thread.join - end -diff --git a/test/drb/ut_eval.rb b/test/drb/ut_eval.rb -index 4df963e..9127939 100644 ---- a/test/drb/ut_eval.rb -+++ b/test/drb/ut_eval.rb -@@ -3,7 +3,7 @@ require 'drb/extserv' - - class EvalAttack - def initialize -- @four = DRb::DRbServer.new('druby://localhost:0', self, {:safe_level => 4}) -+ @four = DRb::DRbServer.new('druby://127.0.0.1:0', self, {:safe_level => 4}) - end - - def four -@@ -25,7 +25,7 @@ if __FILE__ == $0 - - $SAFE = 1 - -- DRb.start_service('druby://localhost:0', EvalAttack.new, {:safe_level => 2}) -+ DRb.start_service('druby://127.0.0.1:0', EvalAttack.new, {:safe_level => 2}) - es = DRb::ExtServ.new(ARGV.shift, ARGV.shift) - DRb.thread.join - end -diff --git a/test/drb/ut_large.rb b/test/drb/ut_large.rb -index d6717c5..0aefd1b 100644 ---- a/test/drb/ut_large.rb -+++ b/test/drb/ut_large.rb -@@ -31,7 +31,7 @@ if __FILE__ == $0 - - DRb::DRbServer.default_argc_limit(3) - DRb::DRbServer.default_load_limit(100000) -- DRb.start_service('druby://localhost:0', DRbLarge.new) -+ DRb.start_service('druby://127.0.0.1:0', DRbLarge.new) - es = DRb::ExtServ.new(ARGV.shift, ARGV.shift) - DRb.thread.join - end -diff --git a/test/drb/ut_safe1.rb b/test/drb/ut_safe1.rb -index 4df8e1e..ee097f6 100644 ---- a/test/drb/ut_safe1.rb -+++ b/test/drb/ut_safe1.rb -@@ -8,7 +8,7 @@ if __FILE__ == $0 - it - end - -- DRb.start_service('druby://localhost:0', [1, 2, 'III', 4, "five", 6], -+ DRb.start_service('druby://127.0.0.1:0', [1, 2, 'III', 4, "five", 6], - {:safe_level => 1}) - es = DRb::ExtServ.new(ARGV.shift, ARGV.shift) - DRb.thread.join -diff --git a/test/net/pop/test_pop.rb b/test/net/pop/test_pop.rb -index c8aa9a8..129ca08 100644 ---- a/test/net/pop/test_pop.rb -+++ b/test/net/pop/test_pop.rb -@@ -3,10 +3,14 @@ require 'test/unit' - require 'digest/md5' - - class TestPOP < Test::Unit::TestCase -+ def localhost -+ '127.0.0.1' -+ end -+ - def setup - @users = {'user' => 'pass' } - @ok_user = 'user' -- @stamp_base = "#{$$}.#{Time.now.to_i}@localhost" -+ @stamp_base = "#{$$}.#{Time.now.to_i}@#{localhost}" - end - - def test_pop_auth_ok -@@ -64,7 +68,7 @@ class TestPOP < Test::Unit::TestCase - end - - def pop_test(apop=false) -- host = 'localhost' -+ host = localhost - server = TCPServer.new(host, 0) - port = server.addr[1] - thread = Thread.start do diff --git a/patches/ruby/1.8.7/p358/railsexpress/03-sigvtalrm-fix.patch b/patches/ruby/1.8.7/p358/railsexpress/03-sigvtalrm-fix.patch deleted file mode 100644 index fe99f6eed6..0000000000 --- a/patches/ruby/1.8.7/p358/railsexpress/03-sigvtalrm-fix.patch +++ /dev/null @@ -1,27 +0,0 @@ -diff --git a/eval.c b/eval.c -index 7886e17..6ff2560 100644 ---- a/eval.c -+++ b/eval.c -@@ -12461,6 +12461,11 @@ rb_thread_start_0(fn, arg, th) - curr_thread->next = th; - th->priority = curr_thread->priority; - th->thgroup = curr_thread->thgroup; -+#if defined(HAVE_SETITIMER) || defined(_THREAD_SAFE) -+ if (!thread_init) { -+ rb_thread_start_timer(); -+ } -+#endif - } - START_TIMER(); - -@@ -13189,7 +13194,9 @@ rb_thread_atfork() - main_thread = curr_thread; - curr_thread->next = curr_thread; - curr_thread->prev = curr_thread; -- STOP_TIMER(); -+#if defined(HAVE_SETITIMER) || defined(_THREAD_SAFE) -+ rb_thread_stop_timer(); -+#endif - } - - diff --git a/patches/ruby/1.8.7/p358/railsexpress/04-railsbench-gc-patch.patch b/patches/ruby/1.8.7/p358/railsexpress/04-railsbench-gc-patch.patch deleted file mode 100644 index 7b6c0e251a..0000000000 --- a/patches/ruby/1.8.7/p358/railsexpress/04-railsbench-gc-patch.patch +++ /dev/null @@ -1,1876 +0,0 @@ -diff --git a/gc.c b/gc.c -index fa45cd1..ab71d22 100644 ---- a/gc.c -+++ b/gc.c -@@ -22,8 +22,16 @@ - #include - #include - -+#ifdef _WIN32 -+#include -+#else -+#include -+#endif -+ - #ifdef HAVE_SYS_TIME_H - #include -+#elif defined(_WIN32) -+#include - #endif - - #ifdef HAVE_SYS_RESOURCE_H -@@ -42,7 +50,6 @@ void rb_io_fptr_finalize _((struct rb_io_t*)); - #ifdef __CYGWIN__ - int _setjmp(), _longjmp(); - #endif -- - /* Make alloca work the best possible way. */ - #ifdef __GNUC__ - # ifndef atarist -@@ -86,12 +93,12 @@ rb_memerror() - rb_thread_t th = rb_curr_thread; - - if (!nomem_error || -- (rb_thread_raised_p(th, RAISED_NOMEMORY) && rb_safe_level() < 4)) { -- fprintf(stderr, "[FATAL] failed to allocate memory\n"); -- exit(1); -+ (rb_thread_raised_p(th, RAISED_NOMEMORY) && rb_safe_level() < 4)) { -+ fprintf(stderr, "[FATAL] failed to allocate memory\n"); -+ exit(1); - } - if (rb_thread_raised_p(th, RAISED_NOMEMORY)) { -- rb_exc_jump(nomem_error); -+ rb_exc_jump(nomem_error); - } - rb_thread_raised_set(th, RAISED_NOMEMORY); - rb_exc_raise(nomem_error); -@@ -139,7 +146,7 @@ ruby_xmalloc(size) - void *mem; - - if (size < 0) { -- rb_raise(rb_eNoMemError, "negative allocation size (or too big)"); -+ rb_raise(rb_eNoMemError, "negative allocation size (or too big)"); - } - if (size == 0) size = 1; - -@@ -148,11 +155,11 @@ ruby_xmalloc(size) - } - RUBY_CRITICAL(mem = malloc(size)); - if (!mem) { -- garbage_collect(); -- RUBY_CRITICAL(mem = malloc(size)); -- if (!mem) { -- rb_memerror(); -- } -+ garbage_collect(); -+ RUBY_CRITICAL(mem = malloc(size)); -+ if (!mem) { -+ rb_memerror(); -+ } - } - malloc_increase += size; - -@@ -179,17 +186,17 @@ ruby_xrealloc(ptr, size) - void *mem; - - if (size < 0) { -- rb_raise(rb_eArgError, "negative re-allocation size"); -+ rb_raise(rb_eArgError, "negative re-allocation size"); - } - if (!ptr) return xmalloc(size); - if (size == 0) size = 1; - if (ruby_gc_stress) garbage_collect(); - RUBY_CRITICAL(mem = realloc(ptr, size)); - if (!mem) { -- garbage_collect(); -- RUBY_CRITICAL(mem = realloc(ptr, size)); -- if (!mem) { -- rb_memerror(); -+ garbage_collect(); -+ RUBY_CRITICAL(mem = realloc(ptr, size)); -+ if (!mem) { -+ rb_memerror(); - } - } - malloc_increase += size; -@@ -202,11 +209,20 @@ ruby_xfree(x) - void *x; - { - if (x) -- RUBY_CRITICAL(free(x)); -+ RUBY_CRITICAL(free(x)); - } - -+#if HAVE_LONG_LONG -+#define GC_TIME_TYPE LONG_LONG -+#else -+#define GC_TIME_TYPE long -+#endif -+ - extern int ruby_in_compile; - static int dont_gc; -+static int gc_statistics = 0; -+static GC_TIME_TYPE gc_time = 0; -+static int gc_collections = 0; - static int during_gc; - static int need_call_final = 0; - static st_table *finalizer_table = 0; -@@ -241,7 +257,7 @@ rb_gc_enable() - * Disables garbage collection, returning true if garbage - * collection was already disabled. - * -- * GC.disable #=> false -+ * GC.disable #=> false or true - * GC.disable #=> true - * - */ -@@ -255,6 +271,104 @@ rb_gc_disable() - return old; - } - -+/* -+ * call-seq: -+ * GC.enable_stats => true or false -+ * -+ * Enables garbage collection statistics, returning true if garbage -+ * collection statistics was already enabled. -+ * -+ * GC.enable_stats #=> false or true -+ * GC.enable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_stats() -+{ -+ int old = gc_statistics; -+ gc_statistics = Qtrue; -+ return old; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_stats => true or false -+ * -+ * Disables garbage collection statistics, returning true if garbage -+ * collection statistics was already disabled. -+ * -+ * GC.disable_stats #=> false or true -+ * GC.disable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_stats() -+{ -+ int old = gc_statistics; -+ gc_statistics = Qfalse; -+ return old; -+} -+ -+/* -+ * call-seq: -+ * GC.clear_stats => nil -+ * -+ * Clears garbage collection statistics, returning nil. This resets the number -+ * of collections (GC.collections) and the time used (GC.time) to 0. -+ * -+ * GC.clear_stats #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_clear_stats() -+{ -+ gc_collections = 0; -+ gc_time = 0; -+ return Qnil; -+} -+ -+/* -+ * call-seq: -+ * GC.collections => Integer -+ * -+ * Returns the number of garbage collections performed while GC statistics collection -+ * was enabled. -+ * -+ * GC.collections #=> 35 -+ * -+ */ -+ -+VALUE -+rb_gc_collections() -+{ -+ return INT2NUM(gc_collections); -+} -+ -+/* -+ * call-seq: -+ * GC.time => Integer -+ * -+ * Returns the time spent during garbage collection while GC statistics collection -+ * was enabled (in micro seconds). -+ * -+ * GC.time #=> 20000 -+ * -+ */ -+ -+VALUE -+rb_gc_time() -+{ -+#if HAVE_LONG_LONG -+ return LL2NUM(gc_time); -+#else -+ return LONG2NUM(gc_time); -+#endif -+} -+ -+ - VALUE rb_mGC; - - static struct gc_list { -@@ -281,19 +395,19 @@ rb_gc_unregister_address(addr) - struct gc_list *tmp = global_List; - - if (tmp->varptr == addr) { -- global_List = tmp->next; -- RUBY_CRITICAL(free(tmp)); -- return; -+ global_List = tmp->next; -+ RUBY_CRITICAL(free(tmp)); -+ return; - } - while (tmp->next) { -- if (tmp->next->varptr == addr) { -- struct gc_list *t = tmp->next; -+ if (tmp->next->varptr == addr) { -+ struct gc_list *t = tmp->next; - -- tmp->next = tmp->next->next; -- RUBY_CRITICAL(free(t)); -- break; -- } -- tmp = tmp->next; -+ tmp->next = tmp->next->next; -+ RUBY_CRITICAL(free(t)); -+ break; -+ } -+ tmp = tmp->next; - } - } - -@@ -312,26 +426,26 @@ rb_global_variable(var) - - typedef struct RVALUE { - union { -- struct { -- unsigned long flags; /* always 0 for freed obj */ -- 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; -- struct RStruct rstruct; -- struct RBignum bignum; -- struct RFile file; -- struct RNode node; -- struct RMatch match; -- struct RVarmap varmap; -- struct SCOPE scope; -+ struct { -+ unsigned long flags; /* always 0 for freed obj */ -+ 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; -+ struct RStruct rstruct; -+ struct RBignum bignum; -+ struct RFile file; -+ struct RNode node; -+ struct RMatch match; -+ struct RVarmap varmap; -+ struct SCOPE scope; - } as; - #ifdef GC_DEBUG - char *file; -@@ -346,7 +460,7 @@ typedef struct RVALUE { - static RVALUE *freelist = 0; - static RVALUE *deferred_final_list = 0; - --#define HEAPS_INCREMENT 10 -+static int heaps_increment = 10; - static struct heaps_slot { - void *membase; - RVALUE *slot; -@@ -355,45 +469,197 @@ static struct heaps_slot { - static int heaps_length = 0; - static int heaps_used = 0; - --#define HEAP_MIN_SLOTS 10000 --static int heap_slots = HEAP_MIN_SLOTS; -+static int heap_min_slots = 10000; -+static int heap_slots = 10000; - --#define FREE_MIN 4096 -+static int heap_free_min = 4096; -+static int heap_slots_increment = 10000; -+static double heap_slots_growth_factor = 1.8; -+ -+static long initial_malloc_limit = GC_MALLOC_LIMIT; -+ -+static int verbose_gc_stats = Qfalse; -+ -+static FILE* gc_data_file = NULL; - - static RVALUE *himem, *lomem; - -+static void set_gc_parameters() -+{ -+ char *gc_stats_ptr, *min_slots_ptr, *free_min_ptr, *heap_slots_incr_ptr, -+ *heap_incr_ptr, *malloc_limit_ptr, *gc_heap_file_ptr, *heap_slots_growth_factor_ptr; -+ -+ gc_data_file = stderr; -+ -+ gc_stats_ptr = getenv("RUBY_GC_STATS"); -+ if (gc_stats_ptr != NULL) { -+ int gc_stats_i = atoi(gc_stats_ptr); -+ if (gc_stats_i > 0) { -+ verbose_gc_stats = Qtrue; -+ } -+ } -+ -+ gc_heap_file_ptr = getenv("RUBY_GC_DATA_FILE"); -+ if (gc_heap_file_ptr != NULL) { -+ FILE* data_file = fopen(gc_heap_file_ptr, "w"); -+ if (data_file != NULL) { -+ gc_data_file = data_file; -+ } -+ else { -+ fprintf(stderr, -+ "can't open gc log file %s for writing, using default\n", gc_heap_file_ptr); -+ } -+ } -+ -+ min_slots_ptr = getenv("RUBY_HEAP_MIN_SLOTS"); -+ if (min_slots_ptr != NULL) { -+ int min_slots_i = atoi(min_slots_ptr); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_MIN_SLOTS=%s\n", min_slots_ptr); -+ } -+ if (min_slots_i > 0) { -+ heap_slots = min_slots_i; -+ heap_min_slots = min_slots_i; -+ } -+ } -+ -+ free_min_ptr = getenv("RUBY_HEAP_FREE_MIN"); -+ if (free_min_ptr != NULL) { -+ int free_min_i = atoi(free_min_ptr); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_FREE_MIN=%s\n", free_min_ptr); -+ } -+ if (free_min_i > 0) { -+ heap_free_min = free_min_i; -+ } -+ } -+ -+ heap_incr_ptr = getenv("RUBY_HEAP_INCREMENT"); -+ if (heap_incr_ptr != NULL) { -+ int heap_incr_i = atoi(heap_incr_ptr); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_INCREMENT=%s\n", heap_incr_ptr); -+ } -+ if (heap_incr_i > 0) { -+ heaps_increment = heap_incr_i; -+ } -+ } -+ -+ heap_slots_incr_ptr = getenv("RUBY_HEAP_SLOTS_INCREMENT"); -+ if (heap_slots_incr_ptr != NULL) { -+ int heap_slots_incr_i = atoi(heap_slots_incr_ptr); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_INCREMENT=%s\n", heap_slots_incr_ptr); -+ } -+ if (heap_slots_incr_i > 0) { -+ heap_slots_increment = heap_slots_incr_i; -+ } -+ } -+ -+ heap_slots_growth_factor_ptr = getenv("RUBY_HEAP_SLOTS_GROWTH_FACTOR"); -+ if (heap_slots_growth_factor_ptr != NULL) { -+ double heap_slots_growth_factor_d = atoi(heap_slots_growth_factor_ptr); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_GROWTH_FACTOR=%s\n", heap_slots_growth_factor_ptr); -+ } -+ if (heap_slots_growth_factor_d > 0) { -+ heap_slots_growth_factor = heap_slots_growth_factor_d; -+ } -+ } -+ -+ malloc_limit_ptr = getenv("RUBY_GC_MALLOC_LIMIT"); -+ if (malloc_limit_ptr != NULL) { -+ int malloc_limit_i = atol(malloc_limit_ptr); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_GC_MALLOC_LIMIT=%s\n", malloc_limit_ptr); -+ } -+ if (malloc_limit_i > 0) { -+ initial_malloc_limit = malloc_limit_i; -+ } -+ } -+} -+ -+/* -+ * call-seq: -+ * GC.dump => nil -+ * -+ * dumps information about the current GC data structures to the GC log file -+ * -+ * GC.dump #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_dump() -+{ -+ int i; -+ -+ for (i = 0; i < heaps_used; i++) { -+ int heap_size = heaps[i].limit; -+ fprintf(gc_data_file, "HEAP[%2d]: size=%7d\n", i, heap_size); -+ } -+ -+ return Qnil; -+} -+ -+/* -+ * call-seq: -+ * GC.log String => String -+ * -+ * Logs string to the GC data file and returns it. -+ * -+ * GC.log "manual GC call" #=> "manual GC call" -+ * -+ */ -+ -+VALUE -+rb_gc_log(self, original_str) -+ VALUE self, original_str; -+{ -+ if (original_str == Qnil) { -+ fprintf(gc_data_file, "\n"); -+ } -+ else { -+ VALUE str = StringValue(original_str); -+ char *p = RSTRING(str)->ptr; -+ fprintf(gc_data_file, "%s\n", p); -+ } -+ return original_str; -+} -+ -+ - static void - add_heap() - { - RVALUE *p, *pend; - - if (heaps_used == heaps_length) { -- /* Realloc heaps */ -- struct heaps_slot *p; -- int length; -- -- heaps_length += HEAPS_INCREMENT; -- length = heaps_length*sizeof(struct heaps_slot); -- RUBY_CRITICAL( -- if (heaps_used > 0) { -- p = (struct heaps_slot *)realloc(heaps, length); -- if (p) heaps = p; -- } -- else { -- p = heaps = (struct heaps_slot *)malloc(length); -- }); -- if (p == 0) rb_memerror(); -+ /* Realloc heaps */ -+ struct heaps_slot *p; -+ int length; -+ -+ heaps_length += heaps_increment; -+ length = heaps_length*sizeof(struct heaps_slot); -+ RUBY_CRITICAL( -+ if (heaps_used > 0) { -+ p = (struct heaps_slot *)realloc(heaps, length); -+ if (p) heaps = p; -+ } -+ else { -+ p = heaps = (struct heaps_slot *)malloc(length); -+ }); -+ if (p == 0) rb_memerror(); - } - - for (;;) { -- RUBY_CRITICAL(p = (RVALUE*)malloc(sizeof(RVALUE)*(heap_slots+1))); -- if (p == 0) { -- if (heap_slots == HEAP_MIN_SLOTS) { -- rb_memerror(); -- } -- heap_slots = HEAP_MIN_SLOTS; -- continue; -- } -+ RUBY_CRITICAL(p = (RVALUE*)malloc(sizeof(RVALUE)*(heap_slots+1))); -+ if (p == 0) { -+ if (heap_slots == heap_min_slots) { -+ rb_memerror(); -+ } -+ heap_slots = heap_min_slots; -+ continue; -+ } - heaps[heaps_used].membase = p; - if ((VALUE)p % sizeof(RVALUE) == 0) - heap_slots += 1; -@@ -401,25 +667,26 @@ add_heap() - p = (RVALUE*)((VALUE)p + sizeof(RVALUE) - ((VALUE)p % sizeof(RVALUE))); - heaps[heaps_used].slot = p; - heaps[heaps_used].limit = heap_slots; -- break; -+ break; - } - pend = p + heap_slots; - if (lomem == 0 || lomem > p) lomem = p; - if (himem < pend) himem = pend; - heaps_used++; -- heap_slots *= 1.8; -- if (heap_slots <= 0) heap_slots = HEAP_MIN_SLOTS; -+ heap_slots += heap_slots_increment; -+ heap_slots_increment *= heap_slots_growth_factor; -+ if (heap_slots <= 0) heap_slots = heap_min_slots; - - while (p < pend) { -- p->as.free.flags = 0; -- p->as.free.next = freelist; -- freelist = p; -- p++; -+ p->as.free.flags = 0; -+ p->as.free.next = freelist; -+ freelist = p; -+ p++; - } - } - #define RANY(o) ((RVALUE*)(o)) - --int -+int - rb_during_gc() - { - return during_gc; -@@ -431,7 +698,7 @@ rb_newobj() - VALUE obj; - - if (during_gc) -- rb_bug("object allocation during garbage collection phase"); -+ rb_bug("object allocation during garbage collection phase"); - - if (ruby_gc_stress || !freelist) garbage_collect(); - -@@ -580,13 +847,13 @@ rb_source_filename(f) - st_data_t name; - - if (!st_lookup(source_filenames, (st_data_t)f, &name)) { -- long len = strlen(f) + 1; -- char *ptr = ALLOC_N(char, len + 1); -- name = (st_data_t)ptr; -- *ptr++ = 0; -- MEMCPY(ptr, f, char, len); -- st_add_direct(source_filenames, (st_data_t)ptr, name); -- return ptr; -+ long len = strlen(f) + 1; -+ char *ptr = ALLOC_N(char, len + 1); -+ name = (st_data_t)ptr; -+ *ptr++ = 0; -+ MEMCPY(ptr, f, char, len); -+ st_add_direct(source_filenames, (st_data_t)ptr, name); -+ return ptr; - } - return (char *)name + 1; - } -@@ -596,7 +863,7 @@ mark_source_filename(f) - char *f; - { - if (f) { -- f[-1] = 1; -+ f[-1] = 1; - } - } - -@@ -605,12 +872,12 @@ sweep_source_filename(key, value) - char *key, *value; - { - if (*value) { -- *value = 0; -- return ST_CONTINUE; -+ *value = 0; -+ return ST_CONTINUE; - } - else { -- free(value); -- return ST_DELETE; -+ free(value); -+ return ST_DELETE; - } - } - -@@ -625,14 +892,14 @@ gc_mark_all() - - init_mark_stack(); - for (i = 0; i < heaps_used; i++) { -- p = heaps[i].slot; pend = p + heaps[i].limit; -- while (p < pend) { -- if ((p->as.basic.flags & FL_MARK) && -- (p->as.basic.flags != FL_MARK)) { -- gc_mark_children((VALUE)p, 0); -- } -- p++; -- } -+ p = heaps[i].slot; pend = p + heaps[i].limit; -+ while (p < pend) { -+ if ((p->as.basic.flags & FL_MARK) && -+ (p->as.basic.flags != FL_MARK)) { -+ gc_mark_children((VALUE)p, 0); -+ } -+ p++; -+ } - } - } - -@@ -647,8 +914,8 @@ gc_mark_rest() - - init_mark_stack(); - while(p != tmp_arry){ -- p--; -- gc_mark_children(*p, 0); -+ p--; -+ gc_mark_children(*p, 0); - } - } - -@@ -665,9 +932,9 @@ is_pointer_to_heap(ptr) - - /* check if p looks like a pointer */ - for (i=0; i < heaps_used; i++) { -- heap_org = heaps[i].slot; -- if (heap_org <= p && p < heap_org + heaps[i].limit) -- return Qtrue; -+ heap_org = heaps[i].slot; -+ if (heap_org <= p && p < heap_org + heaps[i].limit) -+ return Qtrue; - } - return Qfalse; - } -@@ -680,10 +947,10 @@ mark_locations_array(x, n) - VALUE v; - while (n--) { - v = *x; -- if (is_pointer_to_heap((void *)v)) { -- gc_mark(v, 0); -- } -- x++; -+ if (is_pointer_to_heap((void *)v)) { -+ gc_mark(v, 0); -+ } -+ x++; - } - } - -@@ -780,7 +1047,7 @@ rb_gc_mark_maybe(obj) - VALUE obj; - { - if (is_pointer_to_heap((void *)obj)) { -- gc_mark(obj, 0); -+ gc_mark(obj, 0); - } - } - -@@ -828,7 +1095,7 @@ gc_mark_children(ptr, lev) - { - register RVALUE *obj = RANY(ptr); - -- goto marking; /* skip */ -+ goto marking; /* skip */ - - again: - obj = RANY(ptr); -@@ -839,148 +1106,148 @@ gc_mark_children(ptr, lev) - - marking: - if (FL_TEST(obj, FL_EXIVAR)) { -- rb_mark_generic_ivar(ptr); -+ rb_mark_generic_ivar(ptr); - } - - switch (obj->as.basic.flags & T_MASK) { - case T_NIL: - case T_FIXNUM: -- rb_bug("rb_gc_mark() called for broken object"); -- break; -+ rb_bug("rb_gc_mark() called for broken object"); -+ break; - - case T_NODE: -- mark_source_filename(obj->as.node.nd_file); -- switch (nd_type(obj)) { -- case NODE_IF: /* 1,2,3 */ -- case NODE_FOR: -- case NODE_ITER: -- case NODE_CREF: -- case NODE_WHEN: -- case NODE_MASGN: -- case NODE_RESCUE: -- case NODE_RESBODY: -- case NODE_CLASS: -- gc_mark((VALUE)obj->as.node.u2.node, lev); -- /* 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_FBODY: -- case NODE_ENSURE: -- case NODE_CALL: -- case NODE_DEFS: -- case NODE_OP_ASGN1: -- gc_mark((VALUE)obj->as.node.u1.node, lev); -- /* fall through */ -- case NODE_SUPER: /* 3 */ -- case NODE_FCALL: -- case NODE_DEFN: -- case NODE_NEWLINE: -- ptr = (VALUE)obj->as.node.u3.node; -- goto again; -- -- 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_ARGS: -- gc_mark((VALUE)obj->as.node.u1.node, lev); -- /* fall through */ -- case NODE_METHOD: /* 2 */ -- case NODE_NOT: -- case NODE_GASGN: -- case NODE_LASGN: -- case NODE_DASGN: -- case NODE_DASGN_CURR: -- case NODE_IASGN: -- case NODE_CVDECL: -- case NODE_CVASGN: -- case NODE_COLON3: -- case NODE_OPT_N: -- case NODE_EVSTR: -- case NODE_UNDEF: -- ptr = (VALUE)obj->as.node.u2.node; -- goto again; -- -- 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: -- case NODE_SVALUE: -- ptr = (VALUE)obj->as.node.u1.node; -- goto again; -- -- case NODE_SCOPE: /* 2,3 */ -- case NODE_BLOCK_PASS: -- case NODE_CDECL: -- gc_mark((VALUE)obj->as.node.u3.node, lev); -- ptr = (VALUE)obj->as.node.u2.node; -- goto again; -- -- case NODE_ZARRAY: /* - */ -- case NODE_ZSUPER: -- case NODE_CFUNC: -- 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_ATTRSET: -- case NODE_BLOCK_ARG: -- case NODE_POSTEXE: -- break; -- case NODE_ALLOCA: -- mark_locations_array((VALUE*)obj->as.node.u1.value, -- obj->as.node.u3.cnt); -- ptr = (VALUE)obj->as.node.u2.node; -- goto again; -- -- default: /* unlisted NODE */ -- if (is_pointer_to_heap(obj->as.node.u1.node)) { -- gc_mark((VALUE)obj->as.node.u1.node, lev); -- } -- if (is_pointer_to_heap(obj->as.node.u2.node)) { -- gc_mark((VALUE)obj->as.node.u2.node, lev); -- } -- if (is_pointer_to_heap(obj->as.node.u3.node)) { -- gc_mark((VALUE)obj->as.node.u3.node, lev); -- } -- } -- return; /* no need to mark class. */ -+ mark_source_filename(obj->as.node.nd_file); -+ switch (nd_type(obj)) { -+ case NODE_IF: /* 1,2,3 */ -+ case NODE_FOR: -+ case NODE_ITER: -+ case NODE_CREF: -+ case NODE_WHEN: -+ case NODE_MASGN: -+ case NODE_RESCUE: -+ case NODE_RESBODY: -+ case NODE_CLASS: -+ gc_mark((VALUE)obj->as.node.u2.node, lev); -+ /* 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_FBODY: -+ case NODE_ENSURE: -+ case NODE_CALL: -+ case NODE_DEFS: -+ case NODE_OP_ASGN1: -+ gc_mark((VALUE)obj->as.node.u1.node, lev); -+ /* fall through */ -+ case NODE_SUPER: /* 3 */ -+ case NODE_FCALL: -+ case NODE_DEFN: -+ case NODE_NEWLINE: -+ ptr = (VALUE)obj->as.node.u3.node; -+ goto again; -+ -+ 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_ARGS: -+ gc_mark((VALUE)obj->as.node.u1.node, lev); -+ /* fall through */ -+ case NODE_METHOD: /* 2 */ -+ case NODE_NOT: -+ case NODE_GASGN: -+ case NODE_LASGN: -+ case NODE_DASGN: -+ case NODE_DASGN_CURR: -+ case NODE_IASGN: -+ case NODE_CVDECL: -+ case NODE_CVASGN: -+ case NODE_COLON3: -+ case NODE_OPT_N: -+ case NODE_EVSTR: -+ case NODE_UNDEF: -+ ptr = (VALUE)obj->as.node.u2.node; -+ goto again; -+ -+ 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: -+ case NODE_SVALUE: -+ ptr = (VALUE)obj->as.node.u1.node; -+ goto again; -+ -+ case NODE_SCOPE: /* 2,3 */ -+ case NODE_BLOCK_PASS: -+ case NODE_CDECL: -+ gc_mark((VALUE)obj->as.node.u3.node, lev); -+ ptr = (VALUE)obj->as.node.u2.node; -+ goto again; -+ -+ case NODE_ZARRAY: /* - */ -+ case NODE_ZSUPER: -+ case NODE_CFUNC: -+ 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_ATTRSET: -+ case NODE_BLOCK_ARG: -+ case NODE_POSTEXE: -+ break; -+ case NODE_ALLOCA: -+ mark_locations_array((VALUE*)obj->as.node.u1.value, -+ obj->as.node.u3.cnt); -+ ptr = (VALUE)obj->as.node.u2.node; -+ goto again; -+ -+ default: /* unlisted NODE */ -+ if (is_pointer_to_heap(obj->as.node.u1.node)) { -+ gc_mark((VALUE)obj->as.node.u1.node, lev); -+ } -+ if (is_pointer_to_heap(obj->as.node.u2.node)) { -+ gc_mark((VALUE)obj->as.node.u2.node, lev); -+ } -+ if (is_pointer_to_heap(obj->as.node.u3.node)) { -+ gc_mark((VALUE)obj->as.node.u3.node, lev); -+ } -+ } -+ return; /* no need to mark class. */ - } - - gc_mark(obj->as.basic.klass, lev); -@@ -988,92 +1255,92 @@ gc_mark_children(ptr, lev) - case T_ICLASS: - case T_CLASS: - case T_MODULE: -- mark_tbl(obj->as.klass.m_tbl, lev); -- mark_tbl(obj->as.klass.iv_tbl, lev); -- ptr = obj->as.klass.super; -- goto again; -+ mark_tbl(obj->as.klass.m_tbl, lev); -+ mark_tbl(obj->as.klass.iv_tbl, lev); -+ ptr = obj->as.klass.super; -+ goto again; - - case T_ARRAY: -- if (FL_TEST(obj, ELTS_SHARED)) { -- ptr = obj->as.array.aux.shared; -- goto again; -- } -- else { -- long i, len = obj->as.array.len; -- VALUE *ptr = obj->as.array.ptr; -+ if (FL_TEST(obj, ELTS_SHARED)) { -+ ptr = obj->as.array.aux.shared; -+ goto again; -+ } -+ else { -+ long i, len = obj->as.array.len; -+ VALUE *ptr = obj->as.array.ptr; - -- for (i=0; i < len; i++) { -- gc_mark(*ptr++, lev); -- } -- } -- break; -+ for (i=0; i < len; i++) { -+ gc_mark(*ptr++, lev); -+ } -+ } -+ break; - - case T_HASH: -- mark_hash(obj->as.hash.tbl, lev); -- ptr = obj->as.hash.ifnone; -- goto again; -+ mark_hash(obj->as.hash.tbl, lev); -+ ptr = obj->as.hash.ifnone; -+ goto again; - - case T_STRING: - #define STR_ASSOC FL_USER3 /* copied from string.c */ -- if (FL_TEST(obj, ELTS_SHARED|STR_ASSOC)) { -- ptr = obj->as.string.aux.shared; -- goto again; -- } -- break; -+ if (FL_TEST(obj, ELTS_SHARED|STR_ASSOC)) { -+ ptr = obj->as.string.aux.shared; -+ goto again; -+ } -+ break; - - case T_DATA: -- if (obj->as.data.dmark) (*obj->as.data.dmark)(DATA_PTR(obj)); -- break; -+ if (obj->as.data.dmark) (*obj->as.data.dmark)(DATA_PTR(obj)); -+ break; - - case T_OBJECT: -- mark_tbl(obj->as.object.iv_tbl, lev); -- break; -+ mark_tbl(obj->as.object.iv_tbl, lev); -+ break; - - case T_FILE: - case T_REGEXP: - case T_FLOAT: - case T_BIGNUM: - case T_BLKTAG: -- break; -+ break; - - case T_MATCH: -- if (obj->as.match.str) { -- ptr = obj->as.match.str; -- goto again; -- } -- break; -+ if (obj->as.match.str) { -+ ptr = obj->as.match.str; -+ goto again; -+ } -+ break; - - case T_VARMAP: -- gc_mark(obj->as.varmap.val, lev); -- ptr = (VALUE)obj->as.varmap.next; -- goto again; -+ gc_mark(obj->as.varmap.val, lev); -+ ptr = (VALUE)obj->as.varmap.next; -+ goto again; - - case T_SCOPE: -- if (obj->as.scope.local_vars && (obj->as.scope.flags & SCOPE_MALLOC)) { -- int n = obj->as.scope.local_tbl[0]+1; -- VALUE *vars = &obj->as.scope.local_vars[-1]; -+ if (obj->as.scope.local_vars && (obj->as.scope.flags & SCOPE_MALLOC)) { -+ int n = obj->as.scope.local_tbl[0]+1; -+ VALUE *vars = &obj->as.scope.local_vars[-1]; - -- while (n--) { -- gc_mark(*vars++, lev); -- } -- } -- break; -+ while (n--) { -+ gc_mark(*vars++, lev); -+ } -+ } -+ break; - - case T_STRUCT: -- { -- long len = obj->as.rstruct.len; -- VALUE *ptr = obj->as.rstruct.ptr; -+ { -+ long len = obj->as.rstruct.len; -+ VALUE *ptr = obj->as.rstruct.ptr; - -- while (len--) { -- gc_mark(*ptr++, lev); -- } -- } -- break; -+ while (len--) { -+ gc_mark(*ptr++, lev); -+ } -+ } -+ break; - - default: -- rb_bug("rb_gc_mark(): unknown data type 0x%lx(0x%lx) %s", -- obj->as.basic.flags & T_MASK, obj, -- is_pointer_to_heap(obj) ? "corrupted object" : "non object"); -+ rb_bug("rb_gc_mark(): unknown data type 0x%lx(0x%lx) %s", -+ obj->as.basic.flags & T_MASK, obj, -+ is_pointer_to_heap(obj) ? "corrupted object" : "non object"); - } - } - -@@ -1102,22 +1369,55 @@ finalize_list(p) - } - } - -+static char* obj_type(int tp) -+{ -+ switch (tp) { -+ case T_NIL : return "NIL"; -+ case T_OBJECT : return "OBJECT"; -+ case T_CLASS : return "CLASS"; -+ case T_ICLASS : return "ICLASS"; -+ case T_MODULE : return "MODULE"; -+ case T_FLOAT : return "FLOAT"; -+ case T_STRING : return "STRING"; -+ case T_REGEXP : return "REGEXP"; -+ case T_ARRAY : return "ARRAY"; -+ case T_FIXNUM : return "FIXNUM"; -+ case T_HASH : return "HASH"; -+ case T_STRUCT : return "STRUCT"; -+ case T_BIGNUM : return "BIGNUM"; -+ case T_FILE : return "FILE"; -+ -+ case T_TRUE : return "TRUE"; -+ case T_FALSE : return "FALSE"; -+ case T_DATA : return "DATA"; -+ case T_MATCH : return "MATCH"; -+ case T_SYMBOL : return "SYMBOL"; -+ -+ case T_BLKTAG : return "BLKTAG"; -+ case T_UNDEF : return "UNDEF"; -+ case T_VARMAP : return "VARMAP"; -+ case T_SCOPE : return "SCOPE"; -+ case T_NODE : return "NODE"; -+ default: return "____"; -+ } -+} -+ - static void - free_unused_heaps() - { - int i, j; - - for (i = j = 1; j < heaps_used; i++) { -- if (heaps[i].limit == 0) { -- free(heaps[i].membase); -- heaps_used--; -- } -- else { -- if (i != j) { -- heaps[j] = heaps[i]; -- } -- j++; -- } -+ if (heaps[i].limit == 0) { -+ free(heaps[i].membase); -+ heaps_used--; -+ } -+ else { -+ if (i != j) { -+ heaps[j] = heaps[i]; -+ } -+ j++; -+ } - } - } - -@@ -1134,24 +1434,33 @@ gc_sweep() - unsigned long live = 0; - unsigned long free_min = 0; - -+ unsigned long really_freed = 0; -+ int free_counts[256]; -+ int live_counts[256]; -+ int do_gc_stats = gc_statistics & verbose_gc_stats; -+ - for (i = 0; i < heaps_used; i++) { - free_min += heaps[i].limit; - } - free_min = free_min * 0.2; -- if (free_min < FREE_MIN) -- free_min = FREE_MIN; -+ if (free_min < heap_free_min) -+ free_min = heap_free_min; -+ -+ if (do_gc_stats) { -+ for (i = 0 ; i< 256; i++) { free_counts[i] = live_counts[i] = 0; } -+ } - - if (ruby_in_compile && ruby_parser_stack_on_heap()) { -- /* should not reclaim nodes during compilation -+ /* should not reclaim nodes during compilation - if yacc's semantic stack is not allocated on machine stack */ -- for (i = 0; i < heaps_used; i++) { -- p = heaps[i].slot; pend = p + heaps[i].limit; -- while (p < pend) { -- if (!(p->as.basic.flags&FL_MARK) && BUILTIN_TYPE(p) == T_NODE) -- gc_mark((VALUE)p, 0); -- p++; -- } -- } -+ for (i = 0; i < heaps_used; i++) { -+ p = heaps[i].slot; pend = p + heaps[i].limit; -+ while (p < pend) { -+ if (!(p->as.basic.flags&FL_MARK) && BUILTIN_TYPE(p) == T_NODE) -+ gc_mark((VALUE)p, 0); -+ p++; -+ } -+ } - } - - mark_source_filename(ruby_sourcefile); -@@ -1172,7 +1481,7 @@ gc_sweep() - while (p < pend) { - if (!(p->as.basic.flags & FL_MARK)) { - if (p->as.basic.flags && -- ((deferred = obj_free((VALUE)p)) || -+ (((do_gc_stats && really_freed++), deferred = obj_free((VALUE)p)) || - ((FL_TEST(p, FL_FINALIZE)) && need_call_final))) { - if (!deferred) { - p->as.free.flags = T_DEFERRED; -@@ -1183,6 +1492,12 @@ gc_sweep() - final_list = p; - } - else { -+ if (do_gc_stats) { -+ int obt = p->as.basic.flags & T_MASK; -+ if (obt) { -+ free_counts[obt]++; -+ } -+ } - add_freelist(p); - } - n++; -@@ -1194,6 +1509,9 @@ gc_sweep() - else { - RBASIC(p)->flags &= ~FL_MARK; - live++; -+ if (do_gc_stats) { -+ live_counts[RANY((VALUE)p)->as.basic.flags & T_MASK]++; -+ } - } - p++; - } -@@ -1211,15 +1529,29 @@ gc_sweep() - } - } - if (malloc_increase > malloc_limit) { -- malloc_limit += (malloc_increase - malloc_limit) * (double)live / (live + freed); -- if (malloc_limit < GC_MALLOC_LIMIT) malloc_limit = GC_MALLOC_LIMIT; -+ malloc_limit += (malloc_increase - malloc_limit) * (double)live / (live + freed); -+ if (malloc_limit < initial_malloc_limit) malloc_limit = initial_malloc_limit; - } - malloc_increase = 0; - if (freed < free_min) { -- add_heap(); -+ add_heap(); - } - during_gc = 0; - -+ if (do_gc_stats) { -+ fprintf(gc_data_file, "objects processed: %.7d\n", live+freed); -+ fprintf(gc_data_file, "live objects : %.7d\n", live); -+ fprintf(gc_data_file, "freelist objects : %.7d\n", freed - really_freed); -+ fprintf(gc_data_file, "freed objects : %.7d\n", really_freed); -+ for(i=0; i<256; i++) { -+ if (free_counts[i]>0 || live_counts[i]>0) { -+ fprintf(gc_data_file, -+ "kept %.7d / freed %.7d objects of type %s\n", -+ live_counts[i], free_counts[i], obj_type(i)); -+ } -+ } -+ } -+ - /* clear finalization list */ - if (final_list) { - deferred_final_list = final_list; -@@ -1260,51 +1592,51 @@ obj_free(obj) - case T_FIXNUM: - case T_TRUE: - case T_FALSE: -- rb_bug("obj_free() called for broken object"); -- break; -+ rb_bug("obj_free() called for broken object"); -+ break; - } - - if (FL_TEST(obj, FL_EXIVAR)) { -- rb_free_generic_ivar((VALUE)obj); -+ rb_free_generic_ivar((VALUE)obj); - } - - switch (BUILTIN_TYPE(obj)) { - case T_OBJECT: -- if (RANY(obj)->as.object.iv_tbl) { -- st_free_table(RANY(obj)->as.object.iv_tbl); -- } -- break; -+ if (RANY(obj)->as.object.iv_tbl) { -+ st_free_table(RANY(obj)->as.object.iv_tbl); -+ } -+ break; - case T_MODULE: - case T_CLASS: -- rb_clear_cache_by_class((VALUE)obj); -- st_free_table(RANY(obj)->as.klass.m_tbl); -- if (RANY(obj)->as.object.iv_tbl) { -- st_free_table(RANY(obj)->as.object.iv_tbl); -- } -- break; -+ rb_clear_cache_by_class((VALUE)obj); -+ st_free_table(RANY(obj)->as.klass.m_tbl); -+ if (RANY(obj)->as.object.iv_tbl) { -+ st_free_table(RANY(obj)->as.object.iv_tbl); -+ } -+ break; - case T_STRING: -- if (RANY(obj)->as.string.ptr && !FL_TEST(obj, ELTS_SHARED)) { -- RUBY_CRITICAL(free(RANY(obj)->as.string.ptr)); -- } -- break; -+ if (RANY(obj)->as.string.ptr && !FL_TEST(obj, ELTS_SHARED)) { -+ RUBY_CRITICAL(free(RANY(obj)->as.string.ptr)); -+ } -+ break; - case T_ARRAY: -- if (RANY(obj)->as.array.ptr && !FL_TEST(obj, ELTS_SHARED)) { -- RUBY_CRITICAL(free(RANY(obj)->as.array.ptr)); -- } -- break; -+ if (RANY(obj)->as.array.ptr && !FL_TEST(obj, ELTS_SHARED)) { -+ RUBY_CRITICAL(free(RANY(obj)->as.array.ptr)); -+ } -+ break; - case T_HASH: -- if (RANY(obj)->as.hash.tbl) { -- st_free_table(RANY(obj)->as.hash.tbl); -- } -- break; -+ if (RANY(obj)->as.hash.tbl) { -+ st_free_table(RANY(obj)->as.hash.tbl); -+ } -+ break; - case T_REGEXP: -- if (RANY(obj)->as.regexp.ptr) { -- re_free_pattern(RANY(obj)->as.regexp.ptr); -- } -- if (RANY(obj)->as.regexp.str) { -- RUBY_CRITICAL(free(RANY(obj)->as.regexp.str)); -- } -- break; -+ if (RANY(obj)->as.regexp.ptr) { -+ re_free_pattern(RANY(obj)->as.regexp.ptr); -+ } -+ if (RANY(obj)->as.regexp.str) { -+ RUBY_CRITICAL(free(RANY(obj)->as.regexp.str)); -+ } -+ break; - case T_DATA: - if (DATA_PTR(obj)) { - if ((long)RANY(obj)->as.data.dfree == -1) { -@@ -1317,11 +1649,11 @@ obj_free(obj) - } - break; - case T_MATCH: -- if (RANY(obj)->as.match.regs) { -- re_free_registers(RANY(obj)->as.match.regs); -- RUBY_CRITICAL(free(RANY(obj)->as.match.regs)); -- } -- break; -+ if (RANY(obj)->as.match.regs) { -+ re_free_registers(RANY(obj)->as.match.regs); -+ RUBY_CRITICAL(free(RANY(obj)->as.match.regs)); -+ } -+ break; - case T_FILE: - if (RANY(obj)->as.file.fptr) { - struct rb_io_t *fptr = RANY(obj)->as.file.fptr; -@@ -1332,19 +1664,19 @@ obj_free(obj) - } - break; - case T_ICLASS: -- /* iClass shares table with the module */ -- break; -+ /* iClass shares table with the module */ -+ break; - - case T_FLOAT: - case T_VARMAP: - case T_BLKTAG: -- break; -+ break; - - case T_BIGNUM: -- if (RANY(obj)->as.bignum.digits) { -- RUBY_CRITICAL(free(RANY(obj)->as.bignum.digits)); -- } -- break; -+ if (RANY(obj)->as.bignum.digits) { -+ RUBY_CRITICAL(free(RANY(obj)->as.bignum.digits)); -+ } -+ break; - case T_NODE: - switch (nd_type(obj)) { - case NODE_SCOPE: -@@ -1359,7 +1691,7 @@ obj_free(obj) - break; /* no need to free iv_tbl */ - - case T_SCOPE: -- if (RANY(obj)->as.scope.local_vars && -+ if (RANY(obj)->as.scope.local_vars && - RANY(obj)->as.scope.flags != SCOPE_ALLOCA) { - VALUE *vars = RANY(obj)->as.scope.local_vars-1; - if (!(RANY(obj)->as.scope.flags & SCOPE_CLONE) && vars[0] == 0) -@@ -1370,14 +1702,14 @@ obj_free(obj) - break; - - case T_STRUCT: -- if (RANY(obj)->as.rstruct.ptr) { -- RUBY_CRITICAL(free(RANY(obj)->as.rstruct.ptr)); -- } -- break; -+ if (RANY(obj)->as.rstruct.ptr) { -+ RUBY_CRITICAL(free(RANY(obj)->as.rstruct.ptr)); -+ } -+ break; - - default: -- rb_bug("gc_sweep(): unknown data type 0x%lx(0x%lx)", -- RANY(obj)->as.basic.flags & T_MASK, obj); -+ rb_bug("gc_sweep(): unknown data type 0x%lx(0x%lx)", -+ RANY(obj)->as.basic.flags & T_MASK, obj); - } - - return 0; -@@ -1407,18 +1739,18 @@ _rb_setjmp:\n\ - typedef unsigned long rb_jmp_buf[6]; - __asm__ (".align 4\n\ - _rb_setjmp:\n\ -- pushl %ebp\n\ -- movl %esp,%ebp\n\ -- movl 8(%ebp),%ebp\n\ -- movl %eax,(%ebp)\n\ -- movl %ebx,4(%ebp)\n\ -- movl %ecx,8(%ebp)\n\ -- movl %edx,12(%ebp)\n\ -- movl %esi,16(%ebp)\n\ -- movl %edi,20(%ebp)\n\ -- popl %ebp\n\ -- xorl %eax,%eax\n\ -- ret"); -+ pushl %ebp\n\ -+ movl %esp,%ebp\n\ -+ movl 8(%ebp),%ebp\n\ -+ movl %eax,(%ebp)\n\ -+ movl %ebx,4(%ebp)\n\ -+ movl %ecx,8(%ebp)\n\ -+ movl %edx,12(%ebp)\n\ -+ movl %esi,16(%ebp)\n\ -+ movl %edi,20(%ebp)\n\ -+ popl %ebp\n\ -+ xorl %eax,%eax\n\ -+ ret"); - #endif - #endif - int rb_setjmp (rb_jmp_buf); -@@ -1431,41 +1763,50 @@ garbage_collect() - struct gc_list *list; - struct FRAME * volatile frame; /* gcc 2.7.2.3 -O2 bug?? */ - jmp_buf save_regs_gc_mark; -+ struct timeval gctv1, gctv2; - SET_STACK_END; - - #ifdef HAVE_NATIVETHREAD - if (!is_ruby_native_thread()) { -- rb_bug("cross-thread violation on rb_gc()"); -+ rb_bug("cross-thread violation on rb_gc()"); - } - #endif - if (dont_gc || during_gc) { -- if (!freelist) { -- add_heap(); -- } -- return; -+ if (!freelist) { -+ add_heap(); -+ } -+ return; - } - if (during_gc) return; - during_gc++; - -+ if (gc_statistics) { -+ gc_collections++; -+ gettimeofday(&gctv1, NULL); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "Garbage collection started\n"); -+ } -+ } -+ - init_mark_stack(); - - gc_mark((VALUE)ruby_current_node, 0); - - /* mark frame stack */ - for (frame = ruby_frame; frame; frame = frame->prev) { -- rb_gc_mark_frame(frame); -- if (frame->tmp) { -- struct FRAME *tmp = frame->tmp; -- while (tmp) { -- rb_gc_mark_frame(tmp); -- tmp = tmp->prev; -- } -- } -+ rb_gc_mark_frame(frame); -+ if (frame->tmp) { -+ struct FRAME *tmp = frame->tmp; -+ while (tmp) { -+ rb_gc_mark_frame(tmp); -+ tmp = tmp->prev; -+ } -+ } - } - gc_mark((VALUE)ruby_scope, 0); - gc_mark((VALUE)ruby_dyna_vars, 0); - if (finalizer_table) { -- mark_tbl(finalizer_table, 0); -+ mark_tbl(finalizer_table, 0); - } - - FLUSH_REGISTER_WINDOWS; -@@ -1478,9 +1819,9 @@ garbage_collect() - rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)STACK_END + 1); - #else - if ((VALUE*)STACK_END < rb_gc_stack_start) -- rb_gc_mark_locations((VALUE*)STACK_END, rb_gc_stack_start); -+ rb_gc_mark_locations((VALUE*)STACK_END, rb_gc_stack_start); - else -- rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)STACK_END + 1); -+ rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)STACK_END + 1); - #endif - #ifdef __ia64 - /* mark backing store (flushed register window on the stack) */ -@@ -1489,13 +1830,13 @@ garbage_collect() - #endif - #if defined(__human68k__) || defined(__mc68000__) - rb_gc_mark_locations((VALUE*)((char*)STACK_END + 2), -- (VALUE*)((char*)rb_gc_stack_start + 2)); -+ (VALUE*)((char*)rb_gc_stack_start + 2)); - #endif - rb_gc_mark_threads(); - - /* mark protected global variables */ - for (list = global_List; list; list = list->next) { -- rb_gc_mark_maybe(*list->varptr); -+ rb_gc_mark_maybe(*list->varptr); - } - rb_mark_end_proc(); - rb_gc_mark_global_tbl(); -@@ -1510,18 +1851,30 @@ garbage_collect() - - /* gc_mark objects whose marking are not completed*/ - do { -- while (!MARK_STACK_EMPTY) { -- if (mark_stack_overflow){ -- gc_mark_all(); -- } -- else { -- gc_mark_rest(); -- } -- } -- rb_gc_abort_threads(); -+ while (!MARK_STACK_EMPTY) { -+ if (mark_stack_overflow){ -+ gc_mark_all(); -+ } -+ else { -+ gc_mark_rest(); -+ } -+ } -+ rb_gc_abort_threads(); - } while (!MARK_STACK_EMPTY); - - gc_sweep(); -+ -+ if (gc_statistics) { -+ GC_TIME_TYPE musecs_used; -+ gettimeofday(&gctv2, NULL); -+ musecs_used = ((GC_TIME_TYPE)(gctv2.tv_sec - gctv1.tv_sec) * 1000000) + (gctv2.tv_usec - gctv1.tv_usec); -+ gc_time += musecs_used; -+ -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "GC time: %d msec\n", musecs_used / 1000); -+ fflush(gc_data_file); -+ } -+ } - } - - void -@@ -1588,8 +1941,8 @@ Init_stack(addr) - memset(&m, 0, sizeof(m)); - VirtualQuery(&m, &m, sizeof(m)); - rb_gc_stack_start = -- STACK_UPPER((VALUE *)&m, (VALUE *)m.BaseAddress, -- (VALUE *)((char *)m.BaseAddress + m.RegionSize) - 1); -+ STACK_UPPER((VALUE *)&m, (VALUE *)m.BaseAddress, -+ (VALUE *)((char *)m.BaseAddress + m.RegionSize) - 1); - #elif defined(STACK_END_ADDRESS) - { - extern void *STACK_END_ADDRESS; -@@ -1599,24 +1952,24 @@ Init_stack(addr) - if (!addr) addr = (void *)&addr; - STACK_UPPER(&addr, addr, ++addr); - if (rb_gc_stack_start) { -- if (STACK_UPPER(&addr, -- rb_gc_stack_start > addr, -- rb_gc_stack_start < addr)) -- rb_gc_stack_start = addr; -- return; -+ if (STACK_UPPER(&addr, -+ rb_gc_stack_start > addr, -+ rb_gc_stack_start < addr)) -+ rb_gc_stack_start = addr; -+ return; - } - rb_gc_stack_start = addr; - #endif - #ifdef HAVE_GETRLIMIT - { -- struct rlimit rlim; -+ struct rlimit rlim; - -- if (getrlimit(RLIMIT_STACK, &rlim) == 0) { -- unsigned int space = rlim.rlim_cur/5; -+ if (getrlimit(RLIMIT_STACK, &rlim) == 0) { -+ unsigned int space = rlim.rlim_cur/5; - -- if (space > 1024*1024) space = 1024*1024; -- STACK_LEVEL_MAX = (rlim.rlim_cur - space) / sizeof(VALUE); -- } -+ if (space > 1024*1024) space = 1024*1024; -+ STACK_LEVEL_MAX = (rlim.rlim_cur - space) / sizeof(VALUE); -+ } - } - #endif - } -@@ -1652,16 +2005,16 @@ void ruby_init_stack(VALUE *addr - } - #elif defined _WIN32 - { -- MEMORY_BASIC_INFORMATION mi; -- DWORD size; -- DWORD space; -- -- if (VirtualQuery(&mi, &mi, sizeof(mi))) { -- size = (char *)mi.BaseAddress - (char *)mi.AllocationBase; -- space = size / 5; -- if (space > 1024*1024) space = 1024*1024; -- STACK_LEVEL_MAX = (size - space) / sizeof(VALUE); -- } -+ MEMORY_BASIC_INFORMATION mi; -+ DWORD size; -+ DWORD space; -+ -+ if (VirtualQuery(&mi, &mi, sizeof(mi))) { -+ size = (char *)mi.BaseAddress - (char *)mi.AllocationBase; -+ space = size / 5; -+ if (space > 1024*1024) space = 1024*1024; -+ STACK_LEVEL_MAX = (size - space) / sizeof(VALUE); -+ } - } - #endif - } -@@ -1701,8 +2054,9 @@ void - Init_heap() - { - if (!rb_gc_stack_start) { -- Init_stack(0); -+ Init_stack(0); - } -+ set_gc_parameters(); - add_heap(); - } - -@@ -1715,7 +2069,7 @@ os_obj_of(of) - volatile VALUE v; - - for (i = 0; i < heaps_used; i++) { -- RVALUE *p, *pend; -+ RVALUE *p, *pend; - - p = heaps[i].slot; pend = p + heaps[i].limit; - for (;p < pend; p++) { -@@ -1808,8 +2162,8 @@ add_final(os, block) - { - rb_warn("ObjectSpace::add_finalizer is deprecated; use define_finalizer"); - if (!rb_respond_to(block, rb_intern("call"))) { -- rb_raise(rb_eArgError, "wrong type argument %s (should be callable)", -- rb_obj_classname(block)); -+ rb_raise(rb_eArgError, "wrong type argument %s (should be callable)", -+ rb_obj_classname(block)); - } - rb_ary_push(finalizers, block); - return block; -@@ -1864,7 +2218,7 @@ undefine_final(os, obj) - VALUE os, obj; - { - if (finalizer_table) { -- st_delete(finalizer_table, (st_data_t*)&obj, 0); -+ st_delete(finalizer_table, (st_data_t*)&obj, 0); - } - return obj; - } -@@ -1888,11 +2242,11 @@ define_final(argc, argv, os) - - rb_scan_args(argc, argv, "11", &obj, &block); - if (argc == 1) { -- block = rb_block_proc(); -+ block = rb_block_proc(); - } - else if (!rb_respond_to(block, rb_intern("call"))) { -- rb_raise(rb_eArgError, "wrong type argument %s (should be callable)", -- rb_obj_classname(block)); -+ rb_raise(rb_eArgError, "wrong type argument %s (should be callable)", -+ rb_obj_classname(block)); - } - need_call_final = 1; - if (!FL_ABLE(obj)) { -@@ -1905,10 +2259,10 @@ define_final(argc, argv, os) - OBJ_FREEZE(block); - - if (!finalizer_table) { -- finalizer_table = st_init_numtable(); -+ finalizer_table = st_init_numtable(); - } - if (st_lookup(finalizer_table, obj, &table)) { -- rb_ary_push(table, block); -+ rb_ary_push(table, block); - } - else { - table = rb_ary_new3(1, block); -@@ -1927,7 +2281,7 @@ rb_gc_copy_finalizer(dest, obj) - if (!finalizer_table) return; - if (!FL_TEST(obj, FL_FINALIZE)) return; - if (st_lookup(finalizer_table, obj, &table)) { -- st_insert(finalizer_table, dest, table); -+ st_insert(finalizer_table, dest, table); - } - RBASIC(dest)->flags |= FL_FINALIZE; - } -@@ -1957,18 +2311,18 @@ run_final(obj) - args[1] = 0; - args[2] = (VALUE)ruby_safe_level; - for (i=0; ilen; i++) { -- args[0] = RARRAY(finalizers)->ptr[i]; -- if (!args[1]) args[1] = rb_ary_new3(1, objid); -- rb_protect((VALUE(*)_((VALUE)))run_single_final, (VALUE)args, &status); -+ args[0] = RARRAY(finalizers)->ptr[i]; -+ if (!args[1]) args[1] = rb_ary_new3(1, objid); -+ rb_protect((VALUE(*)_((VALUE)))run_single_final, (VALUE)args, &status); - } - if (finalizer_table && st_delete(finalizer_table, (st_data_t*)&obj, &table)) { -- for (i=0; ilen; i++) { -- VALUE final = RARRAY(table)->ptr[i]; -- args[0] = RARRAY(final)->ptr[1]; -- if (!args[1]) args[1] = rb_ary_new3(1, objid); -- args[2] = FIX2INT(RARRAY(final)->ptr[0]); -- rb_protect((VALUE(*)_((VALUE)))run_single_final, (VALUE)args, &status); -- } -+ for (i=0; ilen; i++) { -+ VALUE final = RARRAY(table)->ptr[i]; -+ args[0] = RARRAY(final)->ptr[1]; -+ if (!args[1]) args[1] = rb_ary_new3(1, objid); -+ args[2] = FIX2INT(RARRAY(final)->ptr[0]); -+ rb_protect((VALUE(*)_((VALUE)))run_single_final, (VALUE)args, &status); -+ } - } - rb_thread_critical = critical_save; - } -@@ -1980,8 +2334,8 @@ rb_gc_finalize_deferred() - - deferred_final_list = 0; - if (p) { -- finalize_list(p); -- free_unused_heaps(); -+ finalize_list(p); -+ free_unused_heaps(); - } - } - -@@ -2061,7 +2415,7 @@ id2ref(obj, objid) - if (ptr == Qfalse) return Qfalse; - if (ptr == Qnil) return Qnil; - if (FIXNUM_P(ptr)) return (VALUE)ptr; -- ptr = objid ^ FIXNUM_FLAG; /* unset FIXNUM_FLAG */ -+ ptr = objid ^ FIXNUM_FLAG; /* unset FIXNUM_FLAG */ - - if ((ptr % sizeof(RVALUE)) == (4 << 2)) { - ID symid = ptr / sizeof(RVALUE); -@@ -2075,7 +2429,7 @@ id2ref(obj, objid) - rb_raise(rb_eRangeError, "0x%lx is not id value", p0); - } - if (BUILTIN_TYPE(ptr) == 0 || RBASIC(ptr)->klass == 0) { -- rb_raise(rb_eRangeError, "0x%lx is recycled object", p0); -+ rb_raise(rb_eRangeError, "0x%lx is recycled object", p0); - } - return (VALUE)ptr; - } -@@ -2166,6 +2520,14 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "stress=", gc_stress_set, 1); - rb_define_method(rb_mGC, "garbage_collect", rb_gc_start, 0); - -+ rb_define_singleton_method(rb_mGC, "enable_stats", rb_gc_enable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "disable_stats", rb_gc_disable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0); -+ rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); -+ rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); -+ rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); -+ rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); -+ - rb_mObSpace = rb_define_module("ObjectSpace"); - rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1); - rb_define_module_function(rb_mObSpace, "garbage_collect", rb_gc_start, 0); -@@ -2188,7 +2550,7 @@ Init_GC() - - rb_global_variable(&nomem_error); - nomem_error = rb_exc_new3(rb_eNoMemError, -- rb_obj_freeze(rb_str_new2("failed to allocate memory"))); -+ rb_obj_freeze(rb_str_new2("failed to allocate memory"))); - OBJ_TAINT(nomem_error); - OBJ_FREEZE(nomem_error); - diff --git a/patches/ruby/1.8.7/p358/railsexpress/05-display-full-stack-trace.patch b/patches/ruby/1.8.7/p358/railsexpress/05-display-full-stack-trace.patch deleted file mode 100644 index a927a80ba6..0000000000 --- a/patches/ruby/1.8.7/p358/railsexpress/05-display-full-stack-trace.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/eval.c b/eval.c -index 6ff2560..fb3307c 100644 ---- a/eval.c -+++ b/eval.c -@@ -1325,8 +1325,8 @@ error_print() - int truncate = eclass == rb_eSysStackError; - - #define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5) --#define TRACE_HEAD 8 --#define TRACE_TAIL 5 -+#define TRACE_HEAD 100 -+#define TRACE_TAIL 100 - - ep = RARRAY(errat); - for (i=1; ilen; i++) { diff --git a/patches/ruby/1.8.7/p358/railsexpress/06-better-source-file-tracing.patch b/patches/ruby/1.8.7/p358/railsexpress/06-better-source-file-tracing.patch deleted file mode 100644 index f7a4d4f24f..0000000000 --- a/patches/ruby/1.8.7/p358/railsexpress/06-better-source-file-tracing.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/eval.c b/eval.c -index fb3307c..356226e 100644 ---- a/eval.c -+++ b/eval.c -@@ -1161,7 +1161,7 @@ static VALUE trace_func = 0; - static int tracing = 0; - static void call_trace_func _((rb_event_t,NODE*,VALUE,ID,VALUE)); - --#if 0 -+#if 1 - #define SET_CURRENT_SOURCE() (ruby_sourcefile = ruby_current_node->nd_file, \ - ruby_sourceline = nd_line(ruby_current_node)) - #else diff --git a/patches/ruby/1.8.7/p358/railsexpress/07-heap-dump-support.patch b/patches/ruby/1.8.7/p358/railsexpress/07-heap-dump-support.patch deleted file mode 100644 index 5235be6bcc..0000000000 --- a/patches/ruby/1.8.7/p358/railsexpress/07-heap-dump-support.patch +++ /dev/null @@ -1,159 +0,0 @@ -diff --git a/configure.in b/configure.in -index 62b34a8..4be088c 100644 ---- a/configure.in -+++ b/configure.in -@@ -1595,6 +1595,14 @@ fi - LDFLAGS="-L. $LDFLAGS" - AC_SUBST(ARCHFILE) - -+dnl enable gc debugging -+AC_ARG_ENABLE(gcdebug, -+ [ --enable-gcdebug build garbage collector with debugging enabled. ], -+ [enable_gcdebug=$enableval]) -+if test "$enable_gcdebug" = 'yes'; then -+ AC_DEFINE(GC_DEBUG, 1) -+fi -+ - dnl build rdoc index if requested - RDOCTARGET="" - AC_ARG_ENABLE(install-doc, -diff --git a/gc.c b/gc.c -index ab71d22..9ad716f 100644 ---- a/gc.c -+++ b/gc.c -@@ -411,7 +411,6 @@ rb_gc_unregister_address(addr) - } - } - --#undef GC_DEBUG - - void - rb_global_variable(var) -@@ -602,6 +601,85 @@ rb_gc_dump() - return Qnil; - } - -+ -+static char* obj_type(int tp); -+ -+#ifdef GC_DEBUG -+/* -+ * call-seq: -+ * GC.dump_file_and_line_info(String, boolean) => nil -+ * -+ * dumps information on which currently allocated object was created by which file and on which line -+ * -+ * GC.dump_file_and_line_info(String, boolean) #=> nil -+ * -+ * The second parameter specifies whether class names should be included in the dump. -+ * Note that including class names will allocate additional string objects on the heap. -+ * -+ */ -+ -+VALUE -+rb_gc_dump_file_and_line_info(int argc, VALUE *argv) -+{ -+ VALUE filename, str, include_classnames = Qnil; -+ char *fname = NULL; -+ char *klass = NULL; -+ FILE* f = NULL; -+ int i,n = 0; -+ -+ rb_scan_args(argc, argv, "11", &filename, &include_classnames); -+ -+ str = StringValue(filename); -+ fname = RSTRING(str)->ptr; -+ f = fopen(fname, "w"); -+ -+ for (i = 0; i < heaps_used; i++) { -+ RVALUE *p, *pend; -+ -+ p = heaps[i].slot; pend = p + heaps[i].limit; -+ for (;p < pend; p++) { -+ if (p->as.basic.flags) { -+ fprintf(f, "%s:%s:%d", obj_type(p->as.basic.flags & T_MASK), p->file, p->line); -+ // rb_obj_classname will create objects on the heap, we need a better solution -+ if (include_classnames == Qtrue) { -+ /* write the class */ -+ fprintf(f, ":"); -+ switch (TYPE(p)) { -+ case T_NONE: -+ fprintf(f, "__none__"); -+ break; -+ case T_BLKTAG: -+ fprintf(f, "__blktag__"); -+ break; -+ case T_UNDEF: -+ fprintf(f, "__undef__"); -+ break; -+ case T_VARMAP: -+ fprintf(f, "__varmap__"); -+ break; -+ case T_SCOPE: -+ fprintf(f, "__scope__"); -+ break; -+ case T_NODE: -+ fprintf(f, "__node__"); -+ break; -+ default: -+ if (!p->as.basic.klass) { -+ fprintf(f, "__unknown__"); -+ } else { -+ fprintf(f, rb_obj_classname((VALUE)p)); -+ } -+ } -+ } -+ fprintf(f, "\n"); -+ } -+ } -+ } -+ fclose(f); -+ return Qnil; -+} -+#endif -+ - /* - * call-seq: - * GC.log String => String -@@ -1066,6 +1144,11 @@ gc_mark(ptr, lev) - if (obj->as.basic.flags & FL_MARK) return; /* already marked */ - obj->as.basic.flags |= FL_MARK; - -+#ifdef GC_DEBUG -+ /* mark our new reference point for sourcefile objects */ -+ mark_source_filename(RANY(obj)->file); -+#endif -+ - if (lev > GC_LEVEL_MAX || (lev == 0 && ruby_stack_check())) { - if (!mark_stack_overflow) { - if (mark_stack_ptr - mark_stack < MARK_STACK_MAX) { -@@ -1104,6 +1187,11 @@ gc_mark_children(ptr, lev) - if (obj->as.basic.flags & FL_MARK) return; /* already marked */ - obj->as.basic.flags |= FL_MARK; - -+#ifdef GC_DEBUG -+ /* mark our new reference point for sourcefile objects */ -+ mark_source_filename(RANY(obj)->file); -+#endif -+ - marking: - if (FL_TEST(obj, FL_EXIVAR)) { - rb_mark_generic_ivar(ptr); -@@ -1550,6 +1638,7 @@ gc_sweep() - live_counts[i], free_counts[i], obj_type(i)); - } - } -+ fflush(gc_data_file); - } - - /* clear finalization list */ -@@ -2526,6 +2615,9 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); - rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); - rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); -+#ifdef GC_DEBUG -+ rb_define_singleton_method(rb_mGC, "dump_file_and_line_info", rb_gc_dump_file_and_line_info, -1); -+#endif - rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); - - rb_mObSpace = rb_define_module("ObjectSpace"); diff --git a/patches/ruby/1.8.7/p358/railsexpress/08-fork-support-for-gc-logging.patch b/patches/ruby/1.8.7/p358/railsexpress/08-fork-support-for-gc-logging.patch deleted file mode 100644 index 0f01a75db0..0000000000 --- a/patches/ruby/1.8.7/p358/railsexpress/08-fork-support-for-gc-logging.patch +++ /dev/null @@ -1,249 +0,0 @@ -diff --git a/gc.c b/gc.c -index 9ad716f..a3cbe91 100644 ---- a/gc.c -+++ b/gc.c -@@ -223,6 +223,8 @@ static int dont_gc; - static int gc_statistics = 0; - static GC_TIME_TYPE gc_time = 0; - static int gc_collections = 0; -+static int verbose_gc_stats = Qfalse; -+static FILE* gc_data_file = NULL; - static int during_gc; - static int need_call_final = 0; - static st_table *finalizer_table = 0; -@@ -368,9 +370,148 @@ rb_gc_time() - #endif - } - -- - VALUE rb_mGC; - -+/* -+ * call-seq: -+ * GC.enable_trace => true or false -+ * -+ * Enables garbage collection tracing, returning true if garbage -+ * collection tracing was already enabled. -+ * -+ * GC.enable_trace #=> false or true -+ * GC.enable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_trace() -+{ -+ int old = verbose_gc_stats; -+ verbose_gc_stats = Qtrue; -+ return old; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_trace => true or false -+ * -+ * Disables garbage collection tracing, returning true if garbage -+ * collection tracing was already disabled. -+ * -+ * GC.disable_trace #=> false or true -+ * GC.disable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_trace() -+{ -+ int old = verbose_gc_stats; -+ verbose_gc_stats = Qfalse; -+ return old; -+} -+ -+char* GC_LOGFILE_IVAR = "@gc_logfile_name"; -+ -+/* -+ * call-seq: -+ * GC.log_file(filename=nil, mode="w") => boolean -+ * -+ * Changes the GC data log file. Closes the currently open logfile. -+ * Returns true if the file was successfully opened for -+ * writing. Returns false if the file could not be opened for -+ * writing. Returns the name of the current logfile (or nil) if no -+ * parameter is given. Restores logging to stderr when given nil as -+ * an argument. -+ * -+ * GC.log_file #=> nil -+ * GC.log_file "/tmp/gc.log" #=> true -+ * GC.log_file #=> "/tmp/gc.log" -+ * GC.log_file nil #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_log_file(int argc, VALUE *argv, VALUE self) -+{ -+ VALUE filename = Qnil; -+ VALUE mode_str = Qnil; -+ FILE* f = NULL; -+ char* mode = "w"; -+ -+ VALUE current_logfile_name = rb_iv_get(rb_mGC, GC_LOGFILE_IVAR); -+ -+ if (argc==0) -+ return current_logfile_name; -+ -+ rb_scan_args(argc, argv, "02", &filename, &mode_str); -+ -+ if (filename == Qnil) { -+ /* close current logfile and reset logfile to stderr */ -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+ } -+ return Qtrue; -+ } -+ -+ /* we have a real logfile name */ -+ filename = StringValue(filename); -+ -+ if (rb_equal(current_logfile_name, filename) == Qtrue) { -+ /* do nothing if we get the file name we're already logging to */ -+ return Qtrue; -+ } -+ -+ /* get mode for file opening */ -+ if (mode_str != Qnil) -+ { -+ mode = RSTRING(StringValue(mode_str))->ptr; -+ } -+ -+ /* try to open file in given mode */ -+ if (f = fopen(RSTRING(filename)->ptr, mode)) { -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ } -+ gc_data_file = f; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, filename); -+ } else { -+ return Qfalse; -+ } -+ return Qtrue; -+} -+ -+ -+/* -+ * Called from process.c before a fork. Flushes the gc log file to -+ * avoid writing the buffered output twice (once in the parent, and -+ * once in the child). -+ */ -+void -+rb_gc_before_fork() -+{ -+ /* flush gc log file */ -+ fflush(gc_data_file); -+} -+ -+/* -+ * Called from process.c after a fork in the child process. Turns off -+ * logging, disables GC stats and resets all gc counters and timing -+ * information. -+ */ -+void -+rb_gc_after_fork() -+{ -+ rb_gc_disable_stats(); -+ rb_gc_clear_stats(); -+ rb_gc_disable_trace(); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+} -+ - static struct gc_list { - VALUE *varptr; - struct gc_list *next; -@@ -477,10 +618,6 @@ static double heap_slots_growth_factor = 1.8; - - static long initial_malloc_limit = GC_MALLOC_LIMIT; - --static int verbose_gc_stats = Qfalse; -- --static FILE* gc_data_file = NULL; -- - static RVALUE *himem, *lomem; - - static void set_gc_parameters() -@@ -496,6 +633,8 @@ static void set_gc_parameters() - if (gc_stats_i > 0) { - verbose_gc_stats = Qtrue; - } -+ /* child processes should not inherit RUBY_GC_STATS */ -+ unsetenv("RUBY_GC_STATS"); - } - - gc_heap_file_ptr = getenv("RUBY_GC_DATA_FILE"); -@@ -508,6 +647,8 @@ static void set_gc_parameters() - fprintf(stderr, - "can't open gc log file %s for writing, using default\n", gc_heap_file_ptr); - } -+ /* child processes should not inherit RUBY_GC_DATA_FILE to avoid clobbering */ -+ unsetenv("RUBY_GC_DATA_FILE"); - } - - min_slots_ptr = getenv("RUBY_HEAP_MIN_SLOTS"); -@@ -2619,6 +2760,9 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "dump_file_and_line_info", rb_gc_dump_file_and_line_info, -1); - #endif - rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); -+ rb_define_singleton_method(rb_mGC, "log_file", rb_gc_log_file, -1); -+ rb_define_singleton_method(rb_mGC, "enable_trace", rb_gc_enable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "disable_trace", rb_gc_disable_trace, 0); - - rb_mObSpace = rb_define_module("ObjectSpace"); - rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1); -diff --git a/intern.h b/intern.h -index 950ae9d..99696f1 100644 ---- a/intern.h -+++ b/intern.h -@@ -270,6 +270,8 @@ void rb_gc_call_finalizer_at_exit _((void)); - VALUE rb_gc_enable _((void)); - VALUE rb_gc_disable _((void)); - VALUE rb_gc_start _((void)); -+void rb_gc_before_fork _((void)); -+void rb_gc_after_fork _((void)); - /* hash.c */ - void st_foreach_safe _((struct st_table *, int (*)(ANYARGS), unsigned long)); - void rb_hash_foreach _((VALUE, int (*)(ANYARGS), VALUE)); -diff --git a/process.c b/process.c -index 8f6285d..ea28cb8 100644 ---- a/process.c -+++ b/process.c -@@ -1330,6 +1330,8 @@ rb_f_fork(obj) - fflush(stderr); - #endif - -+ rb_gc_before_fork(); -+ - before_exec(); - pid = fork(); - after_exec(); -@@ -1339,6 +1341,7 @@ rb_f_fork(obj) - #ifdef linux - after_exec(); - #endif -+ rb_gc_after_fork(); - rb_thread_atfork(); - if (rb_block_given_p()) { - int status; -@@ -1574,10 +1577,12 @@ rb_f_system(argc, argv) - - chfunc = signal(SIGCHLD, SIG_DFL); - retry: -+ rb_gc_before_fork(); - before_exec(); - pid = fork(); - if (pid == 0) { - /* child process */ -+ rb_gc_after_fork(); - rb_thread_atfork(); - rb_protect(proc_exec_args, (VALUE)&earg, NULL); - _exit(127); diff --git a/patches/ruby/1.8.7/p358/railsexpress/09-track-malloc-size.patch b/patches/ruby/1.8.7/p358/railsexpress/09-track-malloc-size.patch deleted file mode 100644 index d078748a44..0000000000 --- a/patches/ruby/1.8.7/p358/railsexpress/09-track-malloc-size.patch +++ /dev/null @@ -1,120 +0,0 @@ -diff --git a/gc.c b/gc.c -index a3cbe91..30a1219 100644 ---- a/gc.c -+++ b/gc.c -@@ -79,6 +79,17 @@ void *alloca (); - - static unsigned long malloc_increase = 0; - static unsigned long malloc_limit = GC_MALLOC_LIMIT; -+ -+#ifdef HAVE_LONG_LONG -+static unsigned LONG_LONG gc_allocated_size = 0; -+static unsigned LONG_LONG gc_num_allocations = 0; -+#else -+static unsigned long gc_allocated_size = 0; -+static unsigned long gc_num_allocations = 0; -+#endif -+static int gc_statistics = 0; -+ -+ - static void run_final(); - static VALUE nomem_error; - static void garbage_collect(); -@@ -163,6 +174,11 @@ ruby_xmalloc(size) - } - malloc_increase += size; - -+ if (gc_statistics) { -+ gc_allocated_size += size; -+ gc_num_allocations += 1; -+ } -+ - return mem; - } - -@@ -220,7 +236,6 @@ ruby_xfree(x) - - extern int ruby_in_compile; - static int dont_gc; --static int gc_statistics = 0; - static GC_TIME_TYPE gc_time = 0; - static int gc_collections = 0; - static int verbose_gc_stats = Qfalse; -@@ -329,11 +344,55 @@ rb_gc_clear_stats() - { - gc_collections = 0; - gc_time = 0; -+ gc_allocated_size = 0; -+ gc_num_allocations = 0; - return Qnil; - } - - /* - * call-seq: -+ * GC.allocated_size => Integer -+ * -+ * Returns the size of memory (in bytes) allocated since GC statistics collection -+ * was enabled. -+ * -+ * GC.allocated_size #=> 35 -+ * -+ */ -+VALUE -+rb_gc_allocated_size() -+{ -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_allocated_size); -+#else -+ return ULONG2NUM(gc_allocated_size); -+#endif -+} -+ -+/* -+ * call-seq: -+ * GC.num_allocations => Integer -+ * -+ * Returns the number of memory allocations since GC statistics collection -+ * was enabled. -+ * -+ * GC.num_allocations #=> 150 -+ * -+ */ -+VALUE -+rb_gc_num_allocations() -+{ -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_num_allocations); -+#else -+ return ULONG2NUM(gc_num_allocations); -+#endif -+} -+ -+/* -+ -+/* -+ * call-seq: - * GC.collections => Integer - * - * Returns the number of garbage collections performed while GC statistics collection -@@ -2753,6 +2812,8 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "enable_stats", rb_gc_enable_stats, 0); - rb_define_singleton_method(rb_mGC, "disable_stats", rb_gc_disable_stats, 0); - rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0); -+ rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); -+ rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); - rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); - rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); - rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); -diff --git a/intern.h b/intern.h -index 99696f1..1117614 100644 ---- a/intern.h -+++ b/intern.h -@@ -272,6 +272,8 @@ VALUE rb_gc_disable _((void)); - VALUE rb_gc_start _((void)); - void rb_gc_before_fork _((void)); - void rb_gc_after_fork _((void)); -+VALUE rb_gc_allocated_size _((void)); -+VALUE rb_gc_num_allocations _((void)); - /* hash.c */ - void st_foreach_safe _((struct st_table *, int (*)(ANYARGS), unsigned long)); - void rb_hash_foreach _((VALUE, int (*)(ANYARGS), VALUE)); diff --git a/patches/ruby/1.8.7/p358/railsexpress/10-track-object-allocation.patch b/patches/ruby/1.8.7/p358/railsexpress/10-track-object-allocation.patch deleted file mode 100644 index 0eef717a24..0000000000 --- a/patches/ruby/1.8.7/p358/railsexpress/10-track-object-allocation.patch +++ /dev/null @@ -1,111 +0,0 @@ -diff --git a/gc.c b/gc.c -index 30a1219..5b42b90 100644 ---- a/gc.c -+++ b/gc.c -@@ -96,6 +96,26 @@ static void garbage_collect(); - - int ruby_gc_stress = 0; - -+static unsigned long live_objects = 0; -+unsigned long rb_os_live_objects() -+{ -+ return live_objects; -+} -+ -+#if defined(HAVE_LONG_LONG) -+static unsigned LONG_LONG allocated_objects = 0; -+unsigned LONG_LONG rb_os_allocated_objects() -+{ -+ return allocated_objects; -+} -+#else -+static unsigned long allocated_objects = 0; -+unsigned long rb_os_allocated_objects() -+{ -+ return allocated_objects; -+} -+#endif -+ - NORETURN(void rb_exc_jump _((VALUE))); - - void -@@ -987,6 +1007,8 @@ rb_newobj() - RANY(obj)->file = ruby_sourcefile; - RANY(obj)->line = ruby_sourceline; - #endif -+ live_objects++; -+ allocated_objects++; - return obj; - } - -@@ -1825,6 +1847,7 @@ gc_sweep() - add_heap(); - } - during_gc = 0; -+ live_objects = live; - - if (do_gc_stats) { - fprintf(gc_data_file, "objects processed: %.7d\n", live+freed); -@@ -2790,6 +2813,35 @@ rb_obj_id(VALUE obj) - return (VALUE)((long)obj|FIXNUM_FLAG); - } - -+/* call-seq: -+ * ObjectSpace.live_objects => number -+ * -+ * Returns the count of objects currently allocated in the system. This goes -+ * down after the garbage collector runs. -+ */ -+static -+VALUE os_live_objects(VALUE self) -+{ -+ return ULONG2NUM(live_objects); -+} -+ -+/* call-seq: -+ * ObjectSpace.allocated_objects => number -+ * -+ * Returns the count of objects allocated since the Ruby interpreter has -+ * started. This number can only increase. To know how many objects are -+ * currently allocated, use ObjectSpace::live_objects -+ */ -+static -+VALUE os_allocated_objects(VALUE self) -+{ -+#if defined(HAVE_LONG_LONG) -+ return ULL2NUM(allocated_objects); -+#else -+ return ULONG2NUM(allocated_objects); -+#endif -+} -+ - /* - * The GC module provides an interface to Ruby's mark and - * sweep garbage collection mechanism. Some of the underlying methods -@@ -2833,6 +2885,9 @@ Init_GC() - rb_define_module_function(rb_mObSpace, "finalizers", finals, 0); - rb_define_module_function(rb_mObSpace, "call_finalizer", call_final, 1); - -+ rb_define_module_function(rb_mObSpace, "live_objects", os_live_objects, 0); -+ rb_define_module_function(rb_mObSpace, "allocated_objects", os_allocated_objects, 0); -+ - rb_define_module_function(rb_mObSpace, "define_finalizer", define_final, -1); - rb_define_module_function(rb_mObSpace, "undefine_finalizer", undefine_final, 1); - -diff --git a/intern.h b/intern.h -index 1117614..a87661d 100644 ---- a/intern.h -+++ b/intern.h -@@ -274,6 +274,12 @@ void rb_gc_before_fork _((void)); - void rb_gc_after_fork _((void)); - VALUE rb_gc_allocated_size _((void)); - VALUE rb_gc_num_allocations _((void)); -+unsigned long rb_os_live_objects _((void)); -+#ifdef HAVE_LONG_LONG -+unsigned LONG_LONG rb_os_allocated_objects _((void)); -+#else -+unsigned long rb_os_allocated_objects _((void)); -+#endif - /* hash.c */ - void st_foreach_safe _((struct st_table *, int (*)(ANYARGS), unsigned long)); - void rb_hash_foreach _((VALUE, int (*)(ANYARGS), VALUE)); diff --git a/patches/ruby/1.8.7/p358/railsexpress/11-expose-heap-slots.patch b/patches/ruby/1.8.7/p358/railsexpress/11-expose-heap-slots.patch deleted file mode 100644 index 3ce846c6a0..0000000000 --- a/patches/ruby/1.8.7/p358/railsexpress/11-expose-heap-slots.patch +++ /dev/null @@ -1,70 +0,0 @@ -diff --git a/gc.c b/gc.c -index 5b42b90..21b3f6b 100644 ---- a/gc.c -+++ b/gc.c -@@ -690,6 +690,7 @@ static int heaps_used = 0; - - static int heap_min_slots = 10000; - static int heap_slots = 10000; -+static int heap_size = 0; - - static int heap_free_min = 4096; - static int heap_slots_increment = 10000; -@@ -800,6 +801,21 @@ static void set_gc_parameters() - - /* - * call-seq: -+ * GC.heap_slots => Integer -+ * -+ * Returns the number of heap slots available for object allocations. -+ * -+ * GC.heap_slots #=> 10000 -+ * -+ */ -+VALUE -+rb_gc_heap_slots() -+{ -+ return INT2NUM(heap_size); -+} -+ -+/* -+ * call-seq: - * GC.dump => nil - * - * dumps information about the current GC data structures to the GC log file -@@ -967,6 +983,7 @@ add_heap() - heaps[heaps_used].limit = heap_slots; - break; - } -+ heap_size += heap_slots; - pend = p + heap_slots; - if (lomem == 0 || lomem > p) lomem = p; - if (himem < pend) himem = pend; -@@ -1828,6 +1845,7 @@ gc_sweep() - if (n == heaps[i].limit && freed > free_min) { - RVALUE *pp; - -+ heap_size -= n; - heaps[i].limit = 0; - for (pp = final_list; pp != final; pp = pp->as.free.next) { - pp->as.free.flags |= FL_SINGLETON; /* freeing page mark */ -@@ -2866,6 +2884,7 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0); - rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); - rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); - rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); - rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); - rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); -diff --git a/intern.h b/intern.h -index a87661d..e8f3209 100644 ---- a/intern.h -+++ b/intern.h -@@ -274,6 +274,7 @@ void rb_gc_before_fork _((void)); - void rb_gc_after_fork _((void)); - VALUE rb_gc_allocated_size _((void)); - VALUE rb_gc_num_allocations _((void)); -+VALUE rb_gc_heap_slots _((void)); - unsigned long rb_os_live_objects _((void)); - #ifdef HAVE_LONG_LONG - unsigned LONG_LONG rb_os_allocated_objects _((void)); diff --git a/patches/ruby/1.8.7/p358/railsexpress/12-fix-heap-size-growth-logic.patch b/patches/ruby/1.8.7/p358/railsexpress/12-fix-heap-size-growth-logic.patch deleted file mode 100644 index 1db93f224d..0000000000 --- a/patches/ruby/1.8.7/p358/railsexpress/12-fix-heap-size-growth-logic.patch +++ /dev/null @@ -1,54 +0,0 @@ -diff --git a/gc.c b/gc.c -index 21b3f6b..7db1ef6 100644 ---- a/gc.c -+++ b/gc.c -@@ -694,6 +694,7 @@ static int heap_size = 0; - - static int heap_free_min = 4096; - static int heap_slots_increment = 10000; -+static int initial_heap_slots_increment = 10000; - static double heap_slots_growth_factor = 1.8; - - static long initial_malloc_limit = GC_MALLOC_LIMIT; -@@ -771,14 +772,13 @@ static void set_gc_parameters() - if (verbose_gc_stats) { - fprintf(gc_data_file, "RUBY_HEAP_SLOTS_INCREMENT=%s\n", heap_slots_incr_ptr); - } -- if (heap_slots_incr_i > 0) { -- heap_slots_increment = heap_slots_incr_i; -- } -+ heap_slots_increment = heap_slots_incr_i; -+ initial_heap_slots_increment = heap_slots_increment; - } - - heap_slots_growth_factor_ptr = getenv("RUBY_HEAP_SLOTS_GROWTH_FACTOR"); - if (heap_slots_growth_factor_ptr != NULL) { -- double heap_slots_growth_factor_d = atoi(heap_slots_growth_factor_ptr); -+ double heap_slots_growth_factor_d = atof(heap_slots_growth_factor_ptr); - if (verbose_gc_stats) { - fprintf(gc_data_file, "RUBY_HEAP_SLOTS_GROWTH_FACTOR=%s\n", heap_slots_growth_factor_ptr); - } -@@ -988,8 +988,13 @@ add_heap() - if (lomem == 0 || lomem > p) lomem = p; - if (himem < pend) himem = pend; - heaps_used++; -- heap_slots += heap_slots_increment; -- heap_slots_increment *= heap_slots_growth_factor; -+ if (heaps_used == 1) -+ heap_slots = initial_heap_slots_increment; -+ else { -+ heap_slots_increment *= heap_slots_growth_factor; -+ heap_slots += heap_slots_increment; -+ } -+ - if (heap_slots <= 0) heap_slots = heap_min_slots; - - while (p < pend) { -@@ -1879,6 +1884,7 @@ gc_sweep() - live_counts[i], free_counts[i], obj_type(i)); - } - } -+ rb_gc_dump(); - fflush(gc_data_file); - } - diff --git a/patches/ruby/1.8.7/p358/railsexpress/13-heap-slot-size.patch b/patches/ruby/1.8.7/p358/railsexpress/13-heap-slot-size.patch deleted file mode 100644 index 45091c14ae..0000000000 --- a/patches/ruby/1.8.7/p358/railsexpress/13-heap-slot-size.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/gc.c b/gc.c -index 7db1ef6..57740d2 100644 ---- a/gc.c -+++ b/gc.c -@@ -2891,6 +2891,7 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); - rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); - rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); - rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); - rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); - rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); diff --git a/patches/ruby/1.8.7/p358/railsexpress/14-add-trace-stats-enabled-methods.patch b/patches/ruby/1.8.7/p358/railsexpress/14-add-trace-stats-enabled-methods.patch deleted file mode 100644 index 4e3c4f2132..0000000000 --- a/patches/ruby/1.8.7/p358/railsexpress/14-add-trace-stats-enabled-methods.patch +++ /dev/null @@ -1,66 +0,0 @@ -diff --git a/gc.c b/gc.c -index 57740d2..2c34932 100644 ---- a/gc.c -+++ b/gc.c -@@ -350,6 +350,22 @@ rb_gc_disable_stats() - - /* - * call-seq: -+ * GC.stats_enabled? => true or false -+ * -+ * Check whether GC stats have been enabled. -+ * -+ * GC.stats_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_stats_enabled() -+{ -+ return gc_statistics ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: - * GC.clear_stats => nil - * - * Clears garbage collection statistics, returning nil. This resets the number -@@ -491,6 +507,22 @@ rb_gc_disable_trace() - return old; - } - -+/* -+ * call-seq: -+ * GC.trace_enabled? => true or false -+ * -+ * Check whether GC tracing has been enabled. -+ * -+ * GC.trace_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_trace_enabled() -+{ -+ return verbose_gc_stats ? Qtrue : Qfalse; -+} -+ - char* GC_LOGFILE_IVAR = "@gc_logfile_name"; - - /* -@@ -2887,6 +2919,7 @@ Init_GC() - - rb_define_singleton_method(rb_mGC, "enable_stats", rb_gc_enable_stats, 0); - rb_define_singleton_method(rb_mGC, "disable_stats", rb_gc_disable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "stats_enabled?", rb_gc_stats_enabled, 0); - rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0); - rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); - rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); -@@ -2902,6 +2935,7 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "log_file", rb_gc_log_file, -1); - rb_define_singleton_method(rb_mGC, "enable_trace", rb_gc_enable_trace, 0); - rb_define_singleton_method(rb_mGC, "disable_trace", rb_gc_disable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "trace_enabled?", rb_gc_trace_enabled, 0); - - rb_mObSpace = rb_define_module("ObjectSpace"); - rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1); diff --git a/patches/ruby/1.8.7/p358/railsexpress/15-track-live-dataset-size.patch b/patches/ruby/1.8.7/p358/railsexpress/15-track-live-dataset-size.patch deleted file mode 100644 index de44e6b365..0000000000 --- a/patches/ruby/1.8.7/p358/railsexpress/15-track-live-dataset-size.patch +++ /dev/null @@ -1,52 +0,0 @@ -diff --git a/gc.c b/gc.c -index 2c34932..0ce7e68 100644 ---- a/gc.c -+++ b/gc.c -@@ -89,6 +89,7 @@ static unsigned long gc_num_allocations = 0; - #endif - static int gc_statistics = 0; - -+static unsigned long heap_slots_live_after_last_gc = 0; - - static void run_final(); - static VALUE nomem_error; -@@ -465,6 +466,23 @@ rb_gc_time() - #endif - } - -+/* -+ * call-seq: -+ * GC.heap_slots_live_after_last_gc => Integer -+ * -+ * Returns the number of heap slots which were live after the last garbage collection. -+ * -+ * GC.heap_slots_live_after_last_gc #=> 231223 -+ * -+ */ -+VALUE -+rb_gc_heap_slots_live_after_last_gc() -+{ -+ return ULONG2NUM(heap_slots_live_after_last_gc); -+} -+ -+ -+ - VALUE rb_mGC; - - /* -@@ -1903,6 +1921,7 @@ gc_sweep() - } - during_gc = 0; - live_objects = live; -+ heap_slots_live_after_last_gc = live; - - if (do_gc_stats) { - fprintf(gc_data_file, "objects processed: %.7d\n", live+freed); -@@ -2924,6 +2943,7 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); - rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); - rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots_live_after_last_gc", rb_gc_heap_slots_live_after_last_gc, 0); - rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); - rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); - rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); diff --git a/patches/ruby/1.8.7/p358/railsexpress/16-add-object-size-information-to-heap-dump.patch b/patches/ruby/1.8.7/p358/railsexpress/16-add-object-size-information-to-heap-dump.patch deleted file mode 100644 index e974cdb63a..0000000000 --- a/patches/ruby/1.8.7/p358/railsexpress/16-add-object-size-information-to-heap-dump.patch +++ /dev/null @@ -1,51 +0,0 @@ -diff --git a/gc.c b/gc.c -index 0ce7e68..53450bf 100644 ---- a/gc.c -+++ b/gc.c -@@ -953,9 +953,21 @@ rb_gc_dump_file_and_line_info(int argc, VALUE *argv) - if (!p->as.basic.klass) { - fprintf(f, "__unknown__"); - } else { -- fprintf(f, rb_obj_classname((VALUE)p)); -+ fprintf(f, "%s", rb_obj_classname((VALUE)p)); - } - } -+ /* print object size for some known object types */ -+ switch (TYPE(p)) { -+ case T_STRING: -+ fprintf(f, ":%lu", RSTRING(p)->len); -+ break; -+ case T_ARRAY: -+ fprintf(f, ":%lu", RARRAY(p)->len); -+ break; -+ case T_HASH: -+ fprintf(f, ":%d", RHASH(p)->tbl->num_entries); -+ break; -+ } - } - fprintf(f, "\n"); - } -@@ -1924,10 +1936,10 @@ gc_sweep() - heap_slots_live_after_last_gc = live; - - if (do_gc_stats) { -- fprintf(gc_data_file, "objects processed: %.7d\n", live+freed); -- fprintf(gc_data_file, "live objects : %.7d\n", live); -- fprintf(gc_data_file, "freelist objects : %.7d\n", freed - really_freed); -- fprintf(gc_data_file, "freed objects : %.7d\n", really_freed); -+ fprintf(gc_data_file, "objects processed: %.7lu\n", live+freed); -+ fprintf(gc_data_file, "live objects : %.7lu\n", live); -+ fprintf(gc_data_file, "freelist objects : %.7lu\n", freed - really_freed); -+ fprintf(gc_data_file, "freed objects : %.7lu\n", really_freed); - for(i=0; i<256; i++) { - if (free_counts[i]>0 || live_counts[i]>0) { - fprintf(gc_data_file, -@@ -2258,7 +2270,7 @@ garbage_collect() - gc_time += musecs_used; - - if (verbose_gc_stats) { -- fprintf(gc_data_file, "GC time: %d msec\n", musecs_used / 1000); -+ fprintf(gc_data_file, "GC time: %ld msec\n", (long)(musecs_used / 1000)); - fflush(gc_data_file); - } - } diff --git a/patches/ruby/1.8.7/p358/railsexpress/17-caller-for-all-threads.patch b/patches/ruby/1.8.7/p358/railsexpress/17-caller-for-all-threads.patch deleted file mode 100644 index aa79d1602c..0000000000 --- a/patches/ruby/1.8.7/p358/railsexpress/17-caller-for-all-threads.patch +++ /dev/null @@ -1,230 +0,0 @@ -diff --git a/eval.c b/eval.c -index 356226e..a0fdc55 100644 ---- a/eval.c -+++ b/eval.c -@@ -8199,6 +8199,17 @@ rb_f_method_name() - } - } - -+/* Hash (Thread => Backtrace) used to collect backtrace for each threads. */ -+static VALUE backtrace_for_each_thread; -+ -+static int backtrace_level_for_each_thread; -+ -+static VALUE -+switch_thread_context_to_collect_backtrace(rb_thread_t next); -+ -+static VALUE -+rb_f_caller_for_all_threads(); -+ - void - Init_eval() - { -@@ -8244,6 +8255,7 @@ Init_eval() - rb_define_global_function("fail", rb_f_raise, -1); - - rb_define_global_function("caller", rb_f_caller, -1); -+ rb_define_global_function("caller_for_all_threads", rb_f_caller_for_all_threads, -1); - - rb_define_global_function("exit", rb_f_exit, -1); - rb_define_global_function("abort", rb_f_abort, -1); -@@ -10599,6 +10611,7 @@ static int th_sig, th_safe; - #define RESTORE_RAISE 5 - #define RESTORE_SIGNAL 6 - #define RESTORE_EXIT 7 -+#define RESTORE_BACKTRACE 8 - - extern VALUE *rb_gc_stack_start; - #ifdef __ia64 -@@ -10705,6 +10718,15 @@ rb_thread_switch(n) - } - rb_exc_raise(th_raise_exception); - break; -+ case RESTORE_BACKTRACE: -+ rb_hash_aset(backtrace_for_each_thread, curr_thread->thread, -+ backtrace(backtrace_level_for_each_thread)); -+ if (curr_thread != main_thread) { -+ switch_thread_context_to_collect_backtrace(curr_thread->next); -+ } else { -+ /* Circled back to main thread, cycle is complete. */ -+ } -+ break; - case RESTORE_NORMAL: - default: - break; -@@ -13875,3 +13897,74 @@ rb_throw(tag, val) - argv[1] = val; - rb_f_throw(2, argv); - } -+ -+static VALUE -+switch_thread_context_to_collect_backtrace(rb_thread_t next) -+{ -+ if (THREAD_SAVE_CONTEXT(curr_thread)) { -+ return Qnil; -+ } -+ curr_thread = next; -+ rb_thread_restore_context(next, RESTORE_BACKTRACE); -+ return Qnil; -+} -+ -+ -+/* -+ * call-seq: -+ * caller_for_all_threads(start=1) => array -+ * -+ * Returns the current execution stack for all threads -+ * ---a hash whose keys are thread instances and values -+ * the thread caller backtrace. -+ * -+ * Backtraces are array of hashes indicating location on the -+ * stack. Hash keys include ``:line'' or ``:file'' -+ * and ``:method'''. -+ * -+ * The optional _start_ parameter -+ * determines the number of initial stack entries to omit from the -+ * result. -+ * -+ * def a(skip) -+ * caller_for_all_threads(skip) -+ * end -+ * def b(skip) -+ * a(skip) -+ * end -+ * def c(skip) -+ * b(skip) -+ * end -+ * c(0) #=> ["prog:2:in `a'", "prog:5:in `b'", "prog:8:in `c'", "prog:10"] -+ * c(1) #=> ["prog:5:in `b'", "prog:8:in `c'", "prog:11"] -+ * c(2) #=> ["prog:8:in `c'", "prog:12"] -+ * c(3) #=> ["prog:13"] -+ */ -+static VALUE -+rb_f_caller_for_all_threads(argc, argv) -+ int argc; -+ VALUE *argv; -+{ -+ volatile int critical; -+ VALUE level; -+ VALUE result; -+ -+ rb_scan_args(argc, argv, "01", &level); -+ backtrace_level_for_each_thread = NIL_P(level) ? 0 : NUM2INT(level); -+ if (backtrace_level_for_each_thread < 0) { -+ rb_raise(rb_eArgError, "negative level (%d)", backtrace_level_for_each_thread); -+ } -+ -+ critical = rb_thread_critical; -+ rb_thread_critical = Qtrue; -+ -+ backtrace_for_each_thread = rb_hash_new(); -+ switch_thread_context_to_collect_backtrace(main_thread->next); -+ -+ result = backtrace_for_each_thread; -+ backtrace_for_each_thread = Qnil; -+ backtrace_for_each_thread = 0; -+ -+ rb_thread_critical = critical; -+ return result; -+} -diff --git a/test/callerforallthreads/test_caller_for_each_thread.rb b/test/callerforallthreads/test_caller_for_each_thread.rb -new file mode 100644 -index 0000000..6aebaed ---- /dev/null -+++ b/test/callerforallthreads/test_caller_for_each_thread.rb -@@ -0,0 +1,95 @@ -+# -*- ruby-indent-level: 4 -*- -+require 'thread' -+require 'test/unit' -+ -+class AClassWithNestedmethods -+ -+ def an_ultra_nested_method(skip) -+ caller_for_all_threads skip -+ end -+ -+ def a_nested_method(skip) -+ an_ultra_nested_method skip -+ end -+ -+ def a_method(skip=0) -+ a_nested_method skip -+ end -+ -+end -+ -+class CallerForEachThreadTest < Test::Unit::TestCase -+ -+ def testCollectMeaningfulBacktraceForASingleThread -+ backtraces = AClassWithNestedmethods.new.a_method -+ backtrace = backtraces[Thread.current] -+ assert_not_nil backtrace -+ assert_equal __FILE__ + ":8:in `an_ultra_nested_method'", backtrace[0] -+ assert_equal __FILE__ + ":12:in `a_nested_method'", backtrace[1] -+ assert_equal __FILE__ + ":16:in `a_method'", backtrace[2] -+ assert_equal __FILE__ + ":24:in `testCollectMeaningfulBacktraceForASingleThread'", -+ backtrace[3] -+ end -+ -+ def testCanSkipFirstStackEntries -+ backtraces = AClassWithNestedmethods.new.a_method 2 -+ backtrace = backtraces[Thread.current] -+ assert_not_nil backtrace -+ assert_equal __FILE__ + ":16:in `a_method'", backtrace[0] -+ assert_equal __FILE__ + ":35:in `testCanSkipFirstStackEntries'", -+ backtrace[1] -+ end -+ -+ def testCollectMeaningfulBacktraceForMultipleThreads -+ first_thread = Thread.new do -+ loop do -+ Thread.pass -+ sleep 1 -+ end -+ end -+ -+ second_thread = Thread.new do -+ loop do -+ Thread.pass -+ sleep 1 -+ end -+ end -+ -+ backtraces = AClassWithNestedmethods.new.a_method -+ -+ backtrace = backtraces[Thread.current] -+ assert_not_nil backtrace -+ assert_match __FILE__ + ":8:in `an_ultra_nested_method'", backtrace[0] -+ assert_match __FILE__ + ":12:in `a_nested_method'", backtrace[1] -+ assert_equal __FILE__ + ":16:in `a_method'", backtrace[2] -+ assert_equal __FILE__ + ":58:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[3] -+ -+ backtrace = backtraces[first_thread] -+ assert_not_nil backtrace -+ assert_equal __FILE__ + ":47:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[0] -+ assert_equal __FILE__ + ":45:in `loop'", -+ backtrace[1] -+ assert_equal __FILE__ + ":45:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[2] -+ assert_equal __FILE__ + ":44:in `initialize'",backtrace[3] -+ assert_equal __FILE__ + ":44:in `new'", backtrace[4] -+ assert_equal __FILE__ + ":44:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[5] -+ -+ backtrace = backtraces[second_thread] -+ assert_not_nil backtrace -+ assert_equal __FILE__ + ":53:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[0] -+ assert_equal __FILE__ + ":52:in `loop'", backtrace[1] -+ assert_equal __FILE__ + ":52:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[2] -+ assert_equal __FILE__ + ":51:in `initialize'",backtrace[3] -+ assert_equal __FILE__ + ":51:in `new'", backtrace[4] -+ assert_equal __FILE__ + ":51:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[5] -+ end -+ -+end -+ diff --git a/patches/ruby/1.8.7/p370/railsexpress/01-ignore-generated-files.patch b/patches/ruby/1.8.7/p370/railsexpress/01-ignore-generated-files.patch deleted file mode 100644 index b669ad44bd..0000000000 --- a/patches/ruby/1.8.7/p370/railsexpress/01-ignore-generated-files.patch +++ /dev/null @@ -1,101 +0,0 @@ -diff --git a/.gitignore b/.gitignore -new file mode 100644 -index 0000000..00c347a ---- /dev/null -+++ b/.gitignore -@@ -0,0 +1,95 @@ -+.ext -+.installed.list -+.rbconfig.time -+Makefile -+autom4te.cache/ -+config.h -+config.status -+configure -+ext/Win32API/Makefile -+ext/bigdecimal/Makefile -+ext/curses/Makefile -+ext/dbm/Makefile -+ext/digest/Makefile -+ext/digest/bubblebabble/Makefile -+ext/digest/md5/Makefile -+ext/digest/rmd160/Makefile -+ext/digest/sha1/Makefile -+ext/digest/sha2/Makefile -+ext/dl/Makefile -+ext/dl/call.func -+ext/dl/callback.func -+ext/dl/cbtable.func -+ext/dl/dlconfig.h -+ext/dl/dlconfig.rb -+ext/enumerator/Makefile -+ext/etc/Makefile -+ext/fcntl/Makefile -+ext/gdbm/Makefile -+ext/iconv/Makefile -+ext/io/wait/Makefile -+ext/nkf/Makefile -+ext/openssl/Makefile -+ext/openssl/extconf.h -+ext/pty/Makefile -+ext/racc/cparse/Makefile -+ext/readline/Makefile -+ext/sdbm/Makefile -+ext/socket/Makefile -+ext/stringio/Makefile -+ext/strscan/Makefile -+ext/syck/Makefile -+ext/syslog/Makefile -+ext/thread/Makefile -+ext/tk/Makefile -+ext/tk/tkutil/Makefile -+ext/win32ole/Makefile -+ext/win32ole/.document -+ext/zlib/Makefile -+largefile.h -+miniruby -+parse.c -+rbconfig.rb -+ruby -+enc.mk -+ext/bigdecimal/extconf.h -+ext/continuation/ -+ext/coverage/ -+ext/curses/extconf.h -+ext/dbm/extconf.h -+ext/digest/bubblebabble/extconf.h -+ext/digest/extconf.h -+ext/digest/md5/extconf.h -+ext/digest/rmd160/extconf.h -+ext/digest/sha1/extconf.h -+ext/digest/sha2/extconf.h -+ext/dl/callback.h -+ext/dl/extconf.h -+ext/etc/extconf.h -+ext/fcntl/extconf.h -+ext/fiber/ -+ext/iconv/extconf.h -+ext/io/wait/extconf.h -+ext/json/ -+ext/nkf/extconf.h -+ext/pty/extconf.h -+ext/racc/cparse/extconf.h -+ext/readline/extconf.h -+ext/ripper/ -+ext/sdbm/extconf.h -+ext/socket/constants.h -+ext/socket/extconf.h -+ext/stringio/extconf.h -+ext/strscan/extconf.h -+ext/syck/extconf.h -+ext/syslog/extconf.h -+ext/tk/extconf.h -+ext/tk/tkutil/extconf.h -+ext/zlib/extconf.h -+miniprelude.c -+prelude.c -+revision.h -+*.dylib -+*.log -+*.dSYM -+patches-ruby* diff --git a/patches/ruby/1.8.7/p370/railsexpress/02-fix-tests-for-osx.patch b/patches/ruby/1.8.7/p370/railsexpress/02-fix-tests-for-osx.patch deleted file mode 100644 index 3be8172640..0000000000 --- a/patches/ruby/1.8.7/p370/railsexpress/02-fix-tests-for-osx.patch +++ /dev/null @@ -1,139 +0,0 @@ -diff --git a/test/drb/drbtest.rb b/test/drb/drbtest.rb -index bc16ab1..c12b168 100644 ---- a/test/drb/drbtest.rb -+++ b/test/drb/drbtest.rb -@@ -22,7 +22,7 @@ class DRbService - %w(ut_drb.rb ut_array.rb ut_port.rb ut_large.rb ut_safe1.rb ut_eval.rb).each do |nm| - add_service_command(nm) - end -- @server = @@server = DRb::DRbServer.new('druby://localhost:0', @@manager, {}) -+ @server = @@server = DRb::DRbServer.new('druby://127.0.0.1:0', @@manager, {}) - @@manager.uri = @@server.uri - def self.manager - @@manager -@@ -79,16 +79,16 @@ module DRbCore - end - - def test_00_DRbObject -- ro = DRbObject.new(nil, 'druby://localhost:12345') -- assert_equal('druby://localhost:12345', ro.__drburi) -+ ro = DRbObject.new(nil, 'druby://127.0.0.1:12345') -+ assert_equal('druby://127.0.0.1:12345', ro.__drburi) - assert_equal(nil, ro.__drbref) - -- ro = DRbObject.new_with_uri('druby://localhost:12345') -- assert_equal('druby://localhost:12345', ro.__drburi) -+ ro = DRbObject.new_with_uri('druby://127.0.0.1:12345') -+ assert_equal('druby://127.0.0.1:12345', ro.__drburi) - assert_equal(nil, ro.__drbref) - -- ro = DRbObject.new_with_uri('druby://localhost:12345?foobar') -- assert_equal('druby://localhost:12345', ro.__drburi) -+ ro = DRbObject.new_with_uri('druby://127.0.0.1:12345?foobar') -+ assert_equal('druby://127.0.0.1:12345', ro.__drburi) - assert_equal(DRb::DRbURIOption.new('foobar'), ro.__drbref) - end - -diff --git a/test/drb/ut_drb.rb b/test/drb/ut_drb.rb -index f5720cf..265713d 100644 ---- a/test/drb/ut_drb.rb -+++ b/test/drb/ut_drb.rb -@@ -154,7 +154,7 @@ if __FILE__ == $0 - - DRb::DRbServer.default_argc_limit(8) - DRb::DRbServer.default_load_limit(4096) -- DRb.start_service('druby://localhost:0', DRbEx.new) -+ DRb.start_service('druby://127.0.0.1:0', DRbEx.new) - es = DRb::ExtServ.new(ARGV.shift, ARGV.shift) - DRb.thread.join - end -diff --git a/test/drb/ut_drb_drbssl.rb b/test/drb/ut_drb_drbssl.rb -index 0a2191e..bca3012 100644 ---- a/test/drb/ut_drb_drbssl.rb -+++ b/test/drb/ut_drb_drbssl.rb -@@ -18,7 +18,7 @@ if __FILE__ == $0 - - DRb::DRbServer.default_argc_limit(8) - DRb::DRbServer.default_load_limit(4096) -- DRb.start_service('drbssl://localhost:0', DRbEx.new, config) -+ DRb.start_service('drbssl://127.0.0.1:0', DRbEx.new, config) - es = DRb::ExtServ.new(ARGV.shift, ARGV.shift) - DRb.thread.join - end -diff --git a/test/drb/ut_eval.rb b/test/drb/ut_eval.rb -index 4df963e..9127939 100644 ---- a/test/drb/ut_eval.rb -+++ b/test/drb/ut_eval.rb -@@ -3,7 +3,7 @@ require 'drb/extserv' - - class EvalAttack - def initialize -- @four = DRb::DRbServer.new('druby://localhost:0', self, {:safe_level => 4}) -+ @four = DRb::DRbServer.new('druby://127.0.0.1:0', self, {:safe_level => 4}) - end - - def four -@@ -25,7 +25,7 @@ if __FILE__ == $0 - - $SAFE = 1 - -- DRb.start_service('druby://localhost:0', EvalAttack.new, {:safe_level => 2}) -+ DRb.start_service('druby://127.0.0.1:0', EvalAttack.new, {:safe_level => 2}) - es = DRb::ExtServ.new(ARGV.shift, ARGV.shift) - DRb.thread.join - end -diff --git a/test/drb/ut_large.rb b/test/drb/ut_large.rb -index d6717c5..0aefd1b 100644 ---- a/test/drb/ut_large.rb -+++ b/test/drb/ut_large.rb -@@ -31,7 +31,7 @@ if __FILE__ == $0 - - DRb::DRbServer.default_argc_limit(3) - DRb::DRbServer.default_load_limit(100000) -- DRb.start_service('druby://localhost:0', DRbLarge.new) -+ DRb.start_service('druby://127.0.0.1:0', DRbLarge.new) - es = DRb::ExtServ.new(ARGV.shift, ARGV.shift) - DRb.thread.join - end -diff --git a/test/drb/ut_safe1.rb b/test/drb/ut_safe1.rb -index 4df8e1e..5e7fe82 100644 ---- a/test/drb/ut_safe1.rb -+++ b/test/drb/ut_safe1.rb -@@ -8,7 +8,7 @@ if __FILE__ == $0 - it - end - -- DRb.start_service('druby://localhost:0', [1, 2, 'III', 4, "five", 6], -+ DRb.start_service('druby://127.0.0.1:0', [1, 2, 'III', 4, "five", 6], - {:safe_level => 1}) - es = DRb::ExtServ.new(ARGV.shift, ARGV.shift) - DRb.thread.join -diff --git a/test/net/pop/test_pop.rb b/test/net/pop/test_pop.rb -index c8aa9a8..129ca08 100644 ---- a/test/net/pop/test_pop.rb -+++ b/test/net/pop/test_pop.rb -@@ -3,10 +3,14 @@ require 'test/unit' - require 'digest/md5' - - class TestPOP < Test::Unit::TestCase -+ def localhost -+ '127.0.0.1' -+ end -+ - def setup - @users = {'user' => 'pass' } - @ok_user = 'user' -- @stamp_base = "#{$$}.#{Time.now.to_i}@localhost" -+ @stamp_base = "#{$$}.#{Time.now.to_i}@#{localhost}" - end - - def test_pop_auth_ok -@@ -64,7 +68,7 @@ class TestPOP < Test::Unit::TestCase - end - - def pop_test(apop=false) -- host = 'localhost' -+ host = localhost - server = TCPServer.new(host, 0) - port = server.addr[1] - thread = Thread.start do diff --git a/patches/ruby/1.8.7/p370/railsexpress/03-sigvtalrm-fix.patch b/patches/ruby/1.8.7/p370/railsexpress/03-sigvtalrm-fix.patch deleted file mode 100644 index 15d54f5834..0000000000 --- a/patches/ruby/1.8.7/p370/railsexpress/03-sigvtalrm-fix.patch +++ /dev/null @@ -1,27 +0,0 @@ -diff --git a/eval.c b/eval.c -index c2049c7..f49044a 100644 ---- a/eval.c -+++ b/eval.c -@@ -12483,6 +12483,11 @@ rb_thread_start_0(fn, arg, th) - curr_thread->next = th; - th->priority = curr_thread->priority; - th->thgroup = curr_thread->thgroup; -+#if defined(HAVE_SETITIMER) || defined(_THREAD_SAFE) -+ if (!thread_init) { -+ rb_thread_start_timer(); -+ } -+#endif - } - START_TIMER(); - -@@ -13211,7 +13216,9 @@ rb_thread_atfork() - main_thread = curr_thread; - curr_thread->next = curr_thread; - curr_thread->prev = curr_thread; -- STOP_TIMER(); -+#if defined(HAVE_SETITIMER) || defined(_THREAD_SAFE) -+ rb_thread_stop_timer(); -+#endif - } - - diff --git a/patches/ruby/1.8.7/p370/railsexpress/04-railsbench-gc-patch.patch b/patches/ruby/1.8.7/p370/railsexpress/04-railsbench-gc-patch.patch deleted file mode 100644 index 7b6c0e251a..0000000000 --- a/patches/ruby/1.8.7/p370/railsexpress/04-railsbench-gc-patch.patch +++ /dev/null @@ -1,1876 +0,0 @@ -diff --git a/gc.c b/gc.c -index fa45cd1..ab71d22 100644 ---- a/gc.c -+++ b/gc.c -@@ -22,8 +22,16 @@ - #include - #include - -+#ifdef _WIN32 -+#include -+#else -+#include -+#endif -+ - #ifdef HAVE_SYS_TIME_H - #include -+#elif defined(_WIN32) -+#include - #endif - - #ifdef HAVE_SYS_RESOURCE_H -@@ -42,7 +50,6 @@ void rb_io_fptr_finalize _((struct rb_io_t*)); - #ifdef __CYGWIN__ - int _setjmp(), _longjmp(); - #endif -- - /* Make alloca work the best possible way. */ - #ifdef __GNUC__ - # ifndef atarist -@@ -86,12 +93,12 @@ rb_memerror() - rb_thread_t th = rb_curr_thread; - - if (!nomem_error || -- (rb_thread_raised_p(th, RAISED_NOMEMORY) && rb_safe_level() < 4)) { -- fprintf(stderr, "[FATAL] failed to allocate memory\n"); -- exit(1); -+ (rb_thread_raised_p(th, RAISED_NOMEMORY) && rb_safe_level() < 4)) { -+ fprintf(stderr, "[FATAL] failed to allocate memory\n"); -+ exit(1); - } - if (rb_thread_raised_p(th, RAISED_NOMEMORY)) { -- rb_exc_jump(nomem_error); -+ rb_exc_jump(nomem_error); - } - rb_thread_raised_set(th, RAISED_NOMEMORY); - rb_exc_raise(nomem_error); -@@ -139,7 +146,7 @@ ruby_xmalloc(size) - void *mem; - - if (size < 0) { -- rb_raise(rb_eNoMemError, "negative allocation size (or too big)"); -+ rb_raise(rb_eNoMemError, "negative allocation size (or too big)"); - } - if (size == 0) size = 1; - -@@ -148,11 +155,11 @@ ruby_xmalloc(size) - } - RUBY_CRITICAL(mem = malloc(size)); - if (!mem) { -- garbage_collect(); -- RUBY_CRITICAL(mem = malloc(size)); -- if (!mem) { -- rb_memerror(); -- } -+ garbage_collect(); -+ RUBY_CRITICAL(mem = malloc(size)); -+ if (!mem) { -+ rb_memerror(); -+ } - } - malloc_increase += size; - -@@ -179,17 +186,17 @@ ruby_xrealloc(ptr, size) - void *mem; - - if (size < 0) { -- rb_raise(rb_eArgError, "negative re-allocation size"); -+ rb_raise(rb_eArgError, "negative re-allocation size"); - } - if (!ptr) return xmalloc(size); - if (size == 0) size = 1; - if (ruby_gc_stress) garbage_collect(); - RUBY_CRITICAL(mem = realloc(ptr, size)); - if (!mem) { -- garbage_collect(); -- RUBY_CRITICAL(mem = realloc(ptr, size)); -- if (!mem) { -- rb_memerror(); -+ garbage_collect(); -+ RUBY_CRITICAL(mem = realloc(ptr, size)); -+ if (!mem) { -+ rb_memerror(); - } - } - malloc_increase += size; -@@ -202,11 +209,20 @@ ruby_xfree(x) - void *x; - { - if (x) -- RUBY_CRITICAL(free(x)); -+ RUBY_CRITICAL(free(x)); - } - -+#if HAVE_LONG_LONG -+#define GC_TIME_TYPE LONG_LONG -+#else -+#define GC_TIME_TYPE long -+#endif -+ - extern int ruby_in_compile; - static int dont_gc; -+static int gc_statistics = 0; -+static GC_TIME_TYPE gc_time = 0; -+static int gc_collections = 0; - static int during_gc; - static int need_call_final = 0; - static st_table *finalizer_table = 0; -@@ -241,7 +257,7 @@ rb_gc_enable() - * Disables garbage collection, returning true if garbage - * collection was already disabled. - * -- * GC.disable #=> false -+ * GC.disable #=> false or true - * GC.disable #=> true - * - */ -@@ -255,6 +271,104 @@ rb_gc_disable() - return old; - } - -+/* -+ * call-seq: -+ * GC.enable_stats => true or false -+ * -+ * Enables garbage collection statistics, returning true if garbage -+ * collection statistics was already enabled. -+ * -+ * GC.enable_stats #=> false or true -+ * GC.enable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_stats() -+{ -+ int old = gc_statistics; -+ gc_statistics = Qtrue; -+ return old; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_stats => true or false -+ * -+ * Disables garbage collection statistics, returning true if garbage -+ * collection statistics was already disabled. -+ * -+ * GC.disable_stats #=> false or true -+ * GC.disable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_stats() -+{ -+ int old = gc_statistics; -+ gc_statistics = Qfalse; -+ return old; -+} -+ -+/* -+ * call-seq: -+ * GC.clear_stats => nil -+ * -+ * Clears garbage collection statistics, returning nil. This resets the number -+ * of collections (GC.collections) and the time used (GC.time) to 0. -+ * -+ * GC.clear_stats #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_clear_stats() -+{ -+ gc_collections = 0; -+ gc_time = 0; -+ return Qnil; -+} -+ -+/* -+ * call-seq: -+ * GC.collections => Integer -+ * -+ * Returns the number of garbage collections performed while GC statistics collection -+ * was enabled. -+ * -+ * GC.collections #=> 35 -+ * -+ */ -+ -+VALUE -+rb_gc_collections() -+{ -+ return INT2NUM(gc_collections); -+} -+ -+/* -+ * call-seq: -+ * GC.time => Integer -+ * -+ * Returns the time spent during garbage collection while GC statistics collection -+ * was enabled (in micro seconds). -+ * -+ * GC.time #=> 20000 -+ * -+ */ -+ -+VALUE -+rb_gc_time() -+{ -+#if HAVE_LONG_LONG -+ return LL2NUM(gc_time); -+#else -+ return LONG2NUM(gc_time); -+#endif -+} -+ -+ - VALUE rb_mGC; - - static struct gc_list { -@@ -281,19 +395,19 @@ rb_gc_unregister_address(addr) - struct gc_list *tmp = global_List; - - if (tmp->varptr == addr) { -- global_List = tmp->next; -- RUBY_CRITICAL(free(tmp)); -- return; -+ global_List = tmp->next; -+ RUBY_CRITICAL(free(tmp)); -+ return; - } - while (tmp->next) { -- if (tmp->next->varptr == addr) { -- struct gc_list *t = tmp->next; -+ if (tmp->next->varptr == addr) { -+ struct gc_list *t = tmp->next; - -- tmp->next = tmp->next->next; -- RUBY_CRITICAL(free(t)); -- break; -- } -- tmp = tmp->next; -+ tmp->next = tmp->next->next; -+ RUBY_CRITICAL(free(t)); -+ break; -+ } -+ tmp = tmp->next; - } - } - -@@ -312,26 +426,26 @@ rb_global_variable(var) - - typedef struct RVALUE { - union { -- struct { -- unsigned long flags; /* always 0 for freed obj */ -- 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; -- struct RStruct rstruct; -- struct RBignum bignum; -- struct RFile file; -- struct RNode node; -- struct RMatch match; -- struct RVarmap varmap; -- struct SCOPE scope; -+ struct { -+ unsigned long flags; /* always 0 for freed obj */ -+ 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; -+ struct RStruct rstruct; -+ struct RBignum bignum; -+ struct RFile file; -+ struct RNode node; -+ struct RMatch match; -+ struct RVarmap varmap; -+ struct SCOPE scope; - } as; - #ifdef GC_DEBUG - char *file; -@@ -346,7 +460,7 @@ typedef struct RVALUE { - static RVALUE *freelist = 0; - static RVALUE *deferred_final_list = 0; - --#define HEAPS_INCREMENT 10 -+static int heaps_increment = 10; - static struct heaps_slot { - void *membase; - RVALUE *slot; -@@ -355,45 +469,197 @@ static struct heaps_slot { - static int heaps_length = 0; - static int heaps_used = 0; - --#define HEAP_MIN_SLOTS 10000 --static int heap_slots = HEAP_MIN_SLOTS; -+static int heap_min_slots = 10000; -+static int heap_slots = 10000; - --#define FREE_MIN 4096 -+static int heap_free_min = 4096; -+static int heap_slots_increment = 10000; -+static double heap_slots_growth_factor = 1.8; -+ -+static long initial_malloc_limit = GC_MALLOC_LIMIT; -+ -+static int verbose_gc_stats = Qfalse; -+ -+static FILE* gc_data_file = NULL; - - static RVALUE *himem, *lomem; - -+static void set_gc_parameters() -+{ -+ char *gc_stats_ptr, *min_slots_ptr, *free_min_ptr, *heap_slots_incr_ptr, -+ *heap_incr_ptr, *malloc_limit_ptr, *gc_heap_file_ptr, *heap_slots_growth_factor_ptr; -+ -+ gc_data_file = stderr; -+ -+ gc_stats_ptr = getenv("RUBY_GC_STATS"); -+ if (gc_stats_ptr != NULL) { -+ int gc_stats_i = atoi(gc_stats_ptr); -+ if (gc_stats_i > 0) { -+ verbose_gc_stats = Qtrue; -+ } -+ } -+ -+ gc_heap_file_ptr = getenv("RUBY_GC_DATA_FILE"); -+ if (gc_heap_file_ptr != NULL) { -+ FILE* data_file = fopen(gc_heap_file_ptr, "w"); -+ if (data_file != NULL) { -+ gc_data_file = data_file; -+ } -+ else { -+ fprintf(stderr, -+ "can't open gc log file %s for writing, using default\n", gc_heap_file_ptr); -+ } -+ } -+ -+ min_slots_ptr = getenv("RUBY_HEAP_MIN_SLOTS"); -+ if (min_slots_ptr != NULL) { -+ int min_slots_i = atoi(min_slots_ptr); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_MIN_SLOTS=%s\n", min_slots_ptr); -+ } -+ if (min_slots_i > 0) { -+ heap_slots = min_slots_i; -+ heap_min_slots = min_slots_i; -+ } -+ } -+ -+ free_min_ptr = getenv("RUBY_HEAP_FREE_MIN"); -+ if (free_min_ptr != NULL) { -+ int free_min_i = atoi(free_min_ptr); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_FREE_MIN=%s\n", free_min_ptr); -+ } -+ if (free_min_i > 0) { -+ heap_free_min = free_min_i; -+ } -+ } -+ -+ heap_incr_ptr = getenv("RUBY_HEAP_INCREMENT"); -+ if (heap_incr_ptr != NULL) { -+ int heap_incr_i = atoi(heap_incr_ptr); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_INCREMENT=%s\n", heap_incr_ptr); -+ } -+ if (heap_incr_i > 0) { -+ heaps_increment = heap_incr_i; -+ } -+ } -+ -+ heap_slots_incr_ptr = getenv("RUBY_HEAP_SLOTS_INCREMENT"); -+ if (heap_slots_incr_ptr != NULL) { -+ int heap_slots_incr_i = atoi(heap_slots_incr_ptr); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_INCREMENT=%s\n", heap_slots_incr_ptr); -+ } -+ if (heap_slots_incr_i > 0) { -+ heap_slots_increment = heap_slots_incr_i; -+ } -+ } -+ -+ heap_slots_growth_factor_ptr = getenv("RUBY_HEAP_SLOTS_GROWTH_FACTOR"); -+ if (heap_slots_growth_factor_ptr != NULL) { -+ double heap_slots_growth_factor_d = atoi(heap_slots_growth_factor_ptr); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_GROWTH_FACTOR=%s\n", heap_slots_growth_factor_ptr); -+ } -+ if (heap_slots_growth_factor_d > 0) { -+ heap_slots_growth_factor = heap_slots_growth_factor_d; -+ } -+ } -+ -+ malloc_limit_ptr = getenv("RUBY_GC_MALLOC_LIMIT"); -+ if (malloc_limit_ptr != NULL) { -+ int malloc_limit_i = atol(malloc_limit_ptr); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_GC_MALLOC_LIMIT=%s\n", malloc_limit_ptr); -+ } -+ if (malloc_limit_i > 0) { -+ initial_malloc_limit = malloc_limit_i; -+ } -+ } -+} -+ -+/* -+ * call-seq: -+ * GC.dump => nil -+ * -+ * dumps information about the current GC data structures to the GC log file -+ * -+ * GC.dump #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_dump() -+{ -+ int i; -+ -+ for (i = 0; i < heaps_used; i++) { -+ int heap_size = heaps[i].limit; -+ fprintf(gc_data_file, "HEAP[%2d]: size=%7d\n", i, heap_size); -+ } -+ -+ return Qnil; -+} -+ -+/* -+ * call-seq: -+ * GC.log String => String -+ * -+ * Logs string to the GC data file and returns it. -+ * -+ * GC.log "manual GC call" #=> "manual GC call" -+ * -+ */ -+ -+VALUE -+rb_gc_log(self, original_str) -+ VALUE self, original_str; -+{ -+ if (original_str == Qnil) { -+ fprintf(gc_data_file, "\n"); -+ } -+ else { -+ VALUE str = StringValue(original_str); -+ char *p = RSTRING(str)->ptr; -+ fprintf(gc_data_file, "%s\n", p); -+ } -+ return original_str; -+} -+ -+ - static void - add_heap() - { - RVALUE *p, *pend; - - if (heaps_used == heaps_length) { -- /* Realloc heaps */ -- struct heaps_slot *p; -- int length; -- -- heaps_length += HEAPS_INCREMENT; -- length = heaps_length*sizeof(struct heaps_slot); -- RUBY_CRITICAL( -- if (heaps_used > 0) { -- p = (struct heaps_slot *)realloc(heaps, length); -- if (p) heaps = p; -- } -- else { -- p = heaps = (struct heaps_slot *)malloc(length); -- }); -- if (p == 0) rb_memerror(); -+ /* Realloc heaps */ -+ struct heaps_slot *p; -+ int length; -+ -+ heaps_length += heaps_increment; -+ length = heaps_length*sizeof(struct heaps_slot); -+ RUBY_CRITICAL( -+ if (heaps_used > 0) { -+ p = (struct heaps_slot *)realloc(heaps, length); -+ if (p) heaps = p; -+ } -+ else { -+ p = heaps = (struct heaps_slot *)malloc(length); -+ }); -+ if (p == 0) rb_memerror(); - } - - for (;;) { -- RUBY_CRITICAL(p = (RVALUE*)malloc(sizeof(RVALUE)*(heap_slots+1))); -- if (p == 0) { -- if (heap_slots == HEAP_MIN_SLOTS) { -- rb_memerror(); -- } -- heap_slots = HEAP_MIN_SLOTS; -- continue; -- } -+ RUBY_CRITICAL(p = (RVALUE*)malloc(sizeof(RVALUE)*(heap_slots+1))); -+ if (p == 0) { -+ if (heap_slots == heap_min_slots) { -+ rb_memerror(); -+ } -+ heap_slots = heap_min_slots; -+ continue; -+ } - heaps[heaps_used].membase = p; - if ((VALUE)p % sizeof(RVALUE) == 0) - heap_slots += 1; -@@ -401,25 +667,26 @@ add_heap() - p = (RVALUE*)((VALUE)p + sizeof(RVALUE) - ((VALUE)p % sizeof(RVALUE))); - heaps[heaps_used].slot = p; - heaps[heaps_used].limit = heap_slots; -- break; -+ break; - } - pend = p + heap_slots; - if (lomem == 0 || lomem > p) lomem = p; - if (himem < pend) himem = pend; - heaps_used++; -- heap_slots *= 1.8; -- if (heap_slots <= 0) heap_slots = HEAP_MIN_SLOTS; -+ heap_slots += heap_slots_increment; -+ heap_slots_increment *= heap_slots_growth_factor; -+ if (heap_slots <= 0) heap_slots = heap_min_slots; - - while (p < pend) { -- p->as.free.flags = 0; -- p->as.free.next = freelist; -- freelist = p; -- p++; -+ p->as.free.flags = 0; -+ p->as.free.next = freelist; -+ freelist = p; -+ p++; - } - } - #define RANY(o) ((RVALUE*)(o)) - --int -+int - rb_during_gc() - { - return during_gc; -@@ -431,7 +698,7 @@ rb_newobj() - VALUE obj; - - if (during_gc) -- rb_bug("object allocation during garbage collection phase"); -+ rb_bug("object allocation during garbage collection phase"); - - if (ruby_gc_stress || !freelist) garbage_collect(); - -@@ -580,13 +847,13 @@ rb_source_filename(f) - st_data_t name; - - if (!st_lookup(source_filenames, (st_data_t)f, &name)) { -- long len = strlen(f) + 1; -- char *ptr = ALLOC_N(char, len + 1); -- name = (st_data_t)ptr; -- *ptr++ = 0; -- MEMCPY(ptr, f, char, len); -- st_add_direct(source_filenames, (st_data_t)ptr, name); -- return ptr; -+ long len = strlen(f) + 1; -+ char *ptr = ALLOC_N(char, len + 1); -+ name = (st_data_t)ptr; -+ *ptr++ = 0; -+ MEMCPY(ptr, f, char, len); -+ st_add_direct(source_filenames, (st_data_t)ptr, name); -+ return ptr; - } - return (char *)name + 1; - } -@@ -596,7 +863,7 @@ mark_source_filename(f) - char *f; - { - if (f) { -- f[-1] = 1; -+ f[-1] = 1; - } - } - -@@ -605,12 +872,12 @@ sweep_source_filename(key, value) - char *key, *value; - { - if (*value) { -- *value = 0; -- return ST_CONTINUE; -+ *value = 0; -+ return ST_CONTINUE; - } - else { -- free(value); -- return ST_DELETE; -+ free(value); -+ return ST_DELETE; - } - } - -@@ -625,14 +892,14 @@ gc_mark_all() - - init_mark_stack(); - for (i = 0; i < heaps_used; i++) { -- p = heaps[i].slot; pend = p + heaps[i].limit; -- while (p < pend) { -- if ((p->as.basic.flags & FL_MARK) && -- (p->as.basic.flags != FL_MARK)) { -- gc_mark_children((VALUE)p, 0); -- } -- p++; -- } -+ p = heaps[i].slot; pend = p + heaps[i].limit; -+ while (p < pend) { -+ if ((p->as.basic.flags & FL_MARK) && -+ (p->as.basic.flags != FL_MARK)) { -+ gc_mark_children((VALUE)p, 0); -+ } -+ p++; -+ } - } - } - -@@ -647,8 +914,8 @@ gc_mark_rest() - - init_mark_stack(); - while(p != tmp_arry){ -- p--; -- gc_mark_children(*p, 0); -+ p--; -+ gc_mark_children(*p, 0); - } - } - -@@ -665,9 +932,9 @@ is_pointer_to_heap(ptr) - - /* check if p looks like a pointer */ - for (i=0; i < heaps_used; i++) { -- heap_org = heaps[i].slot; -- if (heap_org <= p && p < heap_org + heaps[i].limit) -- return Qtrue; -+ heap_org = heaps[i].slot; -+ if (heap_org <= p && p < heap_org + heaps[i].limit) -+ return Qtrue; - } - return Qfalse; - } -@@ -680,10 +947,10 @@ mark_locations_array(x, n) - VALUE v; - while (n--) { - v = *x; -- if (is_pointer_to_heap((void *)v)) { -- gc_mark(v, 0); -- } -- x++; -+ if (is_pointer_to_heap((void *)v)) { -+ gc_mark(v, 0); -+ } -+ x++; - } - } - -@@ -780,7 +1047,7 @@ rb_gc_mark_maybe(obj) - VALUE obj; - { - if (is_pointer_to_heap((void *)obj)) { -- gc_mark(obj, 0); -+ gc_mark(obj, 0); - } - } - -@@ -828,7 +1095,7 @@ gc_mark_children(ptr, lev) - { - register RVALUE *obj = RANY(ptr); - -- goto marking; /* skip */ -+ goto marking; /* skip */ - - again: - obj = RANY(ptr); -@@ -839,148 +1106,148 @@ gc_mark_children(ptr, lev) - - marking: - if (FL_TEST(obj, FL_EXIVAR)) { -- rb_mark_generic_ivar(ptr); -+ rb_mark_generic_ivar(ptr); - } - - switch (obj->as.basic.flags & T_MASK) { - case T_NIL: - case T_FIXNUM: -- rb_bug("rb_gc_mark() called for broken object"); -- break; -+ rb_bug("rb_gc_mark() called for broken object"); -+ break; - - case T_NODE: -- mark_source_filename(obj->as.node.nd_file); -- switch (nd_type(obj)) { -- case NODE_IF: /* 1,2,3 */ -- case NODE_FOR: -- case NODE_ITER: -- case NODE_CREF: -- case NODE_WHEN: -- case NODE_MASGN: -- case NODE_RESCUE: -- case NODE_RESBODY: -- case NODE_CLASS: -- gc_mark((VALUE)obj->as.node.u2.node, lev); -- /* 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_FBODY: -- case NODE_ENSURE: -- case NODE_CALL: -- case NODE_DEFS: -- case NODE_OP_ASGN1: -- gc_mark((VALUE)obj->as.node.u1.node, lev); -- /* fall through */ -- case NODE_SUPER: /* 3 */ -- case NODE_FCALL: -- case NODE_DEFN: -- case NODE_NEWLINE: -- ptr = (VALUE)obj->as.node.u3.node; -- goto again; -- -- 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_ARGS: -- gc_mark((VALUE)obj->as.node.u1.node, lev); -- /* fall through */ -- case NODE_METHOD: /* 2 */ -- case NODE_NOT: -- case NODE_GASGN: -- case NODE_LASGN: -- case NODE_DASGN: -- case NODE_DASGN_CURR: -- case NODE_IASGN: -- case NODE_CVDECL: -- case NODE_CVASGN: -- case NODE_COLON3: -- case NODE_OPT_N: -- case NODE_EVSTR: -- case NODE_UNDEF: -- ptr = (VALUE)obj->as.node.u2.node; -- goto again; -- -- 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: -- case NODE_SVALUE: -- ptr = (VALUE)obj->as.node.u1.node; -- goto again; -- -- case NODE_SCOPE: /* 2,3 */ -- case NODE_BLOCK_PASS: -- case NODE_CDECL: -- gc_mark((VALUE)obj->as.node.u3.node, lev); -- ptr = (VALUE)obj->as.node.u2.node; -- goto again; -- -- case NODE_ZARRAY: /* - */ -- case NODE_ZSUPER: -- case NODE_CFUNC: -- 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_ATTRSET: -- case NODE_BLOCK_ARG: -- case NODE_POSTEXE: -- break; -- case NODE_ALLOCA: -- mark_locations_array((VALUE*)obj->as.node.u1.value, -- obj->as.node.u3.cnt); -- ptr = (VALUE)obj->as.node.u2.node; -- goto again; -- -- default: /* unlisted NODE */ -- if (is_pointer_to_heap(obj->as.node.u1.node)) { -- gc_mark((VALUE)obj->as.node.u1.node, lev); -- } -- if (is_pointer_to_heap(obj->as.node.u2.node)) { -- gc_mark((VALUE)obj->as.node.u2.node, lev); -- } -- if (is_pointer_to_heap(obj->as.node.u3.node)) { -- gc_mark((VALUE)obj->as.node.u3.node, lev); -- } -- } -- return; /* no need to mark class. */ -+ mark_source_filename(obj->as.node.nd_file); -+ switch (nd_type(obj)) { -+ case NODE_IF: /* 1,2,3 */ -+ case NODE_FOR: -+ case NODE_ITER: -+ case NODE_CREF: -+ case NODE_WHEN: -+ case NODE_MASGN: -+ case NODE_RESCUE: -+ case NODE_RESBODY: -+ case NODE_CLASS: -+ gc_mark((VALUE)obj->as.node.u2.node, lev); -+ /* 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_FBODY: -+ case NODE_ENSURE: -+ case NODE_CALL: -+ case NODE_DEFS: -+ case NODE_OP_ASGN1: -+ gc_mark((VALUE)obj->as.node.u1.node, lev); -+ /* fall through */ -+ case NODE_SUPER: /* 3 */ -+ case NODE_FCALL: -+ case NODE_DEFN: -+ case NODE_NEWLINE: -+ ptr = (VALUE)obj->as.node.u3.node; -+ goto again; -+ -+ 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_ARGS: -+ gc_mark((VALUE)obj->as.node.u1.node, lev); -+ /* fall through */ -+ case NODE_METHOD: /* 2 */ -+ case NODE_NOT: -+ case NODE_GASGN: -+ case NODE_LASGN: -+ case NODE_DASGN: -+ case NODE_DASGN_CURR: -+ case NODE_IASGN: -+ case NODE_CVDECL: -+ case NODE_CVASGN: -+ case NODE_COLON3: -+ case NODE_OPT_N: -+ case NODE_EVSTR: -+ case NODE_UNDEF: -+ ptr = (VALUE)obj->as.node.u2.node; -+ goto again; -+ -+ 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: -+ case NODE_SVALUE: -+ ptr = (VALUE)obj->as.node.u1.node; -+ goto again; -+ -+ case NODE_SCOPE: /* 2,3 */ -+ case NODE_BLOCK_PASS: -+ case NODE_CDECL: -+ gc_mark((VALUE)obj->as.node.u3.node, lev); -+ ptr = (VALUE)obj->as.node.u2.node; -+ goto again; -+ -+ case NODE_ZARRAY: /* - */ -+ case NODE_ZSUPER: -+ case NODE_CFUNC: -+ 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_ATTRSET: -+ case NODE_BLOCK_ARG: -+ case NODE_POSTEXE: -+ break; -+ case NODE_ALLOCA: -+ mark_locations_array((VALUE*)obj->as.node.u1.value, -+ obj->as.node.u3.cnt); -+ ptr = (VALUE)obj->as.node.u2.node; -+ goto again; -+ -+ default: /* unlisted NODE */ -+ if (is_pointer_to_heap(obj->as.node.u1.node)) { -+ gc_mark((VALUE)obj->as.node.u1.node, lev); -+ } -+ if (is_pointer_to_heap(obj->as.node.u2.node)) { -+ gc_mark((VALUE)obj->as.node.u2.node, lev); -+ } -+ if (is_pointer_to_heap(obj->as.node.u3.node)) { -+ gc_mark((VALUE)obj->as.node.u3.node, lev); -+ } -+ } -+ return; /* no need to mark class. */ - } - - gc_mark(obj->as.basic.klass, lev); -@@ -988,92 +1255,92 @@ gc_mark_children(ptr, lev) - case T_ICLASS: - case T_CLASS: - case T_MODULE: -- mark_tbl(obj->as.klass.m_tbl, lev); -- mark_tbl(obj->as.klass.iv_tbl, lev); -- ptr = obj->as.klass.super; -- goto again; -+ mark_tbl(obj->as.klass.m_tbl, lev); -+ mark_tbl(obj->as.klass.iv_tbl, lev); -+ ptr = obj->as.klass.super; -+ goto again; - - case T_ARRAY: -- if (FL_TEST(obj, ELTS_SHARED)) { -- ptr = obj->as.array.aux.shared; -- goto again; -- } -- else { -- long i, len = obj->as.array.len; -- VALUE *ptr = obj->as.array.ptr; -+ if (FL_TEST(obj, ELTS_SHARED)) { -+ ptr = obj->as.array.aux.shared; -+ goto again; -+ } -+ else { -+ long i, len = obj->as.array.len; -+ VALUE *ptr = obj->as.array.ptr; - -- for (i=0; i < len; i++) { -- gc_mark(*ptr++, lev); -- } -- } -- break; -+ for (i=0; i < len; i++) { -+ gc_mark(*ptr++, lev); -+ } -+ } -+ break; - - case T_HASH: -- mark_hash(obj->as.hash.tbl, lev); -- ptr = obj->as.hash.ifnone; -- goto again; -+ mark_hash(obj->as.hash.tbl, lev); -+ ptr = obj->as.hash.ifnone; -+ goto again; - - case T_STRING: - #define STR_ASSOC FL_USER3 /* copied from string.c */ -- if (FL_TEST(obj, ELTS_SHARED|STR_ASSOC)) { -- ptr = obj->as.string.aux.shared; -- goto again; -- } -- break; -+ if (FL_TEST(obj, ELTS_SHARED|STR_ASSOC)) { -+ ptr = obj->as.string.aux.shared; -+ goto again; -+ } -+ break; - - case T_DATA: -- if (obj->as.data.dmark) (*obj->as.data.dmark)(DATA_PTR(obj)); -- break; -+ if (obj->as.data.dmark) (*obj->as.data.dmark)(DATA_PTR(obj)); -+ break; - - case T_OBJECT: -- mark_tbl(obj->as.object.iv_tbl, lev); -- break; -+ mark_tbl(obj->as.object.iv_tbl, lev); -+ break; - - case T_FILE: - case T_REGEXP: - case T_FLOAT: - case T_BIGNUM: - case T_BLKTAG: -- break; -+ break; - - case T_MATCH: -- if (obj->as.match.str) { -- ptr = obj->as.match.str; -- goto again; -- } -- break; -+ if (obj->as.match.str) { -+ ptr = obj->as.match.str; -+ goto again; -+ } -+ break; - - case T_VARMAP: -- gc_mark(obj->as.varmap.val, lev); -- ptr = (VALUE)obj->as.varmap.next; -- goto again; -+ gc_mark(obj->as.varmap.val, lev); -+ ptr = (VALUE)obj->as.varmap.next; -+ goto again; - - case T_SCOPE: -- if (obj->as.scope.local_vars && (obj->as.scope.flags & SCOPE_MALLOC)) { -- int n = obj->as.scope.local_tbl[0]+1; -- VALUE *vars = &obj->as.scope.local_vars[-1]; -+ if (obj->as.scope.local_vars && (obj->as.scope.flags & SCOPE_MALLOC)) { -+ int n = obj->as.scope.local_tbl[0]+1; -+ VALUE *vars = &obj->as.scope.local_vars[-1]; - -- while (n--) { -- gc_mark(*vars++, lev); -- } -- } -- break; -+ while (n--) { -+ gc_mark(*vars++, lev); -+ } -+ } -+ break; - - case T_STRUCT: -- { -- long len = obj->as.rstruct.len; -- VALUE *ptr = obj->as.rstruct.ptr; -+ { -+ long len = obj->as.rstruct.len; -+ VALUE *ptr = obj->as.rstruct.ptr; - -- while (len--) { -- gc_mark(*ptr++, lev); -- } -- } -- break; -+ while (len--) { -+ gc_mark(*ptr++, lev); -+ } -+ } -+ break; - - default: -- rb_bug("rb_gc_mark(): unknown data type 0x%lx(0x%lx) %s", -- obj->as.basic.flags & T_MASK, obj, -- is_pointer_to_heap(obj) ? "corrupted object" : "non object"); -+ rb_bug("rb_gc_mark(): unknown data type 0x%lx(0x%lx) %s", -+ obj->as.basic.flags & T_MASK, obj, -+ is_pointer_to_heap(obj) ? "corrupted object" : "non object"); - } - } - -@@ -1102,22 +1369,55 @@ finalize_list(p) - } - } - -+static char* obj_type(int tp) -+{ -+ switch (tp) { -+ case T_NIL : return "NIL"; -+ case T_OBJECT : return "OBJECT"; -+ case T_CLASS : return "CLASS"; -+ case T_ICLASS : return "ICLASS"; -+ case T_MODULE : return "MODULE"; -+ case T_FLOAT : return "FLOAT"; -+ case T_STRING : return "STRING"; -+ case T_REGEXP : return "REGEXP"; -+ case T_ARRAY : return "ARRAY"; -+ case T_FIXNUM : return "FIXNUM"; -+ case T_HASH : return "HASH"; -+ case T_STRUCT : return "STRUCT"; -+ case T_BIGNUM : return "BIGNUM"; -+ case T_FILE : return "FILE"; -+ -+ case T_TRUE : return "TRUE"; -+ case T_FALSE : return "FALSE"; -+ case T_DATA : return "DATA"; -+ case T_MATCH : return "MATCH"; -+ case T_SYMBOL : return "SYMBOL"; -+ -+ case T_BLKTAG : return "BLKTAG"; -+ case T_UNDEF : return "UNDEF"; -+ case T_VARMAP : return "VARMAP"; -+ case T_SCOPE : return "SCOPE"; -+ case T_NODE : return "NODE"; -+ default: return "____"; -+ } -+} -+ - static void - free_unused_heaps() - { - int i, j; - - for (i = j = 1; j < heaps_used; i++) { -- if (heaps[i].limit == 0) { -- free(heaps[i].membase); -- heaps_used--; -- } -- else { -- if (i != j) { -- heaps[j] = heaps[i]; -- } -- j++; -- } -+ if (heaps[i].limit == 0) { -+ free(heaps[i].membase); -+ heaps_used--; -+ } -+ else { -+ if (i != j) { -+ heaps[j] = heaps[i]; -+ } -+ j++; -+ } - } - } - -@@ -1134,24 +1434,33 @@ gc_sweep() - unsigned long live = 0; - unsigned long free_min = 0; - -+ unsigned long really_freed = 0; -+ int free_counts[256]; -+ int live_counts[256]; -+ int do_gc_stats = gc_statistics & verbose_gc_stats; -+ - for (i = 0; i < heaps_used; i++) { - free_min += heaps[i].limit; - } - free_min = free_min * 0.2; -- if (free_min < FREE_MIN) -- free_min = FREE_MIN; -+ if (free_min < heap_free_min) -+ free_min = heap_free_min; -+ -+ if (do_gc_stats) { -+ for (i = 0 ; i< 256; i++) { free_counts[i] = live_counts[i] = 0; } -+ } - - if (ruby_in_compile && ruby_parser_stack_on_heap()) { -- /* should not reclaim nodes during compilation -+ /* should not reclaim nodes during compilation - if yacc's semantic stack is not allocated on machine stack */ -- for (i = 0; i < heaps_used; i++) { -- p = heaps[i].slot; pend = p + heaps[i].limit; -- while (p < pend) { -- if (!(p->as.basic.flags&FL_MARK) && BUILTIN_TYPE(p) == T_NODE) -- gc_mark((VALUE)p, 0); -- p++; -- } -- } -+ for (i = 0; i < heaps_used; i++) { -+ p = heaps[i].slot; pend = p + heaps[i].limit; -+ while (p < pend) { -+ if (!(p->as.basic.flags&FL_MARK) && BUILTIN_TYPE(p) == T_NODE) -+ gc_mark((VALUE)p, 0); -+ p++; -+ } -+ } - } - - mark_source_filename(ruby_sourcefile); -@@ -1172,7 +1481,7 @@ gc_sweep() - while (p < pend) { - if (!(p->as.basic.flags & FL_MARK)) { - if (p->as.basic.flags && -- ((deferred = obj_free((VALUE)p)) || -+ (((do_gc_stats && really_freed++), deferred = obj_free((VALUE)p)) || - ((FL_TEST(p, FL_FINALIZE)) && need_call_final))) { - if (!deferred) { - p->as.free.flags = T_DEFERRED; -@@ -1183,6 +1492,12 @@ gc_sweep() - final_list = p; - } - else { -+ if (do_gc_stats) { -+ int obt = p->as.basic.flags & T_MASK; -+ if (obt) { -+ free_counts[obt]++; -+ } -+ } - add_freelist(p); - } - n++; -@@ -1194,6 +1509,9 @@ gc_sweep() - else { - RBASIC(p)->flags &= ~FL_MARK; - live++; -+ if (do_gc_stats) { -+ live_counts[RANY((VALUE)p)->as.basic.flags & T_MASK]++; -+ } - } - p++; - } -@@ -1211,15 +1529,29 @@ gc_sweep() - } - } - if (malloc_increase > malloc_limit) { -- malloc_limit += (malloc_increase - malloc_limit) * (double)live / (live + freed); -- if (malloc_limit < GC_MALLOC_LIMIT) malloc_limit = GC_MALLOC_LIMIT; -+ malloc_limit += (malloc_increase - malloc_limit) * (double)live / (live + freed); -+ if (malloc_limit < initial_malloc_limit) malloc_limit = initial_malloc_limit; - } - malloc_increase = 0; - if (freed < free_min) { -- add_heap(); -+ add_heap(); - } - during_gc = 0; - -+ if (do_gc_stats) { -+ fprintf(gc_data_file, "objects processed: %.7d\n", live+freed); -+ fprintf(gc_data_file, "live objects : %.7d\n", live); -+ fprintf(gc_data_file, "freelist objects : %.7d\n", freed - really_freed); -+ fprintf(gc_data_file, "freed objects : %.7d\n", really_freed); -+ for(i=0; i<256; i++) { -+ if (free_counts[i]>0 || live_counts[i]>0) { -+ fprintf(gc_data_file, -+ "kept %.7d / freed %.7d objects of type %s\n", -+ live_counts[i], free_counts[i], obj_type(i)); -+ } -+ } -+ } -+ - /* clear finalization list */ - if (final_list) { - deferred_final_list = final_list; -@@ -1260,51 +1592,51 @@ obj_free(obj) - case T_FIXNUM: - case T_TRUE: - case T_FALSE: -- rb_bug("obj_free() called for broken object"); -- break; -+ rb_bug("obj_free() called for broken object"); -+ break; - } - - if (FL_TEST(obj, FL_EXIVAR)) { -- rb_free_generic_ivar((VALUE)obj); -+ rb_free_generic_ivar((VALUE)obj); - } - - switch (BUILTIN_TYPE(obj)) { - case T_OBJECT: -- if (RANY(obj)->as.object.iv_tbl) { -- st_free_table(RANY(obj)->as.object.iv_tbl); -- } -- break; -+ if (RANY(obj)->as.object.iv_tbl) { -+ st_free_table(RANY(obj)->as.object.iv_tbl); -+ } -+ break; - case T_MODULE: - case T_CLASS: -- rb_clear_cache_by_class((VALUE)obj); -- st_free_table(RANY(obj)->as.klass.m_tbl); -- if (RANY(obj)->as.object.iv_tbl) { -- st_free_table(RANY(obj)->as.object.iv_tbl); -- } -- break; -+ rb_clear_cache_by_class((VALUE)obj); -+ st_free_table(RANY(obj)->as.klass.m_tbl); -+ if (RANY(obj)->as.object.iv_tbl) { -+ st_free_table(RANY(obj)->as.object.iv_tbl); -+ } -+ break; - case T_STRING: -- if (RANY(obj)->as.string.ptr && !FL_TEST(obj, ELTS_SHARED)) { -- RUBY_CRITICAL(free(RANY(obj)->as.string.ptr)); -- } -- break; -+ if (RANY(obj)->as.string.ptr && !FL_TEST(obj, ELTS_SHARED)) { -+ RUBY_CRITICAL(free(RANY(obj)->as.string.ptr)); -+ } -+ break; - case T_ARRAY: -- if (RANY(obj)->as.array.ptr && !FL_TEST(obj, ELTS_SHARED)) { -- RUBY_CRITICAL(free(RANY(obj)->as.array.ptr)); -- } -- break; -+ if (RANY(obj)->as.array.ptr && !FL_TEST(obj, ELTS_SHARED)) { -+ RUBY_CRITICAL(free(RANY(obj)->as.array.ptr)); -+ } -+ break; - case T_HASH: -- if (RANY(obj)->as.hash.tbl) { -- st_free_table(RANY(obj)->as.hash.tbl); -- } -- break; -+ if (RANY(obj)->as.hash.tbl) { -+ st_free_table(RANY(obj)->as.hash.tbl); -+ } -+ break; - case T_REGEXP: -- if (RANY(obj)->as.regexp.ptr) { -- re_free_pattern(RANY(obj)->as.regexp.ptr); -- } -- if (RANY(obj)->as.regexp.str) { -- RUBY_CRITICAL(free(RANY(obj)->as.regexp.str)); -- } -- break; -+ if (RANY(obj)->as.regexp.ptr) { -+ re_free_pattern(RANY(obj)->as.regexp.ptr); -+ } -+ if (RANY(obj)->as.regexp.str) { -+ RUBY_CRITICAL(free(RANY(obj)->as.regexp.str)); -+ } -+ break; - case T_DATA: - if (DATA_PTR(obj)) { - if ((long)RANY(obj)->as.data.dfree == -1) { -@@ -1317,11 +1649,11 @@ obj_free(obj) - } - break; - case T_MATCH: -- if (RANY(obj)->as.match.regs) { -- re_free_registers(RANY(obj)->as.match.regs); -- RUBY_CRITICAL(free(RANY(obj)->as.match.regs)); -- } -- break; -+ if (RANY(obj)->as.match.regs) { -+ re_free_registers(RANY(obj)->as.match.regs); -+ RUBY_CRITICAL(free(RANY(obj)->as.match.regs)); -+ } -+ break; - case T_FILE: - if (RANY(obj)->as.file.fptr) { - struct rb_io_t *fptr = RANY(obj)->as.file.fptr; -@@ -1332,19 +1664,19 @@ obj_free(obj) - } - break; - case T_ICLASS: -- /* iClass shares table with the module */ -- break; -+ /* iClass shares table with the module */ -+ break; - - case T_FLOAT: - case T_VARMAP: - case T_BLKTAG: -- break; -+ break; - - case T_BIGNUM: -- if (RANY(obj)->as.bignum.digits) { -- RUBY_CRITICAL(free(RANY(obj)->as.bignum.digits)); -- } -- break; -+ if (RANY(obj)->as.bignum.digits) { -+ RUBY_CRITICAL(free(RANY(obj)->as.bignum.digits)); -+ } -+ break; - case T_NODE: - switch (nd_type(obj)) { - case NODE_SCOPE: -@@ -1359,7 +1691,7 @@ obj_free(obj) - break; /* no need to free iv_tbl */ - - case T_SCOPE: -- if (RANY(obj)->as.scope.local_vars && -+ if (RANY(obj)->as.scope.local_vars && - RANY(obj)->as.scope.flags != SCOPE_ALLOCA) { - VALUE *vars = RANY(obj)->as.scope.local_vars-1; - if (!(RANY(obj)->as.scope.flags & SCOPE_CLONE) && vars[0] == 0) -@@ -1370,14 +1702,14 @@ obj_free(obj) - break; - - case T_STRUCT: -- if (RANY(obj)->as.rstruct.ptr) { -- RUBY_CRITICAL(free(RANY(obj)->as.rstruct.ptr)); -- } -- break; -+ if (RANY(obj)->as.rstruct.ptr) { -+ RUBY_CRITICAL(free(RANY(obj)->as.rstruct.ptr)); -+ } -+ break; - - default: -- rb_bug("gc_sweep(): unknown data type 0x%lx(0x%lx)", -- RANY(obj)->as.basic.flags & T_MASK, obj); -+ rb_bug("gc_sweep(): unknown data type 0x%lx(0x%lx)", -+ RANY(obj)->as.basic.flags & T_MASK, obj); - } - - return 0; -@@ -1407,18 +1739,18 @@ _rb_setjmp:\n\ - typedef unsigned long rb_jmp_buf[6]; - __asm__ (".align 4\n\ - _rb_setjmp:\n\ -- pushl %ebp\n\ -- movl %esp,%ebp\n\ -- movl 8(%ebp),%ebp\n\ -- movl %eax,(%ebp)\n\ -- movl %ebx,4(%ebp)\n\ -- movl %ecx,8(%ebp)\n\ -- movl %edx,12(%ebp)\n\ -- movl %esi,16(%ebp)\n\ -- movl %edi,20(%ebp)\n\ -- popl %ebp\n\ -- xorl %eax,%eax\n\ -- ret"); -+ pushl %ebp\n\ -+ movl %esp,%ebp\n\ -+ movl 8(%ebp),%ebp\n\ -+ movl %eax,(%ebp)\n\ -+ movl %ebx,4(%ebp)\n\ -+ movl %ecx,8(%ebp)\n\ -+ movl %edx,12(%ebp)\n\ -+ movl %esi,16(%ebp)\n\ -+ movl %edi,20(%ebp)\n\ -+ popl %ebp\n\ -+ xorl %eax,%eax\n\ -+ ret"); - #endif - #endif - int rb_setjmp (rb_jmp_buf); -@@ -1431,41 +1763,50 @@ garbage_collect() - struct gc_list *list; - struct FRAME * volatile frame; /* gcc 2.7.2.3 -O2 bug?? */ - jmp_buf save_regs_gc_mark; -+ struct timeval gctv1, gctv2; - SET_STACK_END; - - #ifdef HAVE_NATIVETHREAD - if (!is_ruby_native_thread()) { -- rb_bug("cross-thread violation on rb_gc()"); -+ rb_bug("cross-thread violation on rb_gc()"); - } - #endif - if (dont_gc || during_gc) { -- if (!freelist) { -- add_heap(); -- } -- return; -+ if (!freelist) { -+ add_heap(); -+ } -+ return; - } - if (during_gc) return; - during_gc++; - -+ if (gc_statistics) { -+ gc_collections++; -+ gettimeofday(&gctv1, NULL); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "Garbage collection started\n"); -+ } -+ } -+ - init_mark_stack(); - - gc_mark((VALUE)ruby_current_node, 0); - - /* mark frame stack */ - for (frame = ruby_frame; frame; frame = frame->prev) { -- rb_gc_mark_frame(frame); -- if (frame->tmp) { -- struct FRAME *tmp = frame->tmp; -- while (tmp) { -- rb_gc_mark_frame(tmp); -- tmp = tmp->prev; -- } -- } -+ rb_gc_mark_frame(frame); -+ if (frame->tmp) { -+ struct FRAME *tmp = frame->tmp; -+ while (tmp) { -+ rb_gc_mark_frame(tmp); -+ tmp = tmp->prev; -+ } -+ } - } - gc_mark((VALUE)ruby_scope, 0); - gc_mark((VALUE)ruby_dyna_vars, 0); - if (finalizer_table) { -- mark_tbl(finalizer_table, 0); -+ mark_tbl(finalizer_table, 0); - } - - FLUSH_REGISTER_WINDOWS; -@@ -1478,9 +1819,9 @@ garbage_collect() - rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)STACK_END + 1); - #else - if ((VALUE*)STACK_END < rb_gc_stack_start) -- rb_gc_mark_locations((VALUE*)STACK_END, rb_gc_stack_start); -+ rb_gc_mark_locations((VALUE*)STACK_END, rb_gc_stack_start); - else -- rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)STACK_END + 1); -+ rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)STACK_END + 1); - #endif - #ifdef __ia64 - /* mark backing store (flushed register window on the stack) */ -@@ -1489,13 +1830,13 @@ garbage_collect() - #endif - #if defined(__human68k__) || defined(__mc68000__) - rb_gc_mark_locations((VALUE*)((char*)STACK_END + 2), -- (VALUE*)((char*)rb_gc_stack_start + 2)); -+ (VALUE*)((char*)rb_gc_stack_start + 2)); - #endif - rb_gc_mark_threads(); - - /* mark protected global variables */ - for (list = global_List; list; list = list->next) { -- rb_gc_mark_maybe(*list->varptr); -+ rb_gc_mark_maybe(*list->varptr); - } - rb_mark_end_proc(); - rb_gc_mark_global_tbl(); -@@ -1510,18 +1851,30 @@ garbage_collect() - - /* gc_mark objects whose marking are not completed*/ - do { -- while (!MARK_STACK_EMPTY) { -- if (mark_stack_overflow){ -- gc_mark_all(); -- } -- else { -- gc_mark_rest(); -- } -- } -- rb_gc_abort_threads(); -+ while (!MARK_STACK_EMPTY) { -+ if (mark_stack_overflow){ -+ gc_mark_all(); -+ } -+ else { -+ gc_mark_rest(); -+ } -+ } -+ rb_gc_abort_threads(); - } while (!MARK_STACK_EMPTY); - - gc_sweep(); -+ -+ if (gc_statistics) { -+ GC_TIME_TYPE musecs_used; -+ gettimeofday(&gctv2, NULL); -+ musecs_used = ((GC_TIME_TYPE)(gctv2.tv_sec - gctv1.tv_sec) * 1000000) + (gctv2.tv_usec - gctv1.tv_usec); -+ gc_time += musecs_used; -+ -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "GC time: %d msec\n", musecs_used / 1000); -+ fflush(gc_data_file); -+ } -+ } - } - - void -@@ -1588,8 +1941,8 @@ Init_stack(addr) - memset(&m, 0, sizeof(m)); - VirtualQuery(&m, &m, sizeof(m)); - rb_gc_stack_start = -- STACK_UPPER((VALUE *)&m, (VALUE *)m.BaseAddress, -- (VALUE *)((char *)m.BaseAddress + m.RegionSize) - 1); -+ STACK_UPPER((VALUE *)&m, (VALUE *)m.BaseAddress, -+ (VALUE *)((char *)m.BaseAddress + m.RegionSize) - 1); - #elif defined(STACK_END_ADDRESS) - { - extern void *STACK_END_ADDRESS; -@@ -1599,24 +1952,24 @@ Init_stack(addr) - if (!addr) addr = (void *)&addr; - STACK_UPPER(&addr, addr, ++addr); - if (rb_gc_stack_start) { -- if (STACK_UPPER(&addr, -- rb_gc_stack_start > addr, -- rb_gc_stack_start < addr)) -- rb_gc_stack_start = addr; -- return; -+ if (STACK_UPPER(&addr, -+ rb_gc_stack_start > addr, -+ rb_gc_stack_start < addr)) -+ rb_gc_stack_start = addr; -+ return; - } - rb_gc_stack_start = addr; - #endif - #ifdef HAVE_GETRLIMIT - { -- struct rlimit rlim; -+ struct rlimit rlim; - -- if (getrlimit(RLIMIT_STACK, &rlim) == 0) { -- unsigned int space = rlim.rlim_cur/5; -+ if (getrlimit(RLIMIT_STACK, &rlim) == 0) { -+ unsigned int space = rlim.rlim_cur/5; - -- if (space > 1024*1024) space = 1024*1024; -- STACK_LEVEL_MAX = (rlim.rlim_cur - space) / sizeof(VALUE); -- } -+ if (space > 1024*1024) space = 1024*1024; -+ STACK_LEVEL_MAX = (rlim.rlim_cur - space) / sizeof(VALUE); -+ } - } - #endif - } -@@ -1652,16 +2005,16 @@ void ruby_init_stack(VALUE *addr - } - #elif defined _WIN32 - { -- MEMORY_BASIC_INFORMATION mi; -- DWORD size; -- DWORD space; -- -- if (VirtualQuery(&mi, &mi, sizeof(mi))) { -- size = (char *)mi.BaseAddress - (char *)mi.AllocationBase; -- space = size / 5; -- if (space > 1024*1024) space = 1024*1024; -- STACK_LEVEL_MAX = (size - space) / sizeof(VALUE); -- } -+ MEMORY_BASIC_INFORMATION mi; -+ DWORD size; -+ DWORD space; -+ -+ if (VirtualQuery(&mi, &mi, sizeof(mi))) { -+ size = (char *)mi.BaseAddress - (char *)mi.AllocationBase; -+ space = size / 5; -+ if (space > 1024*1024) space = 1024*1024; -+ STACK_LEVEL_MAX = (size - space) / sizeof(VALUE); -+ } - } - #endif - } -@@ -1701,8 +2054,9 @@ void - Init_heap() - { - if (!rb_gc_stack_start) { -- Init_stack(0); -+ Init_stack(0); - } -+ set_gc_parameters(); - add_heap(); - } - -@@ -1715,7 +2069,7 @@ os_obj_of(of) - volatile VALUE v; - - for (i = 0; i < heaps_used; i++) { -- RVALUE *p, *pend; -+ RVALUE *p, *pend; - - p = heaps[i].slot; pend = p + heaps[i].limit; - for (;p < pend; p++) { -@@ -1808,8 +2162,8 @@ add_final(os, block) - { - rb_warn("ObjectSpace::add_finalizer is deprecated; use define_finalizer"); - if (!rb_respond_to(block, rb_intern("call"))) { -- rb_raise(rb_eArgError, "wrong type argument %s (should be callable)", -- rb_obj_classname(block)); -+ rb_raise(rb_eArgError, "wrong type argument %s (should be callable)", -+ rb_obj_classname(block)); - } - rb_ary_push(finalizers, block); - return block; -@@ -1864,7 +2218,7 @@ undefine_final(os, obj) - VALUE os, obj; - { - if (finalizer_table) { -- st_delete(finalizer_table, (st_data_t*)&obj, 0); -+ st_delete(finalizer_table, (st_data_t*)&obj, 0); - } - return obj; - } -@@ -1888,11 +2242,11 @@ define_final(argc, argv, os) - - rb_scan_args(argc, argv, "11", &obj, &block); - if (argc == 1) { -- block = rb_block_proc(); -+ block = rb_block_proc(); - } - else if (!rb_respond_to(block, rb_intern("call"))) { -- rb_raise(rb_eArgError, "wrong type argument %s (should be callable)", -- rb_obj_classname(block)); -+ rb_raise(rb_eArgError, "wrong type argument %s (should be callable)", -+ rb_obj_classname(block)); - } - need_call_final = 1; - if (!FL_ABLE(obj)) { -@@ -1905,10 +2259,10 @@ define_final(argc, argv, os) - OBJ_FREEZE(block); - - if (!finalizer_table) { -- finalizer_table = st_init_numtable(); -+ finalizer_table = st_init_numtable(); - } - if (st_lookup(finalizer_table, obj, &table)) { -- rb_ary_push(table, block); -+ rb_ary_push(table, block); - } - else { - table = rb_ary_new3(1, block); -@@ -1927,7 +2281,7 @@ rb_gc_copy_finalizer(dest, obj) - if (!finalizer_table) return; - if (!FL_TEST(obj, FL_FINALIZE)) return; - if (st_lookup(finalizer_table, obj, &table)) { -- st_insert(finalizer_table, dest, table); -+ st_insert(finalizer_table, dest, table); - } - RBASIC(dest)->flags |= FL_FINALIZE; - } -@@ -1957,18 +2311,18 @@ run_final(obj) - args[1] = 0; - args[2] = (VALUE)ruby_safe_level; - for (i=0; ilen; i++) { -- args[0] = RARRAY(finalizers)->ptr[i]; -- if (!args[1]) args[1] = rb_ary_new3(1, objid); -- rb_protect((VALUE(*)_((VALUE)))run_single_final, (VALUE)args, &status); -+ args[0] = RARRAY(finalizers)->ptr[i]; -+ if (!args[1]) args[1] = rb_ary_new3(1, objid); -+ rb_protect((VALUE(*)_((VALUE)))run_single_final, (VALUE)args, &status); - } - if (finalizer_table && st_delete(finalizer_table, (st_data_t*)&obj, &table)) { -- for (i=0; ilen; i++) { -- VALUE final = RARRAY(table)->ptr[i]; -- args[0] = RARRAY(final)->ptr[1]; -- if (!args[1]) args[1] = rb_ary_new3(1, objid); -- args[2] = FIX2INT(RARRAY(final)->ptr[0]); -- rb_protect((VALUE(*)_((VALUE)))run_single_final, (VALUE)args, &status); -- } -+ for (i=0; ilen; i++) { -+ VALUE final = RARRAY(table)->ptr[i]; -+ args[0] = RARRAY(final)->ptr[1]; -+ if (!args[1]) args[1] = rb_ary_new3(1, objid); -+ args[2] = FIX2INT(RARRAY(final)->ptr[0]); -+ rb_protect((VALUE(*)_((VALUE)))run_single_final, (VALUE)args, &status); -+ } - } - rb_thread_critical = critical_save; - } -@@ -1980,8 +2334,8 @@ rb_gc_finalize_deferred() - - deferred_final_list = 0; - if (p) { -- finalize_list(p); -- free_unused_heaps(); -+ finalize_list(p); -+ free_unused_heaps(); - } - } - -@@ -2061,7 +2415,7 @@ id2ref(obj, objid) - if (ptr == Qfalse) return Qfalse; - if (ptr == Qnil) return Qnil; - if (FIXNUM_P(ptr)) return (VALUE)ptr; -- ptr = objid ^ FIXNUM_FLAG; /* unset FIXNUM_FLAG */ -+ ptr = objid ^ FIXNUM_FLAG; /* unset FIXNUM_FLAG */ - - if ((ptr % sizeof(RVALUE)) == (4 << 2)) { - ID symid = ptr / sizeof(RVALUE); -@@ -2075,7 +2429,7 @@ id2ref(obj, objid) - rb_raise(rb_eRangeError, "0x%lx is not id value", p0); - } - if (BUILTIN_TYPE(ptr) == 0 || RBASIC(ptr)->klass == 0) { -- rb_raise(rb_eRangeError, "0x%lx is recycled object", p0); -+ rb_raise(rb_eRangeError, "0x%lx is recycled object", p0); - } - return (VALUE)ptr; - } -@@ -2166,6 +2520,14 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "stress=", gc_stress_set, 1); - rb_define_method(rb_mGC, "garbage_collect", rb_gc_start, 0); - -+ rb_define_singleton_method(rb_mGC, "enable_stats", rb_gc_enable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "disable_stats", rb_gc_disable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0); -+ rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); -+ rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); -+ rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); -+ rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); -+ - rb_mObSpace = rb_define_module("ObjectSpace"); - rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1); - rb_define_module_function(rb_mObSpace, "garbage_collect", rb_gc_start, 0); -@@ -2188,7 +2550,7 @@ Init_GC() - - rb_global_variable(&nomem_error); - nomem_error = rb_exc_new3(rb_eNoMemError, -- rb_obj_freeze(rb_str_new2("failed to allocate memory"))); -+ rb_obj_freeze(rb_str_new2("failed to allocate memory"))); - OBJ_TAINT(nomem_error); - OBJ_FREEZE(nomem_error); - diff --git a/patches/ruby/1.8.7/p370/railsexpress/05-display-full-stack-trace.patch b/patches/ruby/1.8.7/p370/railsexpress/05-display-full-stack-trace.patch deleted file mode 100644 index 014747fa7f..0000000000 --- a/patches/ruby/1.8.7/p370/railsexpress/05-display-full-stack-trace.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/eval.c b/eval.c -index f49044a..213e78c 100644 ---- a/eval.c -+++ b/eval.c -@@ -1335,8 +1335,8 @@ error_print() - int truncate = eclass == rb_eSysStackError; - - #define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5) --#define TRACE_HEAD 8 --#define TRACE_TAIL 5 -+#define TRACE_HEAD 100 -+#define TRACE_TAIL 100 - - ep = RARRAY(errat); - for (i=1; ilen; i++) { diff --git a/patches/ruby/1.8.7/p370/railsexpress/06-better-source-file-tracing.patch b/patches/ruby/1.8.7/p370/railsexpress/06-better-source-file-tracing.patch deleted file mode 100644 index b0a636857f..0000000000 --- a/patches/ruby/1.8.7/p370/railsexpress/06-better-source-file-tracing.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/eval.c b/eval.c -index 213e78c..c37136f 100644 ---- a/eval.c -+++ b/eval.c -@@ -1171,7 +1171,7 @@ static VALUE trace_func = 0; - static int tracing = 0; - static void call_trace_func _((rb_event_t,NODE*,VALUE,ID,VALUE)); - --#if 0 -+#if 1 - #define SET_CURRENT_SOURCE() (ruby_sourcefile = ruby_current_node->nd_file, \ - ruby_sourceline = nd_line(ruby_current_node)) - #else diff --git a/patches/ruby/1.8.7/p370/railsexpress/07-heap-dump-support.patch b/patches/ruby/1.8.7/p370/railsexpress/07-heap-dump-support.patch deleted file mode 100644 index 5235be6bcc..0000000000 --- a/patches/ruby/1.8.7/p370/railsexpress/07-heap-dump-support.patch +++ /dev/null @@ -1,159 +0,0 @@ -diff --git a/configure.in b/configure.in -index 62b34a8..4be088c 100644 ---- a/configure.in -+++ b/configure.in -@@ -1595,6 +1595,14 @@ fi - LDFLAGS="-L. $LDFLAGS" - AC_SUBST(ARCHFILE) - -+dnl enable gc debugging -+AC_ARG_ENABLE(gcdebug, -+ [ --enable-gcdebug build garbage collector with debugging enabled. ], -+ [enable_gcdebug=$enableval]) -+if test "$enable_gcdebug" = 'yes'; then -+ AC_DEFINE(GC_DEBUG, 1) -+fi -+ - dnl build rdoc index if requested - RDOCTARGET="" - AC_ARG_ENABLE(install-doc, -diff --git a/gc.c b/gc.c -index ab71d22..9ad716f 100644 ---- a/gc.c -+++ b/gc.c -@@ -411,7 +411,6 @@ rb_gc_unregister_address(addr) - } - } - --#undef GC_DEBUG - - void - rb_global_variable(var) -@@ -602,6 +601,85 @@ rb_gc_dump() - return Qnil; - } - -+ -+static char* obj_type(int tp); -+ -+#ifdef GC_DEBUG -+/* -+ * call-seq: -+ * GC.dump_file_and_line_info(String, boolean) => nil -+ * -+ * dumps information on which currently allocated object was created by which file and on which line -+ * -+ * GC.dump_file_and_line_info(String, boolean) #=> nil -+ * -+ * The second parameter specifies whether class names should be included in the dump. -+ * Note that including class names will allocate additional string objects on the heap. -+ * -+ */ -+ -+VALUE -+rb_gc_dump_file_and_line_info(int argc, VALUE *argv) -+{ -+ VALUE filename, str, include_classnames = Qnil; -+ char *fname = NULL; -+ char *klass = NULL; -+ FILE* f = NULL; -+ int i,n = 0; -+ -+ rb_scan_args(argc, argv, "11", &filename, &include_classnames); -+ -+ str = StringValue(filename); -+ fname = RSTRING(str)->ptr; -+ f = fopen(fname, "w"); -+ -+ for (i = 0; i < heaps_used; i++) { -+ RVALUE *p, *pend; -+ -+ p = heaps[i].slot; pend = p + heaps[i].limit; -+ for (;p < pend; p++) { -+ if (p->as.basic.flags) { -+ fprintf(f, "%s:%s:%d", obj_type(p->as.basic.flags & T_MASK), p->file, p->line); -+ // rb_obj_classname will create objects on the heap, we need a better solution -+ if (include_classnames == Qtrue) { -+ /* write the class */ -+ fprintf(f, ":"); -+ switch (TYPE(p)) { -+ case T_NONE: -+ fprintf(f, "__none__"); -+ break; -+ case T_BLKTAG: -+ fprintf(f, "__blktag__"); -+ break; -+ case T_UNDEF: -+ fprintf(f, "__undef__"); -+ break; -+ case T_VARMAP: -+ fprintf(f, "__varmap__"); -+ break; -+ case T_SCOPE: -+ fprintf(f, "__scope__"); -+ break; -+ case T_NODE: -+ fprintf(f, "__node__"); -+ break; -+ default: -+ if (!p->as.basic.klass) { -+ fprintf(f, "__unknown__"); -+ } else { -+ fprintf(f, rb_obj_classname((VALUE)p)); -+ } -+ } -+ } -+ fprintf(f, "\n"); -+ } -+ } -+ } -+ fclose(f); -+ return Qnil; -+} -+#endif -+ - /* - * call-seq: - * GC.log String => String -@@ -1066,6 +1144,11 @@ gc_mark(ptr, lev) - if (obj->as.basic.flags & FL_MARK) return; /* already marked */ - obj->as.basic.flags |= FL_MARK; - -+#ifdef GC_DEBUG -+ /* mark our new reference point for sourcefile objects */ -+ mark_source_filename(RANY(obj)->file); -+#endif -+ - if (lev > GC_LEVEL_MAX || (lev == 0 && ruby_stack_check())) { - if (!mark_stack_overflow) { - if (mark_stack_ptr - mark_stack < MARK_STACK_MAX) { -@@ -1104,6 +1187,11 @@ gc_mark_children(ptr, lev) - if (obj->as.basic.flags & FL_MARK) return; /* already marked */ - obj->as.basic.flags |= FL_MARK; - -+#ifdef GC_DEBUG -+ /* mark our new reference point for sourcefile objects */ -+ mark_source_filename(RANY(obj)->file); -+#endif -+ - marking: - if (FL_TEST(obj, FL_EXIVAR)) { - rb_mark_generic_ivar(ptr); -@@ -1550,6 +1638,7 @@ gc_sweep() - live_counts[i], free_counts[i], obj_type(i)); - } - } -+ fflush(gc_data_file); - } - - /* clear finalization list */ -@@ -2526,6 +2615,9 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); - rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); - rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); -+#ifdef GC_DEBUG -+ rb_define_singleton_method(rb_mGC, "dump_file_and_line_info", rb_gc_dump_file_and_line_info, -1); -+#endif - rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); - - rb_mObSpace = rb_define_module("ObjectSpace"); diff --git a/patches/ruby/1.8.7/p370/railsexpress/08-fork-support-for-gc-logging.patch b/patches/ruby/1.8.7/p370/railsexpress/08-fork-support-for-gc-logging.patch deleted file mode 100644 index 0f01a75db0..0000000000 --- a/patches/ruby/1.8.7/p370/railsexpress/08-fork-support-for-gc-logging.patch +++ /dev/null @@ -1,249 +0,0 @@ -diff --git a/gc.c b/gc.c -index 9ad716f..a3cbe91 100644 ---- a/gc.c -+++ b/gc.c -@@ -223,6 +223,8 @@ static int dont_gc; - static int gc_statistics = 0; - static GC_TIME_TYPE gc_time = 0; - static int gc_collections = 0; -+static int verbose_gc_stats = Qfalse; -+static FILE* gc_data_file = NULL; - static int during_gc; - static int need_call_final = 0; - static st_table *finalizer_table = 0; -@@ -368,9 +370,148 @@ rb_gc_time() - #endif - } - -- - VALUE rb_mGC; - -+/* -+ * call-seq: -+ * GC.enable_trace => true or false -+ * -+ * Enables garbage collection tracing, returning true if garbage -+ * collection tracing was already enabled. -+ * -+ * GC.enable_trace #=> false or true -+ * GC.enable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_trace() -+{ -+ int old = verbose_gc_stats; -+ verbose_gc_stats = Qtrue; -+ return old; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_trace => true or false -+ * -+ * Disables garbage collection tracing, returning true if garbage -+ * collection tracing was already disabled. -+ * -+ * GC.disable_trace #=> false or true -+ * GC.disable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_trace() -+{ -+ int old = verbose_gc_stats; -+ verbose_gc_stats = Qfalse; -+ return old; -+} -+ -+char* GC_LOGFILE_IVAR = "@gc_logfile_name"; -+ -+/* -+ * call-seq: -+ * GC.log_file(filename=nil, mode="w") => boolean -+ * -+ * Changes the GC data log file. Closes the currently open logfile. -+ * Returns true if the file was successfully opened for -+ * writing. Returns false if the file could not be opened for -+ * writing. Returns the name of the current logfile (or nil) if no -+ * parameter is given. Restores logging to stderr when given nil as -+ * an argument. -+ * -+ * GC.log_file #=> nil -+ * GC.log_file "/tmp/gc.log" #=> true -+ * GC.log_file #=> "/tmp/gc.log" -+ * GC.log_file nil #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_log_file(int argc, VALUE *argv, VALUE self) -+{ -+ VALUE filename = Qnil; -+ VALUE mode_str = Qnil; -+ FILE* f = NULL; -+ char* mode = "w"; -+ -+ VALUE current_logfile_name = rb_iv_get(rb_mGC, GC_LOGFILE_IVAR); -+ -+ if (argc==0) -+ return current_logfile_name; -+ -+ rb_scan_args(argc, argv, "02", &filename, &mode_str); -+ -+ if (filename == Qnil) { -+ /* close current logfile and reset logfile to stderr */ -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+ } -+ return Qtrue; -+ } -+ -+ /* we have a real logfile name */ -+ filename = StringValue(filename); -+ -+ if (rb_equal(current_logfile_name, filename) == Qtrue) { -+ /* do nothing if we get the file name we're already logging to */ -+ return Qtrue; -+ } -+ -+ /* get mode for file opening */ -+ if (mode_str != Qnil) -+ { -+ mode = RSTRING(StringValue(mode_str))->ptr; -+ } -+ -+ /* try to open file in given mode */ -+ if (f = fopen(RSTRING(filename)->ptr, mode)) { -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ } -+ gc_data_file = f; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, filename); -+ } else { -+ return Qfalse; -+ } -+ return Qtrue; -+} -+ -+ -+/* -+ * Called from process.c before a fork. Flushes the gc log file to -+ * avoid writing the buffered output twice (once in the parent, and -+ * once in the child). -+ */ -+void -+rb_gc_before_fork() -+{ -+ /* flush gc log file */ -+ fflush(gc_data_file); -+} -+ -+/* -+ * Called from process.c after a fork in the child process. Turns off -+ * logging, disables GC stats and resets all gc counters and timing -+ * information. -+ */ -+void -+rb_gc_after_fork() -+{ -+ rb_gc_disable_stats(); -+ rb_gc_clear_stats(); -+ rb_gc_disable_trace(); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+} -+ - static struct gc_list { - VALUE *varptr; - struct gc_list *next; -@@ -477,10 +618,6 @@ static double heap_slots_growth_factor = 1.8; - - static long initial_malloc_limit = GC_MALLOC_LIMIT; - --static int verbose_gc_stats = Qfalse; -- --static FILE* gc_data_file = NULL; -- - static RVALUE *himem, *lomem; - - static void set_gc_parameters() -@@ -496,6 +633,8 @@ static void set_gc_parameters() - if (gc_stats_i > 0) { - verbose_gc_stats = Qtrue; - } -+ /* child processes should not inherit RUBY_GC_STATS */ -+ unsetenv("RUBY_GC_STATS"); - } - - gc_heap_file_ptr = getenv("RUBY_GC_DATA_FILE"); -@@ -508,6 +647,8 @@ static void set_gc_parameters() - fprintf(stderr, - "can't open gc log file %s for writing, using default\n", gc_heap_file_ptr); - } -+ /* child processes should not inherit RUBY_GC_DATA_FILE to avoid clobbering */ -+ unsetenv("RUBY_GC_DATA_FILE"); - } - - min_slots_ptr = getenv("RUBY_HEAP_MIN_SLOTS"); -@@ -2619,6 +2760,9 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "dump_file_and_line_info", rb_gc_dump_file_and_line_info, -1); - #endif - rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); -+ rb_define_singleton_method(rb_mGC, "log_file", rb_gc_log_file, -1); -+ rb_define_singleton_method(rb_mGC, "enable_trace", rb_gc_enable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "disable_trace", rb_gc_disable_trace, 0); - - rb_mObSpace = rb_define_module("ObjectSpace"); - rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1); -diff --git a/intern.h b/intern.h -index 950ae9d..99696f1 100644 ---- a/intern.h -+++ b/intern.h -@@ -270,6 +270,8 @@ void rb_gc_call_finalizer_at_exit _((void)); - VALUE rb_gc_enable _((void)); - VALUE rb_gc_disable _((void)); - VALUE rb_gc_start _((void)); -+void rb_gc_before_fork _((void)); -+void rb_gc_after_fork _((void)); - /* hash.c */ - void st_foreach_safe _((struct st_table *, int (*)(ANYARGS), unsigned long)); - void rb_hash_foreach _((VALUE, int (*)(ANYARGS), VALUE)); -diff --git a/process.c b/process.c -index 8f6285d..ea28cb8 100644 ---- a/process.c -+++ b/process.c -@@ -1330,6 +1330,8 @@ rb_f_fork(obj) - fflush(stderr); - #endif - -+ rb_gc_before_fork(); -+ - before_exec(); - pid = fork(); - after_exec(); -@@ -1339,6 +1341,7 @@ rb_f_fork(obj) - #ifdef linux - after_exec(); - #endif -+ rb_gc_after_fork(); - rb_thread_atfork(); - if (rb_block_given_p()) { - int status; -@@ -1574,10 +1577,12 @@ rb_f_system(argc, argv) - - chfunc = signal(SIGCHLD, SIG_DFL); - retry: -+ rb_gc_before_fork(); - before_exec(); - pid = fork(); - if (pid == 0) { - /* child process */ -+ rb_gc_after_fork(); - rb_thread_atfork(); - rb_protect(proc_exec_args, (VALUE)&earg, NULL); - _exit(127); diff --git a/patches/ruby/1.8.7/p370/railsexpress/09-track-malloc-size.patch b/patches/ruby/1.8.7/p370/railsexpress/09-track-malloc-size.patch deleted file mode 100644 index d078748a44..0000000000 --- a/patches/ruby/1.8.7/p370/railsexpress/09-track-malloc-size.patch +++ /dev/null @@ -1,120 +0,0 @@ -diff --git a/gc.c b/gc.c -index a3cbe91..30a1219 100644 ---- a/gc.c -+++ b/gc.c -@@ -79,6 +79,17 @@ void *alloca (); - - static unsigned long malloc_increase = 0; - static unsigned long malloc_limit = GC_MALLOC_LIMIT; -+ -+#ifdef HAVE_LONG_LONG -+static unsigned LONG_LONG gc_allocated_size = 0; -+static unsigned LONG_LONG gc_num_allocations = 0; -+#else -+static unsigned long gc_allocated_size = 0; -+static unsigned long gc_num_allocations = 0; -+#endif -+static int gc_statistics = 0; -+ -+ - static void run_final(); - static VALUE nomem_error; - static void garbage_collect(); -@@ -163,6 +174,11 @@ ruby_xmalloc(size) - } - malloc_increase += size; - -+ if (gc_statistics) { -+ gc_allocated_size += size; -+ gc_num_allocations += 1; -+ } -+ - return mem; - } - -@@ -220,7 +236,6 @@ ruby_xfree(x) - - extern int ruby_in_compile; - static int dont_gc; --static int gc_statistics = 0; - static GC_TIME_TYPE gc_time = 0; - static int gc_collections = 0; - static int verbose_gc_stats = Qfalse; -@@ -329,11 +344,55 @@ rb_gc_clear_stats() - { - gc_collections = 0; - gc_time = 0; -+ gc_allocated_size = 0; -+ gc_num_allocations = 0; - return Qnil; - } - - /* - * call-seq: -+ * GC.allocated_size => Integer -+ * -+ * Returns the size of memory (in bytes) allocated since GC statistics collection -+ * was enabled. -+ * -+ * GC.allocated_size #=> 35 -+ * -+ */ -+VALUE -+rb_gc_allocated_size() -+{ -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_allocated_size); -+#else -+ return ULONG2NUM(gc_allocated_size); -+#endif -+} -+ -+/* -+ * call-seq: -+ * GC.num_allocations => Integer -+ * -+ * Returns the number of memory allocations since GC statistics collection -+ * was enabled. -+ * -+ * GC.num_allocations #=> 150 -+ * -+ */ -+VALUE -+rb_gc_num_allocations() -+{ -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_num_allocations); -+#else -+ return ULONG2NUM(gc_num_allocations); -+#endif -+} -+ -+/* -+ -+/* -+ * call-seq: - * GC.collections => Integer - * - * Returns the number of garbage collections performed while GC statistics collection -@@ -2753,6 +2812,8 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "enable_stats", rb_gc_enable_stats, 0); - rb_define_singleton_method(rb_mGC, "disable_stats", rb_gc_disable_stats, 0); - rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0); -+ rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); -+ rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); - rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); - rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); - rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); -diff --git a/intern.h b/intern.h -index 99696f1..1117614 100644 ---- a/intern.h -+++ b/intern.h -@@ -272,6 +272,8 @@ VALUE rb_gc_disable _((void)); - VALUE rb_gc_start _((void)); - void rb_gc_before_fork _((void)); - void rb_gc_after_fork _((void)); -+VALUE rb_gc_allocated_size _((void)); -+VALUE rb_gc_num_allocations _((void)); - /* hash.c */ - void st_foreach_safe _((struct st_table *, int (*)(ANYARGS), unsigned long)); - void rb_hash_foreach _((VALUE, int (*)(ANYARGS), VALUE)); diff --git a/patches/ruby/1.8.7/p370/railsexpress/10-track-object-allocation.patch b/patches/ruby/1.8.7/p370/railsexpress/10-track-object-allocation.patch deleted file mode 100644 index 0eef717a24..0000000000 --- a/patches/ruby/1.8.7/p370/railsexpress/10-track-object-allocation.patch +++ /dev/null @@ -1,111 +0,0 @@ -diff --git a/gc.c b/gc.c -index 30a1219..5b42b90 100644 ---- a/gc.c -+++ b/gc.c -@@ -96,6 +96,26 @@ static void garbage_collect(); - - int ruby_gc_stress = 0; - -+static unsigned long live_objects = 0; -+unsigned long rb_os_live_objects() -+{ -+ return live_objects; -+} -+ -+#if defined(HAVE_LONG_LONG) -+static unsigned LONG_LONG allocated_objects = 0; -+unsigned LONG_LONG rb_os_allocated_objects() -+{ -+ return allocated_objects; -+} -+#else -+static unsigned long allocated_objects = 0; -+unsigned long rb_os_allocated_objects() -+{ -+ return allocated_objects; -+} -+#endif -+ - NORETURN(void rb_exc_jump _((VALUE))); - - void -@@ -987,6 +1007,8 @@ rb_newobj() - RANY(obj)->file = ruby_sourcefile; - RANY(obj)->line = ruby_sourceline; - #endif -+ live_objects++; -+ allocated_objects++; - return obj; - } - -@@ -1825,6 +1847,7 @@ gc_sweep() - add_heap(); - } - during_gc = 0; -+ live_objects = live; - - if (do_gc_stats) { - fprintf(gc_data_file, "objects processed: %.7d\n", live+freed); -@@ -2790,6 +2813,35 @@ rb_obj_id(VALUE obj) - return (VALUE)((long)obj|FIXNUM_FLAG); - } - -+/* call-seq: -+ * ObjectSpace.live_objects => number -+ * -+ * Returns the count of objects currently allocated in the system. This goes -+ * down after the garbage collector runs. -+ */ -+static -+VALUE os_live_objects(VALUE self) -+{ -+ return ULONG2NUM(live_objects); -+} -+ -+/* call-seq: -+ * ObjectSpace.allocated_objects => number -+ * -+ * Returns the count of objects allocated since the Ruby interpreter has -+ * started. This number can only increase. To know how many objects are -+ * currently allocated, use ObjectSpace::live_objects -+ */ -+static -+VALUE os_allocated_objects(VALUE self) -+{ -+#if defined(HAVE_LONG_LONG) -+ return ULL2NUM(allocated_objects); -+#else -+ return ULONG2NUM(allocated_objects); -+#endif -+} -+ - /* - * The GC module provides an interface to Ruby's mark and - * sweep garbage collection mechanism. Some of the underlying methods -@@ -2833,6 +2885,9 @@ Init_GC() - rb_define_module_function(rb_mObSpace, "finalizers", finals, 0); - rb_define_module_function(rb_mObSpace, "call_finalizer", call_final, 1); - -+ rb_define_module_function(rb_mObSpace, "live_objects", os_live_objects, 0); -+ rb_define_module_function(rb_mObSpace, "allocated_objects", os_allocated_objects, 0); -+ - rb_define_module_function(rb_mObSpace, "define_finalizer", define_final, -1); - rb_define_module_function(rb_mObSpace, "undefine_finalizer", undefine_final, 1); - -diff --git a/intern.h b/intern.h -index 1117614..a87661d 100644 ---- a/intern.h -+++ b/intern.h -@@ -274,6 +274,12 @@ void rb_gc_before_fork _((void)); - void rb_gc_after_fork _((void)); - VALUE rb_gc_allocated_size _((void)); - VALUE rb_gc_num_allocations _((void)); -+unsigned long rb_os_live_objects _((void)); -+#ifdef HAVE_LONG_LONG -+unsigned LONG_LONG rb_os_allocated_objects _((void)); -+#else -+unsigned long rb_os_allocated_objects _((void)); -+#endif - /* hash.c */ - void st_foreach_safe _((struct st_table *, int (*)(ANYARGS), unsigned long)); - void rb_hash_foreach _((VALUE, int (*)(ANYARGS), VALUE)); diff --git a/patches/ruby/1.8.7/p370/railsexpress/11-expose-heap-slots.patch b/patches/ruby/1.8.7/p370/railsexpress/11-expose-heap-slots.patch deleted file mode 100644 index 3ce846c6a0..0000000000 --- a/patches/ruby/1.8.7/p370/railsexpress/11-expose-heap-slots.patch +++ /dev/null @@ -1,70 +0,0 @@ -diff --git a/gc.c b/gc.c -index 5b42b90..21b3f6b 100644 ---- a/gc.c -+++ b/gc.c -@@ -690,6 +690,7 @@ static int heaps_used = 0; - - static int heap_min_slots = 10000; - static int heap_slots = 10000; -+static int heap_size = 0; - - static int heap_free_min = 4096; - static int heap_slots_increment = 10000; -@@ -800,6 +801,21 @@ static void set_gc_parameters() - - /* - * call-seq: -+ * GC.heap_slots => Integer -+ * -+ * Returns the number of heap slots available for object allocations. -+ * -+ * GC.heap_slots #=> 10000 -+ * -+ */ -+VALUE -+rb_gc_heap_slots() -+{ -+ return INT2NUM(heap_size); -+} -+ -+/* -+ * call-seq: - * GC.dump => nil - * - * dumps information about the current GC data structures to the GC log file -@@ -967,6 +983,7 @@ add_heap() - heaps[heaps_used].limit = heap_slots; - break; - } -+ heap_size += heap_slots; - pend = p + heap_slots; - if (lomem == 0 || lomem > p) lomem = p; - if (himem < pend) himem = pend; -@@ -1828,6 +1845,7 @@ gc_sweep() - if (n == heaps[i].limit && freed > free_min) { - RVALUE *pp; - -+ heap_size -= n; - heaps[i].limit = 0; - for (pp = final_list; pp != final; pp = pp->as.free.next) { - pp->as.free.flags |= FL_SINGLETON; /* freeing page mark */ -@@ -2866,6 +2884,7 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0); - rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); - rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); - rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); - rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); - rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); -diff --git a/intern.h b/intern.h -index a87661d..e8f3209 100644 ---- a/intern.h -+++ b/intern.h -@@ -274,6 +274,7 @@ void rb_gc_before_fork _((void)); - void rb_gc_after_fork _((void)); - VALUE rb_gc_allocated_size _((void)); - VALUE rb_gc_num_allocations _((void)); -+VALUE rb_gc_heap_slots _((void)); - unsigned long rb_os_live_objects _((void)); - #ifdef HAVE_LONG_LONG - unsigned LONG_LONG rb_os_allocated_objects _((void)); diff --git a/patches/ruby/1.8.7/p370/railsexpress/12-fix-heap-size-growth-logic.patch b/patches/ruby/1.8.7/p370/railsexpress/12-fix-heap-size-growth-logic.patch deleted file mode 100644 index 1db93f224d..0000000000 --- a/patches/ruby/1.8.7/p370/railsexpress/12-fix-heap-size-growth-logic.patch +++ /dev/null @@ -1,54 +0,0 @@ -diff --git a/gc.c b/gc.c -index 21b3f6b..7db1ef6 100644 ---- a/gc.c -+++ b/gc.c -@@ -694,6 +694,7 @@ static int heap_size = 0; - - static int heap_free_min = 4096; - static int heap_slots_increment = 10000; -+static int initial_heap_slots_increment = 10000; - static double heap_slots_growth_factor = 1.8; - - static long initial_malloc_limit = GC_MALLOC_LIMIT; -@@ -771,14 +772,13 @@ static void set_gc_parameters() - if (verbose_gc_stats) { - fprintf(gc_data_file, "RUBY_HEAP_SLOTS_INCREMENT=%s\n", heap_slots_incr_ptr); - } -- if (heap_slots_incr_i > 0) { -- heap_slots_increment = heap_slots_incr_i; -- } -+ heap_slots_increment = heap_slots_incr_i; -+ initial_heap_slots_increment = heap_slots_increment; - } - - heap_slots_growth_factor_ptr = getenv("RUBY_HEAP_SLOTS_GROWTH_FACTOR"); - if (heap_slots_growth_factor_ptr != NULL) { -- double heap_slots_growth_factor_d = atoi(heap_slots_growth_factor_ptr); -+ double heap_slots_growth_factor_d = atof(heap_slots_growth_factor_ptr); - if (verbose_gc_stats) { - fprintf(gc_data_file, "RUBY_HEAP_SLOTS_GROWTH_FACTOR=%s\n", heap_slots_growth_factor_ptr); - } -@@ -988,8 +988,13 @@ add_heap() - if (lomem == 0 || lomem > p) lomem = p; - if (himem < pend) himem = pend; - heaps_used++; -- heap_slots += heap_slots_increment; -- heap_slots_increment *= heap_slots_growth_factor; -+ if (heaps_used == 1) -+ heap_slots = initial_heap_slots_increment; -+ else { -+ heap_slots_increment *= heap_slots_growth_factor; -+ heap_slots += heap_slots_increment; -+ } -+ - if (heap_slots <= 0) heap_slots = heap_min_slots; - - while (p < pend) { -@@ -1879,6 +1884,7 @@ gc_sweep() - live_counts[i], free_counts[i], obj_type(i)); - } - } -+ rb_gc_dump(); - fflush(gc_data_file); - } - diff --git a/patches/ruby/1.8.7/p370/railsexpress/13-heap-slot-size.patch b/patches/ruby/1.8.7/p370/railsexpress/13-heap-slot-size.patch deleted file mode 100644 index 45091c14ae..0000000000 --- a/patches/ruby/1.8.7/p370/railsexpress/13-heap-slot-size.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/gc.c b/gc.c -index 7db1ef6..57740d2 100644 ---- a/gc.c -+++ b/gc.c -@@ -2891,6 +2891,7 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); - rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); - rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); - rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); - rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); - rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); diff --git a/patches/ruby/1.8.7/p370/railsexpress/14-add-trace-stats-enabled-methods.patch b/patches/ruby/1.8.7/p370/railsexpress/14-add-trace-stats-enabled-methods.patch deleted file mode 100644 index 4e3c4f2132..0000000000 --- a/patches/ruby/1.8.7/p370/railsexpress/14-add-trace-stats-enabled-methods.patch +++ /dev/null @@ -1,66 +0,0 @@ -diff --git a/gc.c b/gc.c -index 57740d2..2c34932 100644 ---- a/gc.c -+++ b/gc.c -@@ -350,6 +350,22 @@ rb_gc_disable_stats() - - /* - * call-seq: -+ * GC.stats_enabled? => true or false -+ * -+ * Check whether GC stats have been enabled. -+ * -+ * GC.stats_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_stats_enabled() -+{ -+ return gc_statistics ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: - * GC.clear_stats => nil - * - * Clears garbage collection statistics, returning nil. This resets the number -@@ -491,6 +507,22 @@ rb_gc_disable_trace() - return old; - } - -+/* -+ * call-seq: -+ * GC.trace_enabled? => true or false -+ * -+ * Check whether GC tracing has been enabled. -+ * -+ * GC.trace_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_trace_enabled() -+{ -+ return verbose_gc_stats ? Qtrue : Qfalse; -+} -+ - char* GC_LOGFILE_IVAR = "@gc_logfile_name"; - - /* -@@ -2887,6 +2919,7 @@ Init_GC() - - rb_define_singleton_method(rb_mGC, "enable_stats", rb_gc_enable_stats, 0); - rb_define_singleton_method(rb_mGC, "disable_stats", rb_gc_disable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "stats_enabled?", rb_gc_stats_enabled, 0); - rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0); - rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); - rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); -@@ -2902,6 +2935,7 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "log_file", rb_gc_log_file, -1); - rb_define_singleton_method(rb_mGC, "enable_trace", rb_gc_enable_trace, 0); - rb_define_singleton_method(rb_mGC, "disable_trace", rb_gc_disable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "trace_enabled?", rb_gc_trace_enabled, 0); - - rb_mObSpace = rb_define_module("ObjectSpace"); - rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1); diff --git a/patches/ruby/1.8.7/p370/railsexpress/15-track-live-dataset-size.patch b/patches/ruby/1.8.7/p370/railsexpress/15-track-live-dataset-size.patch deleted file mode 100644 index de44e6b365..0000000000 --- a/patches/ruby/1.8.7/p370/railsexpress/15-track-live-dataset-size.patch +++ /dev/null @@ -1,52 +0,0 @@ -diff --git a/gc.c b/gc.c -index 2c34932..0ce7e68 100644 ---- a/gc.c -+++ b/gc.c -@@ -89,6 +89,7 @@ static unsigned long gc_num_allocations = 0; - #endif - static int gc_statistics = 0; - -+static unsigned long heap_slots_live_after_last_gc = 0; - - static void run_final(); - static VALUE nomem_error; -@@ -465,6 +466,23 @@ rb_gc_time() - #endif - } - -+/* -+ * call-seq: -+ * GC.heap_slots_live_after_last_gc => Integer -+ * -+ * Returns the number of heap slots which were live after the last garbage collection. -+ * -+ * GC.heap_slots_live_after_last_gc #=> 231223 -+ * -+ */ -+VALUE -+rb_gc_heap_slots_live_after_last_gc() -+{ -+ return ULONG2NUM(heap_slots_live_after_last_gc); -+} -+ -+ -+ - VALUE rb_mGC; - - /* -@@ -1903,6 +1921,7 @@ gc_sweep() - } - during_gc = 0; - live_objects = live; -+ heap_slots_live_after_last_gc = live; - - if (do_gc_stats) { - fprintf(gc_data_file, "objects processed: %.7d\n", live+freed); -@@ -2924,6 +2943,7 @@ Init_GC() - rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); - rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); - rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots_live_after_last_gc", rb_gc_heap_slots_live_after_last_gc, 0); - rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); - rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); - rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); diff --git a/patches/ruby/1.8.7/p370/railsexpress/16-add-object-size-information-to-heap-dump.patch b/patches/ruby/1.8.7/p370/railsexpress/16-add-object-size-information-to-heap-dump.patch deleted file mode 100644 index e974cdb63a..0000000000 --- a/patches/ruby/1.8.7/p370/railsexpress/16-add-object-size-information-to-heap-dump.patch +++ /dev/null @@ -1,51 +0,0 @@ -diff --git a/gc.c b/gc.c -index 0ce7e68..53450bf 100644 ---- a/gc.c -+++ b/gc.c -@@ -953,9 +953,21 @@ rb_gc_dump_file_and_line_info(int argc, VALUE *argv) - if (!p->as.basic.klass) { - fprintf(f, "__unknown__"); - } else { -- fprintf(f, rb_obj_classname((VALUE)p)); -+ fprintf(f, "%s", rb_obj_classname((VALUE)p)); - } - } -+ /* print object size for some known object types */ -+ switch (TYPE(p)) { -+ case T_STRING: -+ fprintf(f, ":%lu", RSTRING(p)->len); -+ break; -+ case T_ARRAY: -+ fprintf(f, ":%lu", RARRAY(p)->len); -+ break; -+ case T_HASH: -+ fprintf(f, ":%d", RHASH(p)->tbl->num_entries); -+ break; -+ } - } - fprintf(f, "\n"); - } -@@ -1924,10 +1936,10 @@ gc_sweep() - heap_slots_live_after_last_gc = live; - - if (do_gc_stats) { -- fprintf(gc_data_file, "objects processed: %.7d\n", live+freed); -- fprintf(gc_data_file, "live objects : %.7d\n", live); -- fprintf(gc_data_file, "freelist objects : %.7d\n", freed - really_freed); -- fprintf(gc_data_file, "freed objects : %.7d\n", really_freed); -+ fprintf(gc_data_file, "objects processed: %.7lu\n", live+freed); -+ fprintf(gc_data_file, "live objects : %.7lu\n", live); -+ fprintf(gc_data_file, "freelist objects : %.7lu\n", freed - really_freed); -+ fprintf(gc_data_file, "freed objects : %.7lu\n", really_freed); - for(i=0; i<256; i++) { - if (free_counts[i]>0 || live_counts[i]>0) { - fprintf(gc_data_file, -@@ -2258,7 +2270,7 @@ garbage_collect() - gc_time += musecs_used; - - if (verbose_gc_stats) { -- fprintf(gc_data_file, "GC time: %d msec\n", musecs_used / 1000); -+ fprintf(gc_data_file, "GC time: %ld msec\n", (long)(musecs_used / 1000)); - fflush(gc_data_file); - } - } diff --git a/patches/ruby/1.8.7/p370/railsexpress/17-caller-for-all-threads.patch b/patches/ruby/1.8.7/p370/railsexpress/17-caller-for-all-threads.patch deleted file mode 100644 index 74f99fce0b..0000000000 --- a/patches/ruby/1.8.7/p370/railsexpress/17-caller-for-all-threads.patch +++ /dev/null @@ -1,229 +0,0 @@ -diff --git a/eval.c b/eval.c -index c37136f..55fe096 100644 ---- a/eval.c -+++ b/eval.c -@@ -8209,6 +8209,17 @@ rb_f_method_name() - } - } - -+/* Hash (Thread => Backtrace) used to collect backtrace for each threads. */ -+static VALUE backtrace_for_each_thread; -+ -+static int backtrace_level_for_each_thread; -+ -+static VALUE -+switch_thread_context_to_collect_backtrace(rb_thread_t next); -+ -+static VALUE -+rb_f_caller_for_all_threads(); -+ - void - Init_eval() - { -@@ -8254,6 +8265,7 @@ Init_eval() - rb_define_global_function("fail", rb_f_raise, -1); - - rb_define_global_function("caller", rb_f_caller, -1); -+ rb_define_global_function("caller_for_all_threads", rb_f_caller_for_all_threads, -1); - - rb_define_global_function("exit", rb_f_exit, -1); - rb_define_global_function("abort", rb_f_abort, -1); -@@ -10609,6 +10621,7 @@ static int th_sig, th_safe; - #define RESTORE_RAISE 5 - #define RESTORE_SIGNAL 6 - #define RESTORE_EXIT 7 -+#define RESTORE_BACKTRACE 8 - - extern VALUE *rb_gc_stack_start; - #ifdef __ia64 -@@ -10715,6 +10728,15 @@ rb_thread_switch(n) - } - rb_exc_raise(th_raise_exception); - break; -+ case RESTORE_BACKTRACE: -+ rb_hash_aset(backtrace_for_each_thread, curr_thread->thread, -+ backtrace(backtrace_level_for_each_thread)); -+ if (curr_thread != main_thread) { -+ switch_thread_context_to_collect_backtrace(curr_thread->next); -+ } else { -+ /* Circled back to main thread, cycle is complete. */ -+ } -+ break; - case RESTORE_NORMAL: - default: - break; -@@ -13897,3 +13919,74 @@ rb_throw(tag, val) - argv[1] = val; - rb_f_throw(2, argv); - } -+ -+static VALUE -+switch_thread_context_to_collect_backtrace(rb_thread_t next) -+{ -+ if (THREAD_SAVE_CONTEXT(curr_thread)) { -+ return Qnil; -+ } -+ curr_thread = next; -+ rb_thread_restore_context(next, RESTORE_BACKTRACE); -+ return Qnil; -+} -+ -+ -+/* -+ * call-seq: -+ * caller_for_all_threads(start=1) => array -+ * -+ * Returns the current execution stack for all threads -+ * ---a hash whose keys are thread instances and values -+ * the thread caller backtrace. -+ * -+ * Backtraces are array of hashes indicating location on the -+ * stack. Hash keys include ``:line'' or ``:file'' -+ * and ``:method'''. -+ * -+ * The optional _start_ parameter -+ * determines the number of initial stack entries to omit from the -+ * result. -+ * -+ * def a(skip) -+ * caller_for_all_threads(skip) -+ * end -+ * def b(skip) -+ * a(skip) -+ * end -+ * def c(skip) -+ * b(skip) -+ * end -+ * c(0) #=> ["prog:2:in `a'", "prog:5:in `b'", "prog:8:in `c'", "prog:10"] -+ * c(1) #=> ["prog:5:in `b'", "prog:8:in `c'", "prog:11"] -+ * c(2) #=> ["prog:8:in `c'", "prog:12"] -+ * c(3) #=> ["prog:13"] -+ */ -+static VALUE -+rb_f_caller_for_all_threads(argc, argv) -+ int argc; -+ VALUE *argv; -+{ -+ volatile int critical; -+ VALUE level; -+ VALUE result; -+ -+ rb_scan_args(argc, argv, "01", &level); -+ backtrace_level_for_each_thread = NIL_P(level) ? 0 : NUM2INT(level); -+ if (backtrace_level_for_each_thread < 0) { -+ rb_raise(rb_eArgError, "negative level (%d)", backtrace_level_for_each_thread); -+ } -+ -+ critical = rb_thread_critical; -+ rb_thread_critical = Qtrue; -+ -+ backtrace_for_each_thread = rb_hash_new(); -+ switch_thread_context_to_collect_backtrace(main_thread->next); -+ -+ result = backtrace_for_each_thread; -+ backtrace_for_each_thread = Qnil; -+ backtrace_for_each_thread = 0; -+ -+ rb_thread_critical = critical; -+ return result; -+} -diff --git a/test/callerforallthreads/test_caller_for_each_thread.rb b/test/callerforallthreads/test_caller_for_each_thread.rb -new file mode 100644 -index 0000000..abffd8e ---- /dev/null -+++ b/test/callerforallthreads/test_caller_for_each_thread.rb -@@ -0,0 +1,94 @@ -+# -*- ruby-indent-level: 4 -*- -+require 'thread' -+require 'test/unit' -+ -+class AClassWithNestedmethods -+ -+ def an_ultra_nested_method(skip) -+ caller_for_all_threads skip -+ end -+ -+ def a_nested_method(skip) -+ an_ultra_nested_method skip -+ end -+ -+ def a_method(skip=0) -+ a_nested_method skip -+ end -+ -+end -+ -+class CallerForEachThreadTest < Test::Unit::TestCase -+ -+ def testCollectMeaningfulBacktraceForASingleThread -+ backtraces = AClassWithNestedmethods.new.a_method -+ backtrace = backtraces[Thread.current] -+ assert_not_nil backtrace -+ assert_equal __FILE__ + ":8:in `an_ultra_nested_method'", backtrace[0] -+ assert_equal __FILE__ + ":12:in `a_nested_method'", backtrace[1] -+ assert_equal __FILE__ + ":16:in `a_method'", backtrace[2] -+ assert_equal __FILE__ + ":24:in `testCollectMeaningfulBacktraceForASingleThread'", -+ backtrace[3] -+ end -+ -+ def testCanSkipFirstStackEntries -+ backtraces = AClassWithNestedmethods.new.a_method 2 -+ backtrace = backtraces[Thread.current] -+ assert_not_nil backtrace -+ assert_equal __FILE__ + ":16:in `a_method'", backtrace[0] -+ assert_equal __FILE__ + ":35:in `testCanSkipFirstStackEntries'", -+ backtrace[1] -+ end -+ -+ def testCollectMeaningfulBacktraceForMultipleThreads -+ first_thread = Thread.new do -+ loop do -+ Thread.pass -+ sleep 1 -+ end -+ end -+ -+ second_thread = Thread.new do -+ loop do -+ Thread.pass -+ sleep 1 -+ end -+ end -+ -+ backtraces = AClassWithNestedmethods.new.a_method -+ -+ backtrace = backtraces[Thread.current] -+ assert_not_nil backtrace -+ assert_match __FILE__ + ":8:in `an_ultra_nested_method'", backtrace[0] -+ assert_match __FILE__ + ":12:in `a_nested_method'", backtrace[1] -+ assert_equal __FILE__ + ":16:in `a_method'", backtrace[2] -+ assert_equal __FILE__ + ":58:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[3] -+ -+ backtrace = backtraces[first_thread] -+ assert_not_nil backtrace -+ assert_equal __FILE__ + ":47:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[0] -+ assert_equal __FILE__ + ":45:in `loop'", -+ backtrace[1] -+ assert_equal __FILE__ + ":45:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[2] -+ assert_equal __FILE__ + ":44:in `initialize'",backtrace[3] -+ assert_equal __FILE__ + ":44:in `new'", backtrace[4] -+ assert_equal __FILE__ + ":44:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[5] -+ -+ backtrace = backtraces[second_thread] -+ assert_not_nil backtrace -+ assert_equal __FILE__ + ":53:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[0] -+ assert_equal __FILE__ + ":52:in `loop'", backtrace[1] -+ assert_equal __FILE__ + ":52:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[2] -+ assert_equal __FILE__ + ":51:in `initialize'",backtrace[3] -+ assert_equal __FILE__ + ":51:in `new'", backtrace[4] -+ assert_equal __FILE__ + ":51:in `testCollectMeaningfulBacktraceForMultipleThreads'", -+ backtrace[5] -+ end -+ -+end diff --git a/patches/ruby/1.8.7/p370/railsexpress/18-fix-zlib-deflate.patch b/patches/ruby/1.8.7/p370/railsexpress/18-fix-zlib-deflate.patch deleted file mode 100644 index d83bf0e12e..0000000000 --- a/patches/ruby/1.8.7/p370/railsexpress/18-fix-zlib-deflate.patch +++ /dev/null @@ -1,26 +0,0 @@ -diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c -index 98141b2..da9ef72 100644 ---- a/ext/zlib/zlib.c -+++ b/ext/zlib/zlib.c -@@ -1374,16 +1374,20 @@ rb_deflate_params(obj, v_level, v_strategy) - struct zstream *z = get_zstream(obj); - int level, strategy; - int err; -+ uInt n; - - level = ARG_LEVEL(v_level); - strategy = ARG_STRATEGY(v_strategy); - -- zstream_run(z, (Bytef*)"", 0, Z_SYNC_FLUSH); -+ n = z->stream.avail_out; - err = deflateParams(&z->stream, level, strategy); -+ z->buf_filled += n - z->stream.avail_out; - while (err == Z_BUF_ERROR) { - rb_warning("deflateParams() returned Z_BUF_ERROR"); - zstream_expand_buffer(z); -+ n = z->stream.avail_out; - err = deflateParams(&z->stream, level, strategy); -+ z->buf_filled += n - z->stream.avail_out; - } - if (err != Z_OK) { - raise_zlib_error(err, z->stream.msg); diff --git a/patches/ruby/1.8.7/p370/railsexpress/19-fix-broken-seek-on-osx.patch b/patches/ruby/1.8.7/p370/railsexpress/19-fix-broken-seek-on-osx.patch deleted file mode 100644 index 1a6d28af0d..0000000000 --- a/patches/ruby/1.8.7/p370/railsexpress/19-fix-broken-seek-on-osx.patch +++ /dev/null @@ -1,29 +0,0 @@ -diff --git a/io.c b/io.c -index 00a1820..70382a0 100644 ---- a/io.c -+++ b/io.c -@@ -1300,8 +1300,23 @@ io_getpartial(int argc, VALUE *argv, VALUE io, int nonblock) - goto again; - rb_sys_fail(fptr->path); - } -- if (fptr->f) /* update pos in FILE structure [ruby-core:21561] */ -+ if (fptr->f) /* update pos in FILE structure [ruby-core:21561] */ { -+#ifndef __APPLE__ - fflush(fptr->f); -+#else -+ /* fptr could be a pipe, causing seek to fail */ -+ off_t a = lseek(fileno(fptr->f), 0, SEEK_CUR); -+ if (a >= 0) { -+ off_t b = ftello(fptr->f); -+ if (b >= 0 && a != b) { -+ int rc = fseeko(fptr->f, a, SEEK_SET); -+ if (rc < 0) rb_sys_fail(fptr->path); -+ } -+ } -+ clearerr(fptr->f); -+ errno = 0; -+#endif -+ } - } - rb_str_resize(str, n); - diff --git a/patches/ruby/1.9.2/p180/railsexpress/01-railsbench-gc-patch.patch b/patches/ruby/1.9.2/p180/railsexpress/01-railsbench-gc-patch.patch deleted file mode 100644 index 52ba5a1323..0000000000 --- a/patches/ruby/1.9.2/p180/railsexpress/01-railsbench-gc-patch.patch +++ /dev/null @@ -1,1081 +0,0 @@ -diff --git a/configure.in b/configure.in -index 7fba909..b53e1ea 100644 ---- a/configure.in -+++ b/configure.in -@@ -2207,6 +2207,14 @@ if test "$EXEEXT" = .exe; then - AC_SUBST(EXECUTABLE_EXTS) - fi - -+dnl enable gc debugging -+AC_ARG_ENABLE(gcdebug, -+ [ --enable-gcdebug build garbage collector with debugging enabled. ], -+ [enable_gcdebug=$enableval]) -+if test "$enable_gcdebug" = 'yes'; then -+ AC_DEFINE(GC_DEBUG, 1) -+fi -+ - dnl } - dnl build section { - -diff --git a/gc.c b/gc.c -index 564d260..27d9177 100644 ---- a/gc.c -+++ b/gc.c -@@ -78,6 +78,17 @@ void *alloca (); - #define GC_MALLOC_LIMIT 8000000 - #endif - -+#ifndef HAVE_LONG_LONG -+#define LONG_LONG long -+#endif -+ -+static size_t heap_free_min = 4096; -+static int heap_min_slots = 10000; -+static int heap_slots_increment = 10000; -+static int initial_heap_slots_increment = 10000; -+static double heap_slots_growth_factor = 1.8; -+static size_t initial_malloc_limit = GC_MALLOC_LIMIT; -+ - #define nomem_error GET_VM()->special_exceptions[ruby_error_nomemory] - - #define MARK_STACK_MAX 1024 -@@ -267,7 +278,7 @@ typedef struct RVALUE { - struct RComplex complex; - } as; - #ifdef GC_DEBUG -- const char *file; -+ VALUE file; - int line; - #endif - } RVALUE; -@@ -314,6 +325,8 @@ typedef struct rb_objspace { - struct { - int dont_gc; - int during_gc; -+ int gc_statistics; -+ int verbose_gc_stats; - } flags; - struct { - st_table *table; -@@ -334,6 +347,14 @@ typedef struct rb_objspace { - struct gc_list *global_list; - unsigned int count; - int gc_stress; -+ long heap_size; -+ unsigned LONG_LONG gc_time_accumulator; -+ FILE* gc_data_file; -+ long gc_collections; -+ unsigned LONG_LONG gc_allocated_size; -+ unsigned LONG_LONG gc_num_allocations; -+ unsigned long live_objects; -+ unsigned LONG_LONG allocated_objects; - } rb_objspace_t; - - #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE -@@ -357,6 +378,16 @@ int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress; - #define heaps_freed objspace->heap.freed - #define dont_gc objspace->flags.dont_gc - #define during_gc objspace->flags.during_gc -+#define gc_statistics objspace->flags.gc_statistics -+#define verbose_gc_stats objspace->flags.verbose_gc_stats -+#define heap_size objspace->heap_size -+#define gc_time_accumulator objspace->gc_time_accumulator -+#define gc_data_file objspace->gc_data_file -+#define gc_collections objspace->gc_collections -+#define gc_allocated_size objspace->gc_allocated_size -+#define gc_num_allocations objspace->gc_num_allocations -+#define live_objects objspace->live_objects -+#define allocated_objects objspace->allocated_objects - #define finalizer_table objspace->final.table - #define deferred_final_list objspace->final.deferred - #define mark_stack objspace->markstack.buffer -@@ -375,7 +406,8 @@ rb_objspace_alloc(void) - { - rb_objspace_t *objspace = malloc(sizeof(rb_objspace_t)); - memset(objspace, 0, sizeof(*objspace)); -- malloc_limit = GC_MALLOC_LIMIT; -+ malloc_limit = initial_malloc_limit; -+ - ruby_gc_stress = ruby_initial_gc_stress; - - return objspace; -@@ -409,23 +441,8 @@ rb_objspace_free(rb_objspace_t *objspace) - } - #endif - --/* tiny heap size */ --/* 32KB */ --/*#define HEAP_SIZE 0x8000 */ --/* 128KB */ --/*#define HEAP_SIZE 0x20000 */ --/* 64KB */ --/*#define HEAP_SIZE 0x10000 */ --/* 16KB */ --#define HEAP_SIZE 0x4000 --/* 8KB */ --/*#define HEAP_SIZE 0x2000 */ --/* 4KB */ --/*#define HEAP_SIZE 0x1000 */ --/* 2KB */ --/*#define HEAP_SIZE 0x800 */ -- --#define HEAP_OBJ_LIMIT (HEAP_SIZE / sizeof(struct RVALUE)) -+#define HEAP_OBJ_LIMIT 8000 -+#define HEAP_SIZE (HEAP_OBJ_LIMIT * sizeof(struct RVALUE)) - - extern VALUE rb_cMutex; - extern st_table *rb_class_tbl; -@@ -673,6 +690,11 @@ vm_xmalloc(rb_objspace_t *objspace, size_t size) - mem = (size_t *)mem + 1; - #endif - -+ if (gc_statistics) { -+ gc_allocated_size += size; -+ gc_num_allocations += 1; -+ } -+ - return mem; - } - -@@ -780,6 +802,92 @@ ruby_xfree(void *x) - vm_xfree(&rb_objspace, x); - } - -+static void set_gc_parameters(rb_objspace_t *objspace) -+{ -+ char *envp; -+ -+ gc_data_file = stderr; -+ -+ envp = getenv("RUBY_GC_STATS"); -+ if (envp != NULL) { -+ int i = atoi(envp); -+ if (i > 0) { -+ verbose_gc_stats = 1; -+ } -+ /* child processes should not inherit RUBY_GC_STATS */ -+ ruby_unsetenv("RUBY_GC_STATS"); -+ } -+ -+ envp = getenv("RUBY_GC_DATA_FILE"); -+ if (envp != NULL) { -+ FILE* data_file = fopen(envp, "w"); -+ if (data_file != NULL) { -+ gc_data_file = data_file; -+ } -+ else { -+ fprintf(stderr, "can't open gc log file %s for writing, using default\n", envp); -+ } -+ /* child processes should not inherit RUBY_GC_DATA_FILE to avoid clobbering */ -+ ruby_unsetenv("RUBY_GC_DATA_FILE"); -+ } -+ -+ envp = getenv("RUBY_HEAP_MIN_SLOTS"); -+ if (envp != NULL) { -+ int i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_MIN_SLOTS=%s\n", envp); -+ } -+ if (i > 0) { -+ heap_min_slots = i; -+ } -+ } -+ -+ envp = getenv("RUBY_HEAP_FREE_MIN"); -+ if (envp != NULL) { -+ int i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_FREE_MIN=%s\n", envp); -+ } -+ if (i > 0) { -+ heap_free_min = i; -+ } -+ } -+ -+ envp = getenv("RUBY_HEAP_SLOTS_INCREMENT"); -+ if (envp != NULL) { -+ int i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_INCREMENT=%s\n", envp); -+ } -+ heap_slots_increment = i; -+ initial_heap_slots_increment = heap_slots_increment; -+ } -+ -+ envp = getenv("RUBY_HEAP_SLOTS_GROWTH_FACTOR"); -+ if (envp != NULL) { -+ double d = atof(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_GROWTH_FACTOR=%s\n", envp); -+ } -+ if (d > 0) { -+ heap_slots_growth_factor = d; -+ } -+ } -+ -+ envp = getenv("RUBY_GC_MALLOC_LIMIT"); -+ if (envp != NULL) { -+ long l = atol(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_GC_MALLOC_LIMIT=%s\n", envp); -+ } -+ if (l > 0) { -+ initial_malloc_limit = l; -+ malloc_limit = initial_malloc_limit; -+ } -+ } -+ -+ fflush(gc_data_file); -+} - - /* - * call-seq: -@@ -826,6 +934,454 @@ rb_gc_disable(void) - return old ? Qtrue : Qfalse; - } - -+/* -+ * call-seq: -+ * GC.enable_stats => true or false -+ * -+ * Enables garbage collection statistics, returning true if garbage -+ * collection statistics was already enabled. -+ * -+ * GC.enable_stats #=> false or true -+ * GC.enable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = gc_statistics; -+ gc_statistics = 1; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_stats => true or false -+ * -+ * Disables garbage collection statistics, returning true if garbage -+ * collection statistics was already disabled. -+ * -+ * GC.disable_stats #=> false or true -+ * GC.disable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = gc_statistics; -+ gc_statistics = 0; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.stats_enabled? => true or false -+ * -+ * Check whether GC stats have been enabled. -+ * -+ * GC.stats_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_stats_enabled() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return gc_statistics ? Qtrue : Qfalse; -+} -+ -+ -+/* -+ * call-seq: -+ * GC.clear_stats => nil -+ * -+ * Clears garbage collection statistics, returning nil. This resets the number -+ * of collections (GC.collections) and the time used (GC.time) to 0. -+ * -+ * GC.clear_stats #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_clear_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ gc_collections = 0; -+ gc_time_accumulator = 0; -+ gc_allocated_size = 0; -+ gc_num_allocations = 0; -+ return Qnil; -+} -+ -+/* -+ * call-seq: -+ * GC.allocated_size => Integer -+ * -+ * Returns the size of memory (in bytes) allocated since GC statistics collection -+ * was enabled. -+ * -+ * GC.allocated_size #=> 35 -+ * -+ */ -+ -+VALUE -+rb_gc_allocated_size() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_allocated_size); -+#else -+ return ULONG2NUM(gc_allocated_size); -+#endif -+} -+ -+/* -+ * call-seq: -+ * GC.num_allocations => Integer -+ * -+ * Returns the number of memory allocations since GC statistics collection -+ * was enabled. -+ * -+ * GC.num_allocations #=> 150 -+ * -+ */ -+VALUE -+rb_gc_num_allocations() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_num_allocations); -+#else -+ return ULONG2NUM(gc_num_allocations); -+#endif -+} -+ -+/* -+ * call-seq: -+ * GC.enable_trace => true or false -+ * -+ * Enables garbage collection tracing, returning true if garbage -+ * collection tracing was already enabled. -+ * -+ * GC.enable_trace #=> false or true -+ * GC.enable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_trace() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = verbose_gc_stats; -+ verbose_gc_stats = 1; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_trace => true or false -+ * -+ * Disables garbage collection tracing, returning true if garbage -+ * collection tracing was already disabled. -+ * -+ * GC.disable_trace #=> false or true -+ * GC.disable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_trace() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = verbose_gc_stats; -+ verbose_gc_stats = 0; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.trace_enabled? => true or false -+ * -+ * Check whether GC tracing has been enabled. -+ * -+ * GC.trace_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_trace_enabled() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return verbose_gc_stats ? Qtrue : Qfalse; -+} -+ -+ -+const char* GC_LOGFILE_IVAR = "@gc_logfile_name"; -+ -+/* -+ * call-seq: -+ * GC.log_file(filename=nil, mode="w") => boolean -+ * -+ * Changes the GC data log file. Closes the currently open logfile. -+ * Returns true if the file was successfully opened for -+ * writing. Returns false if the file could not be opened for -+ * writing. Returns the name of the current logfile (or nil) if no -+ * parameter is given. Restores logging to stderr when given nil as -+ * an argument. -+ * -+ * GC.log_file #=> nil -+ * GC.log_file "/tmp/gc.log" #=> true -+ * GC.log_file #=> "/tmp/gc.log" -+ * GC.log_file nil #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_log_file(int argc, VALUE *argv, VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ VALUE filename = Qnil; -+ VALUE mode_str = Qnil; -+ FILE* f = NULL; -+ const char* mode = "w"; -+ -+ VALUE current_logfile_name = rb_iv_get(rb_mGC, GC_LOGFILE_IVAR); -+ -+ if (argc==0) -+ return current_logfile_name; -+ -+ rb_scan_args(argc, argv, "02", &filename, &mode_str); -+ -+ if (filename == Qnil) { -+ /* close current logfile and reset logfile to stderr */ -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+ } -+ return Qtrue; -+ } -+ -+ /* we have a real logfile name */ -+ filename = StringValue(filename); -+ -+ if (rb_equal(current_logfile_name, filename) == Qtrue) { -+ /* do nothing if we get the file name we're already logging to */ -+ return Qtrue; -+ } -+ -+ /* get mode for file opening */ -+ if (mode_str != Qnil) -+ { -+ mode = RSTRING_PTR(StringValue(mode_str)); -+ } -+ -+ /* try to open file in given mode */ -+ if (f = fopen(RSTRING_PTR(filename), mode)) { -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ } -+ gc_data_file = f; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, filename); -+ } else { -+ return Qfalse; -+ } -+ return Qtrue; -+} -+ -+/* -+ * call-seq: -+ * GC.log String => String -+ * -+ * Logs string to the GC data file and returns it. -+ * -+ * GC.log "manual GC call" #=> "manual GC call" -+ * -+ */ -+ -+VALUE -+rb_gc_log(self, original_str) -+ VALUE self, original_str; -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ if (original_str == Qnil) { -+ fprintf(gc_data_file, "\n"); -+ } -+ else { -+ VALUE str = StringValue(original_str); -+ char *p = RSTRING_PTR(str); -+ fprintf(gc_data_file, "%s\n", p); -+ } -+ return original_str; -+} -+ -+/* -+ * call-seq: -+ * GC.dump => nil -+ * -+ * dumps information about the current GC data structures to the GC log file -+ * -+ * GC.dump #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_dump() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ size_t i; -+ -+ for (i = 0; i < heaps_used; i++) { -+ size_t limit = heaps[i].limit; -+ fprintf(gc_data_file, "HEAP[%2lu]: size=%7lu\n", (unsigned long)i, (unsigned long)limit); -+ } -+ -+ return Qnil; -+} -+ -+static const char* obj_type(VALUE tp); -+ -+#ifdef GC_DEBUG -+/* -+ * call-seq: -+ * GC.dump_file_and_line_info(String, boolean) => nil -+ * -+ * dumps information on which currently allocated object was created by which file and on which line -+ * -+ * GC.dump_file_and_line_info(String, boolean) #=> nil -+ * -+ * The second parameter specifies whether class names should be included in the dump. -+ * Note that including class names will allocate additional string objects on the heap. -+ * -+ */ -+ -+VALUE -+rb_gc_dump_file_and_line_info(int argc, VALUE *argv) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ VALUE filename, str, include_classnames = Qnil; -+ char *fname = NULL; -+ char *klass = NULL; -+ FILE* f = NULL; -+ size_t i = 0; -+ -+ rb_scan_args(argc, argv, "11", &filename, &include_classnames); -+ -+ str = StringValue(filename); -+ fname = RSTRING_PTR(str); -+ f = fopen(fname, "w"); -+ -+ for (i = 0; i < heaps_used; i++) { -+ RVALUE *p, *pend; -+ -+ p = heaps[i].slot; pend = p + heaps[i].limit; -+ for (;p < pend; p++) { -+ if (p->as.basic.flags) { -+ const char *src_filename = (p->file && p->file != Qnil )? RSTRING_PTR(p->file) : ""; -+ fprintf(f, "%s:%s:%d", obj_type(p->as.basic.flags & T_MASK), src_filename, (int)p->line); -+ // rb_obj_classname will create objects on the heap, we need a better solution -+ if (include_classnames == Qtrue) { -+ /* write the class */ -+ fprintf(f, ":"); -+ switch (BUILTIN_TYPE(p)) { -+ case T_NONE: -+ fprintf(f, "__none__"); -+ break; -+ case T_UNDEF: -+ fprintf(f, "__undef__"); -+ break; -+ case T_NODE: -+ fprintf(f, "__node__"); -+ break; -+ default: -+ if (!p->as.basic.klass) { -+ fprintf(f, "__unknown__"); -+ } else { -+ fprintf(f, "%s", rb_obj_classname((VALUE)p)); -+ } -+ } -+ /* print object size for some known object types */ -+ switch (BUILTIN_TYPE(p)) { -+ case T_STRING: -+ fprintf(f, ":%lu", RSTRING_LEN(p)); -+ break; -+ case T_ARRAY: -+ fprintf(f, ":%lu", RARRAY_LEN(p)); -+ break; -+ case T_HASH: -+ fprintf(f, ":%lu", (long unsigned int)RHASH_SIZE(p)); -+ break; -+ } -+ } -+ fprintf(f, "\n"); -+ } -+ } -+ } -+ fclose(f); -+ return Qnil; -+} -+#endif -+ -+/* -+ * call-seq: -+ * GC.heap_slots => Integer -+ * -+ * Returns the number of heap slots available for object allocations. -+ * -+ * GC.heap_slots #=> 10000 -+ * -+ */ -+VALUE -+rb_gc_heap_slots() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return LONG2NUM(heap_size); -+} -+ -+ -+/* -+ * call-seq: -+ * GC.collections => Integer -+ * -+ * Returns the number of garbage collections performed while GC statistics collection -+ * was enabled. -+ * -+ * GC.collections #=> 35 -+ * -+ */ -+ -+VALUE -+rb_gc_collections() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return LONG2NUM(gc_collections); -+} -+ -+/* -+ * call-seq: -+ * GC.time => Integer -+ * -+ * Returns the time spent during garbage collection while GC statistics collection -+ * was enabled (in micro seconds). -+ * -+ * GC.time #=> 20000 -+ * -+ */ -+ -+VALUE -+rb_gc_time() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return LL2NUM(gc_time_accumulator); -+#else -+ return LONG2NUM(gc_time_accumulator); -+#endif -+} -+ - VALUE rb_mGC; - - void -@@ -944,6 +1500,7 @@ assign_heap_slot(rb_objspace_t *objspace) - if (lomem == 0 || lomem > p) lomem = p; - if (himem < pend) himem = pend; - heaps_used++; -+ heap_size += objs; - - while (p < pend) { - p->as.free.flags = 0; -@@ -958,7 +1515,7 @@ init_heap(rb_objspace_t *objspace) - { - size_t add, i; - -- add = HEAP_MIN_SLOTS / HEAP_OBJ_LIMIT; -+ add = heap_min_slots / HEAP_OBJ_LIMIT; - - if (!add) { - add = 1; -@@ -979,7 +1536,7 @@ init_heap(rb_objspace_t *objspace) - static void - set_heaps_increment(rb_objspace_t *objspace) - { -- size_t next_heaps_length = (size_t)(heaps_used * 1.8); -+ size_t next_heaps_length = (size_t)(heaps_used * heap_slots_growth_factor); - - if (next_heaps_length == heaps_used) { - next_heaps_length++; -@@ -1005,6 +1562,22 @@ heaps_increment(rb_objspace_t *objspace) - - #define RANY(o) ((RVALUE*)(o)) - -+#ifdef GC_DEBUG -+static VALUE -+_rb_sourcefile(void) -+{ -+ rb_thread_t *th = GET_THREAD(); -+ rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp); -+ -+ if (cfp) { -+ return cfp->iseq->filename; -+ } -+ else { -+ return Qnil; -+ } -+} -+#endif -+ - static VALUE - rb_newobj_from_heap(rb_objspace_t *objspace) - { -@@ -1022,9 +1595,11 @@ rb_newobj_from_heap(rb_objspace_t *objspace) - - MEMZERO((void*)obj, RVALUE, 1); - #ifdef GC_DEBUG -- RANY(obj)->file = rb_sourcefile(); -+ RANY(obj)->file = _rb_sourcefile(); - RANY(obj)->line = rb_sourceline(); - #endif -+ live_objects++; -+ allocated_objects++; - - return obj; - } -@@ -1525,6 +2100,12 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev) - { - register RVALUE *obj = RANY(ptr); - -+#ifdef GC_DEBUG -+ if (obj->file && obj->file != Qnil && is_pointer_to_heap(objspace, (void*)obj->file)) { -+ gc_mark(objspace, obj->file, lev); -+ } -+#endif -+ - goto marking; /* skip */ - - again: -@@ -1534,6 +2115,12 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev) - if (obj->as.basic.flags & FL_MARK) return; /* already marked */ - obj->as.basic.flags |= FL_MARK; - -+#ifdef GC_DEBUG -+ if (obj->file && obj->file != Qnil && is_pointer_to_heap(objspace, (void*)obj->file)) { -+ gc_mark(objspace, obj->file, lev); -+ } -+#endif -+ - marking: - if (FL_TEST(obj, FL_EXIVAR)) { - rb_mark_generic_ivar(ptr); -@@ -1851,6 +2438,39 @@ free_unused_heaps(rb_objspace_t *objspace) - } - } - -+static const char* obj_type(VALUE type) -+{ -+ switch (type) { -+ case T_NIL : return "NIL"; -+ case T_OBJECT : return "OBJECT"; -+ case T_CLASS : return "CLASS"; -+ case T_ICLASS : return "ICLASS"; -+ case T_MODULE : return "MODULE"; -+ case T_FLOAT : return "FLOAT"; -+ case T_COMPLEX: return "COMPLEX"; -+ case T_RATIONAL: return "RATIONAL"; -+ case T_STRING : return "STRING"; -+ case T_REGEXP : return "REGEXP"; -+ case T_ARRAY : return "ARRAY"; -+ case T_FIXNUM : return "FIXNUM"; -+ case T_HASH : return "HASH"; -+ case T_STRUCT : return "STRUCT"; -+ case T_BIGNUM : return "BIGNUM"; -+ case T_FILE : return "FILE"; -+ -+ case T_TRUE : return "TRUE"; -+ case T_FALSE : return "FALSE"; -+ case T_DATA : return "DATA"; -+ case T_MATCH : return "MATCH"; -+ case T_SYMBOL : return "SYMBOL"; -+ case T_ZOMBIE : return "ZOMBIE"; -+ -+ case T_UNDEF : return "UNDEF"; -+ case T_NODE : return "NODE"; -+ default: return "____"; -+ } -+} -+ - static void - gc_sweep(rb_objspace_t *objspace) - { -@@ -1859,12 +2479,27 @@ gc_sweep(rb_objspace_t *objspace) - size_t i; - size_t live = 0, free_min = 0, do_heap_free = 0; - -+ long max_blocks_to_free = heaps_used - (heap_min_slots / HEAP_OBJ_LIMIT); -+ int freed_blocks = 0; -+ -+ unsigned long processed = 0; -+ unsigned long freelist_size = 0; -+ unsigned long zombies = 0; -+ unsigned long free_counts[T_MASK]; -+ unsigned long live_counts[T_MASK]; -+ int do_gc_stats = gc_statistics & verbose_gc_stats; -+ -+ if (do_gc_stats) { -+ MEMZERO((void*)free_counts, unsigned long, T_MASK); -+ MEMZERO((void*)live_counts, unsigned long, T_MASK); -+ } -+ - do_heap_free = (size_t)((heaps_used * HEAP_OBJ_LIMIT) * 0.65); - free_min = (size_t)((heaps_used * HEAP_OBJ_LIMIT) * 0.2); - -- if (free_min < FREE_MIN) { -+ if (free_min < heap_free_min) { - do_heap_free = heaps_used * HEAP_OBJ_LIMIT; -- free_min = FREE_MIN; -+ free_min = heap_free_min; - } - - freelist = 0; -@@ -1881,10 +2516,15 @@ gc_sweep(rb_objspace_t *objspace) - p = heaps[i].slot; pend = p + heaps[i].limit; - while (p < pend) { - if (!(p->as.basic.flags & FL_MARK)) { -+ if (do_gc_stats && !p->as.basic.flags) { -+ /* slot was free before GC */ -+ freelist_size++; -+ } - if (p->as.basic.flags && - ((deferred = obj_free(objspace, (VALUE)p)) || - ((FL_TEST(p, FL_FINALIZE)) && need_call_final))) { - if (!deferred) { -+ if (do_gc_stats) zombies++; - p->as.free.flags = T_ZOMBIE; - RDATA(p)->dfree = 0; - } -@@ -1894,6 +2534,10 @@ gc_sweep(rb_objspace_t *objspace) - final_num++; - } - else { -+ if (do_gc_stats) { -+ VALUE obt = p->as.basic.flags & T_MASK; -+ if (obt) free_counts[obt]++; -+ } - add_freelist(objspace, p); - free_num++; - } -@@ -1901,16 +2545,23 @@ gc_sweep(rb_objspace_t *objspace) - else if (BUILTIN_TYPE(p) == T_ZOMBIE) { - /* objects to be finalized */ - /* do nothing remain marked */ -+ if (do_gc_stats) zombies++; - } - else { - RBASIC(p)->flags &= ~FL_MARK; - live++; -+ if (do_gc_stats) { -+ live_counts[p->as.basic.flags & T_MASK]++; -+ } - } - p++; - } -- if (final_num + free_num == heaps[i].limit && freed > do_heap_free) { -+ if (final_num + free_num == heaps[i].limit && freed > do_heap_free && freed_blocks < max_blocks_to_free) { - RVALUE *pp; - -+ freed_blocks += 1; -+ heap_size -= final_num + free_num; -+ - for (pp = final_list; pp != final; pp = pp->as.free.next) { - RDATA(pp)->dmark = (void (*)())(VALUE)&heaps[i]; - pp->as.free.flags |= FL_SINGLETON; /* freeing page mark */ -@@ -1922,11 +2573,13 @@ gc_sweep(rb_objspace_t *objspace) - else { - freed += free_num; - } -+ processed += heaps[i].limit; - } - GC_PROF_SET_MALLOC_INFO; - if (malloc_increase > malloc_limit) { - malloc_limit += (size_t)((malloc_increase - malloc_limit) * (double)live / (live + freed)); -- if (malloc_limit < GC_MALLOC_LIMIT) malloc_limit = GC_MALLOC_LIMIT; -+ if (malloc_limit < initial_malloc_limit) malloc_limit = initial_malloc_limit; -+ - } - malloc_increase = 0; - if (freed < free_min) { -@@ -1934,6 +2587,25 @@ gc_sweep(rb_objspace_t *objspace) - heaps_increment(objspace); - } - during_gc = 0; -+ live_objects = live; -+ -+ /* log gc stats if requested */ -+ if (do_gc_stats) { -+ fprintf(gc_data_file, "objects processed: %.7lu\n", (unsigned long)processed); -+ fprintf(gc_data_file, "live objects : %.7lu\n", (unsigned long)live); -+ fprintf(gc_data_file, "freelist objects : %.7lu\n", (unsigned long)freelist_size); -+ fprintf(gc_data_file, "freed objects : %.7lu\n", (unsigned long)freed); -+ fprintf(gc_data_file, "zombies : %.7lu\n", (unsigned long)zombies); -+ for(i=0; i0 || live_counts[i]>0) { -+ fprintf(gc_data_file, -+ "kept %.7lu / freed %.7lu objects of type %s\n", -+ (unsigned long)live_counts[i], (unsigned long)free_counts[i], obj_type((int)i)); -+ } -+ } -+ rb_gc_dump(); -+ fflush(gc_data_file); -+ } - - /* clear finalization list */ - if (final_list) { -@@ -2140,6 +2812,7 @@ void rb_gc_mark_encodings(void); - static int - garbage_collect(rb_objspace_t *objspace) - { -+ struct timeval gctv1, gctv2; - struct gc_list *list; - rb_thread_t *th = GET_THREAD(); - INIT_GC_PROF_PARAMS; -@@ -2162,6 +2835,14 @@ garbage_collect(rb_objspace_t *objspace) - during_gc++; - objspace->count++; - -+ if (gc_statistics) { -+ gc_collections++; -+ gettimeofday(&gctv1, NULL); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "Garbage collection started\n"); -+ } -+ } -+ - GC_PROF_TIMER_START; - GC_PROF_MARK_TIMER_START; - SET_STACK_END; -@@ -2216,6 +2897,19 @@ garbage_collect(rb_objspace_t *objspace) - - GC_PROF_TIMER_STOP; - if (GC_NOTIFY) printf("end garbage_collect()\n"); -+ -+ if (gc_statistics) { -+ unsigned LONG_LONG musecs_used; -+ gettimeofday(&gctv2, NULL); -+ musecs_used = ((unsigned LONG_LONG)(gctv2.tv_sec - gctv1.tv_sec) * 1000000) + (gctv2.tv_usec - gctv1.tv_usec); -+ gc_time_accumulator += musecs_used; -+ -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "GC time: %lu msec\n", (unsigned long)(musecs_used / 1000)); -+ fflush(gc_data_file); -+ } -+ } -+ - return TRUE; - } - -@@ -2298,6 +2992,7 @@ Init_stack(volatile VALUE *addr) - void - Init_heap(void) - { -+ set_gc_parameters(&rb_objspace); - init_heap(&rb_objspace); - } - -@@ -2982,6 +3677,49 @@ count_objects(int argc, VALUE *argv, VALUE os) - return hash; - } - -+/* call-seq: -+ * ObjectSpace.live_objects => number -+ * -+ * Returns the count of objects currently allocated in the system. This goes -+ * down after the garbage collector runs. -+ */ -+static -+VALUE os_live_objects(VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return ULONG2NUM(live_objects); -+} -+ -+unsigned long rb_os_live_objects() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return live_objects; -+} -+ -+/* call-seq: -+ * ObjectSpace.allocated_objects => number -+ * -+ * Returns the count of objects allocated since the Ruby interpreter has -+ * started. This number can only increase. To know how many objects are -+ * currently allocated, use ObjectSpace::live_objects -+ */ -+static -+VALUE os_allocated_objects(VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if defined(HAVE_LONG_LONG) -+ return ULL2NUM(allocated_objects); -+#else -+ return ULONG2NUM(allocated_objects); -+#endif -+} -+ -+unsigned LONG_LONG rb_os_allocated_objects() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return allocated_objects; -+} -+ - /* - * call-seq: - * GC.count -> Integer -@@ -3188,6 +3926,28 @@ Init_GC(void) - rb_define_singleton_method(rb_mGC, "count", gc_count, 0); - rb_define_method(rb_mGC, "garbage_collect", rb_gc_start, 0); - -+ rb_define_singleton_method(rb_mGC, "enable_stats", rb_gc_enable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "disable_stats", rb_gc_disable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "stats_enabled?", rb_gc_stats_enabled, 0); -+ rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0); -+ rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); -+ rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); -+ -+ rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); -+ rb_define_singleton_method(rb_mGC, "log_file", rb_gc_log_file, -1); -+ rb_define_singleton_method(rb_mGC, "enable_trace", rb_gc_enable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "disable_trace", rb_gc_disable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "trace_enabled?", rb_gc_trace_enabled, 0); -+ -+ rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); -+ rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); -+ rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); -+#ifdef GC_DEBUG -+ rb_define_singleton_method(rb_mGC, "dump_file_and_line_info", rb_gc_dump_file_and_line_info, -1); -+#endif -+ - 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); -@@ -3201,6 +3961,9 @@ Init_GC(void) - rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1); - rb_define_module_function(rb_mObSpace, "garbage_collect", rb_gc_start, 0); - -+ rb_define_module_function(rb_mObSpace, "live_objects", os_live_objects, 0); -+ rb_define_module_function(rb_mObSpace, "allocated_objects", os_allocated_objects, 0); -+ - rb_define_module_function(rb_mObSpace, "define_finalizer", define_final, -1); - rb_define_module_function(rb_mObSpace, "undefine_finalizer", undefine_final, 1); - -diff --git a/sample/test.rb b/sample/test.rb -old mode 100644 -new mode 100755 diff --git a/patches/ruby/1.9.2/p180/railsexpress/02-display-more-detailed-stack-trace.patch b/patches/ruby/1.9.2/p180/railsexpress/02-display-more-detailed-stack-trace.patch deleted file mode 100644 index 232b7ff6ce..0000000000 --- a/patches/ruby/1.9.2/p180/railsexpress/02-display-more-detailed-stack-trace.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/eval_error.c b/eval_error.c -index 41fcbb0..9e065f9 100644 ---- a/eval_error.c -+++ b/eval_error.c -@@ -166,8 +166,8 @@ error_print(void) - int skip = eclass == rb_eSysStackError; - - #define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5) --#define TRACE_HEAD 8 --#define TRACE_TAIL 5 -+#define TRACE_HEAD 100 -+#define TRACE_TAIL 100 - - for (i = 1; i < len; i++) { - if (TYPE(ptr[i]) == T_STRING) { diff --git a/patches/ruby/1.9.2/p180/railsexpress/03-fork-support-for-gc-logging.patch b/patches/ruby/1.9.2/p180/railsexpress/03-fork-support-for-gc-logging.patch deleted file mode 100644 index 3d6a771ce9..0000000000 --- a/patches/ruby/1.9.2/p180/railsexpress/03-fork-support-for-gc-logging.patch +++ /dev/null @@ -1,68 +0,0 @@ -diff --git a/gc.c b/gc.c -index 27d9177..7673687 100644 ---- a/gc.c -+++ b/gc.c -@@ -1193,6 +1193,34 @@ rb_gc_log_file(int argc, VALUE *argv, VALUE self) - } - - /* -+ * Called from process.c before a fork. Flushes the gc log file to -+ * avoid writing the buffered output twice (once in the parent, and -+ * once in the child). -+ */ -+void -+rb_gc_before_fork() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ fflush(gc_data_file); -+} -+ -+/* -+ * Called from process.c after a fork in the child process. Turns off -+ * logging, disables GC stats and resets all gc counters and timing -+ * information. -+ */ -+void -+rb_gc_after_fork() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ rb_gc_disable_stats(); -+ rb_gc_clear_stats(); -+ rb_gc_disable_trace(); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+} -+ -+/* - * call-seq: - * GC.log String => String - * -diff --git a/include/ruby/intern.h b/include/ruby/intern.h -index af97c2a..0088fcc 100644 ---- a/include/ruby/intern.h -+++ b/include/ruby/intern.h -@@ -389,6 +389,8 @@ void rb_gc_call_finalizer_at_exit(void); - VALUE rb_gc_enable(void); - VALUE rb_gc_disable(void); - VALUE rb_gc_start(void); -+void rb_gc_before_fork _((void)); -+void rb_gc_after_fork _((void)); - #define Init_stack(addr) ruby_init_stack(addr) - /* hash.c */ - void st_foreach_safe(struct st_table *, int (*)(ANYARGS), st_data_t); -diff --git a/process.c b/process.c -index e883050..1ab2706 100644 ---- a/process.c -+++ b/process.c -@@ -2617,9 +2617,11 @@ rb_f_fork(VALUE obj) - rb_pid_t pid; - - rb_secure(2); -+ rb_gc_before_fork(); - - switch (pid = rb_fork(0, 0, 0, Qnil)) { - case 0: -+ rb_gc_after_fork(); - rb_thread_atfork(); - if (rb_block_given_p()) { - int status; diff --git a/patches/ruby/1.9.2/p180/railsexpress/04-track-live-dataset-size.patch b/patches/ruby/1.9.2/p180/railsexpress/04-track-live-dataset-size.patch deleted file mode 100644 index 9f28390919..0000000000 --- a/patches/ruby/1.9.2/p180/railsexpress/04-track-live-dataset-size.patch +++ /dev/null @@ -1,69 +0,0 @@ -diff --git a/gc.c b/gc.c -index 7673687..4d9ca88 100644 ---- a/gc.c -+++ b/gc.c -@@ -248,7 +248,6 @@ getrusage_time(void) - } while(0) - #endif - -- - #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__) - #pragma pack(push, 1) /* magic for reducing sizeof(RVALUE): 24 -> 20 */ - #endif -@@ -355,6 +354,7 @@ typedef struct rb_objspace { - unsigned LONG_LONG gc_num_allocations; - unsigned long live_objects; - unsigned LONG_LONG allocated_objects; -+ unsigned long heap_slots_live_after_last_gc; - } rb_objspace_t; - - #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE -@@ -388,6 +388,7 @@ int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress; - #define gc_num_allocations objspace->gc_num_allocations - #define live_objects objspace->live_objects - #define allocated_objects objspace->allocated_objects -+#define heap_slots_live_after_last_gc objspace->heap_slots_live_after_last_gc - #define finalizer_table objspace->final.table - #define deferred_final_list objspace->final.deferred - #define mark_stack objspace->markstack.buffer -@@ -1410,6 +1411,24 @@ rb_gc_time() - #endif - } - -+/* -+ * call-seq: -+ * GC.heap_slots_live_after_last_gc => Integer -+ * -+ * Returns the number of heap slots which were live after the last garbage collection. -+ * -+ * GC.heap_slots_live_after_last_gc #=> 231223 -+ * -+ */ -+VALUE -+rb_gc_heap_slots_live_after_last_gc() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return ULONG2NUM(heap_slots_live_after_last_gc); -+} -+ -+ -+ - VALUE rb_mGC; - - void -@@ -2616,6 +2635,7 @@ gc_sweep(rb_objspace_t *objspace) - } - during_gc = 0; - live_objects = live; -+ heap_slots_live_after_last_gc = live; - - /* log gc stats if requested */ - if (do_gc_stats) { -@@ -3961,6 +3981,7 @@ Init_GC(void) - rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); - rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); - rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots_live_after_last_gc", rb_gc_heap_slots_live_after_last_gc, 0); - rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); - - rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); diff --git a/patches/ruby/1.9.2/p180/railsexpress/05-load-performance-fix.patch b/patches/ruby/1.9.2/p180/railsexpress/05-load-performance-fix.patch deleted file mode 100644 index 6289026ea2..0000000000 --- a/patches/ruby/1.9.2/p180/railsexpress/05-load-performance-fix.patch +++ /dev/null @@ -1,36 +0,0 @@ -diff --git a/load.c b/load.c -index f8f0551..cb5c491 100644 ---- a/load.c -+++ b/load.c -@@ -81,16 +81,27 @@ loaded_feature_path(const char *name, long vlen, const char *feature, long len, - int type, VALUE load_path) - { - long i; -- -+ long plen; -+ const char *e; -+ -+ if(vlen < len) return 0; -+ if (!strncmp(name+(vlen-len),feature,len)){ -+ plen = vlen - len - 1; -+ } else { -+ for (e = name + vlen; name != e && *e != '.' && *e != '/'; --e); -+ if (*e!='.' || -+ e-name < len || -+ strncmp(e-len,feature,len) ) -+ return 0; -+ plen = e - name - len - 1; -+ } - for (i = 0; i < RARRAY_LEN(load_path); ++i) { - VALUE p = RARRAY_PTR(load_path)[i]; - const char *s = StringValuePtr(p); - long n = RSTRING_LEN(p); - -- if (vlen < n + len + 1) continue; -+ if (n != plen ) continue; - if (n && (strncmp(name, s, n) || name[n] != '/')) continue; -- if (strncmp(name + n + 1, feature, len)) continue; -- if (name[n+len+1] && name[n+len+1] != '.') continue; - switch (type) { - case 's': - if (IS_DLEXT(&name[n+len+1])) return p; diff --git a/patches/ruby/1.9.2/p290/railsexpress/01-railsbench-gc-patch.patch b/patches/ruby/1.9.2/p290/railsexpress/01-railsbench-gc-patch.patch deleted file mode 100644 index 002b4a3350..0000000000 --- a/patches/ruby/1.9.2/p290/railsexpress/01-railsbench-gc-patch.patch +++ /dev/null @@ -1,1081 +0,0 @@ -diff --git a/configure.in b/configure.in -index 8e481b7..8c67a8a 100644 ---- a/configure.in -+++ b/configure.in -@@ -2206,6 +2206,14 @@ if test "$EXEEXT" = .exe; then - AC_SUBST(EXECUTABLE_EXTS) - fi - -+dnl enable gc debugging -+AC_ARG_ENABLE(gcdebug, -+ [ --enable-gcdebug build garbage collector with debugging enabled. ], -+ [enable_gcdebug=$enableval]) -+if test "$enable_gcdebug" = 'yes'; then -+ AC_DEFINE(GC_DEBUG, 1) -+fi -+ - dnl } - dnl build section { - -diff --git a/gc.c b/gc.c -index 564d260..27d9177 100644 ---- a/gc.c -+++ b/gc.c -@@ -78,6 +78,17 @@ void *alloca (); - #define GC_MALLOC_LIMIT 8000000 - #endif - -+#ifndef HAVE_LONG_LONG -+#define LONG_LONG long -+#endif -+ -+static size_t heap_free_min = 4096; -+static int heap_min_slots = 10000; -+static int heap_slots_increment = 10000; -+static int initial_heap_slots_increment = 10000; -+static double heap_slots_growth_factor = 1.8; -+static size_t initial_malloc_limit = GC_MALLOC_LIMIT; -+ - #define nomem_error GET_VM()->special_exceptions[ruby_error_nomemory] - - #define MARK_STACK_MAX 1024 -@@ -267,7 +278,7 @@ typedef struct RVALUE { - struct RComplex complex; - } as; - #ifdef GC_DEBUG -- const char *file; -+ VALUE file; - int line; - #endif - } RVALUE; -@@ -314,6 +325,8 @@ typedef struct rb_objspace { - struct { - int dont_gc; - int during_gc; -+ int gc_statistics; -+ int verbose_gc_stats; - } flags; - struct { - st_table *table; -@@ -334,6 +347,14 @@ typedef struct rb_objspace { - struct gc_list *global_list; - unsigned int count; - int gc_stress; -+ long heap_size; -+ unsigned LONG_LONG gc_time_accumulator; -+ FILE* gc_data_file; -+ long gc_collections; -+ unsigned LONG_LONG gc_allocated_size; -+ unsigned LONG_LONG gc_num_allocations; -+ unsigned long live_objects; -+ unsigned LONG_LONG allocated_objects; - } rb_objspace_t; - - #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE -@@ -357,6 +378,16 @@ int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress; - #define heaps_freed objspace->heap.freed - #define dont_gc objspace->flags.dont_gc - #define during_gc objspace->flags.during_gc -+#define gc_statistics objspace->flags.gc_statistics -+#define verbose_gc_stats objspace->flags.verbose_gc_stats -+#define heap_size objspace->heap_size -+#define gc_time_accumulator objspace->gc_time_accumulator -+#define gc_data_file objspace->gc_data_file -+#define gc_collections objspace->gc_collections -+#define gc_allocated_size objspace->gc_allocated_size -+#define gc_num_allocations objspace->gc_num_allocations -+#define live_objects objspace->live_objects -+#define allocated_objects objspace->allocated_objects - #define finalizer_table objspace->final.table - #define deferred_final_list objspace->final.deferred - #define mark_stack objspace->markstack.buffer -@@ -375,7 +406,8 @@ rb_objspace_alloc(void) - { - rb_objspace_t *objspace = malloc(sizeof(rb_objspace_t)); - memset(objspace, 0, sizeof(*objspace)); -- malloc_limit = GC_MALLOC_LIMIT; -+ malloc_limit = initial_malloc_limit; -+ - ruby_gc_stress = ruby_initial_gc_stress; - - return objspace; -@@ -409,23 +441,8 @@ rb_objspace_free(rb_objspace_t *objspace) - } - #endif - --/* tiny heap size */ --/* 32KB */ --/*#define HEAP_SIZE 0x8000 */ --/* 128KB */ --/*#define HEAP_SIZE 0x20000 */ --/* 64KB */ --/*#define HEAP_SIZE 0x10000 */ --/* 16KB */ --#define HEAP_SIZE 0x4000 --/* 8KB */ --/*#define HEAP_SIZE 0x2000 */ --/* 4KB */ --/*#define HEAP_SIZE 0x1000 */ --/* 2KB */ --/*#define HEAP_SIZE 0x800 */ -- --#define HEAP_OBJ_LIMIT (HEAP_SIZE / sizeof(struct RVALUE)) -+#define HEAP_OBJ_LIMIT 8000 -+#define HEAP_SIZE (HEAP_OBJ_LIMIT * sizeof(struct RVALUE)) - - extern VALUE rb_cMutex; - extern st_table *rb_class_tbl; -@@ -673,6 +690,11 @@ vm_xmalloc(rb_objspace_t *objspace, size_t size) - mem = (size_t *)mem + 1; - #endif - -+ if (gc_statistics) { -+ gc_allocated_size += size; -+ gc_num_allocations += 1; -+ } -+ - return mem; - } - -@@ -780,6 +802,92 @@ ruby_xfree(void *x) - vm_xfree(&rb_objspace, x); - } - -+static void set_gc_parameters(rb_objspace_t *objspace) -+{ -+ char *envp; -+ -+ gc_data_file = stderr; -+ -+ envp = getenv("RUBY_GC_STATS"); -+ if (envp != NULL) { -+ int i = atoi(envp); -+ if (i > 0) { -+ verbose_gc_stats = 1; -+ } -+ /* child processes should not inherit RUBY_GC_STATS */ -+ ruby_unsetenv("RUBY_GC_STATS"); -+ } -+ -+ envp = getenv("RUBY_GC_DATA_FILE"); -+ if (envp != NULL) { -+ FILE* data_file = fopen(envp, "w"); -+ if (data_file != NULL) { -+ gc_data_file = data_file; -+ } -+ else { -+ fprintf(stderr, "can't open gc log file %s for writing, using default\n", envp); -+ } -+ /* child processes should not inherit RUBY_GC_DATA_FILE to avoid clobbering */ -+ ruby_unsetenv("RUBY_GC_DATA_FILE"); -+ } -+ -+ envp = getenv("RUBY_HEAP_MIN_SLOTS"); -+ if (envp != NULL) { -+ int i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_MIN_SLOTS=%s\n", envp); -+ } -+ if (i > 0) { -+ heap_min_slots = i; -+ } -+ } -+ -+ envp = getenv("RUBY_HEAP_FREE_MIN"); -+ if (envp != NULL) { -+ int i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_FREE_MIN=%s\n", envp); -+ } -+ if (i > 0) { -+ heap_free_min = i; -+ } -+ } -+ -+ envp = getenv("RUBY_HEAP_SLOTS_INCREMENT"); -+ if (envp != NULL) { -+ int i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_INCREMENT=%s\n", envp); -+ } -+ heap_slots_increment = i; -+ initial_heap_slots_increment = heap_slots_increment; -+ } -+ -+ envp = getenv("RUBY_HEAP_SLOTS_GROWTH_FACTOR"); -+ if (envp != NULL) { -+ double d = atof(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_GROWTH_FACTOR=%s\n", envp); -+ } -+ if (d > 0) { -+ heap_slots_growth_factor = d; -+ } -+ } -+ -+ envp = getenv("RUBY_GC_MALLOC_LIMIT"); -+ if (envp != NULL) { -+ long l = atol(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_GC_MALLOC_LIMIT=%s\n", envp); -+ } -+ if (l > 0) { -+ initial_malloc_limit = l; -+ malloc_limit = initial_malloc_limit; -+ } -+ } -+ -+ fflush(gc_data_file); -+} - - /* - * call-seq: -@@ -826,6 +934,454 @@ rb_gc_disable(void) - return old ? Qtrue : Qfalse; - } - -+/* -+ * call-seq: -+ * GC.enable_stats => true or false -+ * -+ * Enables garbage collection statistics, returning true if garbage -+ * collection statistics was already enabled. -+ * -+ * GC.enable_stats #=> false or true -+ * GC.enable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = gc_statistics; -+ gc_statistics = 1; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_stats => true or false -+ * -+ * Disables garbage collection statistics, returning true if garbage -+ * collection statistics was already disabled. -+ * -+ * GC.disable_stats #=> false or true -+ * GC.disable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = gc_statistics; -+ gc_statistics = 0; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.stats_enabled? => true or false -+ * -+ * Check whether GC stats have been enabled. -+ * -+ * GC.stats_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_stats_enabled() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return gc_statistics ? Qtrue : Qfalse; -+} -+ -+ -+/* -+ * call-seq: -+ * GC.clear_stats => nil -+ * -+ * Clears garbage collection statistics, returning nil. This resets the number -+ * of collections (GC.collections) and the time used (GC.time) to 0. -+ * -+ * GC.clear_stats #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_clear_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ gc_collections = 0; -+ gc_time_accumulator = 0; -+ gc_allocated_size = 0; -+ gc_num_allocations = 0; -+ return Qnil; -+} -+ -+/* -+ * call-seq: -+ * GC.allocated_size => Integer -+ * -+ * Returns the size of memory (in bytes) allocated since GC statistics collection -+ * was enabled. -+ * -+ * GC.allocated_size #=> 35 -+ * -+ */ -+ -+VALUE -+rb_gc_allocated_size() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_allocated_size); -+#else -+ return ULONG2NUM(gc_allocated_size); -+#endif -+} -+ -+/* -+ * call-seq: -+ * GC.num_allocations => Integer -+ * -+ * Returns the number of memory allocations since GC statistics collection -+ * was enabled. -+ * -+ * GC.num_allocations #=> 150 -+ * -+ */ -+VALUE -+rb_gc_num_allocations() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_num_allocations); -+#else -+ return ULONG2NUM(gc_num_allocations); -+#endif -+} -+ -+/* -+ * call-seq: -+ * GC.enable_trace => true or false -+ * -+ * Enables garbage collection tracing, returning true if garbage -+ * collection tracing was already enabled. -+ * -+ * GC.enable_trace #=> false or true -+ * GC.enable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_trace() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = verbose_gc_stats; -+ verbose_gc_stats = 1; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_trace => true or false -+ * -+ * Disables garbage collection tracing, returning true if garbage -+ * collection tracing was already disabled. -+ * -+ * GC.disable_trace #=> false or true -+ * GC.disable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_trace() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = verbose_gc_stats; -+ verbose_gc_stats = 0; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.trace_enabled? => true or false -+ * -+ * Check whether GC tracing has been enabled. -+ * -+ * GC.trace_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_trace_enabled() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return verbose_gc_stats ? Qtrue : Qfalse; -+} -+ -+ -+const char* GC_LOGFILE_IVAR = "@gc_logfile_name"; -+ -+/* -+ * call-seq: -+ * GC.log_file(filename=nil, mode="w") => boolean -+ * -+ * Changes the GC data log file. Closes the currently open logfile. -+ * Returns true if the file was successfully opened for -+ * writing. Returns false if the file could not be opened for -+ * writing. Returns the name of the current logfile (or nil) if no -+ * parameter is given. Restores logging to stderr when given nil as -+ * an argument. -+ * -+ * GC.log_file #=> nil -+ * GC.log_file "/tmp/gc.log" #=> true -+ * GC.log_file #=> "/tmp/gc.log" -+ * GC.log_file nil #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_log_file(int argc, VALUE *argv, VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ VALUE filename = Qnil; -+ VALUE mode_str = Qnil; -+ FILE* f = NULL; -+ const char* mode = "w"; -+ -+ VALUE current_logfile_name = rb_iv_get(rb_mGC, GC_LOGFILE_IVAR); -+ -+ if (argc==0) -+ return current_logfile_name; -+ -+ rb_scan_args(argc, argv, "02", &filename, &mode_str); -+ -+ if (filename == Qnil) { -+ /* close current logfile and reset logfile to stderr */ -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+ } -+ return Qtrue; -+ } -+ -+ /* we have a real logfile name */ -+ filename = StringValue(filename); -+ -+ if (rb_equal(current_logfile_name, filename) == Qtrue) { -+ /* do nothing if we get the file name we're already logging to */ -+ return Qtrue; -+ } -+ -+ /* get mode for file opening */ -+ if (mode_str != Qnil) -+ { -+ mode = RSTRING_PTR(StringValue(mode_str)); -+ } -+ -+ /* try to open file in given mode */ -+ if (f = fopen(RSTRING_PTR(filename), mode)) { -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ } -+ gc_data_file = f; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, filename); -+ } else { -+ return Qfalse; -+ } -+ return Qtrue; -+} -+ -+/* -+ * call-seq: -+ * GC.log String => String -+ * -+ * Logs string to the GC data file and returns it. -+ * -+ * GC.log "manual GC call" #=> "manual GC call" -+ * -+ */ -+ -+VALUE -+rb_gc_log(self, original_str) -+ VALUE self, original_str; -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ if (original_str == Qnil) { -+ fprintf(gc_data_file, "\n"); -+ } -+ else { -+ VALUE str = StringValue(original_str); -+ char *p = RSTRING_PTR(str); -+ fprintf(gc_data_file, "%s\n", p); -+ } -+ return original_str; -+} -+ -+/* -+ * call-seq: -+ * GC.dump => nil -+ * -+ * dumps information about the current GC data structures to the GC log file -+ * -+ * GC.dump #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_dump() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ size_t i; -+ -+ for (i = 0; i < heaps_used; i++) { -+ size_t limit = heaps[i].limit; -+ fprintf(gc_data_file, "HEAP[%2lu]: size=%7lu\n", (unsigned long)i, (unsigned long)limit); -+ } -+ -+ return Qnil; -+} -+ -+static const char* obj_type(VALUE tp); -+ -+#ifdef GC_DEBUG -+/* -+ * call-seq: -+ * GC.dump_file_and_line_info(String, boolean) => nil -+ * -+ * dumps information on which currently allocated object was created by which file and on which line -+ * -+ * GC.dump_file_and_line_info(String, boolean) #=> nil -+ * -+ * The second parameter specifies whether class names should be included in the dump. -+ * Note that including class names will allocate additional string objects on the heap. -+ * -+ */ -+ -+VALUE -+rb_gc_dump_file_and_line_info(int argc, VALUE *argv) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ VALUE filename, str, include_classnames = Qnil; -+ char *fname = NULL; -+ char *klass = NULL; -+ FILE* f = NULL; -+ size_t i = 0; -+ -+ rb_scan_args(argc, argv, "11", &filename, &include_classnames); -+ -+ str = StringValue(filename); -+ fname = RSTRING_PTR(str); -+ f = fopen(fname, "w"); -+ -+ for (i = 0; i < heaps_used; i++) { -+ RVALUE *p, *pend; -+ -+ p = heaps[i].slot; pend = p + heaps[i].limit; -+ for (;p < pend; p++) { -+ if (p->as.basic.flags) { -+ const char *src_filename = (p->file && p->file != Qnil )? RSTRING_PTR(p->file) : ""; -+ fprintf(f, "%s:%s:%d", obj_type(p->as.basic.flags & T_MASK), src_filename, (int)p->line); -+ // rb_obj_classname will create objects on the heap, we need a better solution -+ if (include_classnames == Qtrue) { -+ /* write the class */ -+ fprintf(f, ":"); -+ switch (BUILTIN_TYPE(p)) { -+ case T_NONE: -+ fprintf(f, "__none__"); -+ break; -+ case T_UNDEF: -+ fprintf(f, "__undef__"); -+ break; -+ case T_NODE: -+ fprintf(f, "__node__"); -+ break; -+ default: -+ if (!p->as.basic.klass) { -+ fprintf(f, "__unknown__"); -+ } else { -+ fprintf(f, "%s", rb_obj_classname((VALUE)p)); -+ } -+ } -+ /* print object size for some known object types */ -+ switch (BUILTIN_TYPE(p)) { -+ case T_STRING: -+ fprintf(f, ":%lu", RSTRING_LEN(p)); -+ break; -+ case T_ARRAY: -+ fprintf(f, ":%lu", RARRAY_LEN(p)); -+ break; -+ case T_HASH: -+ fprintf(f, ":%lu", (long unsigned int)RHASH_SIZE(p)); -+ break; -+ } -+ } -+ fprintf(f, "\n"); -+ } -+ } -+ } -+ fclose(f); -+ return Qnil; -+} -+#endif -+ -+/* -+ * call-seq: -+ * GC.heap_slots => Integer -+ * -+ * Returns the number of heap slots available for object allocations. -+ * -+ * GC.heap_slots #=> 10000 -+ * -+ */ -+VALUE -+rb_gc_heap_slots() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return LONG2NUM(heap_size); -+} -+ -+ -+/* -+ * call-seq: -+ * GC.collections => Integer -+ * -+ * Returns the number of garbage collections performed while GC statistics collection -+ * was enabled. -+ * -+ * GC.collections #=> 35 -+ * -+ */ -+ -+VALUE -+rb_gc_collections() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return LONG2NUM(gc_collections); -+} -+ -+/* -+ * call-seq: -+ * GC.time => Integer -+ * -+ * Returns the time spent during garbage collection while GC statistics collection -+ * was enabled (in micro seconds). -+ * -+ * GC.time #=> 20000 -+ * -+ */ -+ -+VALUE -+rb_gc_time() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return LL2NUM(gc_time_accumulator); -+#else -+ return LONG2NUM(gc_time_accumulator); -+#endif -+} -+ - VALUE rb_mGC; - - void -@@ -944,6 +1500,7 @@ assign_heap_slot(rb_objspace_t *objspace) - if (lomem == 0 || lomem > p) lomem = p; - if (himem < pend) himem = pend; - heaps_used++; -+ heap_size += objs; - - while (p < pend) { - p->as.free.flags = 0; -@@ -958,7 +1515,7 @@ init_heap(rb_objspace_t *objspace) - { - size_t add, i; - -- add = HEAP_MIN_SLOTS / HEAP_OBJ_LIMIT; -+ add = heap_min_slots / HEAP_OBJ_LIMIT; - - if (!add) { - add = 1; -@@ -979,7 +1536,7 @@ init_heap(rb_objspace_t *objspace) - static void - set_heaps_increment(rb_objspace_t *objspace) - { -- size_t next_heaps_length = (size_t)(heaps_used * 1.8); -+ size_t next_heaps_length = (size_t)(heaps_used * heap_slots_growth_factor); - - if (next_heaps_length == heaps_used) { - next_heaps_length++; -@@ -1005,6 +1562,22 @@ heaps_increment(rb_objspace_t *objspace) - - #define RANY(o) ((RVALUE*)(o)) - -+#ifdef GC_DEBUG -+static VALUE -+_rb_sourcefile(void) -+{ -+ rb_thread_t *th = GET_THREAD(); -+ rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp); -+ -+ if (cfp) { -+ return cfp->iseq->filename; -+ } -+ else { -+ return Qnil; -+ } -+} -+#endif -+ - static VALUE - rb_newobj_from_heap(rb_objspace_t *objspace) - { -@@ -1022,9 +1595,11 @@ rb_newobj_from_heap(rb_objspace_t *objspace) - - MEMZERO((void*)obj, RVALUE, 1); - #ifdef GC_DEBUG -- RANY(obj)->file = rb_sourcefile(); -+ RANY(obj)->file = _rb_sourcefile(); - RANY(obj)->line = rb_sourceline(); - #endif -+ live_objects++; -+ allocated_objects++; - - return obj; - } -@@ -1525,6 +2100,12 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev) - { - register RVALUE *obj = RANY(ptr); - -+#ifdef GC_DEBUG -+ if (obj->file && obj->file != Qnil && is_pointer_to_heap(objspace, (void*)obj->file)) { -+ gc_mark(objspace, obj->file, lev); -+ } -+#endif -+ - goto marking; /* skip */ - - again: -@@ -1534,6 +2115,12 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev) - if (obj->as.basic.flags & FL_MARK) return; /* already marked */ - obj->as.basic.flags |= FL_MARK; - -+#ifdef GC_DEBUG -+ if (obj->file && obj->file != Qnil && is_pointer_to_heap(objspace, (void*)obj->file)) { -+ gc_mark(objspace, obj->file, lev); -+ } -+#endif -+ - marking: - if (FL_TEST(obj, FL_EXIVAR)) { - rb_mark_generic_ivar(ptr); -@@ -1851,6 +2438,39 @@ free_unused_heaps(rb_objspace_t *objspace) - } - } - -+static const char* obj_type(VALUE type) -+{ -+ switch (type) { -+ case T_NIL : return "NIL"; -+ case T_OBJECT : return "OBJECT"; -+ case T_CLASS : return "CLASS"; -+ case T_ICLASS : return "ICLASS"; -+ case T_MODULE : return "MODULE"; -+ case T_FLOAT : return "FLOAT"; -+ case T_COMPLEX: return "COMPLEX"; -+ case T_RATIONAL: return "RATIONAL"; -+ case T_STRING : return "STRING"; -+ case T_REGEXP : return "REGEXP"; -+ case T_ARRAY : return "ARRAY"; -+ case T_FIXNUM : return "FIXNUM"; -+ case T_HASH : return "HASH"; -+ case T_STRUCT : return "STRUCT"; -+ case T_BIGNUM : return "BIGNUM"; -+ case T_FILE : return "FILE"; -+ -+ case T_TRUE : return "TRUE"; -+ case T_FALSE : return "FALSE"; -+ case T_DATA : return "DATA"; -+ case T_MATCH : return "MATCH"; -+ case T_SYMBOL : return "SYMBOL"; -+ case T_ZOMBIE : return "ZOMBIE"; -+ -+ case T_UNDEF : return "UNDEF"; -+ case T_NODE : return "NODE"; -+ default: return "____"; -+ } -+} -+ - static void - gc_sweep(rb_objspace_t *objspace) - { -@@ -1859,12 +2479,27 @@ gc_sweep(rb_objspace_t *objspace) - size_t i; - size_t live = 0, free_min = 0, do_heap_free = 0; - -+ long max_blocks_to_free = heaps_used - (heap_min_slots / HEAP_OBJ_LIMIT); -+ int freed_blocks = 0; -+ -+ unsigned long processed = 0; -+ unsigned long freelist_size = 0; -+ unsigned long zombies = 0; -+ unsigned long free_counts[T_MASK]; -+ unsigned long live_counts[T_MASK]; -+ int do_gc_stats = gc_statistics & verbose_gc_stats; -+ -+ if (do_gc_stats) { -+ MEMZERO((void*)free_counts, unsigned long, T_MASK); -+ MEMZERO((void*)live_counts, unsigned long, T_MASK); -+ } -+ - do_heap_free = (size_t)((heaps_used * HEAP_OBJ_LIMIT) * 0.65); - free_min = (size_t)((heaps_used * HEAP_OBJ_LIMIT) * 0.2); - -- if (free_min < FREE_MIN) { -+ if (free_min < heap_free_min) { - do_heap_free = heaps_used * HEAP_OBJ_LIMIT; -- free_min = FREE_MIN; -+ free_min = heap_free_min; - } - - freelist = 0; -@@ -1881,10 +2516,15 @@ gc_sweep(rb_objspace_t *objspace) - p = heaps[i].slot; pend = p + heaps[i].limit; - while (p < pend) { - if (!(p->as.basic.flags & FL_MARK)) { -+ if (do_gc_stats && !p->as.basic.flags) { -+ /* slot was free before GC */ -+ freelist_size++; -+ } - if (p->as.basic.flags && - ((deferred = obj_free(objspace, (VALUE)p)) || - ((FL_TEST(p, FL_FINALIZE)) && need_call_final))) { - if (!deferred) { -+ if (do_gc_stats) zombies++; - p->as.free.flags = T_ZOMBIE; - RDATA(p)->dfree = 0; - } -@@ -1894,6 +2534,10 @@ gc_sweep(rb_objspace_t *objspace) - final_num++; - } - else { -+ if (do_gc_stats) { -+ VALUE obt = p->as.basic.flags & T_MASK; -+ if (obt) free_counts[obt]++; -+ } - add_freelist(objspace, p); - free_num++; - } -@@ -1901,16 +2545,23 @@ gc_sweep(rb_objspace_t *objspace) - else if (BUILTIN_TYPE(p) == T_ZOMBIE) { - /* objects to be finalized */ - /* do nothing remain marked */ -+ if (do_gc_stats) zombies++; - } - else { - RBASIC(p)->flags &= ~FL_MARK; - live++; -+ if (do_gc_stats) { -+ live_counts[p->as.basic.flags & T_MASK]++; -+ } - } - p++; - } -- if (final_num + free_num == heaps[i].limit && freed > do_heap_free) { -+ if (final_num + free_num == heaps[i].limit && freed > do_heap_free && freed_blocks < max_blocks_to_free) { - RVALUE *pp; - -+ freed_blocks += 1; -+ heap_size -= final_num + free_num; -+ - for (pp = final_list; pp != final; pp = pp->as.free.next) { - RDATA(pp)->dmark = (void (*)())(VALUE)&heaps[i]; - pp->as.free.flags |= FL_SINGLETON; /* freeing page mark */ -@@ -1922,11 +2573,13 @@ gc_sweep(rb_objspace_t *objspace) - else { - freed += free_num; - } -+ processed += heaps[i].limit; - } - GC_PROF_SET_MALLOC_INFO; - if (malloc_increase > malloc_limit) { - malloc_limit += (size_t)((malloc_increase - malloc_limit) * (double)live / (live + freed)); -- if (malloc_limit < GC_MALLOC_LIMIT) malloc_limit = GC_MALLOC_LIMIT; -+ if (malloc_limit < initial_malloc_limit) malloc_limit = initial_malloc_limit; -+ - } - malloc_increase = 0; - if (freed < free_min) { -@@ -1934,6 +2587,25 @@ gc_sweep(rb_objspace_t *objspace) - heaps_increment(objspace); - } - during_gc = 0; -+ live_objects = live; -+ -+ /* log gc stats if requested */ -+ if (do_gc_stats) { -+ fprintf(gc_data_file, "objects processed: %.7lu\n", (unsigned long)processed); -+ fprintf(gc_data_file, "live objects : %.7lu\n", (unsigned long)live); -+ fprintf(gc_data_file, "freelist objects : %.7lu\n", (unsigned long)freelist_size); -+ fprintf(gc_data_file, "freed objects : %.7lu\n", (unsigned long)freed); -+ fprintf(gc_data_file, "zombies : %.7lu\n", (unsigned long)zombies); -+ for(i=0; i0 || live_counts[i]>0) { -+ fprintf(gc_data_file, -+ "kept %.7lu / freed %.7lu objects of type %s\n", -+ (unsigned long)live_counts[i], (unsigned long)free_counts[i], obj_type((int)i)); -+ } -+ } -+ rb_gc_dump(); -+ fflush(gc_data_file); -+ } - - /* clear finalization list */ - if (final_list) { -@@ -2140,6 +2812,7 @@ void rb_gc_mark_encodings(void); - static int - garbage_collect(rb_objspace_t *objspace) - { -+ struct timeval gctv1, gctv2; - struct gc_list *list; - rb_thread_t *th = GET_THREAD(); - INIT_GC_PROF_PARAMS; -@@ -2162,6 +2835,14 @@ garbage_collect(rb_objspace_t *objspace) - during_gc++; - objspace->count++; - -+ if (gc_statistics) { -+ gc_collections++; -+ gettimeofday(&gctv1, NULL); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "Garbage collection started\n"); -+ } -+ } -+ - GC_PROF_TIMER_START; - GC_PROF_MARK_TIMER_START; - SET_STACK_END; -@@ -2216,6 +2897,19 @@ garbage_collect(rb_objspace_t *objspace) - - GC_PROF_TIMER_STOP; - if (GC_NOTIFY) printf("end garbage_collect()\n"); -+ -+ if (gc_statistics) { -+ unsigned LONG_LONG musecs_used; -+ gettimeofday(&gctv2, NULL); -+ musecs_used = ((unsigned LONG_LONG)(gctv2.tv_sec - gctv1.tv_sec) * 1000000) + (gctv2.tv_usec - gctv1.tv_usec); -+ gc_time_accumulator += musecs_used; -+ -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "GC time: %lu msec\n", (unsigned long)(musecs_used / 1000)); -+ fflush(gc_data_file); -+ } -+ } -+ - return TRUE; - } - -@@ -2298,6 +2992,7 @@ Init_stack(volatile VALUE *addr) - void - Init_heap(void) - { -+ set_gc_parameters(&rb_objspace); - init_heap(&rb_objspace); - } - -@@ -2982,6 +3677,49 @@ count_objects(int argc, VALUE *argv, VALUE os) - return hash; - } - -+/* call-seq: -+ * ObjectSpace.live_objects => number -+ * -+ * Returns the count of objects currently allocated in the system. This goes -+ * down after the garbage collector runs. -+ */ -+static -+VALUE os_live_objects(VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return ULONG2NUM(live_objects); -+} -+ -+unsigned long rb_os_live_objects() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return live_objects; -+} -+ -+/* call-seq: -+ * ObjectSpace.allocated_objects => number -+ * -+ * Returns the count of objects allocated since the Ruby interpreter has -+ * started. This number can only increase. To know how many objects are -+ * currently allocated, use ObjectSpace::live_objects -+ */ -+static -+VALUE os_allocated_objects(VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if defined(HAVE_LONG_LONG) -+ return ULL2NUM(allocated_objects); -+#else -+ return ULONG2NUM(allocated_objects); -+#endif -+} -+ -+unsigned LONG_LONG rb_os_allocated_objects() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return allocated_objects; -+} -+ - /* - * call-seq: - * GC.count -> Integer -@@ -3188,6 +3926,28 @@ Init_GC(void) - rb_define_singleton_method(rb_mGC, "count", gc_count, 0); - rb_define_method(rb_mGC, "garbage_collect", rb_gc_start, 0); - -+ rb_define_singleton_method(rb_mGC, "enable_stats", rb_gc_enable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "disable_stats", rb_gc_disable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "stats_enabled?", rb_gc_stats_enabled, 0); -+ rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0); -+ rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); -+ rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); -+ -+ rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); -+ rb_define_singleton_method(rb_mGC, "log_file", rb_gc_log_file, -1); -+ rb_define_singleton_method(rb_mGC, "enable_trace", rb_gc_enable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "disable_trace", rb_gc_disable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "trace_enabled?", rb_gc_trace_enabled, 0); -+ -+ rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); -+ rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); -+ rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); -+#ifdef GC_DEBUG -+ rb_define_singleton_method(rb_mGC, "dump_file_and_line_info", rb_gc_dump_file_and_line_info, -1); -+#endif -+ - 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); -@@ -3201,6 +3961,9 @@ Init_GC(void) - rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1); - rb_define_module_function(rb_mObSpace, "garbage_collect", rb_gc_start, 0); - -+ rb_define_module_function(rb_mObSpace, "live_objects", os_live_objects, 0); -+ rb_define_module_function(rb_mObSpace, "allocated_objects", os_allocated_objects, 0); -+ - rb_define_module_function(rb_mObSpace, "define_finalizer", define_final, -1); - rb_define_module_function(rb_mObSpace, "undefine_finalizer", undefine_final, 1); - -diff --git a/sample/test.rb b/sample/test.rb -old mode 100644 -new mode 100755 diff --git a/patches/ruby/1.9.2/p290/railsexpress/02-display-more-detailed-stack-trace.patch b/patches/ruby/1.9.2/p290/railsexpress/02-display-more-detailed-stack-trace.patch deleted file mode 100644 index 232b7ff6ce..0000000000 --- a/patches/ruby/1.9.2/p290/railsexpress/02-display-more-detailed-stack-trace.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/eval_error.c b/eval_error.c -index 41fcbb0..9e065f9 100644 ---- a/eval_error.c -+++ b/eval_error.c -@@ -166,8 +166,8 @@ error_print(void) - int skip = eclass == rb_eSysStackError; - - #define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5) --#define TRACE_HEAD 8 --#define TRACE_TAIL 5 -+#define TRACE_HEAD 100 -+#define TRACE_TAIL 100 - - for (i = 1; i < len; i++) { - if (TYPE(ptr[i]) == T_STRING) { diff --git a/patches/ruby/1.9.2/p290/railsexpress/03-fork-support-for-gc-logging.patch b/patches/ruby/1.9.2/p290/railsexpress/03-fork-support-for-gc-logging.patch deleted file mode 100644 index 7126c9103e..0000000000 --- a/patches/ruby/1.9.2/p290/railsexpress/03-fork-support-for-gc-logging.patch +++ /dev/null @@ -1,68 +0,0 @@ -diff --git a/gc.c b/gc.c -index 27d9177..7673687 100644 ---- a/gc.c -+++ b/gc.c -@@ -1193,6 +1193,34 @@ rb_gc_log_file(int argc, VALUE *argv, VALUE self) - } - - /* -+ * Called from process.c before a fork. Flushes the gc log file to -+ * avoid writing the buffered output twice (once in the parent, and -+ * once in the child). -+ */ -+void -+rb_gc_before_fork() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ fflush(gc_data_file); -+} -+ -+/* -+ * Called from process.c after a fork in the child process. Turns off -+ * logging, disables GC stats and resets all gc counters and timing -+ * information. -+ */ -+void -+rb_gc_after_fork() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ rb_gc_disable_stats(); -+ rb_gc_clear_stats(); -+ rb_gc_disable_trace(); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+} -+ -+/* - * call-seq: - * GC.log String => String - * -diff --git a/include/ruby/intern.h b/include/ruby/intern.h -index f0cff67..a374c7e 100644 ---- a/include/ruby/intern.h -+++ b/include/ruby/intern.h -@@ -390,6 +390,8 @@ void rb_gc_call_finalizer_at_exit(void); - VALUE rb_gc_enable(void); - VALUE rb_gc_disable(void); - VALUE rb_gc_start(void); -+void rb_gc_before_fork _((void)); -+void rb_gc_after_fork _((void)); - #define Init_stack(addr) ruby_init_stack(addr) - /* hash.c */ - void st_foreach_safe(struct st_table *, int (*)(ANYARGS), st_data_t); -diff --git a/process.c b/process.c -index c180492..d20d44c 100644 ---- a/process.c -+++ b/process.c -@@ -2617,9 +2617,11 @@ rb_f_fork(VALUE obj) - rb_pid_t pid; - - rb_secure(2); -+ rb_gc_before_fork(); - - switch (pid = rb_fork(0, 0, 0, Qnil)) { - case 0: -+ rb_gc_after_fork(); - rb_thread_atfork(); - if (rb_block_given_p()) { - int status; diff --git a/patches/ruby/1.9.2/p290/railsexpress/04-track-live-dataset-size.patch b/patches/ruby/1.9.2/p290/railsexpress/04-track-live-dataset-size.patch deleted file mode 100644 index 9f28390919..0000000000 --- a/patches/ruby/1.9.2/p290/railsexpress/04-track-live-dataset-size.patch +++ /dev/null @@ -1,69 +0,0 @@ -diff --git a/gc.c b/gc.c -index 7673687..4d9ca88 100644 ---- a/gc.c -+++ b/gc.c -@@ -248,7 +248,6 @@ getrusage_time(void) - } while(0) - #endif - -- - #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__) - #pragma pack(push, 1) /* magic for reducing sizeof(RVALUE): 24 -> 20 */ - #endif -@@ -355,6 +354,7 @@ typedef struct rb_objspace { - unsigned LONG_LONG gc_num_allocations; - unsigned long live_objects; - unsigned LONG_LONG allocated_objects; -+ unsigned long heap_slots_live_after_last_gc; - } rb_objspace_t; - - #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE -@@ -388,6 +388,7 @@ int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress; - #define gc_num_allocations objspace->gc_num_allocations - #define live_objects objspace->live_objects - #define allocated_objects objspace->allocated_objects -+#define heap_slots_live_after_last_gc objspace->heap_slots_live_after_last_gc - #define finalizer_table objspace->final.table - #define deferred_final_list objspace->final.deferred - #define mark_stack objspace->markstack.buffer -@@ -1410,6 +1411,24 @@ rb_gc_time() - #endif - } - -+/* -+ * call-seq: -+ * GC.heap_slots_live_after_last_gc => Integer -+ * -+ * Returns the number of heap slots which were live after the last garbage collection. -+ * -+ * GC.heap_slots_live_after_last_gc #=> 231223 -+ * -+ */ -+VALUE -+rb_gc_heap_slots_live_after_last_gc() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return ULONG2NUM(heap_slots_live_after_last_gc); -+} -+ -+ -+ - VALUE rb_mGC; - - void -@@ -2616,6 +2635,7 @@ gc_sweep(rb_objspace_t *objspace) - } - during_gc = 0; - live_objects = live; -+ heap_slots_live_after_last_gc = live; - - /* log gc stats if requested */ - if (do_gc_stats) { -@@ -3961,6 +3981,7 @@ Init_GC(void) - rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); - rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); - rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots_live_after_last_gc", rb_gc_heap_slots_live_after_last_gc, 0); - rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); - - rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); diff --git a/patches/ruby/1.9.2/p290/railsexpress/05-load-performance-fix.patch b/patches/ruby/1.9.2/p290/railsexpress/05-load-performance-fix.patch deleted file mode 100644 index abd34090ef..0000000000 --- a/patches/ruby/1.9.2/p290/railsexpress/05-load-performance-fix.patch +++ /dev/null @@ -1,36 +0,0 @@ -diff --git a/load.c b/load.c -index cd19233..94a3f1d 100644 ---- a/load.c -+++ b/load.c -@@ -73,16 +73,27 @@ loaded_feature_path(const char *name, long vlen, const char *feature, long len, - int type, VALUE load_path) - { - long i; -- -+ long plen; -+ const char *e; -+ -+ if(vlen < len) return 0; -+ if (!strncmp(name+(vlen-len),feature,len)){ -+ plen = vlen - len - 1; -+ } else { -+ for (e = name + vlen; name != e && *e != '.' && *e != '/'; --e); -+ if (*e!='.' || -+ e-name < len || -+ strncmp(e-len,feature,len) ) -+ return 0; -+ plen = e - name - len - 1; -+ } - for (i = 0; i < RARRAY_LEN(load_path); ++i) { - VALUE p = RARRAY_PTR(load_path)[i]; - const char *s = StringValuePtr(p); - long n = RSTRING_LEN(p); - -- if (vlen < n + len + 1) continue; -+ if (n != plen ) continue; - if (n && (strncmp(name, s, n) || name[n] != '/')) continue; -- if (strncmp(name + n + 1, feature, len)) continue; -- if (name[n+len+1] && name[n+len+1] != '.') continue; - switch (type) { - case 's': - if (IS_DLEXT(&name[n+len+1])) return p; diff --git a/patches/ruby/1.9.2/p290/railsexpress/06-trace-bmethods.patch b/patches/ruby/1.9.2/p290/railsexpress/06-trace-bmethods.patch deleted file mode 100644 index ef2005dc39..0000000000 --- a/patches/ruby/1.9.2/p290/railsexpress/06-trace-bmethods.patch +++ /dev/null @@ -1,24 +0,0 @@ -commit 9fa6fc6ac323d68ab4166f27247a290e2877e774 -Author: Stefan Kaes -Date: Sun Dec 11 06:57:31 2011 +0100 - - trace bmethods - -diff --git a/vm_insnhelper.c b/vm_insnhelper.c -index 6b78394..bc84327 100644 ---- a/vm_insnhelper.c -+++ b/vm_insnhelper.c -@@ -422,8 +422,13 @@ vm_call_bmethod(rb_thread_t *th, VALUE recv, int argc, const VALUE *argv, - /* control block frame */ - th->passed_me = me; - -+ EXEC_EVENT_HOOK(th, RUBY_EVENT_CALL, recv, me->called_id, me->klass); -+ - GetProcPtr(me->def->body.proc, proc); - val = rb_vm_invoke_proc(th, proc, recv, argc, argv, blockptr); -+ -+ EXEC_EVENT_HOOK(th, RUBY_EVENT_RETURN, recv, me->called_id, me->klass); -+ - return val; - } - diff --git a/patches/ruby/1.9.2/p318/railsexpress/01-railsbench-gc-patch.patch b/patches/ruby/1.9.2/p318/railsexpress/01-railsbench-gc-patch.patch deleted file mode 100644 index 5b4792b3f7..0000000000 --- a/patches/ruby/1.9.2/p318/railsexpress/01-railsbench-gc-patch.patch +++ /dev/null @@ -1,1081 +0,0 @@ -diff --git a/configure.in b/configure.in -index 3f94ac8..591aab9 100644 ---- a/configure.in -+++ b/configure.in -@@ -2209,6 +2209,14 @@ if test "$EXEEXT" = .exe; then - AC_SUBST(EXECUTABLE_EXTS) - fi - -+dnl enable gc debugging -+AC_ARG_ENABLE(gcdebug, -+ [ --enable-gcdebug build garbage collector with debugging enabled. ], -+ [enable_gcdebug=$enableval]) -+if test "$enable_gcdebug" = 'yes'; then -+ AC_DEFINE(GC_DEBUG, 1) -+fi -+ - dnl } - dnl build section { - -diff --git a/gc.c b/gc.c -index 564d260..27d9177 100644 ---- a/gc.c -+++ b/gc.c -@@ -78,6 +78,17 @@ void *alloca (); - #define GC_MALLOC_LIMIT 8000000 - #endif - -+#ifndef HAVE_LONG_LONG -+#define LONG_LONG long -+#endif -+ -+static size_t heap_free_min = 4096; -+static int heap_min_slots = 10000; -+static int heap_slots_increment = 10000; -+static int initial_heap_slots_increment = 10000; -+static double heap_slots_growth_factor = 1.8; -+static size_t initial_malloc_limit = GC_MALLOC_LIMIT; -+ - #define nomem_error GET_VM()->special_exceptions[ruby_error_nomemory] - - #define MARK_STACK_MAX 1024 -@@ -267,7 +278,7 @@ typedef struct RVALUE { - struct RComplex complex; - } as; - #ifdef GC_DEBUG -- const char *file; -+ VALUE file; - int line; - #endif - } RVALUE; -@@ -314,6 +325,8 @@ typedef struct rb_objspace { - struct { - int dont_gc; - int during_gc; -+ int gc_statistics; -+ int verbose_gc_stats; - } flags; - struct { - st_table *table; -@@ -334,6 +347,14 @@ typedef struct rb_objspace { - struct gc_list *global_list; - unsigned int count; - int gc_stress; -+ long heap_size; -+ unsigned LONG_LONG gc_time_accumulator; -+ FILE* gc_data_file; -+ long gc_collections; -+ unsigned LONG_LONG gc_allocated_size; -+ unsigned LONG_LONG gc_num_allocations; -+ unsigned long live_objects; -+ unsigned LONG_LONG allocated_objects; - } rb_objspace_t; - - #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE -@@ -357,6 +378,16 @@ int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress; - #define heaps_freed objspace->heap.freed - #define dont_gc objspace->flags.dont_gc - #define during_gc objspace->flags.during_gc -+#define gc_statistics objspace->flags.gc_statistics -+#define verbose_gc_stats objspace->flags.verbose_gc_stats -+#define heap_size objspace->heap_size -+#define gc_time_accumulator objspace->gc_time_accumulator -+#define gc_data_file objspace->gc_data_file -+#define gc_collections objspace->gc_collections -+#define gc_allocated_size objspace->gc_allocated_size -+#define gc_num_allocations objspace->gc_num_allocations -+#define live_objects objspace->live_objects -+#define allocated_objects objspace->allocated_objects - #define finalizer_table objspace->final.table - #define deferred_final_list objspace->final.deferred - #define mark_stack objspace->markstack.buffer -@@ -375,7 +406,8 @@ rb_objspace_alloc(void) - { - rb_objspace_t *objspace = malloc(sizeof(rb_objspace_t)); - memset(objspace, 0, sizeof(*objspace)); -- malloc_limit = GC_MALLOC_LIMIT; -+ malloc_limit = initial_malloc_limit; -+ - ruby_gc_stress = ruby_initial_gc_stress; - - return objspace; -@@ -409,23 +441,8 @@ rb_objspace_free(rb_objspace_t *objspace) - } - #endif - --/* tiny heap size */ --/* 32KB */ --/*#define HEAP_SIZE 0x8000 */ --/* 128KB */ --/*#define HEAP_SIZE 0x20000 */ --/* 64KB */ --/*#define HEAP_SIZE 0x10000 */ --/* 16KB */ --#define HEAP_SIZE 0x4000 --/* 8KB */ --/*#define HEAP_SIZE 0x2000 */ --/* 4KB */ --/*#define HEAP_SIZE 0x1000 */ --/* 2KB */ --/*#define HEAP_SIZE 0x800 */ -- --#define HEAP_OBJ_LIMIT (HEAP_SIZE / sizeof(struct RVALUE)) -+#define HEAP_OBJ_LIMIT 8000 -+#define HEAP_SIZE (HEAP_OBJ_LIMIT * sizeof(struct RVALUE)) - - extern VALUE rb_cMutex; - extern st_table *rb_class_tbl; -@@ -673,6 +690,11 @@ vm_xmalloc(rb_objspace_t *objspace, size_t size) - mem = (size_t *)mem + 1; - #endif - -+ if (gc_statistics) { -+ gc_allocated_size += size; -+ gc_num_allocations += 1; -+ } -+ - return mem; - } - -@@ -780,6 +802,92 @@ ruby_xfree(void *x) - vm_xfree(&rb_objspace, x); - } - -+static void set_gc_parameters(rb_objspace_t *objspace) -+{ -+ char *envp; -+ -+ gc_data_file = stderr; -+ -+ envp = getenv("RUBY_GC_STATS"); -+ if (envp != NULL) { -+ int i = atoi(envp); -+ if (i > 0) { -+ verbose_gc_stats = 1; -+ } -+ /* child processes should not inherit RUBY_GC_STATS */ -+ ruby_unsetenv("RUBY_GC_STATS"); -+ } -+ -+ envp = getenv("RUBY_GC_DATA_FILE"); -+ if (envp != NULL) { -+ FILE* data_file = fopen(envp, "w"); -+ if (data_file != NULL) { -+ gc_data_file = data_file; -+ } -+ else { -+ fprintf(stderr, "can't open gc log file %s for writing, using default\n", envp); -+ } -+ /* child processes should not inherit RUBY_GC_DATA_FILE to avoid clobbering */ -+ ruby_unsetenv("RUBY_GC_DATA_FILE"); -+ } -+ -+ envp = getenv("RUBY_HEAP_MIN_SLOTS"); -+ if (envp != NULL) { -+ int i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_MIN_SLOTS=%s\n", envp); -+ } -+ if (i > 0) { -+ heap_min_slots = i; -+ } -+ } -+ -+ envp = getenv("RUBY_HEAP_FREE_MIN"); -+ if (envp != NULL) { -+ int i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_FREE_MIN=%s\n", envp); -+ } -+ if (i > 0) { -+ heap_free_min = i; -+ } -+ } -+ -+ envp = getenv("RUBY_HEAP_SLOTS_INCREMENT"); -+ if (envp != NULL) { -+ int i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_INCREMENT=%s\n", envp); -+ } -+ heap_slots_increment = i; -+ initial_heap_slots_increment = heap_slots_increment; -+ } -+ -+ envp = getenv("RUBY_HEAP_SLOTS_GROWTH_FACTOR"); -+ if (envp != NULL) { -+ double d = atof(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_GROWTH_FACTOR=%s\n", envp); -+ } -+ if (d > 0) { -+ heap_slots_growth_factor = d; -+ } -+ } -+ -+ envp = getenv("RUBY_GC_MALLOC_LIMIT"); -+ if (envp != NULL) { -+ long l = atol(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_GC_MALLOC_LIMIT=%s\n", envp); -+ } -+ if (l > 0) { -+ initial_malloc_limit = l; -+ malloc_limit = initial_malloc_limit; -+ } -+ } -+ -+ fflush(gc_data_file); -+} - - /* - * call-seq: -@@ -826,6 +934,454 @@ rb_gc_disable(void) - return old ? Qtrue : Qfalse; - } - -+/* -+ * call-seq: -+ * GC.enable_stats => true or false -+ * -+ * Enables garbage collection statistics, returning true if garbage -+ * collection statistics was already enabled. -+ * -+ * GC.enable_stats #=> false or true -+ * GC.enable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = gc_statistics; -+ gc_statistics = 1; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_stats => true or false -+ * -+ * Disables garbage collection statistics, returning true if garbage -+ * collection statistics was already disabled. -+ * -+ * GC.disable_stats #=> false or true -+ * GC.disable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = gc_statistics; -+ gc_statistics = 0; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.stats_enabled? => true or false -+ * -+ * Check whether GC stats have been enabled. -+ * -+ * GC.stats_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_stats_enabled() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return gc_statistics ? Qtrue : Qfalse; -+} -+ -+ -+/* -+ * call-seq: -+ * GC.clear_stats => nil -+ * -+ * Clears garbage collection statistics, returning nil. This resets the number -+ * of collections (GC.collections) and the time used (GC.time) to 0. -+ * -+ * GC.clear_stats #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_clear_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ gc_collections = 0; -+ gc_time_accumulator = 0; -+ gc_allocated_size = 0; -+ gc_num_allocations = 0; -+ return Qnil; -+} -+ -+/* -+ * call-seq: -+ * GC.allocated_size => Integer -+ * -+ * Returns the size of memory (in bytes) allocated since GC statistics collection -+ * was enabled. -+ * -+ * GC.allocated_size #=> 35 -+ * -+ */ -+ -+VALUE -+rb_gc_allocated_size() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_allocated_size); -+#else -+ return ULONG2NUM(gc_allocated_size); -+#endif -+} -+ -+/* -+ * call-seq: -+ * GC.num_allocations => Integer -+ * -+ * Returns the number of memory allocations since GC statistics collection -+ * was enabled. -+ * -+ * GC.num_allocations #=> 150 -+ * -+ */ -+VALUE -+rb_gc_num_allocations() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_num_allocations); -+#else -+ return ULONG2NUM(gc_num_allocations); -+#endif -+} -+ -+/* -+ * call-seq: -+ * GC.enable_trace => true or false -+ * -+ * Enables garbage collection tracing, returning true if garbage -+ * collection tracing was already enabled. -+ * -+ * GC.enable_trace #=> false or true -+ * GC.enable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_trace() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = verbose_gc_stats; -+ verbose_gc_stats = 1; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_trace => true or false -+ * -+ * Disables garbage collection tracing, returning true if garbage -+ * collection tracing was already disabled. -+ * -+ * GC.disable_trace #=> false or true -+ * GC.disable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_trace() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = verbose_gc_stats; -+ verbose_gc_stats = 0; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.trace_enabled? => true or false -+ * -+ * Check whether GC tracing has been enabled. -+ * -+ * GC.trace_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_trace_enabled() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return verbose_gc_stats ? Qtrue : Qfalse; -+} -+ -+ -+const char* GC_LOGFILE_IVAR = "@gc_logfile_name"; -+ -+/* -+ * call-seq: -+ * GC.log_file(filename=nil, mode="w") => boolean -+ * -+ * Changes the GC data log file. Closes the currently open logfile. -+ * Returns true if the file was successfully opened for -+ * writing. Returns false if the file could not be opened for -+ * writing. Returns the name of the current logfile (or nil) if no -+ * parameter is given. Restores logging to stderr when given nil as -+ * an argument. -+ * -+ * GC.log_file #=> nil -+ * GC.log_file "/tmp/gc.log" #=> true -+ * GC.log_file #=> "/tmp/gc.log" -+ * GC.log_file nil #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_log_file(int argc, VALUE *argv, VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ VALUE filename = Qnil; -+ VALUE mode_str = Qnil; -+ FILE* f = NULL; -+ const char* mode = "w"; -+ -+ VALUE current_logfile_name = rb_iv_get(rb_mGC, GC_LOGFILE_IVAR); -+ -+ if (argc==0) -+ return current_logfile_name; -+ -+ rb_scan_args(argc, argv, "02", &filename, &mode_str); -+ -+ if (filename == Qnil) { -+ /* close current logfile and reset logfile to stderr */ -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+ } -+ return Qtrue; -+ } -+ -+ /* we have a real logfile name */ -+ filename = StringValue(filename); -+ -+ if (rb_equal(current_logfile_name, filename) == Qtrue) { -+ /* do nothing if we get the file name we're already logging to */ -+ return Qtrue; -+ } -+ -+ /* get mode for file opening */ -+ if (mode_str != Qnil) -+ { -+ mode = RSTRING_PTR(StringValue(mode_str)); -+ } -+ -+ /* try to open file in given mode */ -+ if (f = fopen(RSTRING_PTR(filename), mode)) { -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ } -+ gc_data_file = f; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, filename); -+ } else { -+ return Qfalse; -+ } -+ return Qtrue; -+} -+ -+/* -+ * call-seq: -+ * GC.log String => String -+ * -+ * Logs string to the GC data file and returns it. -+ * -+ * GC.log "manual GC call" #=> "manual GC call" -+ * -+ */ -+ -+VALUE -+rb_gc_log(self, original_str) -+ VALUE self, original_str; -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ if (original_str == Qnil) { -+ fprintf(gc_data_file, "\n"); -+ } -+ else { -+ VALUE str = StringValue(original_str); -+ char *p = RSTRING_PTR(str); -+ fprintf(gc_data_file, "%s\n", p); -+ } -+ return original_str; -+} -+ -+/* -+ * call-seq: -+ * GC.dump => nil -+ * -+ * dumps information about the current GC data structures to the GC log file -+ * -+ * GC.dump #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_dump() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ size_t i; -+ -+ for (i = 0; i < heaps_used; i++) { -+ size_t limit = heaps[i].limit; -+ fprintf(gc_data_file, "HEAP[%2lu]: size=%7lu\n", (unsigned long)i, (unsigned long)limit); -+ } -+ -+ return Qnil; -+} -+ -+static const char* obj_type(VALUE tp); -+ -+#ifdef GC_DEBUG -+/* -+ * call-seq: -+ * GC.dump_file_and_line_info(String, boolean) => nil -+ * -+ * dumps information on which currently allocated object was created by which file and on which line -+ * -+ * GC.dump_file_and_line_info(String, boolean) #=> nil -+ * -+ * The second parameter specifies whether class names should be included in the dump. -+ * Note that including class names will allocate additional string objects on the heap. -+ * -+ */ -+ -+VALUE -+rb_gc_dump_file_and_line_info(int argc, VALUE *argv) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ VALUE filename, str, include_classnames = Qnil; -+ char *fname = NULL; -+ char *klass = NULL; -+ FILE* f = NULL; -+ size_t i = 0; -+ -+ rb_scan_args(argc, argv, "11", &filename, &include_classnames); -+ -+ str = StringValue(filename); -+ fname = RSTRING_PTR(str); -+ f = fopen(fname, "w"); -+ -+ for (i = 0; i < heaps_used; i++) { -+ RVALUE *p, *pend; -+ -+ p = heaps[i].slot; pend = p + heaps[i].limit; -+ for (;p < pend; p++) { -+ if (p->as.basic.flags) { -+ const char *src_filename = (p->file && p->file != Qnil )? RSTRING_PTR(p->file) : ""; -+ fprintf(f, "%s:%s:%d", obj_type(p->as.basic.flags & T_MASK), src_filename, (int)p->line); -+ // rb_obj_classname will create objects on the heap, we need a better solution -+ if (include_classnames == Qtrue) { -+ /* write the class */ -+ fprintf(f, ":"); -+ switch (BUILTIN_TYPE(p)) { -+ case T_NONE: -+ fprintf(f, "__none__"); -+ break; -+ case T_UNDEF: -+ fprintf(f, "__undef__"); -+ break; -+ case T_NODE: -+ fprintf(f, "__node__"); -+ break; -+ default: -+ if (!p->as.basic.klass) { -+ fprintf(f, "__unknown__"); -+ } else { -+ fprintf(f, "%s", rb_obj_classname((VALUE)p)); -+ } -+ } -+ /* print object size for some known object types */ -+ switch (BUILTIN_TYPE(p)) { -+ case T_STRING: -+ fprintf(f, ":%lu", RSTRING_LEN(p)); -+ break; -+ case T_ARRAY: -+ fprintf(f, ":%lu", RARRAY_LEN(p)); -+ break; -+ case T_HASH: -+ fprintf(f, ":%lu", (long unsigned int)RHASH_SIZE(p)); -+ break; -+ } -+ } -+ fprintf(f, "\n"); -+ } -+ } -+ } -+ fclose(f); -+ return Qnil; -+} -+#endif -+ -+/* -+ * call-seq: -+ * GC.heap_slots => Integer -+ * -+ * Returns the number of heap slots available for object allocations. -+ * -+ * GC.heap_slots #=> 10000 -+ * -+ */ -+VALUE -+rb_gc_heap_slots() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return LONG2NUM(heap_size); -+} -+ -+ -+/* -+ * call-seq: -+ * GC.collections => Integer -+ * -+ * Returns the number of garbage collections performed while GC statistics collection -+ * was enabled. -+ * -+ * GC.collections #=> 35 -+ * -+ */ -+ -+VALUE -+rb_gc_collections() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return LONG2NUM(gc_collections); -+} -+ -+/* -+ * call-seq: -+ * GC.time => Integer -+ * -+ * Returns the time spent during garbage collection while GC statistics collection -+ * was enabled (in micro seconds). -+ * -+ * GC.time #=> 20000 -+ * -+ */ -+ -+VALUE -+rb_gc_time() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return LL2NUM(gc_time_accumulator); -+#else -+ return LONG2NUM(gc_time_accumulator); -+#endif -+} -+ - VALUE rb_mGC; - - void -@@ -944,6 +1500,7 @@ assign_heap_slot(rb_objspace_t *objspace) - if (lomem == 0 || lomem > p) lomem = p; - if (himem < pend) himem = pend; - heaps_used++; -+ heap_size += objs; - - while (p < pend) { - p->as.free.flags = 0; -@@ -958,7 +1515,7 @@ init_heap(rb_objspace_t *objspace) - { - size_t add, i; - -- add = HEAP_MIN_SLOTS / HEAP_OBJ_LIMIT; -+ add = heap_min_slots / HEAP_OBJ_LIMIT; - - if (!add) { - add = 1; -@@ -979,7 +1536,7 @@ init_heap(rb_objspace_t *objspace) - static void - set_heaps_increment(rb_objspace_t *objspace) - { -- size_t next_heaps_length = (size_t)(heaps_used * 1.8); -+ size_t next_heaps_length = (size_t)(heaps_used * heap_slots_growth_factor); - - if (next_heaps_length == heaps_used) { - next_heaps_length++; -@@ -1005,6 +1562,22 @@ heaps_increment(rb_objspace_t *objspace) - - #define RANY(o) ((RVALUE*)(o)) - -+#ifdef GC_DEBUG -+static VALUE -+_rb_sourcefile(void) -+{ -+ rb_thread_t *th = GET_THREAD(); -+ rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp); -+ -+ if (cfp) { -+ return cfp->iseq->filename; -+ } -+ else { -+ return Qnil; -+ } -+} -+#endif -+ - static VALUE - rb_newobj_from_heap(rb_objspace_t *objspace) - { -@@ -1022,9 +1595,11 @@ rb_newobj_from_heap(rb_objspace_t *objspace) - - MEMZERO((void*)obj, RVALUE, 1); - #ifdef GC_DEBUG -- RANY(obj)->file = rb_sourcefile(); -+ RANY(obj)->file = _rb_sourcefile(); - RANY(obj)->line = rb_sourceline(); - #endif -+ live_objects++; -+ allocated_objects++; - - return obj; - } -@@ -1525,6 +2100,12 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev) - { - register RVALUE *obj = RANY(ptr); - -+#ifdef GC_DEBUG -+ if (obj->file && obj->file != Qnil && is_pointer_to_heap(objspace, (void*)obj->file)) { -+ gc_mark(objspace, obj->file, lev); -+ } -+#endif -+ - goto marking; /* skip */ - - again: -@@ -1534,6 +2115,12 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev) - if (obj->as.basic.flags & FL_MARK) return; /* already marked */ - obj->as.basic.flags |= FL_MARK; - -+#ifdef GC_DEBUG -+ if (obj->file && obj->file != Qnil && is_pointer_to_heap(objspace, (void*)obj->file)) { -+ gc_mark(objspace, obj->file, lev); -+ } -+#endif -+ - marking: - if (FL_TEST(obj, FL_EXIVAR)) { - rb_mark_generic_ivar(ptr); -@@ -1851,6 +2438,39 @@ free_unused_heaps(rb_objspace_t *objspace) - } - } - -+static const char* obj_type(VALUE type) -+{ -+ switch (type) { -+ case T_NIL : return "NIL"; -+ case T_OBJECT : return "OBJECT"; -+ case T_CLASS : return "CLASS"; -+ case T_ICLASS : return "ICLASS"; -+ case T_MODULE : return "MODULE"; -+ case T_FLOAT : return "FLOAT"; -+ case T_COMPLEX: return "COMPLEX"; -+ case T_RATIONAL: return "RATIONAL"; -+ case T_STRING : return "STRING"; -+ case T_REGEXP : return "REGEXP"; -+ case T_ARRAY : return "ARRAY"; -+ case T_FIXNUM : return "FIXNUM"; -+ case T_HASH : return "HASH"; -+ case T_STRUCT : return "STRUCT"; -+ case T_BIGNUM : return "BIGNUM"; -+ case T_FILE : return "FILE"; -+ -+ case T_TRUE : return "TRUE"; -+ case T_FALSE : return "FALSE"; -+ case T_DATA : return "DATA"; -+ case T_MATCH : return "MATCH"; -+ case T_SYMBOL : return "SYMBOL"; -+ case T_ZOMBIE : return "ZOMBIE"; -+ -+ case T_UNDEF : return "UNDEF"; -+ case T_NODE : return "NODE"; -+ default: return "____"; -+ } -+} -+ - static void - gc_sweep(rb_objspace_t *objspace) - { -@@ -1859,12 +2479,27 @@ gc_sweep(rb_objspace_t *objspace) - size_t i; - size_t live = 0, free_min = 0, do_heap_free = 0; - -+ long max_blocks_to_free = heaps_used - (heap_min_slots / HEAP_OBJ_LIMIT); -+ int freed_blocks = 0; -+ -+ unsigned long processed = 0; -+ unsigned long freelist_size = 0; -+ unsigned long zombies = 0; -+ unsigned long free_counts[T_MASK]; -+ unsigned long live_counts[T_MASK]; -+ int do_gc_stats = gc_statistics & verbose_gc_stats; -+ -+ if (do_gc_stats) { -+ MEMZERO((void*)free_counts, unsigned long, T_MASK); -+ MEMZERO((void*)live_counts, unsigned long, T_MASK); -+ } -+ - do_heap_free = (size_t)((heaps_used * HEAP_OBJ_LIMIT) * 0.65); - free_min = (size_t)((heaps_used * HEAP_OBJ_LIMIT) * 0.2); - -- if (free_min < FREE_MIN) { -+ if (free_min < heap_free_min) { - do_heap_free = heaps_used * HEAP_OBJ_LIMIT; -- free_min = FREE_MIN; -+ free_min = heap_free_min; - } - - freelist = 0; -@@ -1881,10 +2516,15 @@ gc_sweep(rb_objspace_t *objspace) - p = heaps[i].slot; pend = p + heaps[i].limit; - while (p < pend) { - if (!(p->as.basic.flags & FL_MARK)) { -+ if (do_gc_stats && !p->as.basic.flags) { -+ /* slot was free before GC */ -+ freelist_size++; -+ } - if (p->as.basic.flags && - ((deferred = obj_free(objspace, (VALUE)p)) || - ((FL_TEST(p, FL_FINALIZE)) && need_call_final))) { - if (!deferred) { -+ if (do_gc_stats) zombies++; - p->as.free.flags = T_ZOMBIE; - RDATA(p)->dfree = 0; - } -@@ -1894,6 +2534,10 @@ gc_sweep(rb_objspace_t *objspace) - final_num++; - } - else { -+ if (do_gc_stats) { -+ VALUE obt = p->as.basic.flags & T_MASK; -+ if (obt) free_counts[obt]++; -+ } - add_freelist(objspace, p); - free_num++; - } -@@ -1901,16 +2545,23 @@ gc_sweep(rb_objspace_t *objspace) - else if (BUILTIN_TYPE(p) == T_ZOMBIE) { - /* objects to be finalized */ - /* do nothing remain marked */ -+ if (do_gc_stats) zombies++; - } - else { - RBASIC(p)->flags &= ~FL_MARK; - live++; -+ if (do_gc_stats) { -+ live_counts[p->as.basic.flags & T_MASK]++; -+ } - } - p++; - } -- if (final_num + free_num == heaps[i].limit && freed > do_heap_free) { -+ if (final_num + free_num == heaps[i].limit && freed > do_heap_free && freed_blocks < max_blocks_to_free) { - RVALUE *pp; - -+ freed_blocks += 1; -+ heap_size -= final_num + free_num; -+ - for (pp = final_list; pp != final; pp = pp->as.free.next) { - RDATA(pp)->dmark = (void (*)())(VALUE)&heaps[i]; - pp->as.free.flags |= FL_SINGLETON; /* freeing page mark */ -@@ -1922,11 +2573,13 @@ gc_sweep(rb_objspace_t *objspace) - else { - freed += free_num; - } -+ processed += heaps[i].limit; - } - GC_PROF_SET_MALLOC_INFO; - if (malloc_increase > malloc_limit) { - malloc_limit += (size_t)((malloc_increase - malloc_limit) * (double)live / (live + freed)); -- if (malloc_limit < GC_MALLOC_LIMIT) malloc_limit = GC_MALLOC_LIMIT; -+ if (malloc_limit < initial_malloc_limit) malloc_limit = initial_malloc_limit; -+ - } - malloc_increase = 0; - if (freed < free_min) { -@@ -1934,6 +2587,25 @@ gc_sweep(rb_objspace_t *objspace) - heaps_increment(objspace); - } - during_gc = 0; -+ live_objects = live; -+ -+ /* log gc stats if requested */ -+ if (do_gc_stats) { -+ fprintf(gc_data_file, "objects processed: %.7lu\n", (unsigned long)processed); -+ fprintf(gc_data_file, "live objects : %.7lu\n", (unsigned long)live); -+ fprintf(gc_data_file, "freelist objects : %.7lu\n", (unsigned long)freelist_size); -+ fprintf(gc_data_file, "freed objects : %.7lu\n", (unsigned long)freed); -+ fprintf(gc_data_file, "zombies : %.7lu\n", (unsigned long)zombies); -+ for(i=0; i0 || live_counts[i]>0) { -+ fprintf(gc_data_file, -+ "kept %.7lu / freed %.7lu objects of type %s\n", -+ (unsigned long)live_counts[i], (unsigned long)free_counts[i], obj_type((int)i)); -+ } -+ } -+ rb_gc_dump(); -+ fflush(gc_data_file); -+ } - - /* clear finalization list */ - if (final_list) { -@@ -2140,6 +2812,7 @@ void rb_gc_mark_encodings(void); - static int - garbage_collect(rb_objspace_t *objspace) - { -+ struct timeval gctv1, gctv2; - struct gc_list *list; - rb_thread_t *th = GET_THREAD(); - INIT_GC_PROF_PARAMS; -@@ -2162,6 +2835,14 @@ garbage_collect(rb_objspace_t *objspace) - during_gc++; - objspace->count++; - -+ if (gc_statistics) { -+ gc_collections++; -+ gettimeofday(&gctv1, NULL); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "Garbage collection started\n"); -+ } -+ } -+ - GC_PROF_TIMER_START; - GC_PROF_MARK_TIMER_START; - SET_STACK_END; -@@ -2216,6 +2897,19 @@ garbage_collect(rb_objspace_t *objspace) - - GC_PROF_TIMER_STOP; - if (GC_NOTIFY) printf("end garbage_collect()\n"); -+ -+ if (gc_statistics) { -+ unsigned LONG_LONG musecs_used; -+ gettimeofday(&gctv2, NULL); -+ musecs_used = ((unsigned LONG_LONG)(gctv2.tv_sec - gctv1.tv_sec) * 1000000) + (gctv2.tv_usec - gctv1.tv_usec); -+ gc_time_accumulator += musecs_used; -+ -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "GC time: %lu msec\n", (unsigned long)(musecs_used / 1000)); -+ fflush(gc_data_file); -+ } -+ } -+ - return TRUE; - } - -@@ -2298,6 +2992,7 @@ Init_stack(volatile VALUE *addr) - void - Init_heap(void) - { -+ set_gc_parameters(&rb_objspace); - init_heap(&rb_objspace); - } - -@@ -2982,6 +3677,49 @@ count_objects(int argc, VALUE *argv, VALUE os) - return hash; - } - -+/* call-seq: -+ * ObjectSpace.live_objects => number -+ * -+ * Returns the count of objects currently allocated in the system. This goes -+ * down after the garbage collector runs. -+ */ -+static -+VALUE os_live_objects(VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return ULONG2NUM(live_objects); -+} -+ -+unsigned long rb_os_live_objects() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return live_objects; -+} -+ -+/* call-seq: -+ * ObjectSpace.allocated_objects => number -+ * -+ * Returns the count of objects allocated since the Ruby interpreter has -+ * started. This number can only increase. To know how many objects are -+ * currently allocated, use ObjectSpace::live_objects -+ */ -+static -+VALUE os_allocated_objects(VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if defined(HAVE_LONG_LONG) -+ return ULL2NUM(allocated_objects); -+#else -+ return ULONG2NUM(allocated_objects); -+#endif -+} -+ -+unsigned LONG_LONG rb_os_allocated_objects() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return allocated_objects; -+} -+ - /* - * call-seq: - * GC.count -> Integer -@@ -3188,6 +3926,28 @@ Init_GC(void) - rb_define_singleton_method(rb_mGC, "count", gc_count, 0); - rb_define_method(rb_mGC, "garbage_collect", rb_gc_start, 0); - -+ rb_define_singleton_method(rb_mGC, "enable_stats", rb_gc_enable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "disable_stats", rb_gc_disable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "stats_enabled?", rb_gc_stats_enabled, 0); -+ rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0); -+ rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); -+ rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); -+ -+ rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); -+ rb_define_singleton_method(rb_mGC, "log_file", rb_gc_log_file, -1); -+ rb_define_singleton_method(rb_mGC, "enable_trace", rb_gc_enable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "disable_trace", rb_gc_disable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "trace_enabled?", rb_gc_trace_enabled, 0); -+ -+ rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); -+ rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); -+ rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); -+#ifdef GC_DEBUG -+ rb_define_singleton_method(rb_mGC, "dump_file_and_line_info", rb_gc_dump_file_and_line_info, -1); -+#endif -+ - 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); -@@ -3201,6 +3961,9 @@ Init_GC(void) - rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1); - rb_define_module_function(rb_mObSpace, "garbage_collect", rb_gc_start, 0); - -+ rb_define_module_function(rb_mObSpace, "live_objects", os_live_objects, 0); -+ rb_define_module_function(rb_mObSpace, "allocated_objects", os_allocated_objects, 0); -+ - rb_define_module_function(rb_mObSpace, "define_finalizer", define_final, -1); - rb_define_module_function(rb_mObSpace, "undefine_finalizer", undefine_final, 1); - -diff --git a/sample/test.rb b/sample/test.rb -old mode 100644 -new mode 100755 diff --git a/patches/ruby/1.9.2/p318/railsexpress/02-display-more-detailed-stack-trace.patch b/patches/ruby/1.9.2/p318/railsexpress/02-display-more-detailed-stack-trace.patch deleted file mode 100644 index 232b7ff6ce..0000000000 --- a/patches/ruby/1.9.2/p318/railsexpress/02-display-more-detailed-stack-trace.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/eval_error.c b/eval_error.c -index 41fcbb0..9e065f9 100644 ---- a/eval_error.c -+++ b/eval_error.c -@@ -166,8 +166,8 @@ error_print(void) - int skip = eclass == rb_eSysStackError; - - #define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5) --#define TRACE_HEAD 8 --#define TRACE_TAIL 5 -+#define TRACE_HEAD 100 -+#define TRACE_TAIL 100 - - for (i = 1; i < len; i++) { - if (TYPE(ptr[i]) == T_STRING) { diff --git a/patches/ruby/1.9.2/p318/railsexpress/03-fork-support-for-gc-logging.patch b/patches/ruby/1.9.2/p318/railsexpress/03-fork-support-for-gc-logging.patch deleted file mode 100644 index 7126c9103e..0000000000 --- a/patches/ruby/1.9.2/p318/railsexpress/03-fork-support-for-gc-logging.patch +++ /dev/null @@ -1,68 +0,0 @@ -diff --git a/gc.c b/gc.c -index 27d9177..7673687 100644 ---- a/gc.c -+++ b/gc.c -@@ -1193,6 +1193,34 @@ rb_gc_log_file(int argc, VALUE *argv, VALUE self) - } - - /* -+ * Called from process.c before a fork. Flushes the gc log file to -+ * avoid writing the buffered output twice (once in the parent, and -+ * once in the child). -+ */ -+void -+rb_gc_before_fork() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ fflush(gc_data_file); -+} -+ -+/* -+ * Called from process.c after a fork in the child process. Turns off -+ * logging, disables GC stats and resets all gc counters and timing -+ * information. -+ */ -+void -+rb_gc_after_fork() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ rb_gc_disable_stats(); -+ rb_gc_clear_stats(); -+ rb_gc_disable_trace(); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+} -+ -+/* - * call-seq: - * GC.log String => String - * -diff --git a/include/ruby/intern.h b/include/ruby/intern.h -index f0cff67..a374c7e 100644 ---- a/include/ruby/intern.h -+++ b/include/ruby/intern.h -@@ -390,6 +390,8 @@ void rb_gc_call_finalizer_at_exit(void); - VALUE rb_gc_enable(void); - VALUE rb_gc_disable(void); - VALUE rb_gc_start(void); -+void rb_gc_before_fork _((void)); -+void rb_gc_after_fork _((void)); - #define Init_stack(addr) ruby_init_stack(addr) - /* hash.c */ - void st_foreach_safe(struct st_table *, int (*)(ANYARGS), st_data_t); -diff --git a/process.c b/process.c -index c180492..d20d44c 100644 ---- a/process.c -+++ b/process.c -@@ -2617,9 +2617,11 @@ rb_f_fork(VALUE obj) - rb_pid_t pid; - - rb_secure(2); -+ rb_gc_before_fork(); - - switch (pid = rb_fork(0, 0, 0, Qnil)) { - case 0: -+ rb_gc_after_fork(); - rb_thread_atfork(); - if (rb_block_given_p()) { - int status; diff --git a/patches/ruby/1.9.2/p318/railsexpress/04-track-live-dataset-size.patch b/patches/ruby/1.9.2/p318/railsexpress/04-track-live-dataset-size.patch deleted file mode 100644 index 9f28390919..0000000000 --- a/patches/ruby/1.9.2/p318/railsexpress/04-track-live-dataset-size.patch +++ /dev/null @@ -1,69 +0,0 @@ -diff --git a/gc.c b/gc.c -index 7673687..4d9ca88 100644 ---- a/gc.c -+++ b/gc.c -@@ -248,7 +248,6 @@ getrusage_time(void) - } while(0) - #endif - -- - #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__) - #pragma pack(push, 1) /* magic for reducing sizeof(RVALUE): 24 -> 20 */ - #endif -@@ -355,6 +354,7 @@ typedef struct rb_objspace { - unsigned LONG_LONG gc_num_allocations; - unsigned long live_objects; - unsigned LONG_LONG allocated_objects; -+ unsigned long heap_slots_live_after_last_gc; - } rb_objspace_t; - - #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE -@@ -388,6 +388,7 @@ int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress; - #define gc_num_allocations objspace->gc_num_allocations - #define live_objects objspace->live_objects - #define allocated_objects objspace->allocated_objects -+#define heap_slots_live_after_last_gc objspace->heap_slots_live_after_last_gc - #define finalizer_table objspace->final.table - #define deferred_final_list objspace->final.deferred - #define mark_stack objspace->markstack.buffer -@@ -1410,6 +1411,24 @@ rb_gc_time() - #endif - } - -+/* -+ * call-seq: -+ * GC.heap_slots_live_after_last_gc => Integer -+ * -+ * Returns the number of heap slots which were live after the last garbage collection. -+ * -+ * GC.heap_slots_live_after_last_gc #=> 231223 -+ * -+ */ -+VALUE -+rb_gc_heap_slots_live_after_last_gc() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return ULONG2NUM(heap_slots_live_after_last_gc); -+} -+ -+ -+ - VALUE rb_mGC; - - void -@@ -2616,6 +2635,7 @@ gc_sweep(rb_objspace_t *objspace) - } - during_gc = 0; - live_objects = live; -+ heap_slots_live_after_last_gc = live; - - /* log gc stats if requested */ - if (do_gc_stats) { -@@ -3961,6 +3981,7 @@ Init_GC(void) - rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); - rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); - rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots_live_after_last_gc", rb_gc_heap_slots_live_after_last_gc, 0); - rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); - - rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); diff --git a/patches/ruby/1.9.2/p320/railsexpress/01-railsbench-gc-patch.patch b/patches/ruby/1.9.2/p320/railsexpress/01-railsbench-gc-patch.patch deleted file mode 100644 index 5b4792b3f7..0000000000 --- a/patches/ruby/1.9.2/p320/railsexpress/01-railsbench-gc-patch.patch +++ /dev/null @@ -1,1081 +0,0 @@ -diff --git a/configure.in b/configure.in -index 3f94ac8..591aab9 100644 ---- a/configure.in -+++ b/configure.in -@@ -2209,6 +2209,14 @@ if test "$EXEEXT" = .exe; then - AC_SUBST(EXECUTABLE_EXTS) - fi - -+dnl enable gc debugging -+AC_ARG_ENABLE(gcdebug, -+ [ --enable-gcdebug build garbage collector with debugging enabled. ], -+ [enable_gcdebug=$enableval]) -+if test "$enable_gcdebug" = 'yes'; then -+ AC_DEFINE(GC_DEBUG, 1) -+fi -+ - dnl } - dnl build section { - -diff --git a/gc.c b/gc.c -index 564d260..27d9177 100644 ---- a/gc.c -+++ b/gc.c -@@ -78,6 +78,17 @@ void *alloca (); - #define GC_MALLOC_LIMIT 8000000 - #endif - -+#ifndef HAVE_LONG_LONG -+#define LONG_LONG long -+#endif -+ -+static size_t heap_free_min = 4096; -+static int heap_min_slots = 10000; -+static int heap_slots_increment = 10000; -+static int initial_heap_slots_increment = 10000; -+static double heap_slots_growth_factor = 1.8; -+static size_t initial_malloc_limit = GC_MALLOC_LIMIT; -+ - #define nomem_error GET_VM()->special_exceptions[ruby_error_nomemory] - - #define MARK_STACK_MAX 1024 -@@ -267,7 +278,7 @@ typedef struct RVALUE { - struct RComplex complex; - } as; - #ifdef GC_DEBUG -- const char *file; -+ VALUE file; - int line; - #endif - } RVALUE; -@@ -314,6 +325,8 @@ typedef struct rb_objspace { - struct { - int dont_gc; - int during_gc; -+ int gc_statistics; -+ int verbose_gc_stats; - } flags; - struct { - st_table *table; -@@ -334,6 +347,14 @@ typedef struct rb_objspace { - struct gc_list *global_list; - unsigned int count; - int gc_stress; -+ long heap_size; -+ unsigned LONG_LONG gc_time_accumulator; -+ FILE* gc_data_file; -+ long gc_collections; -+ unsigned LONG_LONG gc_allocated_size; -+ unsigned LONG_LONG gc_num_allocations; -+ unsigned long live_objects; -+ unsigned LONG_LONG allocated_objects; - } rb_objspace_t; - - #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE -@@ -357,6 +378,16 @@ int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress; - #define heaps_freed objspace->heap.freed - #define dont_gc objspace->flags.dont_gc - #define during_gc objspace->flags.during_gc -+#define gc_statistics objspace->flags.gc_statistics -+#define verbose_gc_stats objspace->flags.verbose_gc_stats -+#define heap_size objspace->heap_size -+#define gc_time_accumulator objspace->gc_time_accumulator -+#define gc_data_file objspace->gc_data_file -+#define gc_collections objspace->gc_collections -+#define gc_allocated_size objspace->gc_allocated_size -+#define gc_num_allocations objspace->gc_num_allocations -+#define live_objects objspace->live_objects -+#define allocated_objects objspace->allocated_objects - #define finalizer_table objspace->final.table - #define deferred_final_list objspace->final.deferred - #define mark_stack objspace->markstack.buffer -@@ -375,7 +406,8 @@ rb_objspace_alloc(void) - { - rb_objspace_t *objspace = malloc(sizeof(rb_objspace_t)); - memset(objspace, 0, sizeof(*objspace)); -- malloc_limit = GC_MALLOC_LIMIT; -+ malloc_limit = initial_malloc_limit; -+ - ruby_gc_stress = ruby_initial_gc_stress; - - return objspace; -@@ -409,23 +441,8 @@ rb_objspace_free(rb_objspace_t *objspace) - } - #endif - --/* tiny heap size */ --/* 32KB */ --/*#define HEAP_SIZE 0x8000 */ --/* 128KB */ --/*#define HEAP_SIZE 0x20000 */ --/* 64KB */ --/*#define HEAP_SIZE 0x10000 */ --/* 16KB */ --#define HEAP_SIZE 0x4000 --/* 8KB */ --/*#define HEAP_SIZE 0x2000 */ --/* 4KB */ --/*#define HEAP_SIZE 0x1000 */ --/* 2KB */ --/*#define HEAP_SIZE 0x800 */ -- --#define HEAP_OBJ_LIMIT (HEAP_SIZE / sizeof(struct RVALUE)) -+#define HEAP_OBJ_LIMIT 8000 -+#define HEAP_SIZE (HEAP_OBJ_LIMIT * sizeof(struct RVALUE)) - - extern VALUE rb_cMutex; - extern st_table *rb_class_tbl; -@@ -673,6 +690,11 @@ vm_xmalloc(rb_objspace_t *objspace, size_t size) - mem = (size_t *)mem + 1; - #endif - -+ if (gc_statistics) { -+ gc_allocated_size += size; -+ gc_num_allocations += 1; -+ } -+ - return mem; - } - -@@ -780,6 +802,92 @@ ruby_xfree(void *x) - vm_xfree(&rb_objspace, x); - } - -+static void set_gc_parameters(rb_objspace_t *objspace) -+{ -+ char *envp; -+ -+ gc_data_file = stderr; -+ -+ envp = getenv("RUBY_GC_STATS"); -+ if (envp != NULL) { -+ int i = atoi(envp); -+ if (i > 0) { -+ verbose_gc_stats = 1; -+ } -+ /* child processes should not inherit RUBY_GC_STATS */ -+ ruby_unsetenv("RUBY_GC_STATS"); -+ } -+ -+ envp = getenv("RUBY_GC_DATA_FILE"); -+ if (envp != NULL) { -+ FILE* data_file = fopen(envp, "w"); -+ if (data_file != NULL) { -+ gc_data_file = data_file; -+ } -+ else { -+ fprintf(stderr, "can't open gc log file %s for writing, using default\n", envp); -+ } -+ /* child processes should not inherit RUBY_GC_DATA_FILE to avoid clobbering */ -+ ruby_unsetenv("RUBY_GC_DATA_FILE"); -+ } -+ -+ envp = getenv("RUBY_HEAP_MIN_SLOTS"); -+ if (envp != NULL) { -+ int i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_MIN_SLOTS=%s\n", envp); -+ } -+ if (i > 0) { -+ heap_min_slots = i; -+ } -+ } -+ -+ envp = getenv("RUBY_HEAP_FREE_MIN"); -+ if (envp != NULL) { -+ int i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_FREE_MIN=%s\n", envp); -+ } -+ if (i > 0) { -+ heap_free_min = i; -+ } -+ } -+ -+ envp = getenv("RUBY_HEAP_SLOTS_INCREMENT"); -+ if (envp != NULL) { -+ int i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_INCREMENT=%s\n", envp); -+ } -+ heap_slots_increment = i; -+ initial_heap_slots_increment = heap_slots_increment; -+ } -+ -+ envp = getenv("RUBY_HEAP_SLOTS_GROWTH_FACTOR"); -+ if (envp != NULL) { -+ double d = atof(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_GROWTH_FACTOR=%s\n", envp); -+ } -+ if (d > 0) { -+ heap_slots_growth_factor = d; -+ } -+ } -+ -+ envp = getenv("RUBY_GC_MALLOC_LIMIT"); -+ if (envp != NULL) { -+ long l = atol(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_GC_MALLOC_LIMIT=%s\n", envp); -+ } -+ if (l > 0) { -+ initial_malloc_limit = l; -+ malloc_limit = initial_malloc_limit; -+ } -+ } -+ -+ fflush(gc_data_file); -+} - - /* - * call-seq: -@@ -826,6 +934,454 @@ rb_gc_disable(void) - return old ? Qtrue : Qfalse; - } - -+/* -+ * call-seq: -+ * GC.enable_stats => true or false -+ * -+ * Enables garbage collection statistics, returning true if garbage -+ * collection statistics was already enabled. -+ * -+ * GC.enable_stats #=> false or true -+ * GC.enable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = gc_statistics; -+ gc_statistics = 1; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_stats => true or false -+ * -+ * Disables garbage collection statistics, returning true if garbage -+ * collection statistics was already disabled. -+ * -+ * GC.disable_stats #=> false or true -+ * GC.disable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = gc_statistics; -+ gc_statistics = 0; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.stats_enabled? => true or false -+ * -+ * Check whether GC stats have been enabled. -+ * -+ * GC.stats_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_stats_enabled() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return gc_statistics ? Qtrue : Qfalse; -+} -+ -+ -+/* -+ * call-seq: -+ * GC.clear_stats => nil -+ * -+ * Clears garbage collection statistics, returning nil. This resets the number -+ * of collections (GC.collections) and the time used (GC.time) to 0. -+ * -+ * GC.clear_stats #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_clear_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ gc_collections = 0; -+ gc_time_accumulator = 0; -+ gc_allocated_size = 0; -+ gc_num_allocations = 0; -+ return Qnil; -+} -+ -+/* -+ * call-seq: -+ * GC.allocated_size => Integer -+ * -+ * Returns the size of memory (in bytes) allocated since GC statistics collection -+ * was enabled. -+ * -+ * GC.allocated_size #=> 35 -+ * -+ */ -+ -+VALUE -+rb_gc_allocated_size() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_allocated_size); -+#else -+ return ULONG2NUM(gc_allocated_size); -+#endif -+} -+ -+/* -+ * call-seq: -+ * GC.num_allocations => Integer -+ * -+ * Returns the number of memory allocations since GC statistics collection -+ * was enabled. -+ * -+ * GC.num_allocations #=> 150 -+ * -+ */ -+VALUE -+rb_gc_num_allocations() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_num_allocations); -+#else -+ return ULONG2NUM(gc_num_allocations); -+#endif -+} -+ -+/* -+ * call-seq: -+ * GC.enable_trace => true or false -+ * -+ * Enables garbage collection tracing, returning true if garbage -+ * collection tracing was already enabled. -+ * -+ * GC.enable_trace #=> false or true -+ * GC.enable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_trace() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = verbose_gc_stats; -+ verbose_gc_stats = 1; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_trace => true or false -+ * -+ * Disables garbage collection tracing, returning true if garbage -+ * collection tracing was already disabled. -+ * -+ * GC.disable_trace #=> false or true -+ * GC.disable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_trace() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = verbose_gc_stats; -+ verbose_gc_stats = 0; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.trace_enabled? => true or false -+ * -+ * Check whether GC tracing has been enabled. -+ * -+ * GC.trace_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_trace_enabled() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return verbose_gc_stats ? Qtrue : Qfalse; -+} -+ -+ -+const char* GC_LOGFILE_IVAR = "@gc_logfile_name"; -+ -+/* -+ * call-seq: -+ * GC.log_file(filename=nil, mode="w") => boolean -+ * -+ * Changes the GC data log file. Closes the currently open logfile. -+ * Returns true if the file was successfully opened for -+ * writing. Returns false if the file could not be opened for -+ * writing. Returns the name of the current logfile (or nil) if no -+ * parameter is given. Restores logging to stderr when given nil as -+ * an argument. -+ * -+ * GC.log_file #=> nil -+ * GC.log_file "/tmp/gc.log" #=> true -+ * GC.log_file #=> "/tmp/gc.log" -+ * GC.log_file nil #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_log_file(int argc, VALUE *argv, VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ VALUE filename = Qnil; -+ VALUE mode_str = Qnil; -+ FILE* f = NULL; -+ const char* mode = "w"; -+ -+ VALUE current_logfile_name = rb_iv_get(rb_mGC, GC_LOGFILE_IVAR); -+ -+ if (argc==0) -+ return current_logfile_name; -+ -+ rb_scan_args(argc, argv, "02", &filename, &mode_str); -+ -+ if (filename == Qnil) { -+ /* close current logfile and reset logfile to stderr */ -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+ } -+ return Qtrue; -+ } -+ -+ /* we have a real logfile name */ -+ filename = StringValue(filename); -+ -+ if (rb_equal(current_logfile_name, filename) == Qtrue) { -+ /* do nothing if we get the file name we're already logging to */ -+ return Qtrue; -+ } -+ -+ /* get mode for file opening */ -+ if (mode_str != Qnil) -+ { -+ mode = RSTRING_PTR(StringValue(mode_str)); -+ } -+ -+ /* try to open file in given mode */ -+ if (f = fopen(RSTRING_PTR(filename), mode)) { -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ } -+ gc_data_file = f; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, filename); -+ } else { -+ return Qfalse; -+ } -+ return Qtrue; -+} -+ -+/* -+ * call-seq: -+ * GC.log String => String -+ * -+ * Logs string to the GC data file and returns it. -+ * -+ * GC.log "manual GC call" #=> "manual GC call" -+ * -+ */ -+ -+VALUE -+rb_gc_log(self, original_str) -+ VALUE self, original_str; -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ if (original_str == Qnil) { -+ fprintf(gc_data_file, "\n"); -+ } -+ else { -+ VALUE str = StringValue(original_str); -+ char *p = RSTRING_PTR(str); -+ fprintf(gc_data_file, "%s\n", p); -+ } -+ return original_str; -+} -+ -+/* -+ * call-seq: -+ * GC.dump => nil -+ * -+ * dumps information about the current GC data structures to the GC log file -+ * -+ * GC.dump #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_dump() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ size_t i; -+ -+ for (i = 0; i < heaps_used; i++) { -+ size_t limit = heaps[i].limit; -+ fprintf(gc_data_file, "HEAP[%2lu]: size=%7lu\n", (unsigned long)i, (unsigned long)limit); -+ } -+ -+ return Qnil; -+} -+ -+static const char* obj_type(VALUE tp); -+ -+#ifdef GC_DEBUG -+/* -+ * call-seq: -+ * GC.dump_file_and_line_info(String, boolean) => nil -+ * -+ * dumps information on which currently allocated object was created by which file and on which line -+ * -+ * GC.dump_file_and_line_info(String, boolean) #=> nil -+ * -+ * The second parameter specifies whether class names should be included in the dump. -+ * Note that including class names will allocate additional string objects on the heap. -+ * -+ */ -+ -+VALUE -+rb_gc_dump_file_and_line_info(int argc, VALUE *argv) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ VALUE filename, str, include_classnames = Qnil; -+ char *fname = NULL; -+ char *klass = NULL; -+ FILE* f = NULL; -+ size_t i = 0; -+ -+ rb_scan_args(argc, argv, "11", &filename, &include_classnames); -+ -+ str = StringValue(filename); -+ fname = RSTRING_PTR(str); -+ f = fopen(fname, "w"); -+ -+ for (i = 0; i < heaps_used; i++) { -+ RVALUE *p, *pend; -+ -+ p = heaps[i].slot; pend = p + heaps[i].limit; -+ for (;p < pend; p++) { -+ if (p->as.basic.flags) { -+ const char *src_filename = (p->file && p->file != Qnil )? RSTRING_PTR(p->file) : ""; -+ fprintf(f, "%s:%s:%d", obj_type(p->as.basic.flags & T_MASK), src_filename, (int)p->line); -+ // rb_obj_classname will create objects on the heap, we need a better solution -+ if (include_classnames == Qtrue) { -+ /* write the class */ -+ fprintf(f, ":"); -+ switch (BUILTIN_TYPE(p)) { -+ case T_NONE: -+ fprintf(f, "__none__"); -+ break; -+ case T_UNDEF: -+ fprintf(f, "__undef__"); -+ break; -+ case T_NODE: -+ fprintf(f, "__node__"); -+ break; -+ default: -+ if (!p->as.basic.klass) { -+ fprintf(f, "__unknown__"); -+ } else { -+ fprintf(f, "%s", rb_obj_classname((VALUE)p)); -+ } -+ } -+ /* print object size for some known object types */ -+ switch (BUILTIN_TYPE(p)) { -+ case T_STRING: -+ fprintf(f, ":%lu", RSTRING_LEN(p)); -+ break; -+ case T_ARRAY: -+ fprintf(f, ":%lu", RARRAY_LEN(p)); -+ break; -+ case T_HASH: -+ fprintf(f, ":%lu", (long unsigned int)RHASH_SIZE(p)); -+ break; -+ } -+ } -+ fprintf(f, "\n"); -+ } -+ } -+ } -+ fclose(f); -+ return Qnil; -+} -+#endif -+ -+/* -+ * call-seq: -+ * GC.heap_slots => Integer -+ * -+ * Returns the number of heap slots available for object allocations. -+ * -+ * GC.heap_slots #=> 10000 -+ * -+ */ -+VALUE -+rb_gc_heap_slots() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return LONG2NUM(heap_size); -+} -+ -+ -+/* -+ * call-seq: -+ * GC.collections => Integer -+ * -+ * Returns the number of garbage collections performed while GC statistics collection -+ * was enabled. -+ * -+ * GC.collections #=> 35 -+ * -+ */ -+ -+VALUE -+rb_gc_collections() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return LONG2NUM(gc_collections); -+} -+ -+/* -+ * call-seq: -+ * GC.time => Integer -+ * -+ * Returns the time spent during garbage collection while GC statistics collection -+ * was enabled (in micro seconds). -+ * -+ * GC.time #=> 20000 -+ * -+ */ -+ -+VALUE -+rb_gc_time() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return LL2NUM(gc_time_accumulator); -+#else -+ return LONG2NUM(gc_time_accumulator); -+#endif -+} -+ - VALUE rb_mGC; - - void -@@ -944,6 +1500,7 @@ assign_heap_slot(rb_objspace_t *objspace) - if (lomem == 0 || lomem > p) lomem = p; - if (himem < pend) himem = pend; - heaps_used++; -+ heap_size += objs; - - while (p < pend) { - p->as.free.flags = 0; -@@ -958,7 +1515,7 @@ init_heap(rb_objspace_t *objspace) - { - size_t add, i; - -- add = HEAP_MIN_SLOTS / HEAP_OBJ_LIMIT; -+ add = heap_min_slots / HEAP_OBJ_LIMIT; - - if (!add) { - add = 1; -@@ -979,7 +1536,7 @@ init_heap(rb_objspace_t *objspace) - static void - set_heaps_increment(rb_objspace_t *objspace) - { -- size_t next_heaps_length = (size_t)(heaps_used * 1.8); -+ size_t next_heaps_length = (size_t)(heaps_used * heap_slots_growth_factor); - - if (next_heaps_length == heaps_used) { - next_heaps_length++; -@@ -1005,6 +1562,22 @@ heaps_increment(rb_objspace_t *objspace) - - #define RANY(o) ((RVALUE*)(o)) - -+#ifdef GC_DEBUG -+static VALUE -+_rb_sourcefile(void) -+{ -+ rb_thread_t *th = GET_THREAD(); -+ rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp); -+ -+ if (cfp) { -+ return cfp->iseq->filename; -+ } -+ else { -+ return Qnil; -+ } -+} -+#endif -+ - static VALUE - rb_newobj_from_heap(rb_objspace_t *objspace) - { -@@ -1022,9 +1595,11 @@ rb_newobj_from_heap(rb_objspace_t *objspace) - - MEMZERO((void*)obj, RVALUE, 1); - #ifdef GC_DEBUG -- RANY(obj)->file = rb_sourcefile(); -+ RANY(obj)->file = _rb_sourcefile(); - RANY(obj)->line = rb_sourceline(); - #endif -+ live_objects++; -+ allocated_objects++; - - return obj; - } -@@ -1525,6 +2100,12 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev) - { - register RVALUE *obj = RANY(ptr); - -+#ifdef GC_DEBUG -+ if (obj->file && obj->file != Qnil && is_pointer_to_heap(objspace, (void*)obj->file)) { -+ gc_mark(objspace, obj->file, lev); -+ } -+#endif -+ - goto marking; /* skip */ - - again: -@@ -1534,6 +2115,12 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev) - if (obj->as.basic.flags & FL_MARK) return; /* already marked */ - obj->as.basic.flags |= FL_MARK; - -+#ifdef GC_DEBUG -+ if (obj->file && obj->file != Qnil && is_pointer_to_heap(objspace, (void*)obj->file)) { -+ gc_mark(objspace, obj->file, lev); -+ } -+#endif -+ - marking: - if (FL_TEST(obj, FL_EXIVAR)) { - rb_mark_generic_ivar(ptr); -@@ -1851,6 +2438,39 @@ free_unused_heaps(rb_objspace_t *objspace) - } - } - -+static const char* obj_type(VALUE type) -+{ -+ switch (type) { -+ case T_NIL : return "NIL"; -+ case T_OBJECT : return "OBJECT"; -+ case T_CLASS : return "CLASS"; -+ case T_ICLASS : return "ICLASS"; -+ case T_MODULE : return "MODULE"; -+ case T_FLOAT : return "FLOAT"; -+ case T_COMPLEX: return "COMPLEX"; -+ case T_RATIONAL: return "RATIONAL"; -+ case T_STRING : return "STRING"; -+ case T_REGEXP : return "REGEXP"; -+ case T_ARRAY : return "ARRAY"; -+ case T_FIXNUM : return "FIXNUM"; -+ case T_HASH : return "HASH"; -+ case T_STRUCT : return "STRUCT"; -+ case T_BIGNUM : return "BIGNUM"; -+ case T_FILE : return "FILE"; -+ -+ case T_TRUE : return "TRUE"; -+ case T_FALSE : return "FALSE"; -+ case T_DATA : return "DATA"; -+ case T_MATCH : return "MATCH"; -+ case T_SYMBOL : return "SYMBOL"; -+ case T_ZOMBIE : return "ZOMBIE"; -+ -+ case T_UNDEF : return "UNDEF"; -+ case T_NODE : return "NODE"; -+ default: return "____"; -+ } -+} -+ - static void - gc_sweep(rb_objspace_t *objspace) - { -@@ -1859,12 +2479,27 @@ gc_sweep(rb_objspace_t *objspace) - size_t i; - size_t live = 0, free_min = 0, do_heap_free = 0; - -+ long max_blocks_to_free = heaps_used - (heap_min_slots / HEAP_OBJ_LIMIT); -+ int freed_blocks = 0; -+ -+ unsigned long processed = 0; -+ unsigned long freelist_size = 0; -+ unsigned long zombies = 0; -+ unsigned long free_counts[T_MASK]; -+ unsigned long live_counts[T_MASK]; -+ int do_gc_stats = gc_statistics & verbose_gc_stats; -+ -+ if (do_gc_stats) { -+ MEMZERO((void*)free_counts, unsigned long, T_MASK); -+ MEMZERO((void*)live_counts, unsigned long, T_MASK); -+ } -+ - do_heap_free = (size_t)((heaps_used * HEAP_OBJ_LIMIT) * 0.65); - free_min = (size_t)((heaps_used * HEAP_OBJ_LIMIT) * 0.2); - -- if (free_min < FREE_MIN) { -+ if (free_min < heap_free_min) { - do_heap_free = heaps_used * HEAP_OBJ_LIMIT; -- free_min = FREE_MIN; -+ free_min = heap_free_min; - } - - freelist = 0; -@@ -1881,10 +2516,15 @@ gc_sweep(rb_objspace_t *objspace) - p = heaps[i].slot; pend = p + heaps[i].limit; - while (p < pend) { - if (!(p->as.basic.flags & FL_MARK)) { -+ if (do_gc_stats && !p->as.basic.flags) { -+ /* slot was free before GC */ -+ freelist_size++; -+ } - if (p->as.basic.flags && - ((deferred = obj_free(objspace, (VALUE)p)) || - ((FL_TEST(p, FL_FINALIZE)) && need_call_final))) { - if (!deferred) { -+ if (do_gc_stats) zombies++; - p->as.free.flags = T_ZOMBIE; - RDATA(p)->dfree = 0; - } -@@ -1894,6 +2534,10 @@ gc_sweep(rb_objspace_t *objspace) - final_num++; - } - else { -+ if (do_gc_stats) { -+ VALUE obt = p->as.basic.flags & T_MASK; -+ if (obt) free_counts[obt]++; -+ } - add_freelist(objspace, p); - free_num++; - } -@@ -1901,16 +2545,23 @@ gc_sweep(rb_objspace_t *objspace) - else if (BUILTIN_TYPE(p) == T_ZOMBIE) { - /* objects to be finalized */ - /* do nothing remain marked */ -+ if (do_gc_stats) zombies++; - } - else { - RBASIC(p)->flags &= ~FL_MARK; - live++; -+ if (do_gc_stats) { -+ live_counts[p->as.basic.flags & T_MASK]++; -+ } - } - p++; - } -- if (final_num + free_num == heaps[i].limit && freed > do_heap_free) { -+ if (final_num + free_num == heaps[i].limit && freed > do_heap_free && freed_blocks < max_blocks_to_free) { - RVALUE *pp; - -+ freed_blocks += 1; -+ heap_size -= final_num + free_num; -+ - for (pp = final_list; pp != final; pp = pp->as.free.next) { - RDATA(pp)->dmark = (void (*)())(VALUE)&heaps[i]; - pp->as.free.flags |= FL_SINGLETON; /* freeing page mark */ -@@ -1922,11 +2573,13 @@ gc_sweep(rb_objspace_t *objspace) - else { - freed += free_num; - } -+ processed += heaps[i].limit; - } - GC_PROF_SET_MALLOC_INFO; - if (malloc_increase > malloc_limit) { - malloc_limit += (size_t)((malloc_increase - malloc_limit) * (double)live / (live + freed)); -- if (malloc_limit < GC_MALLOC_LIMIT) malloc_limit = GC_MALLOC_LIMIT; -+ if (malloc_limit < initial_malloc_limit) malloc_limit = initial_malloc_limit; -+ - } - malloc_increase = 0; - if (freed < free_min) { -@@ -1934,6 +2587,25 @@ gc_sweep(rb_objspace_t *objspace) - heaps_increment(objspace); - } - during_gc = 0; -+ live_objects = live; -+ -+ /* log gc stats if requested */ -+ if (do_gc_stats) { -+ fprintf(gc_data_file, "objects processed: %.7lu\n", (unsigned long)processed); -+ fprintf(gc_data_file, "live objects : %.7lu\n", (unsigned long)live); -+ fprintf(gc_data_file, "freelist objects : %.7lu\n", (unsigned long)freelist_size); -+ fprintf(gc_data_file, "freed objects : %.7lu\n", (unsigned long)freed); -+ fprintf(gc_data_file, "zombies : %.7lu\n", (unsigned long)zombies); -+ for(i=0; i0 || live_counts[i]>0) { -+ fprintf(gc_data_file, -+ "kept %.7lu / freed %.7lu objects of type %s\n", -+ (unsigned long)live_counts[i], (unsigned long)free_counts[i], obj_type((int)i)); -+ } -+ } -+ rb_gc_dump(); -+ fflush(gc_data_file); -+ } - - /* clear finalization list */ - if (final_list) { -@@ -2140,6 +2812,7 @@ void rb_gc_mark_encodings(void); - static int - garbage_collect(rb_objspace_t *objspace) - { -+ struct timeval gctv1, gctv2; - struct gc_list *list; - rb_thread_t *th = GET_THREAD(); - INIT_GC_PROF_PARAMS; -@@ -2162,6 +2835,14 @@ garbage_collect(rb_objspace_t *objspace) - during_gc++; - objspace->count++; - -+ if (gc_statistics) { -+ gc_collections++; -+ gettimeofday(&gctv1, NULL); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "Garbage collection started\n"); -+ } -+ } -+ - GC_PROF_TIMER_START; - GC_PROF_MARK_TIMER_START; - SET_STACK_END; -@@ -2216,6 +2897,19 @@ garbage_collect(rb_objspace_t *objspace) - - GC_PROF_TIMER_STOP; - if (GC_NOTIFY) printf("end garbage_collect()\n"); -+ -+ if (gc_statistics) { -+ unsigned LONG_LONG musecs_used; -+ gettimeofday(&gctv2, NULL); -+ musecs_used = ((unsigned LONG_LONG)(gctv2.tv_sec - gctv1.tv_sec) * 1000000) + (gctv2.tv_usec - gctv1.tv_usec); -+ gc_time_accumulator += musecs_used; -+ -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "GC time: %lu msec\n", (unsigned long)(musecs_used / 1000)); -+ fflush(gc_data_file); -+ } -+ } -+ - return TRUE; - } - -@@ -2298,6 +2992,7 @@ Init_stack(volatile VALUE *addr) - void - Init_heap(void) - { -+ set_gc_parameters(&rb_objspace); - init_heap(&rb_objspace); - } - -@@ -2982,6 +3677,49 @@ count_objects(int argc, VALUE *argv, VALUE os) - return hash; - } - -+/* call-seq: -+ * ObjectSpace.live_objects => number -+ * -+ * Returns the count of objects currently allocated in the system. This goes -+ * down after the garbage collector runs. -+ */ -+static -+VALUE os_live_objects(VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return ULONG2NUM(live_objects); -+} -+ -+unsigned long rb_os_live_objects() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return live_objects; -+} -+ -+/* call-seq: -+ * ObjectSpace.allocated_objects => number -+ * -+ * Returns the count of objects allocated since the Ruby interpreter has -+ * started. This number can only increase. To know how many objects are -+ * currently allocated, use ObjectSpace::live_objects -+ */ -+static -+VALUE os_allocated_objects(VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if defined(HAVE_LONG_LONG) -+ return ULL2NUM(allocated_objects); -+#else -+ return ULONG2NUM(allocated_objects); -+#endif -+} -+ -+unsigned LONG_LONG rb_os_allocated_objects() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return allocated_objects; -+} -+ - /* - * call-seq: - * GC.count -> Integer -@@ -3188,6 +3926,28 @@ Init_GC(void) - rb_define_singleton_method(rb_mGC, "count", gc_count, 0); - rb_define_method(rb_mGC, "garbage_collect", rb_gc_start, 0); - -+ rb_define_singleton_method(rb_mGC, "enable_stats", rb_gc_enable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "disable_stats", rb_gc_disable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "stats_enabled?", rb_gc_stats_enabled, 0); -+ rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0); -+ rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); -+ rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); -+ -+ rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); -+ rb_define_singleton_method(rb_mGC, "log_file", rb_gc_log_file, -1); -+ rb_define_singleton_method(rb_mGC, "enable_trace", rb_gc_enable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "disable_trace", rb_gc_disable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "trace_enabled?", rb_gc_trace_enabled, 0); -+ -+ rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); -+ rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); -+ rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); -+#ifdef GC_DEBUG -+ rb_define_singleton_method(rb_mGC, "dump_file_and_line_info", rb_gc_dump_file_and_line_info, -1); -+#endif -+ - 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); -@@ -3201,6 +3961,9 @@ Init_GC(void) - rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1); - rb_define_module_function(rb_mObSpace, "garbage_collect", rb_gc_start, 0); - -+ rb_define_module_function(rb_mObSpace, "live_objects", os_live_objects, 0); -+ rb_define_module_function(rb_mObSpace, "allocated_objects", os_allocated_objects, 0); -+ - rb_define_module_function(rb_mObSpace, "define_finalizer", define_final, -1); - rb_define_module_function(rb_mObSpace, "undefine_finalizer", undefine_final, 1); - -diff --git a/sample/test.rb b/sample/test.rb -old mode 100644 -new mode 100755 diff --git a/patches/ruby/1.9.2/p320/railsexpress/02-display-more-detailed-stack-trace.patch b/patches/ruby/1.9.2/p320/railsexpress/02-display-more-detailed-stack-trace.patch deleted file mode 100644 index 232b7ff6ce..0000000000 --- a/patches/ruby/1.9.2/p320/railsexpress/02-display-more-detailed-stack-trace.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/eval_error.c b/eval_error.c -index 41fcbb0..9e065f9 100644 ---- a/eval_error.c -+++ b/eval_error.c -@@ -166,8 +166,8 @@ error_print(void) - int skip = eclass == rb_eSysStackError; - - #define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5) --#define TRACE_HEAD 8 --#define TRACE_TAIL 5 -+#define TRACE_HEAD 100 -+#define TRACE_TAIL 100 - - for (i = 1; i < len; i++) { - if (TYPE(ptr[i]) == T_STRING) { diff --git a/patches/ruby/1.9.2/p320/railsexpress/03-fork-support-for-gc-logging.patch b/patches/ruby/1.9.2/p320/railsexpress/03-fork-support-for-gc-logging.patch deleted file mode 100644 index 7126c9103e..0000000000 --- a/patches/ruby/1.9.2/p320/railsexpress/03-fork-support-for-gc-logging.patch +++ /dev/null @@ -1,68 +0,0 @@ -diff --git a/gc.c b/gc.c -index 27d9177..7673687 100644 ---- a/gc.c -+++ b/gc.c -@@ -1193,6 +1193,34 @@ rb_gc_log_file(int argc, VALUE *argv, VALUE self) - } - - /* -+ * Called from process.c before a fork. Flushes the gc log file to -+ * avoid writing the buffered output twice (once in the parent, and -+ * once in the child). -+ */ -+void -+rb_gc_before_fork() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ fflush(gc_data_file); -+} -+ -+/* -+ * Called from process.c after a fork in the child process. Turns off -+ * logging, disables GC stats and resets all gc counters and timing -+ * information. -+ */ -+void -+rb_gc_after_fork() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ rb_gc_disable_stats(); -+ rb_gc_clear_stats(); -+ rb_gc_disable_trace(); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+} -+ -+/* - * call-seq: - * GC.log String => String - * -diff --git a/include/ruby/intern.h b/include/ruby/intern.h -index f0cff67..a374c7e 100644 ---- a/include/ruby/intern.h -+++ b/include/ruby/intern.h -@@ -390,6 +390,8 @@ void rb_gc_call_finalizer_at_exit(void); - VALUE rb_gc_enable(void); - VALUE rb_gc_disable(void); - VALUE rb_gc_start(void); -+void rb_gc_before_fork _((void)); -+void rb_gc_after_fork _((void)); - #define Init_stack(addr) ruby_init_stack(addr) - /* hash.c */ - void st_foreach_safe(struct st_table *, int (*)(ANYARGS), st_data_t); -diff --git a/process.c b/process.c -index c180492..d20d44c 100644 ---- a/process.c -+++ b/process.c -@@ -2617,9 +2617,11 @@ rb_f_fork(VALUE obj) - rb_pid_t pid; - - rb_secure(2); -+ rb_gc_before_fork(); - - switch (pid = rb_fork(0, 0, 0, Qnil)) { - case 0: -+ rb_gc_after_fork(); - rb_thread_atfork(); - if (rb_block_given_p()) { - int status; diff --git a/patches/ruby/1.9.2/p320/railsexpress/04-track-live-dataset-size.patch b/patches/ruby/1.9.2/p320/railsexpress/04-track-live-dataset-size.patch deleted file mode 100644 index 9f28390919..0000000000 --- a/patches/ruby/1.9.2/p320/railsexpress/04-track-live-dataset-size.patch +++ /dev/null @@ -1,69 +0,0 @@ -diff --git a/gc.c b/gc.c -index 7673687..4d9ca88 100644 ---- a/gc.c -+++ b/gc.c -@@ -248,7 +248,6 @@ getrusage_time(void) - } while(0) - #endif - -- - #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__) - #pragma pack(push, 1) /* magic for reducing sizeof(RVALUE): 24 -> 20 */ - #endif -@@ -355,6 +354,7 @@ typedef struct rb_objspace { - unsigned LONG_LONG gc_num_allocations; - unsigned long live_objects; - unsigned LONG_LONG allocated_objects; -+ unsigned long heap_slots_live_after_last_gc; - } rb_objspace_t; - - #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE -@@ -388,6 +388,7 @@ int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress; - #define gc_num_allocations objspace->gc_num_allocations - #define live_objects objspace->live_objects - #define allocated_objects objspace->allocated_objects -+#define heap_slots_live_after_last_gc objspace->heap_slots_live_after_last_gc - #define finalizer_table objspace->final.table - #define deferred_final_list objspace->final.deferred - #define mark_stack objspace->markstack.buffer -@@ -1410,6 +1411,24 @@ rb_gc_time() - #endif - } - -+/* -+ * call-seq: -+ * GC.heap_slots_live_after_last_gc => Integer -+ * -+ * Returns the number of heap slots which were live after the last garbage collection. -+ * -+ * GC.heap_slots_live_after_last_gc #=> 231223 -+ * -+ */ -+VALUE -+rb_gc_heap_slots_live_after_last_gc() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return ULONG2NUM(heap_slots_live_after_last_gc); -+} -+ -+ -+ - VALUE rb_mGC; - - void -@@ -2616,6 +2635,7 @@ gc_sweep(rb_objspace_t *objspace) - } - during_gc = 0; - live_objects = live; -+ heap_slots_live_after_last_gc = live; - - /* log gc stats if requested */ - if (do_gc_stats) { -@@ -3961,6 +3981,7 @@ Init_GC(void) - rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); - rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); - rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots_live_after_last_gc", rb_gc_heap_slots_live_after_last_gc, 0); - rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); - - rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); diff --git a/patches/ruby/1.9.3/head/railsexpress/01-fix-make-clean.patch b/patches/ruby/1.9.3/head/railsexpress/01-fix-make-clean.patch deleted file mode 100644 index ef39286ea5..0000000000 --- a/patches/ruby/1.9.3/head/railsexpress/01-fix-make-clean.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/lib/mkmf.rb b/lib/mkmf.rb -index a751761..f019132 100644 ---- a/lib/mkmf.rb -+++ b/lib/mkmf.rb -@@ -2193,7 +2193,7 @@ def init_mkmf(config = CONFIG, rbconfig = RbConfig::CONFIG) - $LOCAL_LIBS = "" - - $cleanfiles = config_string('CLEANFILES') {|s| Shellwords.shellwords(s)} || [] -- $cleanfiles << "mkmf.log" -+ $cleanfiles << "mkmf.log .*.time" - $distcleanfiles = config_string('DISTCLEANFILES') {|s| Shellwords.shellwords(s)} || [] - $distcleandirs = config_string('DISTCLEANDIRS') {|s| Shellwords.shellwords(s)} || [] - diff --git a/patches/ruby/1.9.3/head/railsexpress/02-railsbench-gc.patch b/patches/ruby/1.9.3/head/railsexpress/02-railsbench-gc.patch deleted file mode 100644 index d7d753baf2..0000000000 --- a/patches/ruby/1.9.3/head/railsexpress/02-railsbench-gc.patch +++ /dev/null @@ -1,1235 +0,0 @@ -diff --git a/configure.in b/configure.in -index 849bb7b..28ddc31 100644 ---- a/configure.in -+++ b/configure.in -@@ -2426,6 +2426,10 @@ if test "$EXEEXT" = .exe; then - AC_SUBST(EXECUTABLE_EXTS) - fi - -+dnl enable gc debugging -+AC_ARG_ENABLE(gcdebug, -+ AS_HELP_STRING([--enable-gcdebug], [build garbage collector with debugging enabled]), -+ [AC_DEFINE(GC_DEBUG,1)]) - dnl } - dnl build section { - -diff --git a/gc.c b/gc.c -index 0f84e22..feb54f1 100644 ---- a/gc.c -+++ b/gc.c -@@ -98,6 +98,15 @@ ruby_gc_params_t initial_params = { - #endif - }; - -+#ifndef HAVE_LONG_LONG -+#define LONG_LONG long -+#endif -+ -+static int heap_min_slots = 10000; -+static int heap_slots_increment = 10000; -+static int initial_heap_slots_increment = 10000; -+static double heap_slots_growth_factor = 1.8; -+ - #define nomem_error GET_VM()->special_exceptions[ruby_error_nomemory] - - #if SIZEOF_LONG == SIZEOF_VOIDP -@@ -302,7 +311,7 @@ typedef struct RVALUE { - struct RComplex complex; - } as; - #ifdef GC_DEBUG -- const char *file; -+ VALUE file; - int line; - #endif - } RVALUE; -@@ -372,11 +381,25 @@ typedef struct rb_objspace { - size_t free_min; - size_t final_num; - size_t do_heap_free; -+ unsigned long max_blocks_to_free; -+ unsigned long freed_blocks; - } heap; - struct { -+ unsigned long processed; -+ unsigned long freed_objects; -+ unsigned long freelist_size; -+ unsigned long zombies; -+ unsigned long free_counts[T_MASK+1]; -+ unsigned long live_counts[T_MASK+1]; -+ unsigned long gc_time_accumulator_before_gc; -+ unsigned long live_after_last_mark_phase; -+ } stats; -+ struct { - int dont_gc; - int dont_lazy_sweep; - int during_gc; -+ int gc_statistics; -+ int verbose_gc_stats; - } flags; - struct { - st_table *table; -@@ -393,6 +416,14 @@ typedef struct rb_objspace { - struct gc_list *global_list; - size_t count; - int gc_stress; -+ long heap_size; -+ unsigned LONG_LONG gc_time_accumulator; -+ FILE* gc_data_file; -+ long gc_collections; -+ unsigned LONG_LONG gc_allocated_size; -+ unsigned LONG_LONG gc_num_allocations; -+ unsigned long live_objects; -+ unsigned LONG_LONG allocated_objects; - } rb_objspace_t; - - #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE -@@ -415,6 +446,16 @@ int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress; - #define heaps_freed objspace->heap.freed - #define dont_gc objspace->flags.dont_gc - #define during_gc objspace->flags.during_gc -+#define gc_statistics objspace->flags.gc_statistics -+#define verbose_gc_stats objspace->flags.verbose_gc_stats -+#define heap_size objspace->heap_size -+#define gc_time_accumulator objspace->gc_time_accumulator -+#define gc_data_file objspace->gc_data_file -+#define gc_collections objspace->gc_collections -+#define gc_allocated_size objspace->gc_allocated_size -+#define gc_num_allocations objspace->gc_num_allocations -+#define live_objects objspace->live_objects -+#define allocated_objects objspace->allocated_objects - #define finalizer_table objspace->final.table - #define deferred_final_list objspace->final.deferred - #define global_List objspace->global_list -@@ -422,6 +463,14 @@ int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress; - #define initial_malloc_limit initial_params.initial_malloc_limit - #define initial_heap_min_slots initial_params.initial_heap_min_slots - #define initial_free_min initial_params.initial_free_min -+#define free_counts objspace->stats.free_counts -+#define live_counts objspace->stats.live_counts -+#define processed objspace->stats.processed -+#define zombies objspace->stats.zombies -+#define freelist_size objspace->stats.freelist_size -+#define freed_objects objspace->stats.freed_objects -+#define gc_time_accumulator_before_gc objspace->stats.gc_time_accumulator_before_gc -+#define live_after_last_mark_phase objspace->stats.live_after_last_mark_phase - - static void rb_objspace_call_finalizer(rb_objspace_t *objspace); - -@@ -444,24 +493,59 @@ static void init_mark_stack(mark_stack_t *stack); - void - rb_gc_set_params(void) - { -- char *malloc_limit_ptr, *heap_min_slots_ptr, *free_min_ptr; -+ char *envp; -+ -+ rb_objspace_t *objspace = &rb_objspace; -+ -+ gc_data_file = stderr; - - if (rb_safe_level() > 0) return; - -- malloc_limit_ptr = getenv("RUBY_GC_MALLOC_LIMIT"); -- if (malloc_limit_ptr != NULL) { -- int malloc_limit_i = atoi(malloc_limit_ptr); -+ envp = getenv("RUBY_GC_STATS"); -+ if (envp != NULL) { -+ int i = atoi(envp); -+ if (i > 0) { -+ verbose_gc_stats = 1; -+ fprintf(stderr, "RUBY_GC_STATS=%d\n", verbose_gc_stats); -+ } -+ /* child processes should not inherit RUBY_GC_STATS */ -+ ruby_unsetenv("RUBY_GC_STATS"); -+ } -+ -+ envp = getenv("RUBY_GC_DATA_FILE"); -+ if (envp != NULL) { -+ FILE* data_file = fopen(envp, "w"); -+ if (data_file != NULL) { -+ gc_data_file = data_file; -+ } -+ else { -+ fprintf(stderr, "can't open gc log file %s for writing, using default\n", envp); -+ } -+ /* child processes should not inherit RUBY_GC_DATA_FILE to avoid clobbering */ -+ ruby_unsetenv("RUBY_GC_DATA_FILE"); -+ } -+ -+ envp = getenv("RUBY_GC_MALLOC_LIMIT"); -+ if (envp != NULL) { -+ int malloc_limit_i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_GC_MALLOC_LIMIT=%s\n", envp); -+ } - if (RTEST(ruby_verbose)) - fprintf(stderr, "malloc_limit=%d (%d)\n", - malloc_limit_i, initial_malloc_limit); - if (malloc_limit_i > 0) { - initial_malloc_limit = malloc_limit_i; -+ // malloc_limit = initial_malloc_limit; - } - } - -- heap_min_slots_ptr = getenv("RUBY_HEAP_MIN_SLOTS"); -- if (heap_min_slots_ptr != NULL) { -- int heap_min_slots_i = atoi(heap_min_slots_ptr); -+ envp = getenv("RUBY_HEAP_MIN_SLOTS"); -+ if (envp != NULL) { -+ int heap_min_slots_i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_MIN_SLOTS=%s\n", envp); -+ } - if (RTEST(ruby_verbose)) - fprintf(stderr, "heap_min_slots=%d (%d)\n", - heap_min_slots_i, initial_heap_min_slots); -@@ -471,15 +555,42 @@ rb_gc_set_params(void) - } - } - -- free_min_ptr = getenv("RUBY_FREE_MIN"); -- if (free_min_ptr != NULL) { -- int free_min_i = atoi(free_min_ptr); -+ if (!(envp = getenv("RUBY_FREE_MIN"))) -+ envp = getenv("RUBY_HEAP_FREE_MIN"); -+ if (envp != NULL) { -+ int free_min_i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_FREE_MIN=%s\n", envp); -+ } - if (RTEST(ruby_verbose)) - fprintf(stderr, "free_min=%d (%d)\n", free_min_i, initial_free_min); - if (free_min_i > 0) { - initial_free_min = free_min_i; - } - } -+ -+ envp = getenv("RUBY_HEAP_SLOTS_INCREMENT"); -+ if (envp != NULL) { -+ int i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_INCREMENT=%s\n", envp); -+ } -+ heap_slots_increment = i; -+ initial_heap_slots_increment = heap_slots_increment; -+ } -+ -+ envp = getenv("RUBY_HEAP_SLOTS_GROWTH_FACTOR"); -+ if (envp != NULL) { -+ double d = atof(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_GROWTH_FACTOR=%s\n", envp); -+ } -+ if (d > 0) { -+ heap_slots_growth_factor = d; -+ } -+ } -+ -+ fflush(gc_data_file); - } - - #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE -@@ -776,6 +887,11 @@ vm_malloc_fixup(rb_objspace_t *objspace, void *mem, size_t size) - mem = (size_t *)mem + 1; - #endif - -+ if (gc_statistics) { -+ gc_allocated_size += size; -+ gc_num_allocations += 1; -+ } -+ - return mem; - } - -@@ -836,6 +952,13 @@ vm_xrealloc(rb_objspace_t *objspace, void *ptr, size_t size) - mem = (size_t *)mem + 1; - #endif - -+ /* TODO: we can't count correctly unless we store old size on heap -+ if (gc_statistics) { -+ gc_allocated_size += size; -+ gc_num_allocations += 1; -+ } -+ */ -+ - return mem; - } - -@@ -917,7 +1040,6 @@ ruby_xfree(void *x) - vm_xfree(&rb_objspace, x); - } - -- - /* - * call-seq: - * GC.enable -> true or false -@@ -963,6 +1085,455 @@ rb_gc_disable(void) - return old ? Qtrue : Qfalse; - } - -+/* -+ * call-seq: -+ * GC.enable_stats => true or false -+ * -+ * Enables garbage collection statistics, returning true if garbage -+ * collection statistics was already enabled. -+ * -+ * GC.enable_stats #=> false or true -+ * GC.enable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = gc_statistics; -+ gc_statistics = 1; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_stats => true or false -+ * -+ * Disables garbage collection statistics, returning true if garbage -+ * collection statistics was already disabled. -+ * -+ * GC.disable_stats #=> false or true -+ * GC.disable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = gc_statistics; -+ gc_statistics = 0; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.stats_enabled? => true or false -+ * -+ * Check whether GC stats have been enabled. -+ * -+ * GC.stats_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_stats_enabled() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return gc_statistics ? Qtrue : Qfalse; -+} -+ -+ -+/* -+ * call-seq: -+ * GC.clear_stats => nil -+ * -+ * Clears garbage collection statistics, returning nil. This resets the number -+ * of collections (GC.collections) and the time used (GC.time) to 0. -+ * -+ * GC.clear_stats #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_clear_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ gc_collections = 0; -+ gc_time_accumulator = 0; -+ gc_time_accumulator_before_gc = 0; -+ gc_allocated_size = 0; -+ gc_num_allocations = 0; -+ return Qnil; -+} -+ -+/* -+ * call-seq: -+ * GC.allocated_size => Integer -+ * -+ * Returns the size of memory (in bytes) allocated since GC statistics collection -+ * was enabled. -+ * -+ * GC.allocated_size #=> 35 -+ * -+ */ -+ -+VALUE -+rb_gc_allocated_size() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_allocated_size); -+#else -+ return ULONG2NUM(gc_allocated_size); -+#endif -+} -+ -+/* -+ * call-seq: -+ * GC.num_allocations => Integer -+ * -+ * Returns the number of memory allocations since GC statistics collection -+ * was enabled. -+ * -+ * GC.num_allocations #=> 150 -+ * -+ */ -+VALUE -+rb_gc_num_allocations() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_num_allocations); -+#else -+ return ULONG2NUM(gc_num_allocations); -+#endif -+} -+ -+/* -+ * call-seq: -+ * GC.enable_trace => true or false -+ * -+ * Enables garbage collection tracing, returning true if garbage -+ * collection tracing was already enabled. -+ * -+ * GC.enable_trace #=> false or true -+ * GC.enable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_trace() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = verbose_gc_stats; -+ verbose_gc_stats = 1; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_trace => true or false -+ * -+ * Disables garbage collection tracing, returning true if garbage -+ * collection tracing was already disabled. -+ * -+ * GC.disable_trace #=> false or true -+ * GC.disable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_trace() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = verbose_gc_stats; -+ verbose_gc_stats = 0; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.trace_enabled? => true or false -+ * -+ * Check whether GC tracing has been enabled. -+ * -+ * GC.trace_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_trace_enabled() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return verbose_gc_stats ? Qtrue : Qfalse; -+} -+ -+ -+const char* GC_LOGFILE_IVAR = "@gc_logfile_name"; -+ -+/* -+ * call-seq: -+ * GC.log_file(filename=nil, mode="w") => boolean -+ * -+ * Changes the GC data log file. Closes the currently open logfile. -+ * Returns true if the file was successfully opened for -+ * writing. Returns false if the file could not be opened for -+ * writing. Returns the name of the current logfile (or nil) if no -+ * parameter is given. Restores logging to stderr when given nil as -+ * an argument. -+ * -+ * GC.log_file #=> nil -+ * GC.log_file "/tmp/gc.log" #=> true -+ * GC.log_file #=> "/tmp/gc.log" -+ * GC.log_file nil #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_log_file(int argc, VALUE *argv, VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ VALUE filename = Qnil; -+ VALUE mode_str = Qnil; -+ FILE* f = NULL; -+ const char* mode = "w"; -+ -+ VALUE current_logfile_name = rb_iv_get(rb_mGC, GC_LOGFILE_IVAR); -+ -+ if (argc==0) -+ return current_logfile_name; -+ -+ rb_scan_args(argc, argv, "02", &filename, &mode_str); -+ -+ if (filename == Qnil) { -+ /* close current logfile and reset logfile to stderr */ -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+ } -+ return Qtrue; -+ } -+ -+ /* we have a real logfile name */ -+ filename = StringValue(filename); -+ -+ if (rb_equal(current_logfile_name, filename) == Qtrue) { -+ /* do nothing if we get the file name we're already logging to */ -+ return Qtrue; -+ } -+ -+ /* get mode for file opening */ -+ if (mode_str != Qnil) -+ { -+ mode = RSTRING_PTR(StringValue(mode_str)); -+ } -+ -+ /* try to open file in given mode */ -+ if (f = fopen(RSTRING_PTR(filename), mode)) { -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ } -+ gc_data_file = f; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, filename); -+ } else { -+ return Qfalse; -+ } -+ return Qtrue; -+} -+ -+/* -+ * call-seq: -+ * GC.log String => String -+ * -+ * Logs string to the GC data file and returns it. -+ * -+ * GC.log "manual GC call" #=> "manual GC call" -+ * -+ */ -+ -+VALUE -+rb_gc_log(self, original_str) -+ VALUE self, original_str; -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ if (original_str == Qnil) { -+ fprintf(gc_data_file, "\n"); -+ } -+ else { -+ VALUE str = StringValue(original_str); -+ char *p = RSTRING_PTR(str); -+ fprintf(gc_data_file, "%s\n", p); -+ } -+ return original_str; -+} -+ -+/* -+ * call-seq: -+ * GC.dump => nil -+ * -+ * dumps information about the current GC data structures to the GC log file -+ * -+ * GC.dump #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_dump() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ size_t i; -+ -+ for (i = 0; i < heaps_used; i++) { -+ size_t limit = objspace->heap.sorted[i].slot->limit; -+ fprintf(gc_data_file, "HEAP[%2lu]: size=%7lu\n", (unsigned long)i, (unsigned long)limit); -+ } -+ -+ return Qnil; -+} -+ -+static const char* obj_type(VALUE tp); -+ -+#ifdef GC_DEBUG -+/* -+ * call-seq: -+ * GC.dump_file_and_line_info(String, boolean) => nil -+ * -+ * dumps information on which currently allocated object was created by which file and on which line -+ * -+ * GC.dump_file_and_line_info(String, boolean) #=> nil -+ * -+ * The second parameter specifies whether class names should be included in the dump. -+ * Note that including class names will allocate additional string objects on the heap. -+ * -+ */ -+ -+VALUE -+rb_gc_dump_file_and_line_info(int argc, VALUE *argv) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ VALUE filename, str, include_classnames = Qnil; -+ char *fname = NULL; -+ char *klass = NULL; -+ FILE* f = NULL; -+ size_t i = 0; -+ -+ rb_scan_args(argc, argv, "11", &filename, &include_classnames); -+ -+ str = StringValue(filename); -+ fname = RSTRING_PTR(str); -+ f = fopen(fname, "w"); -+ -+ for (i = 0; i < heaps_used; i++) { -+ RVALUE *p, *pend; -+ -+ p = objspace->heap.sorted[i].start; pend = objspace->heap.sorted[i].end; -+ for (;p < pend; p++) { -+ if (p->as.basic.flags) { -+ const char *src_filename = (p->file && p->file != Qnil )? RSTRING_PTR(p->file) : ""; -+ fprintf(f, "%s:%s:%d", obj_type(p->as.basic.flags & T_MASK), src_filename, (int)p->line); -+ // rb_obj_classname will create objects on the heap, we need a better solution -+ if (include_classnames == Qtrue) { -+ /* write the class */ -+ fprintf(f, ":"); -+ switch (BUILTIN_TYPE(p)) { -+ case T_NONE: -+ fprintf(f, "__none__"); -+ break; -+ case T_UNDEF: -+ fprintf(f, "__undef__"); -+ break; -+ case T_NODE: -+ fprintf(f, "__node__"); -+ break; -+ default: -+ if (!p->as.basic.klass) { -+ fprintf(f, "__unknown__"); -+ } else { -+ fprintf(f, "%s", rb_obj_classname((VALUE)p)); -+ } -+ } -+ /* print object size for some known object types */ -+ switch (BUILTIN_TYPE(p)) { -+ case T_STRING: -+ fprintf(f, ":%lu", RSTRING_LEN(p)); -+ break; -+ case T_ARRAY: -+ fprintf(f, ":%lu", RARRAY_LEN(p)); -+ break; -+ case T_HASH: -+ fprintf(f, ":%lu", (long unsigned int)RHASH_SIZE(p)); -+ break; -+ } -+ } -+ fprintf(f, "\n"); -+ } -+ } -+ } -+ fclose(f); -+ return Qnil; -+} -+#endif -+ -+/* -+ * call-seq: -+ * GC.heap_slots => Integer -+ * -+ * Returns the number of heap slots available for object allocations. -+ * -+ * GC.heap_slots #=> 10000 -+ * -+ */ -+VALUE -+rb_gc_heap_slots() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return LONG2NUM(heap_size); -+} -+ -+ -+/* -+ * call-seq: -+ * GC.collections => Integer -+ * -+ * Returns the number of garbage collections performed while GC statistics collection -+ * was enabled. -+ * -+ * GC.collections #=> 35 -+ * -+ */ -+ -+VALUE -+rb_gc_collections() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return LONG2NUM(gc_collections); -+} -+ -+/* -+ * call-seq: -+ * GC.time => Integer -+ * -+ * Returns the time spent during garbage collection while GC statistics collection -+ * was enabled (in micro seconds). -+ * -+ * GC.time #=> 20000 -+ * -+ */ -+ -+VALUE -+rb_gc_time() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return LL2NUM(gc_time_accumulator); -+#else -+ return LONG2NUM(gc_time_accumulator); -+#endif -+} -+ - VALUE rb_mGC; - - void -@@ -1034,6 +1605,12 @@ allocate_sorted_heaps(rb_objspace_t *objspace, size_t next_heaps_length) - static void - assign_heap_slot(rb_objspace_t *objspace) - { -+ /* -+ if (gc_statistics & verbose_gc_stats) { -+ fprintf(gc_data_file, "assigning heap slot\n"); -+ } -+ */ -+ - RVALUE *p, *pend, *membase; - struct heaps_slot *slot; - size_t hi, lo, mid; -@@ -1095,6 +1672,7 @@ assign_heap_slot(rb_objspace_t *objspace) - if (lomem == 0 || lomem > p) lomem = p; - if (himem < pend) himem = pend; - heaps_used++; -+ heap_size += objs; - - while (p < pend) { - p->as.free.flags = 0; -@@ -1151,7 +1729,7 @@ initial_expand_heap(rb_objspace_t *objspace) - static void - set_heaps_increment(rb_objspace_t *objspace) - { -- size_t next_heaps_length = (size_t)(heaps_used * 1.8); -+ size_t next_heaps_length = (size_t)(heaps_used * heap_slots_growth_factor); - - if (next_heaps_length == heaps_used) { - next_heaps_length++; -@@ -1184,6 +1762,22 @@ rb_during_gc(void) - - #define RANY(o) ((RVALUE*)(o)) - -+#ifdef GC_DEBUG -+static VALUE -+_rb_sourcefile(void) -+{ -+ rb_thread_t *th = GET_THREAD(); -+ rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp); -+ -+ if (cfp) { -+ return cfp->iseq->filename; -+ } -+ else { -+ return Qnil; -+ } -+} -+#endif -+ - VALUE - rb_newobj(void) - { -@@ -1215,9 +1809,11 @@ rb_newobj(void) - - MEMZERO((void*)obj, RVALUE, 1); - #ifdef GC_DEBUG -- RANY(obj)->file = rb_sourcefile(); -+ RANY(obj)->file = _rb_sourcefile(); - RANY(obj)->line = rb_sourceline(); - #endif -+ live_objects++; -+ allocated_objects++; - GC_PROF_INC_LIVE_NUM; - - return obj; -@@ -1769,6 +2365,12 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr) - { - register RVALUE *obj = RANY(ptr); - -+#ifdef GC_DEBUG -+ if (obj->file && obj->file != Qnil && is_pointer_to_heap(objspace, (void*)obj->file)) { -+ gc_mark(objspace, obj->file, lev); -+ } -+#endif -+ - goto marking; /* skip */ - - again: -@@ -1779,6 +2381,12 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr) - obj->as.basic.flags |= FL_MARK; - objspace->heap.live_num++; - -+#ifdef GC_DEBUG -+ if (obj->file && obj->file != Qnil && is_pointer_to_heap(objspace, (void*)obj->file)) { -+ gc_mark(objspace, obj->file, lev); -+ } -+#endif -+ - marking: - if (FL_TEST(obj, FL_EXIVAR)) { - rb_mark_generic_ivar(ptr); -@@ -2121,6 +2729,25 @@ free_unused_heaps(rb_objspace_t *objspace) - } - } - -+static inline unsigned long -+elapsed_musecs(struct timeval since) -+{ -+ struct timeval now; -+ struct timeval temp; -+ -+ gettimeofday(&now, NULL); -+ -+ if ((now.tv_usec-since.tv_usec)<0) { -+ temp.tv_sec = now.tv_sec-since.tv_sec-1; -+ temp.tv_usec = 1000000+now.tv_usec-since.tv_usec; -+ } else { -+ temp.tv_sec = now.tv_sec-since.tv_sec; -+ temp.tv_usec = now.tv_usec-since.tv_usec; -+ } -+ -+ return temp.tv_sec*1000000 + temp.tv_usec; -+} -+ - static void - slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - { -@@ -2128,14 +2755,23 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - RVALUE *p, *pend; - RVALUE *free = freelist, *final = deferred_final_list; - int deferred; -+ int do_gc_stats = gc_statistics & verbose_gc_stats; -+ -+ struct timeval tv1; -+ if (gc_statistics) gettimeofday(&tv1, NULL); - - p = sweep_slot->slot; pend = p + sweep_slot->limit; - while (p < pend) { - if (!(p->as.basic.flags & FL_MARK)) { -+ if (do_gc_stats && !p->as.basic.flags) { -+ /* slot was free before GC */ -+ freelist_size++; -+ } - if (p->as.basic.flags && - ((deferred = obj_free(objspace, (VALUE)p)) || - (FL_TEST(p, FL_FINALIZE)))) { - if (!deferred) { -+ if (do_gc_stats) zombies++; - p->as.free.flags = T_ZOMBIE; - RDATA(p)->dfree = 0; - } -@@ -2145,6 +2781,10 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - final_num++; - } - else { -+ if (do_gc_stats) { -+ VALUE obt = p->as.basic.flags & T_MASK; -+ if (obt) free_counts[obt]++; -+ } - add_freelist(objspace, p); - free_num++; - } -@@ -2152,13 +2792,22 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - else if (BUILTIN_TYPE(p) == T_ZOMBIE) { - /* objects to be finalized */ - /* do nothing remain marked */ -+ if (do_gc_stats) zombies++; - } - else { - RBASIC(p)->flags &= ~FL_MARK; -+ if (do_gc_stats) { -+ live_counts[p->as.basic.flags & T_MASK]++; -+ } - } - p++; -+ processed++; - } -- if (final_num + free_num == sweep_slot->limit && -+ -+ freed_objects += free_num; -+ -+ if (objspace->heap.freed_blocks < objspace->heap.max_blocks_to_free && -+ final_num + free_num == sweep_slot->limit && - objspace->heap.free_num > objspace->heap.do_heap_free) { - RVALUE *pp; - -@@ -2169,6 +2818,8 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - sweep_slot->limit = final_num; - freelist = free; /* cancel this page from freelist */ - unlink_heap_slot(objspace, sweep_slot); -+ objspace->heap.freed_blocks += 1; -+ heap_size -= final_num + free_num; - } - else { - objspace->heap.free_num += free_num; -@@ -2181,6 +2832,10 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - RUBY_VM_SET_FINALIZER_INTERRUPT(th); - } - } -+ -+ if (gc_statistics) { -+ gc_time_accumulator += elapsed_musecs(tv1); -+ } - } - - static int -@@ -2201,6 +2856,21 @@ ready_to_gc(rb_objspace_t *objspace) - static void - before_gc_sweep(rb_objspace_t *objspace) - { -+ if (gc_statistics & verbose_gc_stats) { -+ /* -+ fprintf(gc_data_file, "Sweep started\n"); -+ */ -+ freed_objects = 0; -+ processed = 0; -+ zombies = 0; -+ freelist_size = 0; -+ MEMZERO((void*)free_counts, unsigned long, T_MASK+1); -+ MEMZERO((void*)live_counts, unsigned long, T_MASK+1); -+ } -+ -+ objspace->heap.max_blocks_to_free = heaps_used - (heap_min_slots / HEAP_OBJ_LIMIT); -+ objspace->heap.freed_blocks = 0; -+ - freelist = 0; - objspace->heap.do_heap_free = (size_t)((heaps_used * HEAP_OBJ_LIMIT) * 0.65); - objspace->heap.free_min = (size_t)((heaps_used * HEAP_OBJ_LIMIT) * 0.2); -@@ -2220,8 +2890,13 @@ before_gc_sweep(rb_objspace_t *objspace) - static void - after_gc_sweep(rb_objspace_t *objspace) - { -+ int i; -+ struct timeval tv1; -+ - GC_PROF_SET_MALLOC_INFO; - -+ if (gc_statistics) gettimeofday(&tv1, NULL); -+ - if (objspace->heap.free_num < objspace->heap.free_min) { - set_heaps_increment(objspace); - heaps_increment(objspace); -@@ -2234,6 +2909,29 @@ after_gc_sweep(rb_objspace_t *objspace) - malloc_increase = 0; - - free_unused_heaps(objspace); -+ -+ if (gc_statistics) { -+ gc_time_accumulator += elapsed_musecs(tv1); -+ -+ if (verbose_gc_stats) { -+ /* log gc stats if requested */ -+ fprintf(gc_data_file, "GC time: %lu musec\n", (unsigned long)(gc_time_accumulator-gc_time_accumulator_before_gc)); -+ fprintf(gc_data_file, "objects processed: %7lu\n", (unsigned long)processed); -+ fprintf(gc_data_file, "live objects : %7lu\n", (unsigned long)live_after_last_mark_phase); -+ fprintf(gc_data_file, "freelist objects : %7lu\n", (unsigned long)freelist_size); -+ fprintf(gc_data_file, "freed objects : %7lu\n", (unsigned long)freed_objects); -+ fprintf(gc_data_file, "zombies : %7lu\n", (unsigned long)zombies); -+ for(i=0; i0 || live_counts[i]>0) { -+ fprintf(gc_data_file, -+ "kept %7lu / freed %7lu objects of type %s\n", -+ (unsigned long)live_counts[i], (unsigned long)free_counts[i], obj_type((int)i)); -+ } -+ } -+ rb_gc_dump(); -+ fflush(gc_data_file); -+ } -+ } - } - - static int -@@ -2267,9 +2965,11 @@ rest_sweep(rb_objspace_t *objspace) - - static void gc_marks(rb_objspace_t *objspace); - -+/* only called from rb_new_obj */ - static int - gc_lazy_sweep(rb_objspace_t *objspace) - { -+ struct timeval gctv1; - int res; - INIT_GC_PROF_PARAMS; - -@@ -2291,7 +2991,6 @@ gc_lazy_sweep(rb_objspace_t *objspace) - GC_PROF_TIMER_STOP(Qfalse); - return res; - } -- after_gc_sweep(objspace); - } - else { - if (heaps_increment(objspace)) { -@@ -2299,6 +2998,18 @@ gc_lazy_sweep(rb_objspace_t *objspace) - return TRUE; - } - } -+ after_gc_sweep(objspace); -+ -+ if (gc_statistics) { -+ gc_time_accumulator_before_gc = gc_time_accumulator; -+ gc_collections++; -+ gettimeofday(&gctv1, NULL); -+ /* -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "Garbage collection started (gc_lazy_sweep)\n"); -+ } -+ */ -+ } - - gc_marks(objspace); - -@@ -2307,6 +3018,10 @@ gc_lazy_sweep(rb_objspace_t *objspace) - set_heaps_increment(objspace); - } - -+ if (gc_statistics) { -+ gc_time_accumulator += elapsed_musecs(gctv1); -+ } -+ - GC_PROF_SWEEP_TIMER_START; - if(!(res = lazy_sweep(objspace))) { - after_gc_sweep(objspace); -@@ -2318,6 +3033,7 @@ gc_lazy_sweep(rb_objspace_t *objspace) - GC_PROF_SWEEP_TIMER_STOP; - - GC_PROF_TIMER_STOP(Qtrue); -+ - return res; - } - -@@ -2544,9 +3260,15 @@ gc_marks(rb_objspace_t *objspace) - rb_thread_t *th = GET_THREAD(); - GC_PROF_MARK_TIMER_START; - -+ /* -+ if (gc_statistics & verbose_gc_stats) { -+ fprintf(gc_data_file, "Marking objects\n"); -+ } -+ */ -+ - objspace->heap.live_num = 0; - objspace->count++; -- -+ live_objects = 0; - - SET_STACK_END; - -@@ -2578,11 +3300,15 @@ gc_marks(rb_objspace_t *objspace) - gc_mark_stacked_objects(objspace); - - GC_PROF_MARK_TIMER_STOP; -+ -+ live_after_last_mark_phase = objspace->heap.live_num; - } - - static int - garbage_collect(rb_objspace_t *objspace) - { -+ struct timeval gctv1; -+ - INIT_GC_PROF_PARAMS; - - if (GC_NOTIFY) printf("start garbage_collect()\n"); -@@ -2598,15 +3324,31 @@ garbage_collect(rb_objspace_t *objspace) - - rest_sweep(objspace); - -+ if (gc_statistics) { -+ gc_time_accumulator_before_gc = gc_time_accumulator; -+ gc_collections++; -+ gettimeofday(&gctv1, NULL); -+ /* -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "Garbage collection started (garbage_collect)\n"); -+ } -+ */ -+ } -+ - during_gc++; - gc_marks(objspace); - -+ if (gc_statistics) { -+ gc_time_accumulator += elapsed_musecs(gctv1); -+ } -+ - GC_PROF_SWEEP_TIMER_START; - gc_sweep(objspace); - GC_PROF_SWEEP_TIMER_STOP; - - GC_PROF_TIMER_STOP(Qtrue); - if (GC_NOTIFY) printf("end garbage_collect()\n"); -+ - return TRUE; - } - -@@ -3080,6 +3822,39 @@ rb_gc_call_finalizer_at_exit(void) - rb_objspace_call_finalizer(&rb_objspace); - } - -+static const char* obj_type(VALUE type) -+{ -+ switch (type) { -+ case T_NIL : return "NIL"; -+ case T_OBJECT : return "OBJECT"; -+ case T_CLASS : return "CLASS"; -+ case T_ICLASS : return "ICLASS"; -+ case T_MODULE : return "MODULE"; -+ case T_FLOAT : return "FLOAT"; -+ case T_COMPLEX: return "COMPLEX"; -+ case T_RATIONAL: return "RATIONAL"; -+ case T_STRING : return "STRING"; -+ case T_REGEXP : return "REGEXP"; -+ case T_ARRAY : return "ARRAY"; -+ case T_FIXNUM : return "FIXNUM"; -+ case T_HASH : return "HASH"; -+ case T_STRUCT : return "STRUCT"; -+ case T_BIGNUM : return "BIGNUM"; -+ case T_FILE : return "FILE"; -+ -+ case T_TRUE : return "TRUE"; -+ case T_FALSE : return "FALSE"; -+ case T_DATA : return "DATA"; -+ case T_MATCH : return "MATCH"; -+ case T_SYMBOL : return "SYMBOL"; -+ case T_ZOMBIE : return "ZOMBIE"; -+ -+ case T_UNDEF : return "UNDEF"; -+ case T_NODE : return "NODE"; -+ default: return "____"; -+ } -+} -+ - static void - rb_objspace_call_finalizer(rb_objspace_t *objspace) - { -@@ -3388,6 +4163,49 @@ count_objects(int argc, VALUE *argv, VALUE os) - return hash; - } - -+/* call-seq: -+ * ObjectSpace.live_objects => number -+ * -+ * Returns the count of objects currently allocated in the system. This goes -+ * down after the garbage collector runs. -+ */ -+static -+VALUE os_live_objects(VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return ULONG2NUM(live_objects); -+} -+ -+unsigned long rb_os_live_objects() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return live_objects; -+} -+ -+/* call-seq: -+ * ObjectSpace.allocated_objects => number -+ * -+ * Returns the count of objects allocated since the Ruby interpreter has -+ * started. This number can only increase. To know how many objects are -+ * currently allocated, use ObjectSpace::live_objects -+ */ -+static -+VALUE os_allocated_objects(VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if defined(HAVE_LONG_LONG) -+ return ULL2NUM(allocated_objects); -+#else -+ return ULONG2NUM(allocated_objects); -+#endif -+} -+ -+unsigned LONG_LONG rb_os_allocated_objects() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return allocated_objects; -+} -+ - /* - * call-seq: - * GC.count -> Integer -@@ -3680,6 +4498,28 @@ Init_GC(void) - rb_define_singleton_method(rb_mGC, "stat", gc_stat, -1); - rb_define_method(rb_mGC, "garbage_collect", rb_gc_start, 0); - -+ rb_define_singleton_method(rb_mGC, "enable_stats", rb_gc_enable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "disable_stats", rb_gc_disable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "stats_enabled?", rb_gc_stats_enabled, 0); -+ rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0); -+ rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); -+ rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); -+ -+ rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); -+ rb_define_singleton_method(rb_mGC, "log_file", rb_gc_log_file, -1); -+ rb_define_singleton_method(rb_mGC, "enable_trace", rb_gc_enable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "disable_trace", rb_gc_disable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "trace_enabled?", rb_gc_trace_enabled, 0); -+ -+ rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); -+ rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); -+ rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); -+#ifdef GC_DEBUG -+ rb_define_singleton_method(rb_mGC, "dump_file_and_line_info", rb_gc_dump_file_and_line_info, -1); -+#endif -+ - 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); -@@ -3693,6 +4533,9 @@ Init_GC(void) - rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1); - rb_define_module_function(rb_mObSpace, "garbage_collect", rb_gc_start, 0); - -+ rb_define_module_function(rb_mObSpace, "live_objects", os_live_objects, 0); -+ rb_define_module_function(rb_mObSpace, "allocated_objects", os_allocated_objects, 0); -+ - rb_define_module_function(rb_mObSpace, "define_finalizer", define_final, -1); - rb_define_module_function(rb_mObSpace, "undefine_finalizer", undefine_final, 1); - diff --git a/patches/ruby/1.9.3/head/railsexpress/03-display-more-detailed-stack-trace.patch b/patches/ruby/1.9.3/head/railsexpress/03-display-more-detailed-stack-trace.patch deleted file mode 100644 index 5c7ad30352..0000000000 --- a/patches/ruby/1.9.3/head/railsexpress/03-display-more-detailed-stack-trace.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/eval_error.c b/eval_error.c -index fd06adf..69c3b48 100644 ---- a/eval_error.c -+++ b/eval_error.c -@@ -164,8 +164,8 @@ error_print(void) - int skip = eclass == rb_eSysStackError; - - #define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5) --#define TRACE_HEAD 8 --#define TRACE_TAIL 5 -+#define TRACE_HEAD 100 -+#define TRACE_TAIL 100 - - for (i = 1; i < len; i++) { - if (TYPE(ptr[i]) == T_STRING) { diff --git a/patches/ruby/1.9.3/head/railsexpress/04-fork-support-for-gc-logging.patch b/patches/ruby/1.9.3/head/railsexpress/04-fork-support-for-gc-logging.patch deleted file mode 100644 index 6dff4a9070..0000000000 --- a/patches/ruby/1.9.3/head/railsexpress/04-fork-support-for-gc-logging.patch +++ /dev/null @@ -1,68 +0,0 @@ -diff --git a/gc.c b/gc.c -index feb54f1..7f65b98 100644 ---- a/gc.c -+++ b/gc.c -@@ -1345,6 +1345,34 @@ rb_gc_log_file(int argc, VALUE *argv, VALUE self) - } - - /* -+ * Called from process.c before a fork. Flushes the gc log file to -+ * avoid writing the buffered output twice (once in the parent, and -+ * once in the child). -+ */ -+void -+rb_gc_before_fork() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ fflush(gc_data_file); -+} -+ -+/* -+ * Called from process.c after a fork in the child process. Turns off -+ * logging, disables GC stats and resets all gc counters and timing -+ * information. -+ */ -+void -+rb_gc_after_fork() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ rb_gc_disable_stats(); -+ rb_gc_clear_stats(); -+ rb_gc_disable_trace(); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+} -+ -+/* - * call-seq: - * GC.log String => String - * -diff --git a/include/ruby/intern.h b/include/ruby/intern.h -index 6e1c2c2..3766d65 100644 ---- a/include/ruby/intern.h -+++ b/include/ruby/intern.h -@@ -431,6 +431,8 @@ void rb_gc_call_finalizer_at_exit(void); - VALUE rb_gc_enable(void); - VALUE rb_gc_disable(void); - VALUE rb_gc_start(void); -+void rb_gc_before_fork _((void)); -+void rb_gc_after_fork _((void)); - #define Init_stack(addr) ruby_init_stack(addr) - void rb_gc_set_params(void); - /* hash.c */ -diff --git a/process.c b/process.c -index 99cfc69..8bee602 100644 ---- a/process.c -+++ b/process.c -@@ -2804,9 +2804,11 @@ rb_f_fork(VALUE obj) - rb_pid_t pid; - - rb_secure(2); -+ rb_gc_before_fork(); - - switch (pid = rb_fork(0, 0, 0, Qnil)) { - case 0: -+ rb_gc_after_fork(); - rb_thread_atfork(); - if (rb_block_given_p()) { - int status; diff --git a/patches/ruby/1.9.3/head/railsexpress/05-track-live-dataset-size.patch b/patches/ruby/1.9.3/head/railsexpress/05-track-live-dataset-size.patch deleted file mode 100644 index 3cfc64abac..0000000000 --- a/patches/ruby/1.9.3/head/railsexpress/05-track-live-dataset-size.patch +++ /dev/null @@ -1,45 +0,0 @@ -diff --git a/gc.c b/gc.c -index 7f65b98..8498fe4 100644 ---- a/gc.c -+++ b/gc.c -@@ -281,7 +281,6 @@ getrusage_time(void) - #define GC_PROF_DEC_LIVE_NUM - #endif - -- - #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__) - #pragma pack(push, 1) /* magic for reducing sizeof(RVALUE): 24 -> 20 */ - #endif -@@ -1562,6 +1561,24 @@ rb_gc_time() - #endif - } - -+/* -+ * call-seq: -+ * GC.heap_slots_live_after_last_gc => Integer -+ * -+ * Returns the number of heap slots which were live after the last garbage collection. -+ * -+ * GC.heap_slots_live_after_last_gc #=> 231223 -+ * -+ */ -+VALUE -+rb_gc_heap_slots_live_after_last_gc() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return ULONG2NUM(live_after_last_mark_phase); -+} -+ -+ -+ - VALUE rb_mGC; - - void -@@ -4533,6 +4550,7 @@ Init_GC(void) - rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); - rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); - rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots_live_after_last_gc", rb_gc_heap_slots_live_after_last_gc, 0); - rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); - - rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); diff --git a/patches/ruby/1.9.3/head/railsexpress/06-webrick_204_304_keep_alive_fix.patch b/patches/ruby/1.9.3/head/railsexpress/06-webrick_204_304_keep_alive_fix.patch deleted file mode 100644 index 34d9b78133..0000000000 --- a/patches/ruby/1.9.3/head/railsexpress/06-webrick_204_304_keep_alive_fix.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/lib/webrick/httpresponse.rb b/lib/webrick/httpresponse.rb -index 0d36c07..ce72b3f 100644 ---- a/lib/webrick/httpresponse.rb -+++ b/lib/webrick/httpresponse.rb -@@ -202,7 +202,7 @@ module WEBrick - if @header['connection'] == "close" - @keep_alive = false - elsif keep_alive? -- if chunked? || @header['content-length'] -+ if chunked? || @header['content-length'] || @status == 304 || @status == 204 - @header['connection'] = "Keep-Alive" - else - msg = "Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true" diff --git a/patches/ruby/1.9.3/head/railsexpress/07-export-a-few-more-symbols-for-ruby-prof.patch b/patches/ruby/1.9.3/head/railsexpress/07-export-a-few-more-symbols-for-ruby-prof.patch deleted file mode 100644 index 4473c341e6..0000000000 --- a/patches/ruby/1.9.3/head/railsexpress/07-export-a-few-more-symbols-for-ruby-prof.patch +++ /dev/null @@ -1,140 +0,0 @@ -diff --git a/gc.c b/gc.c -index 8498fe4..b5fc83c 100644 ---- a/gc.c -+++ b/gc.c -@@ -1052,6 +1052,7 @@ ruby_xfree(void *x) - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_enable(void) - { -@@ -1074,6 +1075,7 @@ rb_gc_enable(void) - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_disable(void) - { -@@ -1096,6 +1098,7 @@ rb_gc_disable(void) - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_enable_stats() - { -@@ -1117,6 +1120,7 @@ rb_gc_enable_stats() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_disable_stats() - { -@@ -1136,6 +1140,7 @@ rb_gc_disable_stats() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_stats_enabled() - { -@@ -1155,6 +1160,7 @@ rb_gc_stats_enabled() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_clear_stats() - { -@@ -1178,6 +1184,7 @@ rb_gc_clear_stats() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_allocated_size() - { -@@ -1222,6 +1229,7 @@ rb_gc_num_allocations() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_enable_trace() - { -@@ -1243,6 +1251,7 @@ rb_gc_enable_trace() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_disable_trace() - { -@@ -1262,6 +1271,7 @@ rb_gc_disable_trace() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_trace_enabled() - { -@@ -1290,6 +1300,7 @@ const char* GC_LOGFILE_IVAR = "@gc_logfile_name"; - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_log_file(int argc, VALUE *argv, VALUE self) - { -@@ -1381,6 +1392,7 @@ rb_gc_after_fork() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_log(self, original_str) - VALUE self, original_str; -@@ -1407,6 +1419,7 @@ rb_gc_log(self, original_str) - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_dump() - { -@@ -1437,6 +1450,7 @@ static const char* obj_type(VALUE tp); - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_dump_file_and_line_info(int argc, VALUE *argv) - { -@@ -1532,6 +1546,7 @@ rb_gc_heap_slots() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_collections() - { -@@ -1550,6 +1565,7 @@ rb_gc_collections() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_time() - { -@@ -4245,6 +4261,7 @@ VALUE os_allocated_objects(VALUE self) - #endif - } - -+RUBY_FUNC_EXPORTED - unsigned LONG_LONG rb_os_allocated_objects() - { - rb_objspace_t *objspace = &rb_objspace; diff --git a/patches/ruby/1.9.3/head/railsexpress/08-thread-variables.patch b/patches/ruby/1.9.3/head/railsexpress/08-thread-variables.patch deleted file mode 100644 index 90d13b15c1..0000000000 --- a/patches/ruby/1.9.3/head/railsexpress/08-thread-variables.patch +++ /dev/null @@ -1,319 +0,0 @@ -diff --git a/NEWS b/NEWS -index 30fec33..9f6c172 100644 ---- a/NEWS -+++ b/NEWS -@@ -103,6 +103,16 @@ with all sufficient information, see the ChangeLog file. - * String#prepend - * String#byteslice - -+ * Thread -+ * added method: -+ * added Thread#thread_variable_get for getting thread local variables -+ (these are different than Fiber local variables). -+ * added Thread#thread_variable_set for setting thread local variables. -+ * added Thread#thread_variables for getting a list of the thread local -+ variable keys. -+ * added Thread#thread_variable? for testing to see if a particular thread -+ variable has been set. -+ - * Time - * extended method: - * Time#strftime supports %:z and %::z. -diff --git a/test/ruby/test_thread.rb b/test/ruby/test_thread.rb -index e8cb3b1..9ff491d 100644 ---- a/test/ruby/test_thread.rb -+++ b/test/ruby/test_thread.rb -@@ -27,6 +27,79 @@ class TestThread < Test::Unit::TestCase - end - end - -+ def test_main_thread_variable_in_enumerator -+ assert_equal Thread.main, Thread.current -+ -+ Thread.current.thread_variable_set :foo, "bar" -+ -+ thread, value = Fiber.new { -+ Fiber.yield [Thread.current, Thread.current.thread_variable_get(:foo)] -+ }.resume -+ -+ assert_equal Thread.current, thread -+ assert_equal Thread.current.thread_variable_get(:foo), value -+ end -+ -+ def test_thread_variable_in_enumerator -+ Thread.new { -+ Thread.current.thread_variable_set :foo, "bar" -+ -+ thread, value = Fiber.new { -+ Fiber.yield [Thread.current, Thread.current.thread_variable_get(:foo)] -+ }.resume -+ -+ assert_equal Thread.current, thread -+ assert_equal Thread.current.thread_variable_get(:foo), value -+ }.join -+ end -+ -+ def test_thread_variables -+ assert_equal [], Thread.new { Thread.current.thread_variables }.join.value -+ -+ t = Thread.new { -+ Thread.current.thread_variable_set(:foo, "bar") -+ Thread.current.thread_variables -+ } -+ assert_equal [:foo], t.join.value -+ end -+ -+ def test_thread_variable? -+ refute Thread.new { Thread.current.thread_variable?("foo") }.join.value -+ t = Thread.new { -+ Thread.current.thread_variable_set("foo", "bar") -+ }.join -+ -+ assert t.thread_variable?("foo") -+ assert t.thread_variable?(:foo) -+ refute t.thread_variable?(:bar) -+ end -+ -+ def test_thread_variable_strings_and_symbols_are_the_same_key -+ t = Thread.new {}.join -+ t.thread_variable_set("foo", "bar") -+ assert_equal "bar", t.thread_variable_get(:foo) -+ end -+ -+ def test_thread_variable_frozen -+ t = Thread.new { }.join -+ t.freeze -+ assert_raises(RuntimeError) do -+ t.thread_variable_set(:foo, "bar") -+ end -+ end -+ -+ def test_thread_variable_security -+ t = Thread.new { sleep } -+ -+ assert_raises(SecurityError) do -+ Thread.new { $SAFE = 4; t.thread_variable_get(:foo) }.join -+ end -+ -+ assert_raises(SecurityError) do -+ Thread.new { $SAFE = 4; t.thread_variable_set(:foo, :baz) }.join -+ end -+ end -+ - def test_mutex_synchronize - m = Mutex.new - r = 0 -diff --git a/thread.c b/thread.c -index 387bf1f..1cf340c 100644 ---- a/thread.c -+++ b/thread.c -@@ -2125,7 +2125,9 @@ rb_thread_local_aset(VALUE thread, ID id, VALUE val) - * thr[sym] = obj -> obj - * - * Attribute Assignment---Sets or creates the value of a thread-local variable, -- * using either a symbol or a string. See also Thread#[]. -+ * using either a symbol or a string. See also Thread#[]. For -+ * thread-local variables, please see Thread#thread_variable_set -+ * and Thread#thread_variable_get. - */ - - static VALUE -@@ -2136,6 +2138,80 @@ rb_thread_aset(VALUE self, VALUE id, VALUE val) - - /* - * call-seq: -+ * thr.thread_variable_get(key) -> obj or nil -+ * -+ * Returns the value of a thread local variable that has been set. Note that -+ * these are different than fiber local values. For fiber local values, -+ * please see Thread#[] and Thread#[]=. -+ * -+ * Thread local values are carried along with threads, and do not respect -+ * fibers. For example: -+ * -+ * Thread.new { -+ * Thread.current.thread_variable_set("foo", "bar") # set a thread local -+ * Thread.current["foo"] = "bar" # set a fiber local -+ * -+ * Fiber.new { -+ * Fiber.yield [ -+ * Thread.current.thread_variable_get("foo"), # get the thread local -+ * Thread.current["foo"], # get the fiber local -+ * ] -+ * }.resume -+ * }.join.value # => ['bar', nil] -+ * -+ * The value "bar" is returned for the thread local, where nil is returned -+ * for the fiber local. The fiber is executed in the same thread, so the -+ * thread local values are available. -+ * -+ * See also Thread#[] -+ */ -+ -+static VALUE -+rb_thread_variable_get(VALUE thread, VALUE id) -+{ -+ VALUE locals; -+ rb_thread_t *th; -+ -+ GetThreadPtr(thread, th); -+ -+ if (rb_safe_level() >= 4 && th != GET_THREAD()) { -+ rb_raise(rb_eSecurityError, "Insecure: can't access thread locals"); -+ } -+ -+ locals = rb_iv_get(thread, "locals"); -+ return rb_hash_aref(locals, ID2SYM(rb_to_id(id))); -+} -+ -+/* -+ * call-seq: -+ * thr.thread_variable_set(key, value) -+ * -+ * Sets a thread local with +key+ to +value+. Note that these are local to -+ * threads, and not to fibers. Please see Thread#thread_variable_get and -+ * Thread#[] for more information. -+ */ -+ -+static VALUE -+rb_thread_variable_set(VALUE thread, VALUE id, VALUE val) -+{ -+ VALUE locals; -+ rb_thread_t *th; -+ -+ GetThreadPtr(thread, th); -+ -+ if (rb_safe_level() >= 4 && th != GET_THREAD()) { -+ rb_raise(rb_eSecurityError, "Insecure: can't modify thread locals"); -+ } -+ if (OBJ_FROZEN(thread)) { -+ rb_error_frozen("thread locals"); -+ } -+ -+ locals = rb_iv_get(thread, "locals"); -+ return rb_hash_aset(locals, ID2SYM(rb_to_id(id)), val); -+} -+ -+/* -+ * call-seq: - * thr.key?(sym) -> true or false - * - * Returns true if the given string (or symbol) exists as a -@@ -3006,6 +3082,9 @@ rb_gc_save_machine_context(rb_thread_t *th) - - /* - * -+ * For thread-local variables, please see Thread#thread_local_get -+ * and Thread#thread_local_set. -+ * - */ - - void -@@ -3208,6 +3287,76 @@ thgroup_list_i(st_data_t key, st_data_t val, st_data_t data) - return ST_CONTINUE; - } - -+static int -+keys_i(VALUE key, VALUE value, VALUE ary) -+{ -+ rb_ary_push(ary, key); -+ return ST_CONTINUE; -+} -+ -+/* -+ * call-seq: -+ * thr.thread_variables -> array -+ * -+ * Returns an an array of the names of the thread-local variables (as Symbols). -+ * -+ * thr = Thread.new do -+ * Thread.current.thread_variable_set(:cat, 'meow') -+ * Thread.current.thread_variable_set("dog", 'woof') -+ * end -+ * thr.join #=> # -+ * thr.thread_variables #=> [:dog, :cat] -+ * -+ * Note that these are not fiber local variables. Please see Thread#[] and -+ * Thread#thread_variable_get for more details. -+ */ -+ -+static VALUE -+rb_thread_variables(VALUE thread) -+{ -+ VALUE locals; -+ VALUE ary; -+ -+ locals = rb_iv_get(thread, "locals"); -+ ary = rb_ary_new(); -+ rb_hash_foreach(locals, keys_i, ary); -+ -+ return ary; -+} -+ -+/* -+ * call-seq: -+ * thr.thread_variable?(key) -> true or false -+ * -+ * Returns true if the given string (or symbol) exists as a -+ * thread-local variable. -+ * -+ * me = Thread.current -+ * me.thread_variable_set(:oliver, "a") -+ * me.thread_variable?(:oliver) #=> true -+ * me.thread_variable?(:stanley) #=> false -+ * -+ * Note that these are not fiber local variables. Please see Thread#[] and -+ * Thread#thread_variable_get for more details. -+ */ -+ -+static VALUE -+rb_thread_variable_p(VALUE thread, VALUE key) -+{ -+ VALUE locals; -+ -+ locals = rb_iv_get(thread, "locals"); -+ -+ if (!RHASH(locals)->ntbl) -+ return Qfalse; -+ -+ if (st_lookup(RHASH(locals)->ntbl, ID2SYM(rb_to_id(key)), 0)) { -+ return Qtrue; -+ } -+ -+ return Qfalse; -+} -+ - /* - * call-seq: - * thgrp.list -> array -@@ -4693,6 +4842,10 @@ Init_Thread(void) - rb_define_method(rb_cThread, "priority", rb_thread_priority, 0); - rb_define_method(rb_cThread, "priority=", rb_thread_priority_set, 1); - rb_define_method(rb_cThread, "status", rb_thread_status, 0); -+ rb_define_method(rb_cThread, "thread_variable_get", rb_thread_variable_get, 1); -+ rb_define_method(rb_cThread, "thread_variable_set", rb_thread_variable_set, 2); -+ rb_define_method(rb_cThread, "thread_variables", rb_thread_variables, 0); -+ rb_define_method(rb_cThread, "thread_variable?", rb_thread_variable_p, 1); - rb_define_method(rb_cThread, "alive?", rb_thread_alive_p, 0); - rb_define_method(rb_cThread, "stop?", rb_thread_stop_p, 0); - rb_define_method(rb_cThread, "abort_on_exception", rb_thread_abort_exc, 0); -diff --git a/vm.c b/vm.c -index 6b2bd90..b5fc485 100644 ---- a/vm.c -+++ b/vm.c -@@ -1910,6 +1910,7 @@ ruby_thread_init(VALUE self) - GetThreadPtr(self, th); - - th_init(th, self); -+ rb_iv_set(self, "locals", rb_hash_new()); - th->vm = vm; - - th->top_wrapper = 0; -@@ -2178,6 +2179,7 @@ Init_VM(void) - - /* create main thread */ - th_self = th->self = TypedData_Wrap_Struct(rb_cThread, &thread_data_type, th); -+ rb_iv_set(th_self, "locals", rb_hash_new()); - vm->main_thread = th; - vm->running_thread = th; - th->vm = vm; diff --git a/patches/ruby/1.9.3/head/railsexpress/09-faster-loading.patch b/patches/ruby/1.9.3/head/railsexpress/09-faster-loading.patch deleted file mode 100644 index c0c7dc1d76..0000000000 --- a/patches/ruby/1.9.3/head/railsexpress/09-faster-loading.patch +++ /dev/null @@ -1,747 +0,0 @@ -diff --git a/array.c b/array.c -index e427cb3..c33d106 100644 ---- a/array.c -+++ b/array.c -@@ -295,6 +295,22 @@ rb_ary_frozen_p(VALUE ary) - return Qfalse; - } - -+/* This can be used to take a snapshot of an array (with -+ e.g. rb_ary_replace) and check later whether the array has been -+ modified from the snapshot. The snapshot is cheap, though if -+ something does modify the array it will pay the cost of copying -+ it. */ -+VALUE -+rb_ary_shared_with_p(VALUE ary1, VALUE ary2) -+{ -+ if (!ARY_EMBED_P(ary1) && ARY_SHARED_P(ary1) -+ && !ARY_EMBED_P(ary2) && ARY_SHARED_P(ary2) -+ && RARRAY(ary1)->as.heap.aux.shared == RARRAY(ary2)->as.heap.aux.shared) { -+ return Qtrue; -+ } -+ return Qfalse; -+} -+ - static VALUE - ary_alloc(VALUE klass) - { -diff --git a/file.c b/file.c -index c60de23..d82b6d5 100644 ---- a/file.c -+++ b/file.c -@@ -153,23 +153,32 @@ file_path_convert(VALUE name) - return name; - } - --static VALUE --rb_get_path_check(VALUE obj, int level) -+VALUE -+rb_get_path_check_to_string(VALUE obj, int level) - { - VALUE tmp; - ID to_path; -- rb_encoding *enc; - - if (insecure_obj_p(obj, level)) { - rb_insecure_operation(); - } - -+ if (RB_TYPE_P(obj, T_STRING)) { -+ return obj; -+ } - CONST_ID(to_path, "to_path"); - tmp = rb_check_funcall(obj, to_path, 0, 0); - if (tmp == Qundef) { - tmp = obj; - } - StringValue(tmp); -+ return tmp; -+} -+ -+VALUE -+rb_get_path_check_convert(VALUE obj, VALUE tmp, int level) -+{ -+ rb_encoding *enc; - - tmp = file_path_convert(tmp); - if (obj != tmp && insecure_obj_p(tmp, level)) { -@@ -187,6 +196,13 @@ rb_get_path_check(VALUE obj, int level) - return rb_str_new4(tmp); - } - -+static VALUE -+rb_get_path_check(VALUE obj, int level) -+{ -+ VALUE tmp = rb_get_path_check_to_string(obj, level); -+ return rb_get_path_check_convert(obj, tmp, level); -+} -+ - VALUE - rb_get_path_no_checksafe(VALUE obj) - { -@@ -3254,7 +3270,6 @@ rb_file_expand_path(VALUE fname, VALUE dname) - VALUE - rb_file_expand_path_fast(VALUE fname, VALUE dname) - { -- check_expand_path_args(fname, dname); - return rb_file_expand_path_internal(fname, dname, 0, 0, EXPAND_PATH_BUFFER()); - } - -@@ -5245,7 +5260,7 @@ rb_find_file_ext_safe(VALUE *filep, const char *const *ext, int safe_level) - rb_raise(rb_eSecurityError, "loading from non-absolute path %s", f); - } - -- RB_GC_GUARD(load_path) = rb_get_load_path(); -+ RB_GC_GUARD(load_path) = rb_get_expanded_load_path(); - if (!load_path) return 0; - - fname = rb_str_dup(*filep); -@@ -5310,7 +5325,7 @@ rb_find_file_safe(VALUE path, int safe_level) - rb_raise(rb_eSecurityError, "loading from non-absolute path %s", f); - } - -- RB_GC_GUARD(load_path) = rb_get_load_path(); -+ RB_GC_GUARD(load_path) = rb_get_expanded_load_path(); - if (load_path) { - long i; - -diff --git a/hash.c b/hash.c -index fbd8237..8423558 100644 ---- a/hash.c -+++ b/hash.c -@@ -1087,7 +1087,7 @@ clear_i(VALUE key, VALUE value, VALUE dummy) - * - */ - --static VALUE -+VALUE - rb_hash_clear(VALUE hash) - { - rb_hash_modify_check(hash); -diff --git a/include/ruby/intern.h b/include/ruby/intern.h -index 3766d65..372ce1f 100644 ---- a/include/ruby/intern.h -+++ b/include/ruby/intern.h -@@ -61,6 +61,7 @@ VALUE rb_ary_tmp_new(long); - void rb_ary_free(VALUE); - void rb_ary_modify(VALUE); - VALUE rb_ary_freeze(VALUE); -+VALUE rb_ary_shared_with_p(VALUE, VALUE); - VALUE rb_ary_aref(int, VALUE*, VALUE); - VALUE rb_ary_subseq(VALUE, long, long); - void rb_ary_store(VALUE, long, VALUE); -@@ -448,6 +449,7 @@ VALUE rb_hash_lookup(VALUE, VALUE); - VALUE rb_hash_lookup2(VALUE, VALUE, VALUE); - VALUE rb_hash_fetch(VALUE, VALUE); - VALUE rb_hash_aset(VALUE, VALUE, VALUE); -+VALUE rb_hash_clear(VALUE); - VALUE rb_hash_delete_if(VALUE); - VALUE rb_hash_delete(VALUE,VALUE); - typedef VALUE rb_hash_update_func(VALUE newkey, VALUE oldkey, VALUE value); -diff --git a/internal.h b/internal.h -index 59c9284..f5af903 100644 ---- a/internal.h -+++ b/internal.h -@@ -94,6 +94,8 @@ VALUE rb_home_dir(const char *user, VALUE result); - VALUE rb_realpath_internal(VALUE basedir, VALUE path, int strict); - VALUE rb_file_expand_path_fast(VALUE, VALUE); - VALUE rb_file_expand_path_internal(VALUE, VALUE, int, int, VALUE); -+VALUE rb_get_path_check_to_string(VALUE, int); -+VALUE rb_get_path_check_convert(VALUE, VALUE, int); - void Init_File(void); - - #ifdef _WIN32 -@@ -119,6 +121,7 @@ VALUE rb_iseq_clone(VALUE iseqval, VALUE newcbase); - - /* load.c */ - VALUE rb_get_load_path(void); -+VALUE rb_get_expanded_load_path(void); - - /* math.c */ - VALUE rb_math_atan2(VALUE, VALUE); -diff --git a/load.c b/load.c -index 163ec4c..e766880 100644 ---- a/load.c -+++ b/load.c -@@ -18,7 +18,6 @@ VALUE ruby_dln_librefs; - #define IS_DLEXT(e) (strcmp((e), DLEXT) == 0) - #endif - -- - static const char *const loadable_ext[] = { - ".rb", DLEXT, - #ifdef DLEXT2 -@@ -34,21 +33,120 @@ rb_get_load_path(void) - return load_path; - } - --VALUE --rb_get_expanded_load_path(void) -+enum expand_type { -+ EXPAND_ALL, -+ EXPAND_RELATIVE, -+ EXPAND_HOME, -+ EXPAND_NON_CACHE -+}; -+ -+/* Construct expanded load path and store it to cache. -+ We rebuild load path partially if the cache is invalid. -+ We don't cache non string object and expand it every times. We ensure that -+ string objects in $LOAD_PATH are frozen. -+ */ -+static void -+rb_construct_expanded_load_path(int type, int *has_relative, int *has_non_cache) - { -- VALUE load_path = rb_get_load_path(); -+ rb_vm_t *vm = GET_VM(); -+ VALUE load_path = vm->load_path; -+ VALUE expanded_load_path = vm->expanded_load_path; - VALUE ary; - long i; -+ int level = rb_safe_level(); - - ary = rb_ary_new2(RARRAY_LEN(load_path)); - for (i = 0; i < RARRAY_LEN(load_path); ++i) { -- VALUE path = rb_file_expand_path_fast(RARRAY_PTR(load_path)[i], Qnil); -- rb_str_freeze(path); -- rb_ary_push(ary, path); -+ VALUE path, as_str, expanded_path; -+ int is_string, non_cache; -+ char *as_cstr; -+ as_str = path = RARRAY_PTR(load_path)[i]; -+ is_string = RB_TYPE_P(path, T_STRING) ? 1 : 0; -+ non_cache = !is_string ? 1 : 0; -+ as_str = rb_get_path_check_to_string(path, level); -+ as_cstr = RSTRING_PTR(as_str); -+ -+ if (!non_cache) { -+ if ((type == EXPAND_RELATIVE && -+ rb_is_absolute_path(as_cstr)) || -+ (type == EXPAND_HOME && -+ (!as_cstr[0] || as_cstr[0] != '~')) || -+ (type == EXPAND_NON_CACHE)) { -+ /* Use cached expanded path. */ -+ rb_ary_push(ary, RARRAY_PTR(expanded_load_path)[i]); -+ continue; -+ } -+ } -+ if (!*has_relative && !rb_is_absolute_path(as_cstr)) -+ *has_relative = 1; -+ if (!*has_non_cache && non_cache) -+ *has_non_cache = 1; -+ /* Freeze only string object. We expand other objects every times. */ -+ if (is_string) -+ rb_str_freeze(path); -+ as_str = rb_get_path_check_convert(path, as_str, level); -+ expanded_path = rb_file_expand_path_fast(as_str, Qnil); -+ rb_str_freeze(expanded_path); -+ rb_ary_push(ary, expanded_path); - } - rb_obj_freeze(ary); -- return ary; -+ vm->expanded_load_path = ary; -+ rb_ary_replace(vm->load_path_snapshot, vm->load_path); -+} -+ -+static VALUE -+load_path_getcwd(void) -+{ -+ char *cwd = my_getcwd(); -+ VALUE cwd_str = rb_filesystem_str_new_cstr(cwd); -+ xfree(cwd); -+ return cwd_str; -+} -+ -+VALUE -+rb_get_expanded_load_path(void) -+{ -+ rb_vm_t *vm = GET_VM(); -+ const VALUE non_cache = Qtrue; -+ -+ if (!rb_ary_shared_with_p(vm->load_path_snapshot, vm->load_path)) { -+ /* The load path was modified. Rebuild the expanded load path. */ -+ int has_relative = 0, has_non_cache = 0; -+ rb_construct_expanded_load_path(EXPAND_ALL, &has_relative, &has_non_cache); -+ if (has_relative) { -+ vm->load_path_check_cache = load_path_getcwd(); -+ } -+ else if (has_non_cache) { -+ /* Non string object. */ -+ vm->load_path_check_cache = non_cache; -+ } -+ else { -+ vm->load_path_check_cache = 0; -+ } -+ } -+ else if (vm->load_path_check_cache == non_cache) { -+ int has_relative = 1, has_non_cache = 1; -+ /* Expand only non-cacheable objects. */ -+ rb_construct_expanded_load_path(EXPAND_NON_CACHE, -+ &has_relative, &has_non_cache); -+ } -+ else if (vm->load_path_check_cache) { -+ int has_relative = 1, has_non_cache = 1; -+ VALUE cwd = load_path_getcwd(); -+ if (!rb_str_equal(vm->load_path_check_cache, cwd)) { -+ /* Current working directory or filesystem encoding was changed. -+ Expand relative load path and non-cacheable objects again. */ -+ vm->load_path_check_cache = cwd; -+ rb_construct_expanded_load_path(EXPAND_RELATIVE, -+ &has_relative, &has_non_cache); -+ } -+ else { -+ /* Expand only tilde (User HOME) and non-cacheable objects. */ -+ rb_construct_expanded_load_path(EXPAND_HOME, -+ &has_relative, &has_non_cache); -+ } -+ } -+ return vm->expanded_load_path; - } - - static VALUE -@@ -63,12 +161,121 @@ get_loaded_features(void) - return GET_VM()->loaded_features; - } - -+static void -+reset_loaded_features_snapshot(void) -+{ -+ rb_vm_t *vm = GET_VM(); -+ rb_ary_replace(vm->loaded_features_snapshot, vm->loaded_features); -+} -+ -+static VALUE -+get_loaded_features_index_raw(void) -+{ -+ return GET_VM()->loaded_features_index; -+} -+ - static st_table * - get_loading_table(void) - { - return GET_VM()->loading_table; - } - -+static void -+features_index_add_single(VALUE short_feature, VALUE offset) -+{ -+ VALUE features_index, this_feature_index; -+ features_index = get_loaded_features_index_raw(); -+ if ((this_feature_index = rb_hash_lookup(features_index, short_feature)) == Qnil) { -+ this_feature_index = rb_ary_new(); -+ rb_hash_aset(features_index, short_feature, this_feature_index); -+ } -+ rb_ary_push(this_feature_index, offset); -+} -+ -+/* Add to the loaded-features index all the required entries for -+ `feature`, located at `offset` in $LOADED_FEATURES. We add an -+ index entry at each string `short_feature` for which -+ feature == "#{prefix}#{short_feature}#{e}" -+ where `e` is empty or matches %r{^\.[^./]*$}, and `prefix` is empty -+ or ends in '/'. This maintains the invariant that `rb_feature_p()` -+ relies on for its fast lookup. -+*/ -+static void -+features_index_add(VALUE feature, VALUE offset) -+{ -+ VALUE short_feature; -+ const char *feature_str, *feature_end, *ext, *p; -+ -+ feature_str = StringValuePtr(feature); -+ feature_end = feature_str + RSTRING_LEN(feature); -+ -+ for (ext = feature_end; ext > feature_str; ext--) -+ if (*ext == '.' || *ext == '/') -+ break; -+ if (*ext != '.') -+ ext = NULL; -+ /* Now `ext` points to the only string matching %r{^\.[^./]*$} that is -+ at the end of `feature`, or is NULL if there is no such string. */ -+ -+ p = ext ? ext : feature_end; -+ while (1) { -+ p--; -+ while (p >= feature_str && *p != '/') -+ p--; -+ if (p < feature_str) -+ break; -+ /* Now *p == '/'. We reach this point for every '/' in `feature`. */ -+ short_feature = rb_str_substr(feature, p + 1 - feature_str, feature_end - p - 1); -+ features_index_add_single(short_feature, offset); -+ if (ext) { -+ short_feature = rb_str_substr(feature, p + 1 - feature_str, ext - p - 1); -+ features_index_add_single(short_feature, offset); -+ } -+ } -+ features_index_add_single(feature, offset); -+ if (ext) { -+ short_feature = rb_str_substr(feature, 0, ext - feature_str); -+ features_index_add_single(short_feature, offset); -+ } -+} -+ -+static VALUE -+get_loaded_features_index(void) -+{ -+ VALUE features; -+ int i; -+ rb_vm_t *vm = GET_VM(); -+ -+ if (!rb_ary_shared_with_p(vm->loaded_features_snapshot, vm->loaded_features)) { -+ /* The sharing was broken; something (other than us in rb_provide_feature()) -+ modified loaded_features. Rebuild the index. */ -+ rb_hash_clear(vm->loaded_features_index); -+ features = vm->loaded_features; -+ for (i = 0; i < RARRAY_LEN(features); i++) { -+ VALUE entry, as_str; -+ as_str = entry = rb_ary_entry(features, i); -+ StringValue(as_str); -+ if (as_str != entry) -+ rb_ary_store(features, i, as_str); -+ rb_str_freeze(as_str); -+ features_index_add(as_str, INT2FIX(i)); -+ } -+ reset_loaded_features_snapshot(); -+ } -+ return vm->loaded_features_index; -+} -+ -+/* This searches `load_path` for a value such that -+ name == "#{load_path[i]}/#{feature}" -+ if `feature` is a suffix of `name`, or otherwise -+ name == "#{load_path[i]}/#{feature}#{ext}" -+ for an acceptable string `ext`. It returns -+ `load_path[i].to_str` if found, else 0. -+ -+ If type is 's', then `ext` is acceptable only if IS_DLEXT(ext); -+ if 'r', then only if IS_RBEXT(ext); otherwise `ext` may be absent -+ or have any value matching `%r{^\.[^./]*$}`. -+*/ - static VALUE - loaded_feature_path(const char *name, long vlen, const char *feature, long len, - int type, VALUE load_path) -@@ -77,7 +284,7 @@ loaded_feature_path(const char *name, long vlen, const char *feature, long len, - long plen; - const char *e; - -- if(vlen < len) return 0; -+ if (vlen < len+1) return 0; - if (!strncmp(name+(vlen-len),feature,len)){ - plen = vlen - len - 1; - } else { -@@ -88,23 +295,22 @@ loaded_feature_path(const char *name, long vlen, const char *feature, long len, - return 0; - plen = e - name - len - 1; - } -+ if (type == 's' && !IS_DLEXT(&name[plen+len+1]) -+ || type == 'r' && !IS_RBEXT(&name[plen+len+1]) -+ || name[plen] != '/') { -+ return 0; -+ } -+ /* Now name == "#{prefix}/#{feature}#{ext}" where ext is acceptable -+ (possibly empty) and prefix is some string of length plen. */ -+ - for (i = 0; i < RARRAY_LEN(load_path); ++i) { - VALUE p = RARRAY_PTR(load_path)[i]; - const char *s = StringValuePtr(p); - long n = RSTRING_LEN(p); - - if (n != plen ) continue; -- if (n && (strncmp(name, s, n) || name[n] != '/')) continue; -- switch (type) { -- case 's': -- if (IS_DLEXT(&name[n+len+1])) return p; -- break; -- case 'r': -- if (IS_RBEXT(&name[n+len+1])) return p; -- break; -- default: -- return p; -- } -+ if (n && strncmp(name, s, n)) continue; -+ return p; - } - return 0; - } -@@ -132,7 +338,7 @@ loaded_feature_path_i(st_data_t v, st_data_t b, st_data_t f) - static int - rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const char **fn) - { -- VALUE v, features, p, load_path = 0; -+ VALUE features, features_index, feature_val, this_feature_index, v, p, load_path = 0; - const char *f, *e; - long i, len, elen, n; - st_table *loading_tbl; -@@ -151,8 +357,39 @@ rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const c - type = 0; - } - features = get_loaded_features(); -- for (i = 0; i < RARRAY_LEN(features); ++i) { -- v = RARRAY_PTR(features)[i]; -+ features_index = get_loaded_features_index(); -+ -+ feature_val = rb_str_new(feature, len); -+ this_feature_index = rb_hash_lookup(features_index, feature_val); -+ /* We search `features` for an entry such that either -+ "#{features[i]}" == "#{load_path[j]}/#{feature}#{e}" -+ for some j, or -+ "#{features[i]}" == "#{feature}#{e}" -+ Here `e` is an "allowed" extension -- either empty or one -+ of the extensions accepted by IS_RBEXT, IS_SOEXT, or -+ IS_DLEXT. Further, if `ext && rb` then `IS_RBEXT(e)`, -+ and if `ext && !rb` then `IS_SOEXT(e) || IS_DLEXT(e)`. -+ -+ If `expanded`, then only the latter form (without load_path[j]) -+ is accepted. Otherwise either form is accepted, *unless* `ext` -+ is false and an otherwise-matching entry of the first form is -+ preceded by an entry of the form -+ "#{features[i2]}" == "#{load_path[j2]}/#{feature}#{e2}" -+ where `e2` matches %r{^\.[^./]*$} but is not an allowed extension. -+ After a "distractor" entry of this form, only entries of the -+ form "#{feature}#{e}" are accepted. -+ -+ In `rb_provide_feature()` and `get_loaded_features_index()` we -+ maintain an invariant that the array `this_feature_index` will -+ point to every entry in `features` which has the form -+ "#{prefix}#{feature}#{e}" -+ where `e` is empty or matches %r{^\.[^./]*$}, and `prefix` is empty -+ or ends in '/'. This includes both match forms above, as well -+ as any distractors, so we may ignore all other entries in `features`. -+ */ -+ for (i = 0; this_feature_index != Qnil && i < RARRAY_LEN(this_feature_index); i++) { -+ long index = FIX2LONG(rb_ary_entry(this_feature_index, i)); -+ v = RARRAY_PTR(features)[index]; - f = StringValuePtr(v); - if ((n = RSTRING_LEN(v)) < len) continue; - if (strncmp(f, feature, len) != 0) { -@@ -175,6 +412,7 @@ rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const c - return 'r'; - } - } -+ - loading_tbl = get_loading_table(); - if (loading_tbl) { - f = 0; -@@ -183,7 +421,7 @@ rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const c - fs.name = feature; - fs.len = len; - fs.type = type; -- fs.load_path = load_path ? load_path : rb_get_load_path(); -+ fs.load_path = load_path ? load_path : rb_get_expanded_load_path(); - fs.result = 0; - st_foreach(loading_tbl, loaded_feature_path_i, (st_data_t)&fs); - if ((f = fs.result) != 0) { -@@ -233,7 +471,7 @@ rb_feature_provided(const char *feature, const char **loading) - - if (*feature == '.' && - (feature[1] == '/' || strncmp(feature+1, "./", 2) == 0)) { -- fullpath = rb_file_expand_path_fast(rb_str_new2(feature), Qnil); -+ fullpath = rb_file_expand_path_fast(rb_get_path(rb_str_new2(feature)), Qnil); - feature = RSTRING_PTR(fullpath); - } - if (ext && !strchr(ext, '/')) { -@@ -254,11 +492,18 @@ rb_feature_provided(const char *feature, const char **loading) - static void - rb_provide_feature(VALUE feature) - { -- if (OBJ_FROZEN(get_loaded_features())) { -+ VALUE features; -+ -+ features = get_loaded_features(); -+ if (OBJ_FROZEN(features)) { - rb_raise(rb_eRuntimeError, - "$LOADED_FEATURES is frozen; cannot append feature"); - } -- rb_ary_push(get_loaded_features(), feature); -+ rb_str_freeze(feature); -+ -+ rb_ary_push(features, feature); -+ features_index_add(feature, INT2FIX(RARRAY_LEN(features)-1)); -+ reset_loaded_features_snapshot(); - } - - void -@@ -774,10 +1019,15 @@ Init_load() - rb_alias_variable(rb_intern("$-I"), id_load_path); - rb_alias_variable(rb_intern("$LOAD_PATH"), id_load_path); - vm->load_path = rb_ary_new(); -+ vm->expanded_load_path = rb_ary_new(); -+ vm->load_path_snapshot = rb_ary_new(); -+ vm->load_path_check_cache = 0; - - rb_define_virtual_variable("$\"", get_loaded_features, 0); - rb_define_virtual_variable("$LOADED_FEATURES", get_loaded_features, 0); - vm->loaded_features = rb_ary_new(); -+ vm->loaded_features_snapshot = rb_ary_new(); -+ vm->loaded_features_index = rb_hash_new(); - - rb_define_global_function("load", rb_f_load, -1); - rb_define_global_function("require", rb_f_require, 1); -diff --git a/ruby.c b/ruby.c -index 3ddd96c..7ffc78e 100644 ---- a/ruby.c -+++ b/ruby.c -@@ -1366,7 +1366,8 @@ process_options(int argc, char **argv, struct cmdline_options *opt) - long i; - VALUE load_path = GET_VM()->load_path; - for (i = 0; i < RARRAY_LEN(load_path); ++i) { -- rb_enc_associate(RARRAY_PTR(load_path)[i], lenc); -+ RARRAY_PTR(load_path)[i] = -+ rb_enc_associate(rb_str_dup(RARRAY_PTR(load_path)[i]), lenc); - } - } - if (!(opt->disable & DISABLE_BIT(gems))) { -diff --git a/test/ruby/test_require.rb b/test/ruby/test_require.rb -index 58a9ee2..ec75096 100644 ---- a/test/ruby/test_require.rb -+++ b/test/ruby/test_require.rb -@@ -356,4 +356,114 @@ class TestRequire < Test::Unit::TestCase - $:.replace(loadpath) - $".replace(features) - end -+ -+ def test_require_changed_current_dir -+ bug7158 = '[ruby-core:47970]' -+ Dir.mktmpdir {|tmp| -+ Dir.chdir(tmp) { -+ Dir.mkdir("a") -+ Dir.mkdir("b") -+ open(File.join("a", "foo.rb"), "w") {} -+ open(File.join("b", "bar.rb"), "w") {|f| -+ f.puts "p :ok" -+ } -+ assert_in_out_err([], <<-INPUT, %w(:ok), [], bug7158) -+ $: << "." -+ Dir.chdir("a") -+ require "foo" -+ Dir.chdir("../b") -+ p :ng unless require "bar" -+ Dir.chdir("..") -+ p :ng if require "b/bar" -+ INPUT -+ } -+ } -+ end -+ -+ def test_require_not_modified_load_path -+ bug7158 = '[ruby-core:47970]' -+ Dir.mktmpdir {|tmp| -+ Dir.chdir(tmp) { -+ open("foo.rb", "w") {} -+ assert_in_out_err([], <<-INPUT, %w(:ok), [], bug7158) -+ a = Object.new -+ def a.to_str -+ "#{tmp}" -+ end -+ $: << a -+ require "foo" -+ last_path = $:.pop -+ p :ok if last_path == a && last_path.class == Object -+ INPUT -+ } -+ } -+ end -+ -+ def test_require_changed_home -+ bug7158 = '[ruby-core:47970]' -+ Dir.mktmpdir {|tmp| -+ Dir.chdir(tmp) { -+ open("foo.rb", "w") {} -+ Dir.mkdir("a") -+ open(File.join("a", "bar.rb"), "w") {} -+ assert_in_out_err([], <<-INPUT, %w(:ok), [], bug7158) -+ $: << '~' -+ ENV['HOME'] = "#{tmp}" -+ require "foo" -+ ENV['HOME'] = "#{tmp}/a" -+ p :ok if require "bar" -+ INPUT -+ } -+ } -+ end -+ -+ def test_require_to_path_redefined_in_load_path -+ bug7158 = '[ruby-core:47970]' -+ Dir.mktmpdir {|tmp| -+ Dir.chdir(tmp) { -+ open("foo.rb", "w") {} -+ assert_in_out_err(["RUBYOPT"=>nil], <<-INPUT, %w(:ok), [], bug7158) -+ a = Object.new -+ def a.to_path -+ "bar" -+ end -+ $: << a -+ begin -+ require "foo" -+ p :ng -+ rescue LoadError -+ end -+ def a.to_path -+ "#{tmp}" -+ end -+ p :ok if require "foo" -+ INPUT -+ } -+ } -+ end -+ -+ def test_require_to_str_redefined_in_load_path -+ bug7158 = '[ruby-core:47970]' -+ Dir.mktmpdir {|tmp| -+ Dir.chdir(tmp) { -+ open("foo.rb", "w") {} -+ assert_in_out_err(["RUBYOPT"=>nil], <<-INPUT, %w(:ok), [], bug7158) -+ a = Object.new -+ def a.to_str -+ "foo" -+ end -+ $: << a -+ begin -+ require "foo" -+ p :ng -+ rescue LoadError -+ end -+ def a.to_str -+ "#{tmp}" -+ end -+ p :ok if require "foo" -+ INPUT -+ } -+ } -+ end - end -diff --git a/vm.c b/vm.c -index b5fc485..5a721d0 100644 ---- a/vm.c -+++ b/vm.c -@@ -1592,7 +1592,12 @@ rb_vm_mark(void *ptr) - RUBY_MARK_UNLESS_NULL(vm->thgroup_default); - RUBY_MARK_UNLESS_NULL(vm->mark_object_ary); - RUBY_MARK_UNLESS_NULL(vm->load_path); -+ RUBY_MARK_UNLESS_NULL(vm->load_path_snapshot); -+ RUBY_MARK_UNLESS_NULL(vm->load_path_check_cache); -+ RUBY_MARK_UNLESS_NULL(vm->expanded_load_path); - RUBY_MARK_UNLESS_NULL(vm->loaded_features); -+ RUBY_MARK_UNLESS_NULL(vm->loaded_features_snapshot); -+ RUBY_MARK_UNLESS_NULL(vm->loaded_features_index); - RUBY_MARK_UNLESS_NULL(vm->top_self); - RUBY_MARK_UNLESS_NULL(vm->coverages); - rb_gc_mark_locations(vm->special_exceptions, vm->special_exceptions + ruby_special_error_count); -diff --git a/vm_core.h b/vm_core.h -index dfc0e3c..70c5f5c 100644 ---- a/vm_core.h -+++ b/vm_core.h -@@ -299,7 +299,12 @@ typedef struct rb_vm_struct { - /* load */ - VALUE top_self; - VALUE load_path; -+ VALUE load_path_snapshot; -+ VALUE load_path_check_cache; -+ VALUE expanded_load_path; - VALUE loaded_features; -+ VALUE loaded_features_snapshot; -+ VALUE loaded_features_index; - struct st_table *loading_table; - - /* signal */ diff --git a/patches/ruby/1.9.3/head/railsexpress/10-falcon-st-opt.patch b/patches/ruby/1.9.3/head/railsexpress/10-falcon-st-opt.patch deleted file mode 100644 index 6964854f09..0000000000 --- a/patches/ruby/1.9.3/head/railsexpress/10-falcon-st-opt.patch +++ /dev/null @@ -1,2333 +0,0 @@ -diff --git a/common.mk b/common.mk -index ccc9647..1d8e442 100644 ---- a/common.mk -+++ b/common.mk -@@ -638,7 +638,8 @@ file.$(OBJEXT): {$(VPATH)}file.c $(RUBY_H_INCLUDES) {$(VPATH)}io.h \ - gc.$(OBJEXT): {$(VPATH)}gc.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \ - {$(VPATH)}regex.h $(ENCODING_H_INCLUDES) $(VM_CORE_H_INCLUDES) \ - {$(VPATH)}gc.h {$(VPATH)}io.h {$(VPATH)}eval_intern.h {$(VPATH)}util.h \ -- {$(VPATH)}debug.h {$(VPATH)}internal.h {$(VPATH)}constant.h -+ {$(VPATH)}debug.h {$(VPATH)}internal.h {$(VPATH)}constant.h \ -+ {$(VPATH)}pool_alloc.inc.h {$(VPATH)}pool_alloc.h - hash.$(OBJEXT): {$(VPATH)}hash.c $(RUBY_H_INCLUDES) {$(VPATH)}util.h \ - $(ENCODING_H_INCLUDES) - inits.$(OBJEXT): {$(VPATH)}inits.c $(RUBY_H_INCLUDES) \ -@@ -702,7 +703,7 @@ signal.$(OBJEXT): {$(VPATH)}signal.c $(RUBY_H_INCLUDES) \ - $(VM_CORE_H_INCLUDES) {$(VPATH)}debug.h - sprintf.$(OBJEXT): {$(VPATH)}sprintf.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \ - {$(VPATH)}regex.h {$(VPATH)}vsnprintf.c $(ENCODING_H_INCLUDES) --st.$(OBJEXT): {$(VPATH)}st.c $(RUBY_H_INCLUDES) -+st.$(OBJEXT): {$(VPATH)}st.c $(RUBY_H_INCLUDES) {$(VPATH)}pool_alloc.h - strftime.$(OBJEXT): {$(VPATH)}strftime.c $(RUBY_H_INCLUDES) \ - {$(VPATH)}timev.h - string.$(OBJEXT): {$(VPATH)}string.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \ -diff --git a/configure.in b/configure.in -index 28ddc31..8c4e3ff 100644 ---- a/configure.in -+++ b/configure.in -@@ -1276,6 +1276,30 @@ if test $rb_cv_stack_end_address != no; then - AC_DEFINE_UNQUOTED(STACK_END_ADDRESS, $rb_cv_stack_end_address) - fi - -+AS_CASE(["$target_os"], -+[openbsd*], [ -+ AC_CACHE_CHECK(for heap align log on openbsd, rb_cv_page_size_log, -+ [rb_cv_page_size_log=no -+ for page_log in 12 13; do -+ AC_TRY_RUN([ -+#include -+#include -+ -+int -+main() { -+ if ((int)log2((double)sysconf(_SC_PAGESIZE)) != $page_log) return 1; -+ return 0; -+} -+ ], -+ rb_cv_page_size_log="$page_log"; break) -+ done]) -+ if test $rb_cv_page_size_log != no; then -+ AC_DEFINE_UNQUOTED(HEAP_ALIGN_LOG, $rb_cv_page_size_log) -+ else -+ AC_DEFINE_UNQUOTED(HEAP_ALIGN_LOG, 12) -+ fi -+]) -+ - dnl Checks for library functions. - AC_TYPE_GETGROUPS - AC_TYPE_SIGNAL -@@ -1375,7 +1399,8 @@ AC_CHECK_FUNCS(fmod killpg wait4 waitpid fork spawnv syscall __syscall chroot ge - setsid telldir seekdir fchmod cosh sinh tanh log2 round\ - setuid setgid daemon select_large_fdset setenv unsetenv\ - mktime timegm gmtime_r clock_gettime gettimeofday poll ppoll\ -- pread sendfile shutdown sigaltstack dl_iterate_phdr) -+ pread sendfile shutdown sigaltstack dl_iterate_phdr\ -+ posix_memalign memalign) - - AC_CACHE_CHECK(for unsetenv returns a value, rb_cv_unsetenv_return_value, - [AC_TRY_COMPILE([ -diff --git a/ext/-test-/st/numhash/numhash.c b/ext/-test-/st/numhash/numhash.c -index e186cd4..53d9e1b 100644 ---- a/ext/-test-/st/numhash/numhash.c -+++ b/ext/-test-/st/numhash/numhash.c -@@ -54,7 +54,7 @@ numhash_i(st_data_t key, st_data_t value, st_data_t arg, int error) - static VALUE - numhash_each(VALUE self) - { -- return st_foreach((st_table *)DATA_PTR(self), numhash_i, self) ? Qtrue : Qfalse; -+ return st_foreach_check((st_table *)DATA_PTR(self), numhash_i, self, 0) ? Qtrue : Qfalse; - } - - void -diff --git a/gc.c b/gc.c -index b5fc83c..3110059 100644 ---- a/gc.c -+++ b/gc.c -@@ -20,6 +20,7 @@ - #include "vm_core.h" - #include "internal.h" - #include "gc.h" -+#include "pool_alloc.h" - #include "constant.h" - #include "ruby_atomic.h" - #include -@@ -37,7 +38,12 @@ - - #if defined _WIN32 || defined __CYGWIN__ - #include -+#elif defined(HAVE_POSIX_MEMALIGN) -+#elif defined(HAVE_MEMALIGN) -+#include - #endif -+static void aligned_free(void *); -+static void *aligned_malloc(size_t alignment, size_t size); - - #ifdef HAVE_VALGRIND_MEMCHECK_H - # include -@@ -356,6 +362,24 @@ typedef struct mark_stack { - - #define CALC_EXACT_MALLOC_SIZE 0 - -+#ifdef POOL_ALLOC_API -+/* POOL ALLOC API */ -+#define POOL_ALLOC_PART 1 -+#include "pool_alloc.inc.h" -+#undef POOL_ALLOC_PART -+ -+typedef struct pool_layout_t pool_layout_t; -+struct pool_layout_t { -+ pool_header -+ p6, /* st_table && st_table_entry */ -+ p11; /* st_table.bins init size */ -+} pool_layout = { -+ INIT_POOL(void*[6]), -+ INIT_POOL(void*[11]) -+}; -+static void pool_finalize_header(pool_header *header); -+#endif -+ - typedef struct rb_objspace { - struct { - size_t limit; -@@ -365,6 +389,9 @@ typedef struct rb_objspace { - size_t allocations; - #endif - } malloc_params; -+#ifdef POOL_ALLOC_API -+ pool_layout_t *pool_headers; -+#endif - struct { - size_t increment; - struct heaps_slot *ptr; -@@ -430,7 +457,11 @@ typedef struct rb_objspace { - #define ruby_initial_gc_stress initial_params.gc_stress - int *ruby_initial_gc_stress_ptr = &ruby_initial_gc_stress; - #else -+# ifdef POOL_ALLOC_API -+static rb_objspace_t rb_objspace = {{GC_MALLOC_LIMIT}, &pool_layout, {HEAP_MIN_SLOTS}}; -+# else - static rb_objspace_t rb_objspace = {{GC_MALLOC_LIMIT}, {HEAP_MIN_SLOTS}}; -+# endif - int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress; - #endif - #define malloc_limit objspace->malloc_params.limit -@@ -481,6 +512,10 @@ rb_objspace_alloc(void) - memset(objspace, 0, sizeof(*objspace)); - malloc_limit = initial_malloc_limit; - ruby_gc_stress = ruby_initial_gc_stress; -+#ifdef POOL_ALLOC_API -+ objspace->pool_headers = (pool_layout_t*) malloc(sizeof(pool_layout)); -+ memcpy(objspace->pool_headers, &pool_layout, sizeof(pool_layout)); -+#endif - - return objspace; - } -@@ -624,6 +659,13 @@ rb_objspace_free(rb_objspace_t *objspace) - heaps = 0; - } - free_stack_chunks(&objspace->mark_stack); -+#ifdef POOL_ALLOC_API -+ if (objspace->pool_headers) { -+ pool_finalize_header(&objspace->pool_headers->p6); -+ pool_finalize_header(&objspace->pool_headers->p11); -+ free(objspace->pool_headers); -+ } -+#endif - free(objspace); - } - #endif -@@ -1148,6 +1190,27 @@ rb_gc_stats_enabled() - return gc_statistics ? Qtrue : Qfalse; - } - -+#ifdef POOL_ALLOC_API -+/* POOL ALLOC API */ -+#define POOL_ALLOC_PART 2 -+#include "pool_alloc.inc.h" -+#undef POOL_ALLOC_PART -+ -+void -+ruby_xpool_free(void *ptr) -+{ -+ pool_free_entry((void**)ptr); -+} -+ -+#define CONCRET_POOL_MALLOC(pnts) \ -+void * ruby_xpool_malloc_##pnts##p () { \ -+ return pool_alloc_entry(&rb_objspace.pool_headers->p##pnts ); \ -+} -+CONCRET_POOL_MALLOC(6) -+CONCRET_POOL_MALLOC(11) -+#undef CONCRET_POOL_MALLOC -+ -+#endif - - /* - * call-seq: -@@ -1663,6 +1726,55 @@ allocate_sorted_heaps(rb_objspace_t *objspace, size_t next_heaps_length) - heaps_length = next_heaps_length; - } - -+static void * -+aligned_malloc(size_t alignment, size_t size) -+{ -+ void *res; -+ -+#if defined __MINGW32__ -+ res = __mingw_aligned_malloc(size, alignment); -+#elif defined _WIN32 && !defined __CYGWIN__ -+ 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 -+ -+#if defined(_DEBUG) || defined(GC_DEBUG) -+ /* alignment must be a power of 2 */ -+ assert((alignment - 1) & alignment == 0); -+ assert(alignment % sizeof(void*) == 0); -+#endif -+ return res; -+} -+ -+static void -+aligned_free(void *ptr) -+{ -+#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 -+} -+ - static void - assign_heap_slot(rb_objspace_t *objspace) - { -diff --git a/hash.c b/hash.c -index 8423558..4cb2e2d 100644 ---- a/hash.c -+++ b/hash.c -@@ -44,7 +44,7 @@ rb_any_cmp(VALUE a, VALUE b) - if (FIXNUM_P(a) && FIXNUM_P(b)) { - return a != b; - } -- if (TYPE(a) == T_STRING && RBASIC(a)->klass == rb_cString && -+ if (RB_TYPE_P(a, T_STRING) && RBASIC(a)->klass == rb_cString && - TYPE(b) == T_STRING && RBASIC(b)->klass == rb_cString) { - return rb_str_hash_cmp(a, b); - } -@@ -80,20 +80,14 @@ rb_any_hash(VALUE a) - VALUE hval; - st_index_t hnum; - -- switch (TYPE(a)) { -- case T_FIXNUM: -- case T_SYMBOL: -- case T_NIL: -- case T_FALSE: -- case T_TRUE: -- hnum = rb_hash_end(rb_hash_start((unsigned int)a)); -- break; -- -- case T_STRING: -+ if (SPECIAL_CONST_P(a)) { -+ if (a == Qundef) return 0; -+ hnum = rb_hash_end(rb_hash_start((st_index_t)a)); -+ } -+ else if (BUILTIN_TYPE(a) == T_STRING) { - hnum = rb_str_hash(a); -- break; -- -- default: -+ } -+ else { - hval = rb_hash(a); - hnum = FIX2LONG(hval); - } -@@ -106,10 +100,8 @@ static const struct st_hash_type objhash = { - rb_any_hash, - }; - --static const struct st_hash_type identhash = { -- st_numcmp, -- st_numhash, --}; -+extern const struct st_hash_type st_hashtype_num; -+#define identhash st_hashtype_num - - typedef int st_foreach_func(st_data_t, st_data_t, st_data_t); - -@@ -124,7 +116,6 @@ foreach_safe_i(st_data_t key, st_data_t value, struct foreach_safe_arg *arg) - { - int status; - -- if (key == Qundef) return ST_CONTINUE; - status = (*arg->func)(key, value, arg->arg); - if (status == ST_CONTINUE) { - return ST_CHECK; -@@ -140,7 +131,7 @@ st_foreach_safe(st_table *table, int (*func)(ANYARGS), st_data_t a) - arg.tbl = table; - arg.func = (st_foreach_func *)func; - arg.arg = a; -- if (st_foreach(table, foreach_safe_i, (st_data_t)&arg)) { -+ if (st_foreach_check(table, foreach_safe_i, (st_data_t)&arg, 0)) { - rb_raise(rb_eRuntimeError, "hash modified during iteration"); - } - } -@@ -154,21 +145,21 @@ struct hash_foreach_arg { - }; - - static int --hash_foreach_iter(st_data_t key, st_data_t value, struct hash_foreach_arg *arg) -+hash_foreach_iter(st_data_t key, st_data_t value, st_data_t argp) - { -+ struct hash_foreach_arg *arg = (struct hash_foreach_arg *)argp; - int status; - st_table *tbl; - - tbl = RHASH(arg->hash)->ntbl; -- if ((VALUE)key == Qundef) return ST_CONTINUE; - status = (*arg->func)((VALUE)key, (VALUE)value, arg->arg); - if (RHASH(arg->hash)->ntbl != tbl) { - rb_raise(rb_eRuntimeError, "rehash occurred during iteration"); - } - switch (status) { - case ST_DELETE: -- st_delete_safe(tbl, &key, 0, Qundef); - FL_SET(arg->hash, HASH_DELETED); -+ return ST_DELETE; - case ST_CONTINUE: - break; - case ST_STOP: -@@ -184,7 +175,7 @@ hash_foreach_ensure(VALUE hash) - - if (RHASH(hash)->iter_lev == 0) { - if (FL_TEST(hash, HASH_DELETED)) { -- st_cleanup_safe(RHASH(hash)->ntbl, Qundef); -+ st_cleanup_safe(RHASH(hash)->ntbl, (st_data_t)Qundef); - FL_UNSET(hash, HASH_DELETED); - } - } -@@ -192,9 +183,10 @@ hash_foreach_ensure(VALUE hash) - } - - static VALUE --hash_foreach_call(struct hash_foreach_arg *arg) -+hash_foreach_call(VALUE arg) - { -- if (st_foreach(RHASH(arg->hash)->ntbl, hash_foreach_iter, (st_data_t)arg)) { -+ VALUE hash = ((struct hash_foreach_arg *)arg)->hash; -+ if (st_foreach_check(RHASH(hash)->ntbl, hash_foreach_iter, (st_data_t)arg, (st_data_t)Qundef)) { - rb_raise(rb_eRuntimeError, "hash modified during iteration"); - } - return Qnil; -@@ -447,7 +439,7 @@ rb_hash_rehash_i(VALUE key, VALUE value, VALUE arg) - { - st_table *tbl = (st_table *)arg; - -- if (key != Qundef) st_insert(tbl, key, value); -+ st_insert(tbl, (st_data_t)key, (st_data_t)value); - return ST_CONTINUE; - } - -@@ -490,6 +482,20 @@ rb_hash_rehash(VALUE hash) - return hash; - } - -+static VALUE -+hash_default_value(VALUE hash, VALUE key) -+{ -+ if (rb_method_basic_definition_p(CLASS_OF(hash), id_default)) { -+ VALUE ifnone = RHASH_IFNONE(hash); -+ if (!FL_TEST(hash, HASH_PROC_DEFAULT)) return ifnone; -+ if (key == Qundef) return Qnil; -+ return rb_funcall(ifnone, id_yield, 2, hash, key); -+ } -+ else { -+ return rb_funcall(hash, id_default, 1, key); -+ } -+} -+ - /* - * call-seq: - * hsh[key] -> value -@@ -510,13 +516,7 @@ rb_hash_aref(VALUE hash, VALUE key) - st_data_t val; - - if (!RHASH(hash)->ntbl || !st_lookup(RHASH(hash)->ntbl, key, &val)) { -- if (!FL_TEST(hash, HASH_PROC_DEFAULT) && -- rb_method_basic_definition_p(CLASS_OF(hash), id_default)) { -- return RHASH_IFNONE(hash); -- } -- else { -- return rb_funcall(hash, id_default, 1, key); -- } -+ return hash_default_value(hash, key); - } - return (VALUE)val; - } -@@ -659,7 +659,7 @@ rb_hash_default(int argc, VALUE *argv, VALUE hash) - static VALUE - rb_hash_set_default(VALUE hash, VALUE ifnone) - { -- rb_hash_modify(hash); -+ rb_hash_modify_check(hash); - RHASH_IFNONE(hash) = ifnone; - FL_UNSET(hash, HASH_PROC_DEFAULT); - return ifnone; -@@ -707,7 +707,7 @@ rb_hash_set_default_proc(VALUE hash, VALUE proc) - { - VALUE b; - -- rb_hash_modify(hash); -+ rb_hash_modify_check(hash); - b = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc"); - if (NIL_P(b) || !rb_obj_is_proc(b)) { - rb_raise(rb_eTypeError, -@@ -776,7 +776,7 @@ rb_hash_delete_key(VALUE hash, VALUE key) - if (!RHASH(hash)->ntbl) - return Qundef; - if (RHASH(hash)->iter_lev > 0) { -- if (st_delete_safe(RHASH(hash)->ntbl, &ktmp, &val, Qundef)) { -+ if (st_delete_safe(RHASH(hash)->ntbl, &ktmp, &val, (st_data_t)Qundef)) { - FL_SET(hash, HASH_DELETED); - return (VALUE)val; - } -@@ -809,7 +809,7 @@ rb_hash_delete(VALUE hash, VALUE key) - { - VALUE val; - -- rb_hash_modify(hash); -+ rb_hash_modify_check(hash); - val = rb_hash_delete_key(hash, key); - if (val != Qundef) return val; - if (rb_block_given_p()) { -@@ -828,7 +828,6 @@ shift_i(VALUE key, VALUE value, VALUE arg) - { - struct shift_var *var = (struct shift_var *)arg; - -- if (key == Qundef) return ST_CONTINUE; - if (var->key != Qundef) return ST_STOP; - var->key = key; - var->val = value; -@@ -840,7 +839,6 @@ shift_i_safe(VALUE key, VALUE value, VALUE arg) - { - struct shift_var *var = (struct shift_var *)arg; - -- if (key == Qundef) return ST_CONTINUE; - var->key = key; - var->val = value; - return ST_STOP; -@@ -864,29 +862,25 @@ rb_hash_shift(VALUE hash) - { - struct shift_var var; - -- rb_hash_modify(hash); -- var.key = Qundef; -- rb_hash_foreach(hash, RHASH(hash)->iter_lev > 0 ? shift_i_safe : shift_i, -- (VALUE)&var); -- -- if (var.key != Qundef) { -- if (RHASH(hash)->iter_lev > 0) { -- rb_hash_delete_key(hash, var.key); -+ rb_hash_modify_check(hash); -+ if (RHASH(hash)->ntbl) { -+ var.key = Qundef; -+ rb_hash_foreach(hash, RHASH(hash)->iter_lev > 0 ? shift_i_safe : shift_i, -+ (VALUE)&var); -+ -+ if (var.key != Qundef) { -+ if (RHASH(hash)->iter_lev > 0) { -+ rb_hash_delete_key(hash, var.key); -+ } -+ return rb_assoc_new(var.key, var.val); - } -- return rb_assoc_new(var.key, var.val); -- } -- else if (FL_TEST(hash, HASH_PROC_DEFAULT)) { -- return rb_funcall(RHASH_IFNONE(hash), id_yield, 2, hash, Qnil); -- } -- else { -- return RHASH_IFNONE(hash); - } -+ return hash_default_value(hash, Qnil); - } - - static int - delete_if_i(VALUE key, VALUE value, VALUE hash) - { -- if (key == Qundef) return ST_CONTINUE; - if (RTEST(rb_yield_values(2, key, value))) { - rb_hash_delete_key(hash, key); - } -@@ -912,8 +906,9 @@ VALUE - rb_hash_delete_if(VALUE hash) - { - RETURN_ENUMERATOR(hash, 0, 0); -- rb_hash_modify(hash); -- rb_hash_foreach(hash, delete_if_i, hash); -+ rb_hash_modify_check(hash); -+ if (RHASH(hash)->ntbl) -+ rb_hash_foreach(hash, delete_if_i, hash); - return hash; - } - -@@ -984,7 +979,6 @@ rb_hash_values_at(int argc, VALUE *argv, VALUE hash) - static int - select_i(VALUE key, VALUE value, VALUE result) - { -- if (key == Qundef) return ST_CONTINUE; - if (RTEST(rb_yield_values(2, key, value))) - rb_hash_aset(result, key, value); - return ST_CONTINUE; -@@ -1018,7 +1012,6 @@ rb_hash_select(VALUE hash) - static int - keep_if_i(VALUE key, VALUE value, VALUE hash) - { -- if (key == Qundef) return ST_CONTINUE; - if (!RTEST(rb_yield_values(2, key, value))) { - return ST_DELETE; - } -@@ -1040,7 +1033,7 @@ rb_hash_select_bang(VALUE hash) - st_index_t n; - - RETURN_ENUMERATOR(hash, 0, 0); -- rb_hash_modify(hash); -+ rb_hash_modify_check(hash); - if (!RHASH(hash)->ntbl) - return Qnil; - n = RHASH(hash)->ntbl->num_entries; -@@ -1065,8 +1058,9 @@ VALUE - rb_hash_keep_if(VALUE hash) - { - RETURN_ENUMERATOR(hash, 0, 0); -- rb_hash_modify(hash); -- rb_hash_foreach(hash, keep_if_i, hash); -+ rb_hash_modify_check(hash); -+ if (RHASH(hash)->ntbl) -+ rb_hash_foreach(hash, keep_if_i, hash); - return hash; - } - -@@ -1144,9 +1138,7 @@ rb_hash_aset(VALUE hash, VALUE key, VALUE val) - static int - replace_i(VALUE key, VALUE val, VALUE hash) - { -- if (key != Qundef) { -- rb_hash_aset(hash, key, val); -- } -+ rb_hash_aset(hash, key, val); - - return ST_CONTINUE; - } -@@ -1227,7 +1219,6 @@ rb_hash_empty_p(VALUE hash) - static int - each_value_i(VALUE key, VALUE value) - { -- if (key == Qundef) return ST_CONTINUE; - rb_yield(value); - return ST_CONTINUE; - } -@@ -1262,7 +1253,6 @@ rb_hash_each_value(VALUE hash) - static int - each_key_i(VALUE key, VALUE value) - { -- if (key == Qundef) return ST_CONTINUE; - rb_yield(key); - return ST_CONTINUE; - } -@@ -1296,7 +1286,6 @@ rb_hash_each_key(VALUE hash) - static int - each_pair_i(VALUE key, VALUE value) - { -- if (key == Qundef) return ST_CONTINUE; - rb_yield(rb_assoc_new(key, value)); - return ST_CONTINUE; - } -@@ -1334,7 +1323,6 @@ rb_hash_each_pair(VALUE hash) - static int - to_a_i(VALUE key, VALUE value, VALUE ary) - { -- if (key == Qundef) return ST_CONTINUE; - rb_ary_push(ary, rb_assoc_new(key, value)); - return ST_CONTINUE; - } -@@ -1367,7 +1355,6 @@ inspect_i(VALUE key, VALUE value, VALUE str) - { - VALUE str2; - -- if (key == Qundef) return ST_CONTINUE; - str2 = rb_inspect(key); - if (RSTRING_LEN(str) > 1) { - rb_str_cat2(str, ", "); -@@ -1434,7 +1421,6 @@ rb_hash_to_hash(VALUE hash) - static int - keys_i(VALUE key, VALUE value, VALUE ary) - { -- if (key == Qundef) return ST_CONTINUE; - rb_ary_push(ary, key); - return ST_CONTINUE; - } -@@ -1465,7 +1451,6 @@ rb_hash_keys(VALUE hash) - static int - values_i(VALUE key, VALUE value, VALUE ary) - { -- if (key == Qundef) return ST_CONTINUE; - rb_ary_push(ary, value); - return ST_CONTINUE; - } -@@ -1524,7 +1509,6 @@ rb_hash_search_value(VALUE key, VALUE value, VALUE arg) - { - VALUE *data = (VALUE *)arg; - -- if (key == Qundef) return ST_CONTINUE; - if (rb_equal(value, data[1])) { - data[0] = Qtrue; - return ST_STOP; -@@ -1568,7 +1552,6 @@ eql_i(VALUE key, VALUE val1, VALUE arg) - struct equal_data *data = (struct equal_data *)arg; - st_data_t val2; - -- if (key == Qundef) return ST_CONTINUE; - if (!st_lookup(data->tbl, key, &val2)) { - data->result = Qfalse; - return ST_STOP; -@@ -1599,7 +1582,7 @@ hash_equal(VALUE hash1, VALUE hash2, int eql) - struct equal_data data; - - if (hash1 == hash2) return Qtrue; -- if (TYPE(hash2) != T_HASH) { -+ if (!RB_TYPE_P(hash2, T_HASH)) { - if (!rb_respond_to(hash2, rb_intern("to_hash"))) { - return Qfalse; - } -@@ -1670,7 +1653,6 @@ hash_i(VALUE key, VALUE val, VALUE arg) - st_index_t *hval = (st_index_t *)arg; - st_index_t hdata[2]; - -- if (key == Qundef) return ST_CONTINUE; - hdata[0] = rb_hash(key); - hdata[1] = rb_hash(val); - *hval ^= st_hash(hdata, sizeof(hdata), 0); -@@ -1711,7 +1693,6 @@ rb_hash_hash(VALUE hash) - static int - rb_hash_invert_i(VALUE key, VALUE value, VALUE hash) - { -- if (key == Qundef) return ST_CONTINUE; - rb_hash_aset(hash, value, key); - return ST_CONTINUE; - } -@@ -1740,7 +1721,6 @@ rb_hash_invert(VALUE hash) - static int - rb_hash_update_i(VALUE key, VALUE value, VALUE hash) - { -- if (key == Qundef) return ST_CONTINUE; - hash_update(hash, key); - st_insert(RHASH(hash)->ntbl, key, value); - return ST_CONTINUE; -@@ -1749,7 +1729,6 @@ rb_hash_update_i(VALUE key, VALUE value, VALUE hash) - static int - rb_hash_update_block_i(VALUE key, VALUE value, VALUE hash) - { -- if (key == Qundef) return ST_CONTINUE; - if (rb_hash_has_key(hash, key)) { - value = rb_yield_values(3, key, rb_hash_aref(hash, key), value); - } -@@ -1806,7 +1785,6 @@ rb_hash_update_func_i(VALUE key, VALUE value, VALUE arg0) - struct update_arg *arg = (struct update_arg *)arg0; - VALUE hash = arg->hash; - -- if (key == Qundef) return ST_CONTINUE; - if (rb_hash_has_key(hash, key)) { - value = (*arg->func)(key, rb_hash_aref(hash, key), value); - } -@@ -1863,7 +1841,6 @@ assoc_i(VALUE key, VALUE val, VALUE arg) - { - VALUE *args = (VALUE *)arg; - -- if (key == Qundef) return ST_CONTINUE; - if (RTEST(rb_equal(args[0], key))) { - args[1] = rb_assoc_new(key, val); - return ST_STOP; -@@ -1901,7 +1878,6 @@ rassoc_i(VALUE key, VALUE val, VALUE arg) - { - VALUE *args = (VALUE *)arg; - -- if (key == Qundef) return ST_CONTINUE; - if (RTEST(rb_equal(args[0], val))) { - args[1] = rb_assoc_new(key, val); - return ST_STOP; -@@ -2198,7 +2174,7 @@ rb_env_path_tainted(void) - } - - #if defined(_WIN32) || (defined(HAVE_SETENV) && defined(HAVE_UNSETENV)) --#elif defined __sun__ -+#elif defined __sun - static int - in_origenv(const char *str) - { -@@ -2286,7 +2262,7 @@ ruby_setenv(const char *name, const char *value) - rb_sys_fail("unsetenv"); - #endif - } --#elif defined __sun__ -+#elif defined __sun - size_t len; - char **env_ptr, *str; - if (strchr(name, '=')) { -@@ -3084,11 +3060,9 @@ env_invert(void) - static int - env_replace_i(VALUE key, VALUE val, VALUE keys) - { -- if (key != Qundef) { -- env_aset(Qnil, key, val); -- if (rb_ary_includes(keys, key)) { -- rb_ary_delete(keys, key); -- } -+ env_aset(Qnil, key, val); -+ if (rb_ary_includes(keys, key)) { -+ rb_ary_delete(keys, key); - } - return ST_CONTINUE; - } -@@ -3120,12 +3094,10 @@ env_replace(VALUE env, VALUE hash) - static int - env_update_i(VALUE key, VALUE val) - { -- if (key != Qundef) { -- if (rb_block_given_p()) { -- val = rb_yield_values(3, key, rb_f_getenv(Qnil, key), val); -- } -- env_aset(Qnil, key, val); -+ if (rb_block_given_p()) { -+ val = rb_yield_values(3, key, rb_f_getenv(Qnil, key), val); - } -+ env_aset(Qnil, key, val); - return ST_CONTINUE; - } - -@@ -3150,15 +3122,116 @@ env_update(VALUE env, VALUE hash) - } - - /* -- * A Hash is a collection of key-value pairs. It is -- * similar to an Array, except that indexing is done via -- * arbitrary keys of any object type, not an integer index. Hashes enumerate -- * their values in the order that the corresponding keys were inserted. -+ * A Hash is a dictionary-like collection of unique keys and their values. -+ * Also called associative arrays, they are similar to Arrays, but where an -+ * Array uses integers as its index, a Hash allows you to use any object -+ * type. -+ * -+ * Hashes enumerate their values in the order that the corresponding keys -+ * were inserted. -+ * -+ * A Hash can be easily created by using its implicit form: -+ * -+ * grades = { "Jane Doe" => 10, "Jim Doe" => 6 } -+ * -+ * Hashes allow an alternate syntax form when your keys are always symbols. -+ * Instead of -+ * -+ * options = { :font_size => 10, :font_family => "Arial" } -+ * -+ * You could write it as: -+ * -+ * options = { font_size: 10, font_family: "Arial" } -+ * -+ * Each named key is a symbol you can access in hash: -+ * -+ * options[:font_size] # => 10 -+ * -+ * A Hash can also be created through its ::new method: -+ * -+ * grades = Hash.new -+ * grades["Dorothy Doe"] = 9 - * - * Hashes have a default value that is returned when accessing -- * keys that do not exist in the hash. By default, that value is -- * nil. -+ * keys that do not exist in the hash. If no default is set +nil+ is used. -+ * You can set the default value by sending it as an argument to Hash.new: -+ * -+ * grades = Hash.new(0) -+ * -+ * Or by using the #default= method: -+ * -+ * grades = {"Timmy Doe" => 8} -+ * grades.default = 0 -+ * -+ * Accessing a value in a Hash requires using its key: -+ * -+ * puts grades["Jane Doe"] # => 10 -+ * -+ * === Common Uses -+ * -+ * Hashes are an easy way to represent data structures, such as -+ * -+ * books = {} -+ * books[:matz] = "The Ruby Language" -+ * books[:black] = "The Well-Grounded Rubyist" -+ * -+ * Hashes are also commonly used as a way to have named parameters in -+ * functions. Note that no brackets are used below. If a hash is the last -+ * argument on a method call, no braces are needed, thus creating a really -+ * clean interface: -+ * -+ * Person.create(name: "John Doe", age: 27) -+ * -+ * def self.create(params) -+ * @name = params[:name] -+ * @age = params[:age] -+ * end -+ * -+ * === Hash Keys -+ * -+ * Two objects refer to the same hash key when their hash value -+ * is identical and the two objects are eql? to each other. -+ * -+ * A user-defined class may be used as a hash key if the hash -+ * and eql? methods are overridden to provide meaningful -+ * behavior. By default, separate instances refer to separate hash keys. -+ * -+ * A typical implementation of hash is based on the -+ * object's data while eql? is usually aliased to the overridden -+ * == method: -+ * -+ * class Book -+ * attr_reader :author, :title -+ * -+ * def initialize(author, title) -+ * @author = author -+ * @title = title -+ * end -+ * -+ * def ==(other) -+ * self.class === other and -+ * other.author == @author and -+ * other.title == @title -+ * end -+ * -+ * alias eql? == -+ * -+ * def hash -+ * @author.hash ^ @title.hash # XOR -+ * end -+ * end -+ * -+ * book1 = Book.new 'matz', 'Ruby in a Nutshell' -+ * book2 = Book.new 'matz', 'Ruby in a Nutshell' -+ * -+ * reviews = {} -+ * -+ * reviews[book1] = 'Great reference!' -+ * reviews[book2] = 'Nice and compact!' -+ * -+ * reviews.length #=> 1 - * -+ * See also Object#hash and Object#eql? - */ - - void -diff --git a/include/ruby/st.h b/include/ruby/st.h -index 50f2a75..119dfde 100644 ---- a/include/ruby/st.h -+++ b/include/ruby/st.h -@@ -36,7 +36,7 @@ typedef unsigned long st_data_t; - #elif SIZEOF_LONG_LONG == SIZEOF_VOIDP - typedef unsigned LONG_LONG st_data_t; - #else --# error ---->> st.c requires sizeof(void*) == sizeof(long) to be compiled. <<---- -+# error ---->> st.c requires sizeof(void*) == sizeof(long) or sizeof(LONG_LONG) to be compiled. <<---- - #endif - #define ST_DATA_T_DEFINED - -@@ -74,6 +74,11 @@ struct st_hash_type { - - #define ST_INDEX_BITS (sizeof(st_index_t) * CHAR_BIT) - -+typedef struct st_packed_entry { -+ st_index_t hash; -+ st_data_t key, val; -+} st_packed_entry; -+ - struct st_table { - const struct st_hash_type *type; - st_index_t num_bins; -@@ -91,8 +96,17 @@ struct st_table { - __extension__ - #endif - st_index_t num_entries : ST_INDEX_BITS - 1; -- struct st_table_entry **bins; -- struct st_table_entry *head, *tail; -+ union { -+ struct { -+ struct st_table_entry **bins; -+ struct st_table_entry *head, *tail; -+ } big; -+ struct { -+ struct st_packed_entry *entries; -+ st_index_t real_entries; -+ } packed; -+ st_packed_entry upacked; -+ } as; - }; - - #define st_is_member(table,key) st_lookup((table),(key),(st_data_t *)0) -@@ -114,6 +128,7 @@ int st_insert2(st_table *, st_data_t, st_data_t, st_data_t (*)(st_data_t)); - int st_lookup(st_table *, st_data_t, st_data_t *); - int st_get_key(st_table *, st_data_t, st_data_t *); - int st_foreach(st_table *, int (*)(ANYARGS), st_data_t); -+int st_foreach_check(st_table *, int (*)(ANYARGS), st_data_t, st_data_t); - int st_reverse_foreach(st_table *, int (*)(ANYARGS), st_data_t); - void st_add_direct(st_table *, st_data_t, st_data_t); - void st_free_table(st_table *); -diff --git a/pool_alloc.h b/pool_alloc.h -new file mode 100644 -index 0000000..957708e ---- /dev/null -+++ b/pool_alloc.h -@@ -0,0 +1,11 @@ -+#ifndef POOL_ALLOC_H -+#define POOL_ALLOC_H -+ -+#define POOL_ALLOC_API -+#ifdef POOL_ALLOC_API -+void ruby_xpool_free(void *ptr); -+void *ruby_xpool_malloc_6p(); -+void *ruby_xpool_malloc_11p(); -+#endif -+ -+#endif -diff --git a/pool_alloc.inc.h b/pool_alloc.inc.h -new file mode 100644 -index 0000000..a7879ab ---- /dev/null -+++ b/pool_alloc.inc.h -@@ -0,0 +1,156 @@ -+/* -+ * this is generic pool allocator -+ * you should define following macroses: -+ * ITEM_NAME - unique identifier, which allows to hold functions in a namespace -+ * ITEM_TYPEDEF(name) - passed to typedef to localize item type -+ * free_entry - desired name of function for free entry -+ * alloc_entry - defired name of function for allocate entry -+ */ -+ -+#if POOL_ALLOC_PART == 1 -+#ifdef HEAP_ALIGN_LOG -+#define DEFAULT_POOL_SIZE (1 << HEAP_ALIGN_LOG) -+#else -+#define DEFAULT_POOL_SIZE (sizeof(void*) * 2048) -+#endif -+typedef unsigned int pool_holder_counter; -+ -+typedef struct pool_entry_list pool_entry_list; -+typedef struct pool_holder pool_holder; -+ -+typedef struct pool_header { -+ pool_holder *first; -+ pool_holder *_black_magick; -+ pool_holder_counter size; // size of entry in sizeof(void*) items -+ pool_holder_counter total; // size of entry in sizeof(void*) items -+} pool_header; -+ -+struct pool_holder { -+ pool_holder_counter free, total; -+ pool_header *header; -+ void *freep; -+ pool_holder *fore, *back; -+ void *data[1]; -+}; -+#define POOL_DATA_SIZE(pool_size) (((pool_size) - sizeof(void*) * 6 - offsetof(pool_holder, data)) / sizeof(void*)) -+#define POOL_ENTRY_SIZE(item_type) ((sizeof(item_type) - 1) / sizeof(void*) + 1) -+#define POOL_HOLDER_COUNT(pool_size, item_type) (POOL_DATA_SIZE(pool_size)/POOL_ENTRY_SIZE(item_type)) -+#define INIT_POOL(item_type) {NULL, NULL, POOL_ENTRY_SIZE(item_type), POOL_HOLDER_COUNT(DEFAULT_POOL_SIZE, item_type)} -+ -+#elif POOL_ALLOC_PART == 2 -+static pool_holder * -+pool_holder_alloc(pool_header *header) -+{ -+ pool_holder *holder; -+ pool_holder_counter i, size, count; -+ register void **ptr; -+ -+ size_t sz = offsetof(pool_holder, data) + -+ header->size * header->total * sizeof(void*); -+#define objspace (&rb_objspace) -+ vm_malloc_prepare(objspace, DEFAULT_POOL_SIZE); -+ if (header->first != NULL) return header->first; -+ TRY_WITH_GC(holder = (pool_holder*) aligned_malloc(DEFAULT_POOL_SIZE, sz)); -+ malloc_increase += DEFAULT_POOL_SIZE; -+#if CALC_EXACT_MALLOC_SIZE -+ objspace->malloc_params.allocated_size += DEFAULT_POOL_SIZE; -+ objspace->malloc_params.allocations++; -+#endif -+#undef objspace -+ -+ size = header->size; -+ count = header->total; -+ holder->free = count; -+ holder->total = count; -+ holder->header = header; -+ holder->fore = NULL; -+ holder->back = NULL; -+ holder->freep = &holder->data; -+ ptr = holder->data; -+ for(i = count - 1; i; i-- ) { -+ ptr = *ptr = ptr + size; -+ } -+ *ptr = NULL; -+ header->first = holder; -+ return holder; -+} -+ -+static inline void -+pool_holder_unchaing(pool_header *header, pool_holder *holder) -+{ -+ register pool_holder *fore = holder->fore, *back = holder->back; -+ holder->fore = NULL; -+ holder->back = NULL; -+ if (fore != NULL) fore->back = back; -+ else header->_black_magick = back; -+ if (back != NULL) back->fore = fore; -+ else header->first = fore; -+} -+ -+static inline pool_holder * -+entry_holder(void **entry) -+{ -+ return (pool_holder*)(((uintptr_t)entry) & ~(DEFAULT_POOL_SIZE - 1)); -+} -+ -+static inline void -+pool_free_entry(void **entry) -+{ -+ pool_holder *holder = entry_holder(entry); -+ pool_header *header = holder->header; -+ -+ if (holder->free++ == 0) { -+ register pool_holder *first = header->first; -+ if (first == NULL) { -+ header->first = holder; -+ } else { -+ holder->back = first; -+ holder->fore = first->fore; -+ first->fore = holder; -+ if (holder->fore) -+ holder->fore->back = holder; -+ else -+ header->_black_magick = holder; -+ } -+ } else if (holder->free == holder->total && header->first != holder ) { -+ pool_holder_unchaing(header, holder); -+ aligned_free(holder); -+#if CALC_EXACT_MALLOC_SIZE -+ rb_objspace.malloc_params.allocated_size -= DEFAULT_POOL_SIZE; -+ rb_objspace.malloc_params.allocations--; -+#endif -+ return; -+ } -+ -+ *entry = holder->freep; -+ holder->freep = entry; -+} -+ -+static inline void* -+pool_alloc_entry(pool_header *header) -+{ -+ pool_holder *holder = header->first; -+ void **result; -+ if (holder == NULL) { -+ holder = pool_holder_alloc(header); -+ } -+ -+ result = holder->freep; -+ holder->freep = *result; -+ -+ if (--holder->free == 0) { -+ pool_holder_unchaing(header, holder); -+ } -+ -+ return result; -+} -+ -+static void -+pool_finalize_header(pool_header *header) -+{ -+ if (header->first) { -+ aligned_free(header->first); -+ header->first = NULL; -+ } -+} -+#endif -diff --git a/st.c b/st.c -index c093bfd..0194022 100644 ---- a/st.c -+++ b/st.c -@@ -7,6 +7,7 @@ - #include "st.h" - #else - #include "ruby/ruby.h" -+#include "pool_alloc.h" - #endif - - #include -@@ -25,8 +26,17 @@ struct st_table_entry { - st_table_entry *fore, *back; - }; - --#define ST_DEFAULT_MAX_DENSITY 5 -+#define STATIC_ASSERT(name, expr) typedef int static_assert_##name##_check[(expr) ? 1 : -1]; -+ -+#define ST_DEFAULT_MAX_DENSITY 2 - #define ST_DEFAULT_INIT_TABLE_SIZE 11 -+#define ST_DEFAULT_SECOND_TABLE_SIZE 19 -+#define ST_DEFAULT_PACKED_TABLE_SIZE 19 -+#define PACKED_UNIT (int)(sizeof(st_packed_entry) / sizeof(st_table_entry*)) -+#define MAX_PACKED_HASH (int)(ST_DEFAULT_PACKED_TABLE_SIZE * sizeof(st_table_entry*) / sizeof(st_packed_entry)) -+ -+STATIC_ASSERT(st_packed_entry, sizeof(st_packed_entry) == sizeof(st_table_entry*[PACKED_UNIT])) -+STATIC_ASSERT(st_packed_bins, sizeof(st_packed_entry[MAX_PACKED_HASH]) <= sizeof(st_table_entry*[ST_DEFAULT_PACKED_TABLE_SIZE])) - - /* - * DEFAULT_MAX_DENSITY is the default for the largest we allow the -@@ -38,7 +48,8 @@ struct st_table_entry { - * - */ - --static const struct st_hash_type type_numhash = { -+#define type_numhash st_hashtype_num -+const struct st_hash_type st_hashtype_num = { - st_numcmp, - st_numhash, - }; -@@ -61,20 +72,128 @@ static void rehash(st_table *); - #ifdef RUBY - #define malloc xmalloc - #define calloc xcalloc -+#define realloc xrealloc - #define free(x) xfree(x) - #endif - - #define numberof(array) (int)(sizeof(array) / sizeof((array)[0])) - --#define alloc(type) (type*)malloc((size_t)sizeof(type)) --#define Calloc(n,s) (char*)calloc((n),(s)) -- - #define EQUAL(table,x,y) ((x)==(y) || (*(table)->type->compare)((x),(y)) == 0) - --/* remove cast to unsigned int in the future */ --#define do_hash(key,table) (unsigned int)(st_index_t)(*(table)->type->hash)((key)) -+#define do_hash(key,table) (st_index_t)(*(table)->type->hash)((key)) - #define do_hash_bin(key,table) (do_hash((key), (table))%(table)->num_bins) - -+/* preparation for possible allocation improvements */ -+#ifdef POOL_ALLOC_API -+#define st_alloc_entry() (st_table_entry *)ruby_xpool_malloc_6p() -+#define st_free_entry(entry) ruby_xpool_free(entry) -+#define st_alloc_table() (st_table *)ruby_xpool_malloc_6p() -+#define st_dealloc_table(table) ruby_xpool_free(table) -+static inline st_table_entry ** -+st_alloc_bins(st_index_t size) -+{ -+ st_table_entry **result; -+ if (size == 11) { -+ result = (st_table_entry **) ruby_xpool_malloc_11p(); -+ memset(result, 0, 11 * sizeof(st_table_entry *)); -+ } -+ else -+ result = (st_table_entry **) ruby_xcalloc(size, sizeof(st_table_entry*)); -+ return result; -+} -+static inline void -+st_free_bins(st_table_entry **bins, st_index_t size) -+{ -+ if (size == 11) -+ ruby_xpool_free(bins); -+ else -+ ruby_xfree(bins); -+} -+static inline st_table_entry** -+st_realloc_bins(st_table_entry **bins, st_index_t newsize, st_index_t oldsize) -+{ -+ st_table_entry **new_bins = st_alloc_bins(newsize); -+ st_free_bins(bins, oldsize); -+ return new_bins; -+} -+#else -+#define st_alloc_entry() (st_table_entry *)malloc(sizeof(st_table_entry)) -+#define st_free_entry(entry) free(entry) -+#define st_alloc_table() (st_table *)malloc(sizeof(st_table)) -+#define st_dealloc_table(table) free(table) -+#define st_alloc_bins(size) (st_table_entry **)calloc(size, sizeof(st_table_entry *)) -+#define st_free_bins(bins, size) free(bins) -+static inline st_table_entry** -+st_realloc_bins(st_table_entry **bins, st_index_t newsize, st_index_t oldsize) -+{ -+ bins = (st_table_entry **)realloc(bins, newsize * sizeof(st_table_entry *)); -+ MEMZERO(bins, st_table_entry*, newsize); -+ return bins; -+} -+#endif -+ -+/* Shortage */ -+#define bins as.big.bins -+#define head as.big.head -+#define tail as.big.tail -+#define real_entries as.packed.real_entries -+ -+/* preparation for possible packing improvements */ -+#define PACKED_BINS(table) ((table)->as.packed.entries) -+#define PACKED_ENT(table, i) PACKED_BINS(table)[i] -+#define PKEY(table, i) PACKED_ENT((table), (i)).key -+#define PVAL(table, i) PACKED_ENT((table), (i)).val -+#define PHASH(table, i) PACKED_ENT((table), (i)).hash -+#define PKEY_SET(table, i, v) (PKEY((table), (i)) = (v)) -+#define PVAL_SET(table, i, v) (PVAL((table), (i)) = (v)) -+#define PHASH_SET(table, i, v) (PHASH((table), (i)) = (v)) -+ -+/* this function depends much on packed layout, so that it placed here */ -+static inline void -+remove_packed_entry(st_table *table, st_index_t i) -+{ -+ table->real_entries--; -+ table->num_entries--; -+ if (i < table->real_entries) { -+ MEMMOVE(&PACKED_ENT(table, i), &PACKED_ENT(table, i+1), -+ st_packed_entry, table->real_entries - i); -+ } -+} -+ -+static inline void -+remove_safe_packed_entry(st_table *table, st_index_t i, st_data_t never) -+{ -+ table->num_entries--; -+ PKEY_SET(table, i, never); -+ PVAL_SET(table, i, never); -+ PHASH_SET(table, i, 0); -+} -+ -+/* ultrapacking */ -+#define real_upacked num_bins -+#define MAX_UPACKED_HASH 1 -+#define ULTRAPACKED(table) ((table)->real_upacked <= 1) -+#define UPACKED_ENT(table) ((table)->as.upacked) -+#define UPKEY(table) UPACKED_ENT(table).key -+#define UPVAL(table) UPACKED_ENT(table).val -+#define UPHASH(table) UPACKED_ENT(table).hash -+#define UPKEY_SET(table, v) (UPACKED_ENT(table).key = (v)) -+#define UPVAL_SET(table, v) (UPACKED_ENT(table).val = (v)) -+#define UPHASH_SET(table, v) (UPACKED_ENT(table).hash = (v)) -+static inline void -+remove_upacked_entry(st_table *table) -+{ -+ table->real_upacked = table->num_entries = 0; -+} -+ -+static inline void -+remove_safe_upacked_entry(st_table *table, st_data_t never) -+{ -+ table->num_entries = 0; -+ UPKEY_SET(table, never); -+ UPVAL_SET(table, never); -+ UPHASH_SET(table, 0); -+} - /* - * MINSIZE is the minimum size of a dictionary. - */ -@@ -85,8 +204,8 @@ static void rehash(st_table *); - Table of prime numbers 2^n+a, 2<=n<=30. - */ - static const unsigned int primes[] = { -- 8 + 3, -- 16 + 3, -+ ST_DEFAULT_INIT_TABLE_SIZE, -+ ST_DEFAULT_SECOND_TABLE_SIZE, - 32 + 5, - 64 + 3, - 128 + 3, -@@ -161,8 +280,6 @@ stat_col(void) - } - #endif - --#define MAX_PACKED_NUMHASH (ST_DEFAULT_INIT_TABLE_SIZE/2) -- - st_table* - st_init_table_with_size(const struct st_hash_type *type, st_index_t size) - { -@@ -181,14 +298,19 @@ st_init_table_with_size(const struct st_hash_type *type, st_index_t size) - } - #endif - -- size = new_size(size); /* round up to prime number */ - -- tbl = alloc(st_table); -+ tbl = st_alloc_table(); - tbl->type = type; - tbl->num_entries = 0; -- tbl->entries_packed = type == &type_numhash && size/2 <= MAX_PACKED_NUMHASH; -+ tbl->entries_packed = size <= MAX_PACKED_HASH; -+ if (tbl->entries_packed) { -+ size = size <= MAX_UPACKED_HASH ? 0 : ST_DEFAULT_PACKED_TABLE_SIZE; -+ } -+ else { -+ size = new_size(size); /* round up to prime number */ -+ } - tbl->num_bins = size; -- tbl->bins = (st_table_entry **)Calloc(size, sizeof(st_table_entry*)); -+ tbl->bins = size ? st_alloc_bins(size) : 0; - tbl->head = 0; - tbl->tail = 0; - -@@ -243,17 +365,23 @@ st_clear(st_table *table) - register st_table_entry *ptr, *next; - st_index_t i; - -+ if (ULTRAPACKED(table)) { -+ remove_upacked_entry(table); -+ return; -+ } -+ - if (table->entries_packed) { - table->num_entries = 0; -+ table->real_entries = 0; - return; - } - -- for(i = 0; i < table->num_bins; i++) { -+ for (i = 0; i < table->num_bins; i++) { - ptr = table->bins[i]; - table->bins[i] = 0; - while (ptr != 0) { - next = ptr->next; -- free(ptr); -+ st_free_entry(ptr); - ptr = next; - } - } -@@ -266,14 +394,19 @@ void - st_free_table(st_table *table) - { - st_clear(table); -- free(table->bins); -- free(table); -+ if (!ULTRAPACKED(table)) { -+ st_free_bins(table->bins, table->num_bins); -+ } -+ st_dealloc_table(table); - } - - size_t - st_memsize(const st_table *table) - { -- if (table->entries_packed) { -+ if (ULTRAPACKED(table)) { -+ return sizeof(st_table); -+ } -+ else if (table->entries_packed) { - return table->num_bins * sizeof (void *) + sizeof(st_table); - } - else { -@@ -306,46 +439,77 @@ count_collision(const struct st_hash_type *type) - #define FOUND_ENTRY - #endif - --#define FIND_ENTRY(table, ptr, hash_val, bin_pos) do {\ -- (bin_pos) = (hash_val)%(table)->num_bins;\ -- (ptr) = (table)->bins[(bin_pos)];\ -- FOUND_ENTRY;\ -- if (PTR_NOT_EQUAL((table), (ptr), (hash_val), key)) {\ -- COLLISION;\ -- while (PTR_NOT_EQUAL((table), (ptr)->next, (hash_val), key)) {\ -- (ptr) = (ptr)->next;\ -- }\ -- (ptr) = (ptr)->next;\ -- }\ --} while (0) -+#define FIND_ENTRY(table, ptr, hash_val, bin_pos) \ -+ ((ptr) = find_entry((table), key, (hash_val), ((bin_pos) = (hash_val)%(table)->num_bins))) -+ -+static st_table_entry * -+find_entry(st_table *table, st_data_t key, st_index_t hash_val, st_index_t bin_pos) -+{ -+ register st_table_entry *ptr = table->bins[bin_pos]; -+ FOUND_ENTRY; -+ if (PTR_NOT_EQUAL(table, ptr, hash_val, key)) { -+ COLLISION; -+ while (PTR_NOT_EQUAL(table, ptr->next, hash_val, key)) { -+ ptr = ptr->next; -+ } -+ ptr = ptr->next; -+ } -+ return ptr; -+} -+ -+static inline st_index_t -+find_packed_index(st_table *table, st_index_t hash_val, st_data_t key) -+{ -+ st_index_t i = 0; -+ while (i < table->real_entries && -+ (PHASH(table, i) != hash_val || !EQUAL(table, key, PKEY(table, i)))) { -+ i++; -+ } -+ return i; -+} -+ -+static inline int -+check_upacked(st_table *table, st_index_t hash_val, st_data_t key) -+{ -+ return table->num_entries && -+ UPHASH(table) == hash_val && -+ EQUAL(table, key, UPKEY(table)); -+} - - #define collision_check 0 - - int - st_lookup(st_table *table, register st_data_t key, st_data_t *value) - { -- st_index_t hash_val, bin_pos; -+ st_index_t hash_val; - register st_table_entry *ptr; - -+ hash_val = do_hash(key, table); -+ -+ if (ULTRAPACKED(table)) { -+ if (check_upacked(table, hash_val, key)) { -+ if (value != 0) *value = UPVAL(table); -+ return 1; -+ } -+ return 0; -+ } -+ - if (table->entries_packed) { -- st_index_t i; -- for (i = 0; i < table->num_entries; i++) { -- if ((st_data_t)table->bins[i*2] == key) { -- if (value !=0) *value = (st_data_t)table->bins[i*2+1]; -- return 1; -- } -- } -+ st_index_t i = find_packed_index(table, hash_val, key); -+ if (i < table->real_entries) { -+ if (value != 0) *value = PVAL(table, i); -+ return 1; -+ } - return 0; - } - -- hash_val = do_hash(key, table); -- FIND_ENTRY(table, ptr, hash_val, bin_pos); -+ ptr = find_entry(table, key, hash_val, hash_val % table->num_bins); - - if (ptr == 0) { - return 0; - } - else { -- if (value != 0) *value = ptr->record; -+ if (value != 0) *value = ptr->record; - return 1; - } - } -@@ -353,22 +517,29 @@ st_lookup(st_table *table, register st_data_t key, st_data_t *value) - int - st_get_key(st_table *table, register st_data_t key, st_data_t *result) - { -- st_index_t hash_val, bin_pos; -+ st_index_t hash_val; - register st_table_entry *ptr; - -+ hash_val = do_hash(key, table); -+ -+ if (ULTRAPACKED(table)) { -+ if (check_upacked(table, hash_val, key)) { -+ if (result != 0) *result = UPKEY(table); -+ return 1; -+ } -+ return 0; -+ } -+ - if (table->entries_packed) { -- st_index_t i; -- for (i = 0; i < table->num_entries; i++) { -- if ((st_data_t)table->bins[i*2] == key) { -- if (result !=0) *result = (st_data_t)table->bins[i*2]; -- return 1; -- } -- } -+ st_index_t i = find_packed_index(table, hash_val, key); -+ if (i < table->real_entries) { -+ if (result != 0) *result = PKEY(table, i); -+ return 1; -+ } - return 0; - } - -- hash_val = do_hash(key, table); -- FIND_ENTRY(table, ptr, hash_val, bin_pos); -+ ptr = find_entry(table, key, hash_val, hash_val % table->num_bins); - - if (ptr == 0) { - return 0; -@@ -382,85 +553,151 @@ st_get_key(st_table *table, register st_data_t key, st_data_t *result) - #undef collision_check - #define collision_check 1 - --#define MORE_PACKABLE_P(table) \ -- ((st_index_t)((table)->num_entries+1) * 2 <= (table)->num_bins && \ -- (table)->num_entries+1 <= MAX_PACKED_NUMHASH) -- --#define ADD_DIRECT(table, key, value, hash_val, bin_pos)\ --do {\ -- st_table_entry *entry;\ -- if ((table)->num_entries > ST_DEFAULT_MAX_DENSITY * (table)->num_bins) {\ -- rehash(table);\ -- (bin_pos) = (hash_val) % (table)->num_bins;\ -- }\ -- \ -- entry = alloc(st_table_entry);\ -- \ -- entry->hash = (hash_val);\ -- entry->key = (key);\ -- entry->record = (value);\ -- entry->next = (table)->bins[(bin_pos)];\ -- if ((table)->head != 0) {\ -- entry->fore = 0;\ -- (entry->back = (table)->tail)->fore = entry;\ -- (table)->tail = entry;\ -- }\ -- else {\ -- (table)->head = (table)->tail = entry;\ -- entry->fore = entry->back = 0;\ -- }\ -- (table)->bins[(bin_pos)] = entry;\ -- (table)->num_entries++;\ --} while (0) -+static inline st_table_entry * -+new_entry(st_table * table, st_data_t key, st_data_t value, -+ st_index_t hash_val, register st_index_t bin_pos) -+{ -+ register st_table_entry *entry = st_alloc_entry(); -+ -+ entry->next = table->bins[bin_pos]; -+ table->bins[bin_pos] = entry; -+ entry->hash = hash_val; -+ entry->key = key; -+ entry->record = value; -+ -+ return entry; -+} -+ -+static inline void -+add_direct(st_table *table, st_data_t key, st_data_t value, -+ st_index_t hash_val, register st_index_t bin_pos) -+{ -+ register st_table_entry *entry; -+ if (table->num_entries > ST_DEFAULT_MAX_DENSITY * table->num_bins) { -+ rehash(table); -+ bin_pos = hash_val % table->num_bins; -+ } -+ -+ entry = new_entry(table, key, value, hash_val, bin_pos); -+ -+ if (table->head != 0) { -+ entry->fore = 0; -+ (entry->back = table->tail)->fore = entry; -+ table->tail = entry; -+ } -+ else { -+ table->head = table->tail = entry; -+ entry->fore = entry->back = 0; -+ } -+ table->num_entries++; -+} - - static void - unpack_entries(register st_table *table) - { - st_index_t i; -- struct st_table_entry *packed_bins[MAX_PACKED_NUMHASH*2]; -+ st_packed_entry packed_bins[MAX_PACKED_HASH]; -+ register st_table_entry *entry, *preventry = 0, **chain; - st_table tmp_table = *table; - -- memcpy(packed_bins, table->bins, sizeof(struct st_table_entry *) * table->num_entries*2); -- table->bins = packed_bins; -+ MEMCPY(packed_bins, PACKED_BINS(table), st_packed_entry, MAX_PACKED_HASH); -+ table->as.packed.entries = packed_bins; - tmp_table.entries_packed = 0; -- tmp_table.num_entries = 0; -- memset(tmp_table.bins, 0, sizeof(struct st_table_entry *) * tmp_table.num_bins); -- for (i = 0; i < table->num_entries; i++) { -- st_insert(&tmp_table, (st_data_t)packed_bins[i*2], (st_data_t)packed_bins[i*2+1]); -- } -+#if ST_DEFAULT_INIT_TABLE_SIZE == ST_DEFAULT_PACKED_TABLE_SIZE -+ MEMZERO(tmp_table.bins, st_table_entry*, tmp_table.num_bins); -+#else -+ tmp_table.bins = st_realloc_bins(tmp_table.bins, ST_DEFAULT_INIT_TABLE_SIZE, tmp_table.num_bins); -+ tmp_table.num_bins = ST_DEFAULT_INIT_TABLE_SIZE; -+#endif -+ i = 0; -+ chain = &tmp_table.head; -+ do { -+ st_data_t key = packed_bins[i].key; -+ st_data_t val = packed_bins[i].val; -+ st_index_t hash = packed_bins[i].hash; -+ entry = new_entry(&tmp_table, key, val, hash, -+ hash % ST_DEFAULT_INIT_TABLE_SIZE); -+ *chain = entry; -+ entry->back = preventry; -+ preventry = entry; -+ chain = &entry->fore; -+ } while (++i < MAX_PACKED_HASH); -+ *chain = NULL; -+ tmp_table.tail = entry; - *table = tmp_table; - } - -+static void -+add_packed_direct(st_table *table, st_data_t key, st_data_t value, st_index_t hash_val) -+{ -+ if (table->real_entries < MAX_PACKED_HASH) { -+ st_index_t i = table->real_entries++; -+ PKEY_SET(table, i, key); -+ PVAL_SET(table, i, value); -+ PHASH_SET(table, i, hash_val); -+ table->num_entries++; -+ } -+ else { -+ unpack_entries(table); -+ add_direct(table, key, value, hash_val, hash_val % table->num_bins); -+ } -+} -+ -+static void -+add_upacked_direct(register st_table *table, register st_data_t key, st_data_t value, st_index_t hash_val) -+{ -+ if (table->real_upacked) { -+ st_packed_entry *entries = (st_packed_entry *) st_alloc_bins(ST_DEFAULT_PACKED_TABLE_SIZE); -+ entries[0] = UPACKED_ENT(table); -+ entries[1].hash = hash_val; -+ entries[1].key = key; -+ entries[1].val = value; -+ table->num_bins = ST_DEFAULT_PACKED_TABLE_SIZE; -+ table->real_entries = 2; -+ table->num_entries++; -+ table->as.packed.entries = entries; -+ } -+ else { -+ table->real_upacked = 1; -+ table->num_entries = 1; -+ UPHASH_SET(table, hash_val); -+ UPKEY_SET(table, key); -+ UPVAL_SET(table, value); -+ } -+} -+ - int - st_insert(register st_table *table, register st_data_t key, st_data_t value) - { -- st_index_t hash_val, bin_pos; -+ st_index_t hash_val; -+ register st_index_t bin_pos; - register st_table_entry *ptr; - -+ hash_val = do_hash(key, table); -+ -+ if (ULTRAPACKED(table)) { -+ if (check_upacked(table, hash_val, key)) { -+ UPVAL_SET(table, value); -+ return 1; -+ } -+ add_upacked_direct(table, key, value, hash_val); -+ return 0; -+ } -+ - if (table->entries_packed) { -- st_index_t i; -- for (i = 0; i < table->num_entries; i++) { -- if ((st_data_t)table->bins[i*2] == key) { -- table->bins[i*2+1] = (struct st_table_entry*)value; -- return 1; -- } -- } -- if (MORE_PACKABLE_P(table)) { -- i = table->num_entries++; -- table->bins[i*2] = (struct st_table_entry*)key; -- table->bins[i*2+1] = (struct st_table_entry*)value; -- return 0; -- } -- else { -- unpack_entries(table); -+ st_index_t i = find_packed_index(table, hash_val, key); -+ if (i < table->real_entries) { -+ PVAL_SET(table, i, value); -+ return 1; - } -+ add_packed_direct(table, key, value, hash_val); -+ return 0; - } - -- hash_val = do_hash(key, table); - FIND_ENTRY(table, ptr, hash_val, bin_pos); - - if (ptr == 0) { -- ADD_DIRECT(table, key, value, hash_val, bin_pos); -+ add_direct(table, key, value, hash_val, bin_pos); - return 0; - } - else { -@@ -473,34 +710,38 @@ int - st_insert2(register st_table *table, register st_data_t key, st_data_t value, - st_data_t (*func)(st_data_t)) - { -- st_index_t hash_val, bin_pos; -+ st_index_t hash_val; -+ register st_index_t bin_pos; - register st_table_entry *ptr; - -+ hash_val = do_hash(key, table); -+ -+ if (ULTRAPACKED(table)) { -+ if (check_upacked(table, hash_val, key)) { -+ UPVAL_SET(table, value); -+ return 1; -+ } -+ key = (*func)(key); -+ add_upacked_direct(table, key, value, hash_val); -+ return 0; -+ } -+ - if (table->entries_packed) { -- st_index_t i; -- for (i = 0; i < table->num_entries; i++) { -- if ((st_data_t)table->bins[i*2] == key) { -- table->bins[i*2+1] = (struct st_table_entry*)value; -- return 1; -- } -- } -- if (MORE_PACKABLE_P(table)) { -- i = table->num_entries++; -- table->bins[i*2] = (struct st_table_entry*)key; -- table->bins[i*2+1] = (struct st_table_entry*)value; -- return 0; -- } -- else { -- unpack_entries(table); -- } -+ st_index_t i = find_packed_index(table, hash_val, key); -+ if (i < table->real_entries) { -+ PVAL_SET(table, i, value); -+ return 1; -+ } -+ key = (*func)(key); -+ add_packed_direct(table, key, value, hash_val); -+ return 0; - } - -- hash_val = do_hash(key, table); - FIND_ENTRY(table, ptr, hash_val, bin_pos); - - if (ptr == 0) { - key = (*func)(key); -- ADD_DIRECT(table, key, value, hash_val, bin_pos); -+ add_direct(table, key, value, hash_val, bin_pos); - return 0; - } - else { -@@ -512,36 +753,30 @@ st_insert2(register st_table *table, register st_data_t key, st_data_t value, - void - st_add_direct(st_table *table, st_data_t key, st_data_t value) - { -- st_index_t hash_val, bin_pos; -+ st_index_t hash_val; -+ -+ hash_val = do_hash(key, table); -+ if (ULTRAPACKED(table)) { -+ add_upacked_direct(table, key, value, hash_val); -+ return; -+ } - - if (table->entries_packed) { -- st_index_t i; -- if (MORE_PACKABLE_P(table)) { -- i = table->num_entries++; -- table->bins[i*2] = (struct st_table_entry*)key; -- table->bins[i*2+1] = (struct st_table_entry*)value; -- return; -- } -- else { -- unpack_entries(table); -- } -+ add_packed_direct(table, key, value, hash_val); -+ return; - } - -- hash_val = do_hash(key, table); -- bin_pos = hash_val % table->num_bins; -- ADD_DIRECT(table, key, value, hash_val, bin_pos); -+ add_direct(table, key, value, hash_val, hash_val % table->num_bins); - } - - static void - rehash(register st_table *table) - { - register st_table_entry *ptr, **new_bins; -- st_index_t i, new_num_bins, hash_val; -+ st_index_t new_num_bins, hash_val; - - new_num_bins = new_size(table->num_bins+1); -- new_bins = (st_table_entry**) -- xrealloc(table->bins, new_num_bins * sizeof(st_table_entry*)); -- for (i = 0; i < new_num_bins; ++i) new_bins[i] = 0; -+ new_bins = st_realloc_bins(table->bins, new_num_bins, table->num_bins); - table->num_bins = new_num_bins; - table->bins = new_bins; - -@@ -558,34 +793,37 @@ st_table* - st_copy(st_table *old_table) - { - st_table *new_table; -- st_table_entry *ptr, *entry, *prev, **tail; -+ st_table_entry *ptr, *entry, *prev, **tailp; - st_index_t num_bins = old_table->num_bins; - st_index_t hash_val; - -- new_table = alloc(st_table); -+ new_table = st_alloc_table(); - if (new_table == 0) { - return 0; - } - - *new_table = *old_table; -- new_table->bins = (st_table_entry**) -- Calloc((unsigned)num_bins, sizeof(st_table_entry*)); -+ if (ULTRAPACKED(old_table)) { -+ return new_table; -+ } -+ -+ new_table->bins = st_alloc_bins(num_bins); - - if (new_table->bins == 0) { -- free(new_table); -+ st_dealloc_table(new_table); - return 0; - } - - if (old_table->entries_packed) { -- memcpy(new_table->bins, old_table->bins, sizeof(struct st_table_entry *) * old_table->num_bins); -+ MEMCPY(new_table->bins, old_table->bins, st_table_entry*, old_table->num_bins); - return new_table; - } - - if ((ptr = old_table->head) != 0) { - prev = 0; -- tail = &new_table->head; -+ tailp = &new_table->head; - do { -- entry = alloc(st_table_entry); -+ entry = st_alloc_entry(); - if (entry == 0) { - st_free_table(new_table); - return 0; -@@ -595,8 +833,8 @@ st_copy(st_table *old_table) - entry->next = new_table->bins[hash_val]; - new_table->bins[hash_val] = entry; - entry->back = prev; -- *tail = prev = entry; -- tail = &entry->fore; -+ *tailp = prev = entry; -+ tailp = &entry->fore; - } while ((ptr = ptr->fore) != 0); - new_table->tail = prev; - } -@@ -604,21 +842,22 @@ st_copy(st_table *old_table) - return new_table; - } - --#define REMOVE_ENTRY(table, ptr) do \ -- { \ -- if ((ptr)->fore == 0 && (ptr)->back == 0) { \ -- (table)->head = 0; \ -- (table)->tail = 0; \ -- } \ -- else { \ -- st_table_entry *fore = (ptr)->fore, *back = (ptr)->back; \ -- if (fore) fore->back = back; \ -- if (back) back->fore = fore; \ -- if ((ptr) == (table)->head) (table)->head = fore; \ -- if ((ptr) == (table)->tail) (table)->tail = back; \ -- } \ -- (table)->num_entries--; \ -- } while (0) -+static inline void -+remove_entry(st_table *table, st_table_entry *ptr) -+{ -+ if (ptr->fore == 0 && ptr->back == 0) { -+ table->head = 0; -+ table->tail = 0; -+ } -+ else { -+ st_table_entry *fore = ptr->fore, *back = ptr->back; -+ if (fore) fore->back = back; -+ if (back) back->fore = fore; -+ if (ptr == table->head) table->head = fore; -+ if (ptr == table->tail) table->tail = back; -+ } -+ table->num_entries--; -+} - - int - st_delete(register st_table *table, register st_data_t *key, st_data_t *value) -@@ -627,30 +866,38 @@ st_delete(register st_table *table, register st_data_t *key, st_data_t *value) - st_table_entry **prev; - register st_table_entry *ptr; - -+ hash_val = do_hash(*key, table); -+ -+ if (ULTRAPACKED(table)) { -+ if (check_upacked(table, hash_val, *key)) { -+ if (value != 0) *value = UPVAL(table); -+ *key = UPKEY(table); -+ remove_upacked_entry(table); -+ return 1; -+ } -+ return 0; -+ } -+ - if (table->entries_packed) { -- st_index_t i; -- for (i = 0; i < table->num_entries; i++) { -- if ((st_data_t)table->bins[i*2] == *key) { -- if (value != 0) *value = (st_data_t)table->bins[i*2+1]; -- table->num_entries--; -- memmove(&table->bins[i*2], &table->bins[(i+1)*2], -- sizeof(struct st_table_entry*) * 2*(table->num_entries-i)); -- return 1; -- } -+ st_index_t i = find_packed_index(table, hash_val, *key); -+ if (i < table->real_entries) { -+ if (value != 0) *value = PVAL(table, i); -+ *key = PKEY(table, i); -+ remove_packed_entry(table, i); -+ return 1; - } - if (value != 0) *value = 0; - return 0; - } - -- hash_val = do_hash_bin(*key, table); -- -- for (prev = &table->bins[hash_val]; (ptr = *prev) != 0; prev = &ptr->next) { -+ prev = &table->bins[hash_val % table->num_bins]; -+ for (;(ptr = *prev) != 0; prev = &ptr->next) { - if (EQUAL(table, *key, ptr->key)) { - *prev = ptr->next; -- REMOVE_ENTRY(table, ptr); -+ remove_entry(table, ptr); - if (value != 0) *value = ptr->record; - *key = ptr->key; -- free(ptr); -+ st_free_entry(ptr); - return 1; - } - } -@@ -665,25 +912,36 @@ st_delete_safe(register st_table *table, register st_data_t *key, st_data_t *val - st_index_t hash_val; - register st_table_entry *ptr; - -+ hash_val = do_hash(*key, table); -+ -+ if (ULTRAPACKED(table)) { -+ if (check_upacked(table, hash_val, *key)) { -+ if (value != 0) *value = UPVAL(table); -+ *key = UPKEY(table); -+ remove_safe_upacked_entry(table, never); -+ return 1; -+ } -+ if (value != 0) *value = 0; -+ return 0; -+ } -+ - if (table->entries_packed) { -- st_index_t i; -- for (i = 0; i < table->num_entries; i++) { -- if ((st_data_t)table->bins[i*2] == *key) { -- if (value != 0) *value = (st_data_t)table->bins[i*2+1]; -- table->bins[i*2] = (void *)never; -- return 1; -- } -+ st_index_t i = find_packed_index(table, hash_val, *key); -+ if (i < table->real_entries) { -+ if (value != 0) *value = PVAL(table, i); -+ *key = PKEY(table, i); -+ remove_safe_packed_entry(table, i, never); -+ return 1; - } - if (value != 0) *value = 0; - return 0; - } - -- hash_val = do_hash_bin(*key, table); -- ptr = table->bins[hash_val]; -+ ptr = table->bins[hash_val % table->num_bins]; - - for (; ptr != 0; ptr = ptr->next) { - if ((ptr->key != never) && EQUAL(table, ptr->key, *key)) { -- REMOVE_ENTRY(table, ptr); -+ remove_entry(table, ptr); - *key = ptr->key; - if (value != 0) *value = ptr->record; - ptr->key = ptr->record = never; -@@ -701,17 +959,23 @@ st_cleanup_safe(st_table *table, st_data_t never) - st_table_entry *ptr, **last, *tmp; - st_index_t i; - -+ if (ULTRAPACKED(table)) { -+ table->real_upacked = table->num_entries; -+ return; -+ } -+ - if (table->entries_packed) { - st_index_t i = 0, j = 0; -- while ((st_data_t)table->bins[i*2] != never) { -- if (i++ == table->num_entries) return; -+ while (PKEY(table, i) != never) { -+ if (i++ == table->real_entries) return; - } -- for (j = i; ++i < table->num_entries;) { -- if ((st_data_t)table->bins[i*2] == never) continue; -- table->bins[j*2] = table->bins[i*2]; -- table->bins[j*2+1] = table->bins[i*2+1]; -+ for (j = i; ++i < table->real_entries;) { -+ if (PKEY(table, i) == never) continue; -+ PACKED_ENT(table, j) = PACKED_ENT(table, i); - j++; - } -+ table->real_entries = j; -+ /* table->num_entries really should be equal j at this moment, but let set it anyway */ - table->num_entries = j; - return; - } -@@ -722,7 +986,7 @@ st_cleanup_safe(st_table *table, st_data_t never) - if (ptr->key == never) { - tmp = ptr; - *last = ptr = ptr->next; -- free(tmp); -+ st_free_entry(tmp); - } - else { - ptr = *(last = &ptr->next); -@@ -732,50 +996,78 @@ st_cleanup_safe(st_table *table, st_data_t never) - } - - int --st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) -+st_foreach_check(st_table *table, int (*func)(ANYARGS), st_data_t arg, st_data_t never) - { - st_table_entry *ptr, **last, *tmp; - enum st_retval retval; -- st_index_t i; -+ st_data_t key, val; -+ st_index_t hash, i = 0; -+ -+ if (table->num_entries == 0) { -+ return 0; -+ } -+ -+ if (ULTRAPACKED(table)) { -+ key = UPKEY(table); -+ val = UPVAL(table); -+ hash = UPHASH(table); -+ if (key == never) return 0; -+ retval = (*func)(key, val, arg); -+ if (!ULTRAPACKED(table)) { -+ goto packed; -+ } -+ switch(retval) { -+ case ST_CHECK: -+ if (UPHASH(table) == 0 && UPKEY(table) == never) -+ break; -+ if (check_upacked(table, hash, key)) -+ break; -+ goto deleted; -+ case ST_DELETE: -+ remove_safe_upacked_entry(table, never); -+ case ST_CONTINUE: -+ case ST_STOP: -+ break; -+ } -+ return 0; -+ } - - if (table->entries_packed) { -- for (i = 0; i < table->num_entries; i++) { -- st_index_t j; -- st_data_t key, val; -- key = (st_data_t)table->bins[i*2]; -- val = (st_data_t)table->bins[i*2+1]; -- retval = (*func)(key, val, arg); -+ for (i = 0; i < table->real_entries; i++) { -+ key = PKEY(table, i); -+ val = PVAL(table, i); -+ hash = PHASH(table, i); -+ if (key == never) continue; -+ retval = (*func)(key, val, arg); -+ packed: - if (!table->entries_packed) { -- FIND_ENTRY(table, ptr, key, i); -+ FIND_ENTRY(table, ptr, hash, i); - if (retval == ST_CHECK) { - if (!ptr) goto deleted; - goto unpacked_continue; - } - goto unpacked; - } -- switch (retval) { -+ switch (retval) { - case ST_CHECK: /* check if hash is modified during iteration */ -- for (j = 0; j < table->num_entries; j++) { -- if ((st_data_t)table->bins[j*2] == key) -- break; -- } -- if (j == table->num_entries) { -+ if (PHASH(table, i) == 0 && PKEY(table, i) == never) { -+ break; -+ } -+ i = find_packed_index(table, hash, key); -+ if (i == table->real_entries) { - goto deleted; -- } -+ } - /* fall through */ - case ST_CONTINUE: - break; - case ST_STOP: - return 0; - case ST_DELETE: -- table->num_entries--; -- memmove(&table->bins[i*2], &table->bins[(i+1)*2], -- sizeof(struct st_table_entry*) * 2*(table->num_entries-i)); -- i--; -- break; -- } -- } -- return 0; -+ remove_safe_packed_entry(table, i, never); -+ break; -+ } -+ } -+ return 0; - } - else { - ptr = table->head; -@@ -783,6 +1075,8 @@ st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) - - if (ptr != 0) { - do { -+ if (ptr->key == never) -+ goto unpacked_continue; - i = ptr->hash % table->num_bins; - retval = (*func)(ptr->key, ptr->record, arg); - unpacked: -@@ -808,10 +1102,100 @@ st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) - for (; (tmp = *last) != 0; last = &tmp->next) { - if (ptr == tmp) { - tmp = ptr->fore; -+ remove_entry(table, ptr); -+ ptr->key = ptr->record = never; -+ ptr->hash = 0; -+ ptr = tmp; -+ break; -+ } -+ } -+ } -+ } while (ptr && table->head); -+ } -+ return 0; -+} -+ -+int -+st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) -+{ -+ st_table_entry *ptr, **last, *tmp; -+ enum st_retval retval; -+ st_data_t key, val; -+ st_index_t hash, i = 0; -+ -+ if (table->num_entries == 0) { -+ return 0; -+ } -+ -+ if (ULTRAPACKED(table)) { -+ key = UPKEY(table); -+ val = UPVAL(table); -+ hash = UPHASH(table); -+ retval = (*func)(key, val, arg); -+ if (!ULTRAPACKED(table)) { -+ goto packed; -+ } -+ switch (retval) { -+ case ST_DELETE: -+ remove_upacked_entry(table); -+ case ST_CONTINUE: -+ case ST_CHECK: -+ case ST_STOP: -+ break; -+ } -+ return 0; -+ } -+ -+ if (table->entries_packed) { -+ for (i = 0; i < table->real_entries; i++) { -+ key = PKEY(table, i); -+ val = PVAL(table, i); -+ hash = PHASH(table, i); -+ retval = (*func)(key, val, arg); -+ packed: -+ if (!table->entries_packed) { -+ FIND_ENTRY(table, ptr, hash, i); -+ if (!ptr) return 0; -+ goto unpacked; -+ } -+ switch (retval) { -+ case ST_CONTINUE: -+ break; -+ case ST_CHECK: -+ case ST_STOP: -+ return 0; -+ case ST_DELETE: -+ remove_packed_entry(table, i); -+ i--; -+ break; -+ } -+ } -+ return 0; -+ } -+ else { -+ ptr = table->head; -+ } -+ -+ if (ptr != 0) { -+ do { -+ i = ptr->hash % table->num_bins; -+ retval = (*func)(ptr->key, ptr->record, arg); -+ unpacked: -+ switch (retval) { -+ case ST_CONTINUE: -+ ptr = ptr->fore; -+ break; -+ case ST_CHECK: -+ case ST_STOP: -+ return 0; -+ case ST_DELETE: -+ last = &table->bins[ptr->hash % table->num_bins]; -+ for (; (tmp = *last) != 0; last = &tmp->next) { -+ if (ptr == tmp) { -+ tmp = ptr->fore; - *last = ptr->next; -- REMOVE_ENTRY(table, ptr); -- free(ptr); -- if (ptr == tmp) return 0; -+ remove_entry(table, ptr); -+ st_free_entry(ptr); - ptr = tmp; - break; - } -@@ -834,13 +1218,13 @@ st_reverse_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) - for (i = table->num_entries-1; 0 <= i; i--) { - int j; - st_data_t key, val; -- key = (st_data_t)table->bins[i*2]; -- val = (st_data_t)table->bins[i*2+1]; -+ key = PKEY(table, i); -+ val = PVAL(table, i); - retval = (*func)(key, val, arg); - switch (retval) { - case ST_CHECK: /* check if hash is modified during iteration */ - for (j = 0; j < table->num_entries; j++) { -- if ((st_data_t)table->bins[j*2] == key) -+ if (PKEY(table, j) == key) - break; - } - if (j == table->num_entries) { -@@ -854,9 +1238,7 @@ st_reverse_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) - case ST_STOP: - return 0; - case ST_DELETE: -- table->num_entries--; -- memmove(&table->bins[i*2], &table->bins[(i+1)*2], -- sizeof(struct st_table_entry*) * 2*(table->num_entries-i)); -+ remove_packed_entry(table, i); - break; - } - } -@@ -889,8 +1271,8 @@ st_reverse_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) - if (ptr == tmp) { - tmp = ptr->back; - *last = ptr->next; -- REMOVE_ENTRY(table, ptr); -- free(ptr); -+ remove_entry(table, ptr); -+ st_free_entry(ptr); - ptr = tmp; - break; - } diff --git a/patches/ruby/1.9.3/head/railsexpress/11-falcon-sparse-array.patch b/patches/ruby/1.9.3/head/railsexpress/11-falcon-sparse-array.patch deleted file mode 100644 index bd7d9b2f8c..0000000000 --- a/patches/ruby/1.9.3/head/railsexpress/11-falcon-sparse-array.patch +++ /dev/null @@ -1,2467 +0,0 @@ -diff --git a/class.c b/class.c -index 4fbdf18..f5cb4a1 100644 ---- a/class.c -+++ b/class.c -@@ -31,7 +31,7 @@ - #include "internal.h" - #include - --extern st_table *rb_class_tbl; -+extern sa_table rb_class_tbl; - static ID id_attached; - - /** -@@ -53,11 +53,15 @@ class_alloc(VALUE flags, VALUE klass) - NEWOBJ(obj, struct RClass); - OBJSETUP(obj, klass, flags); - obj->ptr = ext; -- RCLASS_IV_TBL(obj) = 0; -- RCLASS_CONST_TBL(obj) = 0; -- RCLASS_M_TBL(obj) = 0; -- RCLASS_SUPER(obj) = 0; -- RCLASS_IV_INDEX_TBL(obj) = 0; -+ MEMZERO(ext, struct rb_classext_struct, 1); -+ return (VALUE)obj; -+} -+ -+static VALUE -+iclass_alloc() -+{ -+ NEWOBJ(obj, struct RClass); -+ OBJSETUP(obj, rb_cClass, T_ICLASS); - return (VALUE)obj; - } - -@@ -77,7 +81,6 @@ rb_class_boot(VALUE super) - VALUE klass = class_alloc(T_CLASS, rb_cClass); - - RCLASS_SUPER(klass) = super; -- RCLASS_M_TBL(klass) = st_init_numtable(); - - OBJ_INFECT(klass, super); - return (VALUE)klass; -@@ -120,43 +123,30 @@ rb_class_new(VALUE super) - return rb_class_boot(super); - } - --struct clone_method_data { -- st_table *tbl; -- VALUE klass; --}; -- - VALUE rb_iseq_clone(VALUE iseqval, VALUE newcbase); - --static int --clone_method(ID mid, const rb_method_entry_t *me, struct clone_method_data *data) -+static void -+clone_method(ID mid, const rb_method_entry_t *me, VALUE klass) - { - VALUE newiseqval; - if (me->def && me->def->type == VM_METHOD_TYPE_ISEQ) { - rb_iseq_t *iseq; -- newiseqval = rb_iseq_clone(me->def->body.iseq->self, data->klass); -+ newiseqval = rb_iseq_clone(me->def->body.iseq->self, klass); - GetISeqPtr(newiseqval, iseq); -- rb_add_method(data->klass, mid, VM_METHOD_TYPE_ISEQ, iseq, me->flag); -+ rb_add_method(klass, mid, VM_METHOD_TYPE_ISEQ, iseq, me->flag); - RB_GC_GUARD(newiseqval); - } - else { -- rb_method_entry_set(data->klass, mid, me, me->flag); -+ rb_method_entry_set(klass, mid, me, me->flag); - } -- return ST_CONTINUE; - } - --static int --clone_const(ID key, const rb_const_entry_t *ce, st_table *tbl) -+static void -+clone_const(sa_index_t key, st_data_t ce, sa_table *tbl) - { - rb_const_entry_t *nce = ALLOC(rb_const_entry_t); -- *nce = *ce; -- st_insert(tbl, key, (st_data_t)nce); -- return ST_CONTINUE; --} -- --static int --clone_const_i(st_data_t key, st_data_t value, st_data_t data) --{ -- return clone_const((ID)key, (const rb_const_entry_t *)value, (st_table *)data); -+ *nce = *(const rb_const_entry_t*)ce; -+ sa_insert(tbl, (sa_index_t)key, (st_data_t)nce); - } - - static void -@@ -177,6 +167,7 @@ class_init_copy_check(VALUE clone, VALUE orig) - VALUE - rb_mod_init_copy(VALUE clone, VALUE orig) - { -+ ID id; - if (RB_TYPE_P(clone, T_CLASS)) { - class_init_copy_check(clone, orig); - } -@@ -186,36 +177,22 @@ rb_mod_init_copy(VALUE clone, VALUE orig) - rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone); - } - RCLASS_SUPER(clone) = RCLASS_SUPER(orig); -- if (RCLASS_IV_TBL(orig)) { -- st_data_t id; - -- if (RCLASS_IV_TBL(clone)) { -- st_free_table(RCLASS_IV_TBL(clone)); -- } -- RCLASS_IV_TBL(clone) = st_copy(RCLASS_IV_TBL(orig)); -- CONST_ID(id, "__classpath__"); -- st_delete(RCLASS_IV_TBL(clone), &id, 0); -- CONST_ID(id, "__classid__"); -- st_delete(RCLASS_IV_TBL(clone), &id, 0); -- } -- if (RCLASS_CONST_TBL(orig)) { -- if (RCLASS_CONST_TBL(clone)) { -- rb_free_const_table(RCLASS_CONST_TBL(clone)); -- } -- RCLASS_CONST_TBL(clone) = st_init_numtable(); -- st_foreach(RCLASS_CONST_TBL(orig), clone_const_i, (st_data_t)RCLASS_CONST_TBL(clone)); -- } -- if (RCLASS_M_TBL(orig)) { -- struct clone_method_data data; -+ sa_copy_to(RCLASS_IV_TBL(orig), RCLASS_IV_TBL(clone)); -+ CONST_ID(id, "__classpath__"); -+ sa_delete(RCLASS_IV_TBL(clone), (sa_index_t)id, 0); -+ CONST_ID(id, "__classid__"); -+ sa_delete(RCLASS_IV_TBL(clone), (sa_index_t)id, 0); - -- if (RCLASS_M_TBL(clone)) { -- rb_free_m_table(RCLASS_M_TBL(clone)); -- } -- data.tbl = RCLASS_M_TBL(clone) = st_init_numtable(); -- data.klass = clone; -- st_foreach(RCLASS_M_TBL(orig), clone_method, -- (st_data_t)&data); -- } -+ sa_clear(RCLASS_CONST_TBL(clone)); -+ SA_FOREACH_START(RCLASS_CONST_TBL(orig)); -+ clone_const(entry->key, value, RCLASS_CONST_TBL(clone)); -+ SA_FOREACH_END(); -+ -+ rb_free_m_table(RCLASS_M_TBL(clone)); -+ SA_FOREACH_START(RCLASS_M_TBL(orig)); -+ clone_method(entry->key, (const rb_method_entry_t *)value, clone); -+ SA_FOREACH_END(); - - return clone; - } -@@ -228,7 +205,6 @@ rb_singleton_class_clone(VALUE obj) - if (!FL_TEST(klass, FL_SINGLETON)) - return klass; - else { -- struct clone_method_data data; - /* copy singleton(unnamed) class */ - VALUE clone = class_alloc((RBASIC(klass)->flags & ~(FL_MARK)), 0); - -@@ -240,18 +216,16 @@ rb_singleton_class_clone(VALUE obj) - } - - RCLASS_SUPER(clone) = RCLASS_SUPER(klass); -- if (RCLASS_IV_TBL(klass)) { -- RCLASS_IV_TBL(clone) = st_copy(RCLASS_IV_TBL(klass)); -- } -- if (RCLASS_CONST_TBL(klass)) { -- RCLASS_CONST_TBL(clone) = st_init_numtable(); -- st_foreach(RCLASS_CONST_TBL(klass), clone_const_i, (st_data_t)RCLASS_CONST_TBL(clone)); -- } -- RCLASS_M_TBL(clone) = st_init_numtable(); -- data.tbl = RCLASS_M_TBL(clone); -- data.klass = (VALUE)clone; -- st_foreach(RCLASS_M_TBL(klass), clone_method, -- (st_data_t)&data); -+ sa_copy_to(RCLASS_IV_TBL(klass), RCLASS_IV_TBL(clone)); -+ -+ SA_FOREACH_START(RCLASS_CONST_TBL(klass)); -+ clone_const(entry->key, value, RCLASS_CONST_TBL(clone)); -+ SA_FOREACH_END(); -+ -+ SA_FOREACH_START(RCLASS_M_TBL(klass)); -+ clone_method(entry->key, (const rb_method_entry_t*)value, clone); -+ SA_FOREACH_END(); -+ - rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone); - FL_SET(clone, FL_SINGLETON); - return (VALUE)clone; -@@ -266,10 +240,7 @@ void - rb_singleton_class_attached(VALUE klass, VALUE obj) - { - if (FL_TEST(klass, FL_SINGLETON)) { -- if (!RCLASS_IV_TBL(klass)) { -- RCLASS_IV_TBL(klass) = st_init_numtable(); -- } -- st_insert(RCLASS_IV_TBL(klass), id_attached, obj); -+ sa_insert(RCLASS_IV_TBL(klass), (sa_index_t)id_attached, obj); - } - } - -@@ -356,12 +327,12 @@ make_singleton_class(VALUE obj) - static VALUE - boot_defclass(const char *name, VALUE super) - { -- extern st_table *rb_class_tbl; -+ extern sa_table rb_class_tbl; - VALUE obj = rb_class_boot(super); - ID id = rb_intern(name); - - rb_name_class(obj, id); -- st_add_direct(rb_class_tbl, id, obj); -+ sa_insert(&rb_class_tbl, (sa_index_t)id, obj); - rb_const_set((rb_cObject ? rb_cObject : obj), id, obj); - return obj; - } -@@ -485,7 +456,7 @@ rb_define_class(const char *name, VALUE super) - rb_warn("no super class for `%s', Object assumed", name); - } - klass = rb_define_class_id(id, super); -- st_add_direct(rb_class_tbl, id, klass); -+ sa_insert(&rb_class_tbl, (sa_index_t)id, klass); - rb_name_class(klass, id); - rb_const_set(rb_cObject, id, klass); - rb_class_inherited(super, klass); -@@ -566,8 +537,6 @@ rb_module_new(void) - { - VALUE mdl = class_alloc(T_MODULE, rb_cModule); - -- RCLASS_M_TBL(mdl) = st_init_numtable(); -- - return (VALUE)mdl; - } - -@@ -596,7 +565,7 @@ rb_define_module(const char *name) - rb_raise(rb_eTypeError, "%s is not a module", rb_obj_classname(module)); - } - module = rb_define_module_id(id); -- st_add_direct(rb_class_tbl, id, module); -+ sa_insert(&rb_class_tbl, (sa_index_t)id, module); - rb_const_set(rb_cObject, id, module); - - return module; -@@ -631,27 +600,15 @@ rb_define_module_id_under(VALUE outer, ID id) - static VALUE - include_class_new(VALUE module, VALUE super) - { -- VALUE klass = class_alloc(T_ICLASS, rb_cClass); -+ VALUE klass; - - if (BUILTIN_TYPE(module) == T_ICLASS) { - module = RBASIC(module)->klass; - } -- if (!RCLASS_IV_TBL(module)) { -- RCLASS_IV_TBL(module) = st_init_numtable(); -- } -- if (!RCLASS_CONST_TBL(module)) { -- RCLASS_CONST_TBL(module) = st_init_numtable(); -- } -- RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module); -- RCLASS_CONST_TBL(klass) = RCLASS_CONST_TBL(module); -- RCLASS_M_TBL(klass) = RCLASS_M_TBL(module); -+ klass = iclass_alloc(); -+ RBASIC(klass)->klass = module; -+ RCLASS_EXT(klass) = RCLASS_EXT(module); - RCLASS_SUPER(klass) = super; -- if (TYPE(module) == T_ICLASS) { -- RBASIC(klass)->klass = RBASIC(module)->klass; -- } -- else { -- RBASIC(klass)->klass = module; -- } - OBJ_INFECT(klass, module); - OBJ_INFECT(klass, super); - -@@ -678,13 +635,13 @@ rb_include_module(VALUE klass, VALUE module) - while (module) { - int superclass_seen = FALSE; - -- if (RCLASS_M_TBL(klass) == RCLASS_M_TBL(module)) -+ if (RCLASS_EXT(klass) == RCLASS_EXT(module)) - rb_raise(rb_eArgError, "cyclic include detected"); - /* ignore if the module included already in superclasses */ - for (p = RCLASS_SUPER(klass); p; p = RCLASS_SUPER(p)) { - switch (BUILTIN_TYPE(p)) { - case T_ICLASS: -- if (RCLASS_M_TBL(p) == RCLASS_M_TBL(module)) { -+ if (RCLASS_EXT(p) == RCLASS_EXT(module)) { - if (!superclass_seen) { - c = p; /* move insertion point */ - } -@@ -697,7 +654,7 @@ rb_include_module(VALUE klass, VALUE module) - } - } - c = RCLASS_SUPER(c) = include_class_new(module, RCLASS_SUPER(c)); -- if (RMODULE_M_TBL(module) && RMODULE_M_TBL(module)->num_entries) -+ if (RMODULE_M_TBL(module)->num_entries) - changed = 1; - skip: - module = RCLASS_SUPER(module); -@@ -828,58 +785,58 @@ ins_methods_push(ID name, long type, VALUE ary, long visi) - } - - static int --ins_methods_i(st_data_t name, st_data_t type, st_data_t ary) -+ins_methods_i(sa_index_t name, st_data_t type, st_data_t ary) - { - return ins_methods_push((ID)name, (long)type, (VALUE)ary, -1); /* everything but private */ - } - - static int --ins_methods_prot_i(st_data_t name, st_data_t type, st_data_t ary) -+ins_methods_prot_i(sa_index_t name, st_data_t type, st_data_t ary) - { - return ins_methods_push((ID)name, (long)type, (VALUE)ary, NOEX_PROTECTED); - } - - static int --ins_methods_priv_i(st_data_t name, st_data_t type, st_data_t ary) -+ins_methods_priv_i(sa_index_t name, st_data_t type, st_data_t ary) - { - return ins_methods_push((ID)name, (long)type, (VALUE)ary, NOEX_PRIVATE); - } - - static int --ins_methods_pub_i(st_data_t name, st_data_t type, st_data_t ary) -+ins_methods_pub_i(sa_index_t name, st_data_t type, st_data_t ary) - { - return ins_methods_push((ID)name, (long)type, (VALUE)ary, NOEX_PUBLIC); - } - - static int --method_entry_i(st_data_t key, st_data_t value, st_data_t data) -+method_entry_i(sa_index_t key, st_data_t value, st_data_t data) - { - const rb_method_entry_t *me = (const rb_method_entry_t *)value; -- st_table *list = (st_table *)data; -+ sa_table *list = (sa_table *)data; - long type; - - if ((ID)key == ID_ALLOCATOR) { - return ST_CONTINUE; - } - -- if (!st_lookup(list, key, 0)) { -+ if (!sa_lookup(list, key, 0)) { - if (UNDEFINED_METHOD_ENTRY_P(me)) { - type = -1; /* none */ - } - else { - type = VISI(me->flag); - } -- st_add_direct(list, key, type); -+ sa_insert(list, key, type); - } - return ST_CONTINUE; - } - - static VALUE --class_instance_method_list(int argc, VALUE *argv, VALUE mod, int obj, int (*func) (st_data_t, st_data_t, st_data_t)) -+class_instance_method_list(int argc, VALUE *argv, VALUE mod, int obj, int (*func) (sa_index_t, st_data_t, st_data_t)) - { - VALUE ary; - int recur; -- st_table *list; -+ sa_table list = SA_EMPTY_TABLE; - - if (argc == 0) { - recur = TRUE; -@@ -890,16 +847,15 @@ class_instance_method_list(int argc, VALUE *argv, VALUE mod, int obj, int (*func - recur = RTEST(r); - } - -- list = st_init_numtable(); - for (; mod; mod = RCLASS_SUPER(mod)) { -- st_foreach(RCLASS_M_TBL(mod), method_entry_i, (st_data_t)list); -+ sa_foreach(RCLASS_M_TBL(mod), method_entry_i, (st_data_t)&list); - if (BUILTIN_TYPE(mod) == T_ICLASS) continue; - if (obj && FL_TEST(mod, FL_SINGLETON)) continue; - if (!recur) break; - } - ary = rb_ary_new(); -- st_foreach(list, func, ary); -- st_free_table(list); -+ sa_foreach(&list, func, ary); -+ sa_clear(&list); - - return ary; - } -@@ -1113,7 +1069,7 @@ VALUE - rb_obj_singleton_methods(int argc, VALUE *argv, VALUE obj) - { - VALUE recur, ary, klass; -- st_table *list; -+ sa_table list = SA_EMPTY_TABLE; - - if (argc == 0) { - recur = Qtrue; -@@ -1122,20 +1078,19 @@ rb_obj_singleton_methods(int argc, VALUE *argv, VALUE obj) - rb_scan_args(argc, argv, "01", &recur); - } - klass = CLASS_OF(obj); -- list = st_init_numtable(); - if (klass && FL_TEST(klass, FL_SINGLETON)) { -- st_foreach(RCLASS_M_TBL(klass), method_entry_i, (st_data_t)list); -+ sa_foreach(RCLASS_M_TBL(klass), method_entry_i, (st_data_t)&list); - klass = RCLASS_SUPER(klass); - } - if (RTEST(recur)) { - while (klass && (FL_TEST(klass, FL_SINGLETON) || TYPE(klass) == T_ICLASS)) { -- st_foreach(RCLASS_M_TBL(klass), method_entry_i, (st_data_t)list); -+ sa_foreach(RCLASS_M_TBL(klass), method_entry_i, (st_data_t)&list); - klass = RCLASS_SUPER(klass); - } - } - ary = rb_ary_new(); -- st_foreach(list, ins_methods_i, ary); -- st_free_table(list); -+ sa_foreach(&list, ins_methods_i, ary); -+ sa_clear(&list); - - return ary; - } -diff --git a/common.mk b/common.mk -index 1d8e442..0d767ab 100644 ---- a/common.mk -+++ b/common.mk -@@ -79,6 +79,7 @@ COMMONOBJS = array.$(OBJEXT) \ - safe.$(OBJEXT) \ - signal.$(OBJEXT) \ - sprintf.$(OBJEXT) \ -+ sp_ar.$(OBJEXT) \ - st.$(OBJEXT) \ - strftime.$(OBJEXT) \ - string.$(OBJEXT) \ -@@ -703,6 +704,7 @@ signal.$(OBJEXT): {$(VPATH)}signal.c $(RUBY_H_INCLUDES) \ - $(VM_CORE_H_INCLUDES) {$(VPATH)}debug.h - sprintf.$(OBJEXT): {$(VPATH)}sprintf.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \ - {$(VPATH)}regex.h {$(VPATH)}vsnprintf.c $(ENCODING_H_INCLUDES) -+sp_ar.$(OBJEXT): {$(VPATH)}sp_ar.c $(RUBY_H_INCLUDES) - st.$(OBJEXT): {$(VPATH)}st.c $(RUBY_H_INCLUDES) {$(VPATH)}pool_alloc.h - strftime.$(OBJEXT): {$(VPATH)}strftime.c $(RUBY_H_INCLUDES) \ - {$(VPATH)}timev.h -diff --git a/constant.h b/constant.h -index 8232910..9106847 100644 ---- a/constant.h -+++ b/constant.h -@@ -23,7 +23,7 @@ typedef struct rb_const_entry_struct { - - VALUE rb_mod_private_constant(int argc, VALUE *argv, VALUE obj); - VALUE rb_mod_public_constant(int argc, VALUE *argv, VALUE obj); --void rb_free_const_table(st_table *tbl); -+void rb_free_const_table(sa_table *tbl); - VALUE rb_public_const_get(VALUE klass, ID id); - VALUE rb_public_const_get_at(VALUE klass, ID id); - VALUE rb_public_const_get_from(VALUE klass, ID id); -diff --git a/ext/objspace/objspace.c b/ext/objspace/objspace.c -index fd08158..1e2ee5f 100644 ---- a/ext/objspace/objspace.c -+++ b/ext/objspace/objspace.c -@@ -60,20 +60,10 @@ memsize_of(VALUE obj) - break; - case T_MODULE: - case T_CLASS: -- size += st_memsize(RCLASS_M_TBL(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); -+ size += sa_memsize(RCLASS_M_TBL(obj)); -+ size += sa_memsize(RCLASS_IV_TBL(obj)); -+ size += sa_memsize(RCLASS_IV_INDEX_TBL(obj)); -+ size += sa_memsize(RCLASS_CONST_TBL(obj)); - break; - case T_STRING: - size += rb_str_memsize(obj); -diff --git a/gc.c b/gc.c -index 3110059..56f0217 100644 ---- a/gc.c -+++ b/gc.c -@@ -688,7 +688,7 @@ rb_objspace_free(rb_objspace_t *objspace) - - #define HEAP_OBJ_LIMIT (unsigned int)(HEAP_SIZE / sizeof(struct RVALUE)) - --extern st_table *rb_class_tbl; -+extern sa_table rb_class_tbl; - - int ruby_disable_gc_stress = 0; - -@@ -2358,6 +2358,15 @@ mark_tbl(rb_objspace_t *objspace, st_table *tbl) - st_foreach(tbl, mark_entry, (st_data_t)&arg); - } - -+static void -+mark_sa_tbl(rb_objspace_t *objspace, sa_table *tbl) -+{ -+ if (!tbl) return; -+ SA_FOREACH_START(tbl); -+ gc_mark(objspace, (VALUE)value); -+ SA_FOREACH_END(); -+} -+ - static int - mark_key(VALUE key, VALUE value, st_data_t data) - { -@@ -2434,74 +2443,52 @@ rb_mark_method_entry(const rb_method_entry_t *me) - mark_method_entry(&rb_objspace, me); - } - --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; -- mark_method_entry(arg->objspace, me); -- return ST_CONTINUE; --} -- - static void --mark_m_tbl(rb_objspace_t *objspace, st_table *tbl) --{ -- struct mark_tbl_arg arg; -- if (!tbl) return; -- arg.objspace = objspace; -- st_foreach(tbl, mark_method_entry_i, (st_data_t)&arg); --} -- --static int --free_method_entry_i(ID key, rb_method_entry_t *me, st_data_t data) -+mark_m_tbl(rb_objspace_t *objspace, sa_table *tbl) - { -- if (!me->mark) { -- rb_free_method_entry(me); -- } -- return ST_CONTINUE; -+ SA_FOREACH_START(tbl); -+ mark_method_entry(objspace, (const rb_method_entry_t*)value); -+ SA_FOREACH_END(); - } - - void --rb_free_m_table(st_table *tbl) -+rb_free_m_table(sa_table *tbl) - { -- st_foreach(tbl, free_method_entry_i, 0); -- st_free_table(tbl); --} -- --static int --mark_const_entry_i(ID key, const rb_const_entry_t *ce, st_data_t data) --{ -- struct mark_tbl_arg *arg = (void*)data; -- gc_mark(arg->objspace, ce->value); -- return ST_CONTINUE; -+ SA_FOREACH_START(tbl); -+ if (!((rb_method_entry_t*)value)->mark) { -+ rb_free_method_entry((rb_method_entry_t*)value); -+ } -+ SA_FOREACH_END(); -+ sa_clear(tbl); - } - - static void --mark_const_tbl(rb_objspace_t *objspace, st_table *tbl) -+mark_const_tbl(rb_objspace_t *objspace, sa_table *tbl) - { -- struct mark_tbl_arg arg; -- if (!tbl) return; -- arg.objspace = objspace; -- st_foreach(tbl, mark_const_entry_i, (st_data_t)&arg); -+ SA_FOREACH_START(tbl); -+ gc_mark(objspace, ((const rb_const_entry_t*)value)->value); -+ SA_FOREACH_END(); - } - --static int --free_const_entry_i(ID key, rb_const_entry_t *ce, st_data_t data) -+void -+rb_free_const_table(sa_table *tbl) - { -- xfree(ce); -- return ST_CONTINUE; -+ SA_FOREACH_START(tbl); -+ xfree((rb_const_entry_t*)value); -+ SA_FOREACH_END(); -+ sa_clear(tbl); - } - - void --rb_free_const_table(st_table *tbl) -+rb_mark_tbl(st_table *tbl) - { -- st_foreach(tbl, free_const_entry_i, 0); -- st_free_table(tbl); -+ mark_tbl(&rb_objspace, tbl); - } - - void --rb_mark_tbl(st_table *tbl) -+rb_mark_sa_tbl(sa_table *tbl) - { -- mark_tbl(&rb_objspace, tbl); -+ mark_sa_tbl(&rb_objspace, tbl); - } - - void -@@ -2709,7 +2696,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr) - case T_CLASS: - case T_MODULE: - mark_m_tbl(objspace, RCLASS_M_TBL(obj)); -- mark_tbl(objspace, RCLASS_IV_TBL(obj)); -+ mark_sa_tbl(objspace, RCLASS_IV_TBL(obj)); - mark_const_tbl(objspace, RCLASS_CONST_TBL(obj)); - ptr = RCLASS_SUPER(obj); - goto again; -@@ -3284,15 +3271,9 @@ obj_free(rb_objspace_t *objspace, VALUE obj) - case T_CLASS: - rb_clear_cache_by_class((VALUE)obj); - rb_free_m_table(RCLASS_M_TBL(obj)); -- 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)); -- } -+ sa_clear(RCLASS_IV_TBL(obj)); -+ rb_free_const_table(RCLASS_CONST_TBL(obj)); -+ sa_clear(RCLASS_IV_INDEX_TBL(obj)); - xfree(RANY(obj)->as.klass.ptr); - break; - case T_STRING: -@@ -3345,7 +3326,6 @@ obj_free(rb_objspace_t *objspace, VALUE obj) - break; - case T_ICLASS: - /* iClass shares table with the module */ -- xfree(RANY(obj)->as.klass.ptr); - break; - - case T_FLOAT: -@@ -3460,7 +3440,7 @@ gc_marks(rb_objspace_t *objspace) - rb_mark_end_proc(); - rb_gc_mark_global_tbl(); - -- mark_tbl(objspace, rb_class_tbl); -+ mark_sa_tbl(objspace, &rb_class_tbl); - - /* mark generic instance variables for special constants */ - rb_mark_generic_ivar_tbl(); -diff --git a/include/ruby/intern.h b/include/ruby/intern.h -index 372ce1f..06dd40c 100644 ---- a/include/ruby/intern.h -+++ b/include/ruby/intern.h -@@ -420,6 +420,7 @@ size_t ruby_stack_length(VALUE**); - int rb_during_gc(void); - void rb_gc_mark_locations(VALUE*, VALUE*); - void rb_mark_tbl(struct st_table*); -+void rb_mark_sa_tbl(sa_table*); - void rb_mark_set(struct st_table*); - void rb_mark_hash(struct st_table*); - void rb_gc_mark_maybe(VALUE); -@@ -853,7 +854,7 @@ VALUE rb_f_trace_var(int, VALUE*); - VALUE rb_f_untrace_var(int, VALUE*); - VALUE rb_f_global_variables(void); - void rb_alias_variable(ID, ID); --struct st_table* rb_generic_ivar_table(VALUE); -+sa_table* rb_generic_ivar_table(VALUE); - void rb_copy_generic_ivar(VALUE,VALUE); - void rb_mark_generic_ivar(VALUE); - void rb_mark_generic_ivar_tbl(void); -diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h -index 2f97b33..78a2286 100644 ---- a/include/ruby/ruby.h -+++ b/include/ruby/ruby.h -@@ -605,7 +605,7 @@ struct RObject { - struct { - long numiv; - VALUE *ivptr; -- struct st_table *iv_index_tbl; /* shortcut for RCLASS_IV_INDEX_TBL(rb_obj_class(obj)) */ -+ struct sa_table *iv_index_tbl; /* shortcut for RCLASS_IV_INDEX_TBL(rb_obj_class(obj)) */ - } heap; - VALUE ary[ROBJECT_EMBED_LEN_MAX]; - } as; -@@ -629,9 +629,8 @@ typedef struct rb_classext_struct rb_classext_t; - - struct RClass { - struct RBasic basic; -+ VALUE super; - rb_classext_t *ptr; -- struct st_table *m_tbl; -- struct st_table *iv_index_tbl; - }; - #define RCLASS_SUPER(c) rb_class_get_superclass(c) - #define RMODULE_IV_TBL(m) RCLASS_IV_TBL(m) -diff --git a/include/ruby/st.h b/include/ruby/st.h -index 119dfde..aff94fc 100644 ---- a/include/ruby/st.h -+++ b/include/ruby/st.h -@@ -151,6 +151,51 @@ st_index_t st_hash_start(st_index_t h); - #pragma GCC visibility pop - #endif - -+typedef unsigned int sa_index_t; -+#define SA_STOP ST_STOP -+#define SA_CONTINUE ST_CONTINUE -+ -+#define SA_EMPTY 0 -+ -+typedef struct sa_entry { -+ sa_index_t next; -+ sa_index_t key; -+ st_data_t value; -+} sa_entry; -+ -+typedef struct sa_table { -+ sa_index_t num_bins; -+ sa_index_t num_entries; -+ sa_index_t free_pos; -+ sa_entry *entries; -+} sa_table; -+ -+#define SA_EMPTY_TABLE {0, 0, 0, 0}; -+void sa_init_table(sa_table *, sa_index_t); -+sa_table *sa_new_table(); -+int sa_insert(sa_table *, sa_index_t, st_data_t); -+int sa_lookup(sa_table *, sa_index_t, st_data_t *); -+int sa_delete(sa_table *, sa_index_t, st_data_t *); -+void sa_clear(sa_table *); -+void sa_clear_no_free(sa_table *); -+void sa_free_table(sa_table *); -+int sa_foreach(sa_table *, int (*)(ANYARGS), st_data_t); -+size_t sa_memsize(const sa_table *); -+sa_table *sa_copy(sa_table*); -+void sa_copy_to(sa_table*, sa_table*); -+typedef int (*sa_iter_func)(sa_index_t key, st_data_t val, st_data_t arg); -+ -+#define SA_FOREACH_START_I(table, entry) do { \ -+ sa_table *T##entry = (table); \ -+ sa_index_t K##entry; \ -+ for(K##entry = 0; K##entry < T##entry->num_bins; K##entry++) { \ -+ sa_entry *entry = T##entry->entries + K##entry; \ -+ if (entry->next != SA_EMPTY) { \ -+ st_data_t value = entry->value -+#define SA_FOREACH_END() } } } while(0) -+ -+#define SA_FOREACH_START(table) SA_FOREACH_START_I(table, entry) -+ - #if defined(__cplusplus) - #if 0 - { /* satisfy cc-mode */ -diff --git a/internal.h b/internal.h -index f5af903..5927d93 100644 ---- a/internal.h -+++ b/internal.h -@@ -24,18 +24,19 @@ struct rb_deprecated_classext_struct { - }; - - struct rb_classext_struct { -- VALUE super; -- struct st_table *iv_tbl; -- struct st_table *const_tbl; -+ sa_table m_tbl; -+ sa_table iv_tbl; -+ sa_table const_tbl; -+ sa_table iv_index_tbl; - }; - - #undef RCLASS_SUPER - #define RCLASS_EXT(c) (RCLASS(c)->ptr) --#define RCLASS_SUPER(c) (RCLASS_EXT(c)->super) --#define RCLASS_IV_TBL(c) (RCLASS_EXT(c)->iv_tbl) --#define RCLASS_CONST_TBL(c) (RCLASS_EXT(c)->const_tbl) --#define RCLASS_M_TBL(c) (RCLASS(c)->m_tbl) --#define RCLASS_IV_INDEX_TBL(c) (RCLASS(c)->iv_index_tbl) -+#define RCLASS_SUPER(c) (RCLASS(c)->super) -+#define RCLASS_IV_TBL(c) (&RCLASS_EXT(c)->iv_tbl) -+#define RCLASS_CONST_TBL(c) (&RCLASS_EXT(c)->const_tbl) -+#define RCLASS_M_TBL(c) (&RCLASS_EXT(c)->m_tbl) -+#define RCLASS_IV_INDEX_TBL(c) (&RCLASS_EXT(c)->iv_index_tbl) - - struct vtm; /* defined by timev.h */ - -diff --git a/marshal.c b/marshal.c -index 6ae3a55..48d9d9b 100644 ---- a/marshal.c -+++ b/marshal.c -@@ -506,7 +506,7 @@ w_uclass(VALUE obj, VALUE super, struct dump_arg *arg) - } - - static int --w_obj_each(ID id, VALUE value, struct dump_call_arg *arg) -+w_obj_each(sa_index_t id, VALUE value, struct dump_call_arg *arg) - { - if (id == rb_id_encoding()) return ST_CONTINUE; - if (id == rb_intern("E")) return ST_CONTINUE; -@@ -553,13 +553,13 @@ w_encoding(VALUE obj, long num, struct dump_call_arg *arg) - } - - static void --w_ivar(VALUE obj, st_table *tbl, struct dump_call_arg *arg) -+w_ivar(VALUE obj, sa_table *tbl, struct dump_call_arg *arg) - { - long num = tbl ? tbl->num_entries : 0; - - w_encoding(obj, num, arg); - if (tbl) { -- st_foreach_safe(tbl, w_obj_each, (st_data_t)arg); -+ sa_foreach(tbl, w_obj_each, (st_data_t)arg); - } - } - -@@ -586,7 +586,7 @@ static void - w_object(VALUE obj, struct dump_arg *arg, int limit) - { - struct dump_call_arg c_arg; -- st_table *ivtbl = 0; -+ sa_table *ivtbl = 0; - st_data_t num; - int hasiv = 0; - #define has_ivars(obj, ivtbl) (((ivtbl) = rb_generic_ivar_table(obj)) != 0 || \ -@@ -651,7 +651,7 @@ w_object(VALUE obj, struct dump_arg *arg, int limit) - } - if (rb_respond_to(obj, s_dump)) { - VALUE v; -- st_table *ivtbl2 = 0; -+ sa_table *ivtbl2 = 0; - int hasiv2; - - v = rb_funcall(obj, s_dump, 1, INT2NUM(limit)); -diff --git a/method.h b/method.h -index 9229896..2fecd57 100644 ---- a/method.h -+++ b/method.h -@@ -100,6 +100,6 @@ int rb_method_entry_eq(const rb_method_entry_t *m1, const rb_method_entry_t *m2) - void rb_mark_method_entry(const rb_method_entry_t *me); - void rb_free_method_entry(rb_method_entry_t *me); - void rb_sweep_method_entry(void *vm); --void rb_free_m_table(st_table *tbl); -+void rb_free_m_table(sa_table *tbl); - - #endif /* METHOD_H */ -diff --git a/object.c b/object.c -index 59611fd..4522d08 100644 ---- a/object.c -+++ b/object.c -@@ -236,17 +236,8 @@ init_copy(VALUE dest, VALUE obj) - break; - case T_CLASS: - case T_MODULE: -- if (RCLASS_IV_TBL(dest)) { -- st_free_table(RCLASS_IV_TBL(dest)); -- RCLASS_IV_TBL(dest) = 0; -- } -- if (RCLASS_CONST_TBL(dest)) { -- rb_free_const_table(RCLASS_CONST_TBL(dest)); -- RCLASS_CONST_TBL(dest) = 0; -- } -- if (RCLASS_IV_TBL(obj)) { -- RCLASS_IV_TBL(dest) = st_copy(RCLASS_IV_TBL(obj)); -- } -+ rb_free_const_table(RCLASS_CONST_TBL(dest)); -+ sa_copy_to(RCLASS_IV_TBL(obj), RCLASS_IV_TBL(dest)); - break; - } - } -@@ -537,7 +528,7 @@ rb_obj_is_kind_of(VALUE obj, VALUE c) - } - - while (cl) { -- if (cl == c || RCLASS_M_TBL(cl) == RCLASS_M_TBL(c)) -+ if (cl == c || RCLASS_EXT(cl) == RCLASS_EXT(c)) - return Qtrue; - cl = RCLASS_SUPER(cl); - } -@@ -1362,13 +1353,13 @@ rb_class_inherited_p(VALUE mod, VALUE arg) - rb_raise(rb_eTypeError, "compared with non class/module"); - } - while (mod) { -- if (RCLASS_M_TBL(mod) == RCLASS_M_TBL(arg)) -+ if (RCLASS_EXT(mod) == RCLASS_EXT(arg)) - return Qtrue; - mod = RCLASS_SUPER(mod); - } - /* not mod < arg; check if mod > arg */ - while (arg) { -- if (RCLASS_M_TBL(arg) == RCLASS_M_TBL(start)) -+ if (RCLASS_EXT(arg) == RCLASS_EXT(start)) - return Qfalse; - arg = RCLASS_SUPER(arg); - } -diff --git a/sp_ar.c b/sp_ar.c -new file mode 100644 -index 0000000..2ed69bf ---- /dev/null -+++ b/sp_ar.c -@@ -0,0 +1,374 @@ -+/* -+ * sparse array lib -+ * inspired by Lua table -+ * written by Sokolov Yura aka funny_falcon -+ */ -+#ifdef NOT_RUBY -+#include "regint.h" -+#include "st.h" -+#else -+#include "ruby/ruby.h" -+#endif -+ -+#include -+#ifdef HAVE_STDLIB_H -+#include -+#endif -+#include -+ -+#ifdef RUBY -+#define malloc xmalloc -+#define calloc xcalloc -+#define realloc xrealloc -+#define free xfree -+#endif -+ -+#define sa_table_alloc() (sa_table*)malloc(sizeof(sa_table)) -+#define sa_table_xalloc() (sa_table*)calloc(1, sizeof(sa_table)) -+#define sa_table_dealloc(table) free(table) -+#define sa_entry_alloc(n) (sa_entry*)calloc((n), sizeof(sa_entry)) -+#define sa_entry_dealloc(entries) free(entries) -+ -+#define SA_LAST 1 -+#define SA_OFFSET 2 -+ -+#define SA_MIN_SIZE 4 -+ -+void -+sa_init_table(register sa_table *table, sa_index_t num_bins) -+{ -+ if (num_bins) { -+ table->num_entries = 0; -+ table->entries = sa_entry_alloc(num_bins); -+ table->num_bins = num_bins; -+ table->free_pos = num_bins; -+ } -+ else { -+ memset(table, 0, sizeof(sa_table)); -+ } -+} -+ -+sa_table* -+sa_new_table() -+{ -+ sa_table* table = sa_table_alloc(); -+ sa_init_table(table, 0); -+ return table; -+} -+ -+static inline sa_index_t -+calc_pos(register sa_table* table, sa_index_t key) -+{ -+ /* this formula is empirical */ -+ /* it has no good avalance, but works well in our case */ -+ key ^= key >> 16; -+ key *= 0x445229; -+ return (key + (key >> 16)) % table->num_bins; -+} -+ -+static void -+fix_empty(register sa_table* table) -+{ -+ while(--table->free_pos && -+ table->entries[table->free_pos-1].next != SA_EMPTY); -+} -+ -+#define FLOOR_TO_4 ((~((sa_index_t)0)) << 2) -+static sa_index_t -+find_empty(register sa_table* table, register sa_index_t pos) -+{ -+ sa_index_t new_pos = table->free_pos-1; -+ sa_entry *entry; -+ pos &= FLOOR_TO_4; -+ entry = table->entries+pos; -+ -+ if (entry->next == SA_EMPTY) { new_pos = pos; goto check; } -+ pos++; entry++; -+ if (entry->next == SA_EMPTY) { new_pos = pos; goto check; } -+ pos++; entry++; -+ if (entry->next == SA_EMPTY) { new_pos = pos; goto check; } -+ pos++; entry++; -+ if (entry->next == SA_EMPTY) { new_pos = pos; goto check; } -+ -+check: -+ if (new_pos+1 == table->free_pos) fix_empty(table); -+ return new_pos; -+} -+ -+static void resize(register sa_table* table); -+static int insert_into_chain(register sa_table*, register sa_index_t, st_data_t, sa_index_t pos); -+static int insert_into_main(register sa_table*, sa_index_t, st_data_t, sa_index_t pos, sa_index_t prev_pos); -+ -+int -+sa_insert(register sa_table* table, register sa_index_t key, st_data_t value) -+{ -+ sa_index_t pos, main_pos; -+ register sa_entry *entry; -+ -+ if (table->num_bins == 0) { -+ sa_init_table(table, SA_MIN_SIZE); -+ } -+ -+ pos = calc_pos(table, key); -+ entry = table->entries + pos; -+ -+ if (entry->next == SA_EMPTY) { -+ entry->next = SA_LAST; -+ entry->key = key; -+ entry->value = value; -+ table->num_entries++; -+ if (pos+1 == table->free_pos) fix_empty(table); -+ return 0; -+ } -+ -+ if (entry->key == key) { -+ entry->value = value; -+ return 1; -+ } -+ -+ if (table->num_entries + (table->num_entries >> 2) > table->num_bins) { -+ resize(table); -+ return sa_insert(table, key, value); -+ } -+ -+ main_pos = calc_pos(table, entry->key); -+ if (main_pos == pos) { -+ return insert_into_chain(table, key, value, pos); -+ } -+ else { -+ if (!table->free_pos) { -+ resize(table); -+ return sa_insert(table, key, value); -+ } -+ return insert_into_main(table, key, value, pos, main_pos); -+ } -+} -+ -+static int -+insert_into_chain(register sa_table* table, register sa_index_t key, st_data_t value, sa_index_t pos) -+{ -+ sa_entry *entry = table->entries + pos, *new_entry; -+ sa_index_t new_pos; -+ -+ while (entry->next != SA_LAST) { -+ pos = entry->next - SA_OFFSET; -+ entry = table->entries + pos; -+ if (entry->key == key) { -+ entry->value = value; -+ return 1; -+ } -+ } -+ -+ if (!table->free_pos) { -+ resize(table); -+ return sa_insert(table, key, value); -+ } -+ -+ new_pos = find_empty(table, pos); -+ new_entry = table->entries + new_pos; -+ entry->next = new_pos + SA_OFFSET; -+ -+ new_entry->next = SA_LAST; -+ new_entry->key = key; -+ new_entry->value = value; -+ table->num_entries++; -+ return 0; -+} -+ -+static int -+insert_into_main(register sa_table* table, sa_index_t key, st_data_t value, sa_index_t pos, sa_index_t prev_pos) -+{ -+ sa_entry *entry = table->entries + pos; -+ sa_index_t new_pos = find_empty(table, pos); -+ sa_entry *new_entry = table->entries + new_pos; -+ sa_index_t npos; -+ -+ *new_entry = *entry; -+ -+ while((npos = table->entries[prev_pos].next - SA_OFFSET) != pos) { -+ prev_pos = npos; -+ } -+ table->entries[prev_pos].next = new_pos + SA_OFFSET; -+ -+ entry->next = SA_LAST; -+ entry->key = key; -+ entry->value = value; -+ table->num_entries++; -+ return 0; -+} -+ -+static sa_index_t -+new_size(sa_index_t num_entries) -+{ -+ sa_index_t msb = num_entries; -+ msb |= msb >> 1; -+ msb |= msb >> 2; -+ msb |= msb >> 4; -+ msb |= msb >> 8; -+ msb |= msb >> 16; -+ msb = ((msb >> 4) + 1) << 3; -+ return (num_entries & (msb | (msb >> 1))) + (msb >> 1); -+} -+ -+static void -+resize(register sa_table *table) -+{ -+ sa_table tmp_table; -+ sa_entry *entry; -+ sa_index_t i; -+ -+ if (table->num_entries == 0) { -+ sa_entry_dealloc(table->entries); -+ memset(table, 0, sizeof(sa_table)); -+ return; -+ } -+ -+ sa_init_table(&tmp_table, new_size(table->num_entries + (table->num_entries >> 2))); -+ entry = table->entries; -+ -+ for(i = 0; i < table->num_bins; i++, entry++) { -+ if (entry->next != SA_EMPTY) { -+ sa_insert(&tmp_table, entry->key, entry->value); -+ } -+ } -+ sa_entry_dealloc(table->entries); -+ *table = tmp_table; -+} -+ -+int -+sa_lookup(register sa_table *table, register sa_index_t key, st_data_t *value) -+{ -+ register sa_entry *entry; -+ -+ if (table->num_entries == 0) return 0; -+ -+ entry = table->entries + calc_pos(table, key); -+ if (entry->next == SA_EMPTY) return 0; -+ -+ if (entry->key == key) goto found; -+ if (entry->next == SA_LAST) return 0; -+ -+ entry = table->entries + (entry->next - SA_OFFSET); -+ if (entry->key == key) goto found; -+ -+ while(entry->next != SA_LAST) { -+ entry = table->entries + (entry->next - SA_OFFSET); -+ if (entry->key == key) goto found; -+ } -+ return 0; -+found: -+ if (value) *value = entry->value; -+ return 1; -+} -+ -+void -+sa_clear(sa_table *table) -+{ -+ sa_entry_dealloc(table->entries); -+ memset(table, 0, sizeof(sa_table)); -+} -+ -+void -+sa_clear_no_free(sa_table *table) -+{ -+ memset(table->entries, 0, sizeof(sa_entry) * table->num_bins); -+ table->num_entries = 0; -+ table->free_pos = table->num_bins; -+} -+ -+void -+sa_free_table(sa_table *table) -+{ -+ sa_entry_dealloc(table->entries); -+ sa_table_dealloc(table); -+} -+ -+int -+sa_delete(sa_table *table, sa_index_t key, st_data_t *value) -+{ -+ sa_index_t pos, prev_pos = ~0; -+ sa_entry *entry; -+ -+ if (table->num_entries == 0) goto not_found; -+ -+ pos = calc_pos(table, key); -+ entry = table->entries + pos; -+ -+ if (entry->next == SA_EMPTY) goto not_found; -+ -+ do { -+ if (entry->key == key) { -+ if (value) *value = entry->value; -+ if (entry->next != SA_LAST) { -+ sa_index_t npos = entry->next - SA_OFFSET; -+ *entry = table->entries[npos]; -+ memset(table->entries + npos, 0, sizeof(sa_entry)); -+ } -+ else { -+ memset(table->entries + pos, 0, sizeof(sa_entry)); -+ if (~prev_pos) { -+ table->entries[prev_pos].next = SA_LAST; -+ } -+ } -+ table->num_entries--; -+ if (table->num_entries < table->num_bins / 4) { -+ resize(table); -+ } -+ return 1; -+ } -+ if (entry->next == SA_LAST) break; -+ prev_pos = pos; -+ pos = entry->next - SA_OFFSET; -+ entry = table->entries + pos; -+ } while(1); -+ -+not_found: -+ if (value) *value = 0; -+ return 0; -+} -+ -+int -+sa_foreach(register sa_table *table, int (*func)(), st_data_t arg) -+{ -+ sa_index_t i; -+ if (table->num_bins == 0) { -+ return 0; -+ } -+ for(i = 0; i < table->num_bins ; i++) { -+ if (table->entries[i].next != SA_EMPTY) { -+ sa_index_t key = table->entries[i].key; -+ st_data_t val = table->entries[i].value; -+ if ((*func)(key, val, arg) == SA_STOP) break; -+ } -+ } -+ return 0; -+} -+ -+size_t -+sa_memsize(const sa_table *table) -+{ -+ return sizeof(sa_table) + table->num_bins * sizeof(sa_entry); -+} -+ -+sa_table* -+sa_copy(sa_table *table) -+{ -+ sa_table *new_table = sa_table_alloc(); -+ *new_table = *table; -+ if (table->num_bins) { -+ new_table->entries = sa_entry_alloc(table->num_bins); -+ memcpy(new_table->entries, table->entries, table->num_bins*sizeof(sa_entry)); -+ } -+ return new_table; -+} -+ -+void -+sa_copy_to(sa_table *from, sa_table *to) -+{ -+ sa_entry_dealloc(to->entries); -+ *to = *from; -+ if (to->num_bins) { -+ to->entries = sa_entry_alloc(to->num_bins); -+ memcpy(to->entries, from->entries, from->num_bins*sizeof(sa_entry)); -+ } -+} -diff --git a/test/ruby/test_marshal.rb b/test/ruby/test_marshal.rb -index 0f3f794..5c2e502 100644 ---- a/test/ruby/test_marshal.rb -+++ b/test/ruby/test_marshal.rb -@@ -312,7 +312,7 @@ class TestMarshal < Test::Unit::TestCase - assert_equal(a.instance_variable_get(i), b.instance_variable_get(i), bug1932) - end - end -- a.__send__(a.methods(true).grep(/=\z/)[0], a) -+ a.__send__(a.methods(true).grep(/r.*=\z/)[0], a) - assert_nothing_raised(bug1932) do - b = Marshal.load(Marshal.dump(a)) - assert_equal(ClassISO8859_1, b.class, bug1932) -diff --git a/test/ruby/test_method.rb b/test/ruby/test_method.rb -index ea6c5f2..6ccd37c 100644 ---- a/test/ruby/test_method.rb -+++ b/test/ruby/test_method.rb -@@ -406,7 +406,7 @@ class TestMethod < Test::Unit::TestCase - obj = a.new - assert_equal([:a], obj.public_methods(false), bug) - obj.extend(m) -- assert_equal([:m1, :a], obj.public_methods(false), bug) -+ assert_equal([:a, :m1], obj.public_methods(false).sort, bug) - end - - def test_visibility -diff --git a/test/ruby/test_module.rb b/test/ruby/test_module.rb -index 6176f48..a67d845 100644 ---- a/test/ruby/test_module.rb -+++ b/test/ruby/test_module.rb -@@ -870,7 +870,7 @@ class TestModule < Test::Unit::TestCase - (class << self ; self ; end).class_eval do - define_method :method_added do |sym| - memo << sym -- memo << mod.instance_methods(false) -+ memo << mod.instance_methods(false).sort - memo << (mod.instance_method(sym) rescue nil) - end - end -@@ -887,10 +887,10 @@ class TestModule < Test::Unit::TestCase - assert_equal [:f, :g], memo.shift - assert_equal mod.instance_method(:f), memo.shift - assert_equal :a, memo.shift -- assert_equal [:f, :g, :a], memo.shift -+ assert_equal [:a, :f, :g], memo.shift - assert_equal mod.instance_method(:a), memo.shift - assert_equal :a=, memo.shift -- assert_equal [:f, :g, :a, :a=], memo.shift -+ assert_equal [:a, :a=, :f, :g], memo.shift - assert_equal mod.instance_method(:a=), memo.shift - end - -diff --git a/time.c b/time.c -index 6b6167b..f22debb 100644 ---- a/time.c -+++ b/time.c -@@ -4718,16 +4718,14 @@ time_mload(VALUE time, VALUE str) - long nsec; - VALUE submicro, nano_num, nano_den, offset; - wideval_t timew; -- st_data_t data; - - time_modify(time); - - #define get_attr(attr, iffound) \ - attr = rb_attr_get(str, id_##attr); \ - if (!NIL_P(attr)) { \ -- data = id_##attr; \ - iffound; \ -- st_delete(rb_generic_ivar_table(str), &data, 0); \ -+ sa_delete(rb_generic_ivar_table(str), (sa_index_t)id_##attr, 0); \ - } - - get_attr(nano_num, {}); -diff --git a/variable.c b/variable.c -index 3da500e..4a61453 100644 ---- a/variable.c -+++ b/variable.c -@@ -19,15 +19,15 @@ - #include "constant.h" - #include "internal.h" - --st_table *rb_global_tbl; --st_table *rb_class_tbl; -+sa_table rb_global_tbl; -+sa_table rb_class_tbl; - static ID autoload, classpath, tmp_classpath, classid; - - void - Init_var_tables(void) - { -- rb_global_tbl = st_init_numtable(); -- rb_class_tbl = st_init_numtable(); -+ sa_init_table(&rb_global_tbl, 0); -+ sa_init_table(&rb_class_tbl, 0); - CONST_ID(autoload, "__autoload__"); - CONST_ID(classpath, "__classpath__"); - CONST_ID(tmp_classpath, "__tmp_classpath__"); -@@ -43,7 +43,7 @@ struct fc_result { - }; - - static VALUE --fc_path(struct fc_result *fc, ID name) -+fc_path(struct fc_result *fc, sa_index_t name) - { - VALUE path, tmp; - -@@ -51,8 +51,7 @@ fc_path(struct fc_result *fc, ID name) - while (fc) { - st_data_t n; - if (fc->track == rb_cObject) break; -- if (RCLASS_IV_TBL(fc->track) && -- st_lookup(RCLASS_IV_TBL(fc->track), (st_data_t)classpath, &n)) { -+ if (sa_lookup(RCLASS_IV_TBL(fc->track), (sa_index_t)classpath, &n)) { - tmp = rb_str_dup((VALUE)n); - rb_str_cat2(tmp, "::"); - rb_str_append(tmp, path); -@@ -70,7 +69,7 @@ fc_path(struct fc_result *fc, ID name) - } - - static int --fc_i(ID key, rb_const_entry_t *ce, struct fc_result *res) -+fc_i(sa_index_t key, rb_const_entry_t *ce, struct fc_result *res) - { - VALUE value = ce->value; - if (!rb_is_const_id(key)) return ST_CONTINUE; -@@ -98,7 +97,7 @@ fc_i(ID key, rb_const_entry_t *ce, struct fc_result *res) - arg.klass = res->klass; - arg.track = value; - arg.prev = res; -- st_foreach(RCLASS_CONST_TBL(value), fc_i, (st_data_t)&arg); -+ sa_foreach(RCLASS_CONST_TBL(value), fc_i, (st_data_t)&arg); - if (arg.path) { - res->path = arg.path; - return ST_STOP; -@@ -123,18 +122,14 @@ find_class_path(VALUE klass) - arg.track = rb_cObject; - arg.prev = 0; - if (RCLASS_CONST_TBL(rb_cObject)) { -- st_foreach_safe(RCLASS_CONST_TBL(rb_cObject), fc_i, (st_data_t)&arg); -+ sa_foreach(RCLASS_CONST_TBL(rb_cObject), fc_i, (st_data_t)&arg); - } - if (arg.path == 0) { -- st_foreach_safe(rb_class_tbl, fc_i, (st_data_t)&arg); -+ sa_foreach(&rb_class_tbl, fc_i, (st_data_t)&arg); - } - if (arg.path) { -- st_data_t tmp = tmp_classpath; -- if (!RCLASS_IV_TBL(klass)) { -- RCLASS_IV_TBL(klass) = st_init_numtable(); -- } -- st_insert(RCLASS_IV_TBL(klass), (st_data_t)classpath, arg.path); -- st_delete(RCLASS_IV_TBL(klass), &tmp, 0); -+ sa_insert(RCLASS_IV_TBL(klass), (sa_index_t)classpath, arg.path); -+ sa_delete(RCLASS_IV_TBL(klass), (sa_index_t)tmp_classpath, 0); - return arg.path; - } - return Qnil; -@@ -147,16 +142,15 @@ classname(VALUE klass) - st_data_t n; - - if (!klass) klass = rb_cObject; -- if (RCLASS_IV_TBL(klass)) { -- if (!st_lookup(RCLASS_IV_TBL(klass), (st_data_t)classpath, &n)) { -- if (!st_lookup(RCLASS_IV_TBL(klass), (st_data_t)classid, &n)) { -+ if (RCLASS_IV_TBL(klass)->num_entries) { -+ if (!sa_lookup(RCLASS_IV_TBL(klass), (sa_index_t)classpath, &n)) { -+ if (!sa_lookup(RCLASS_IV_TBL(klass), (sa_index_t)classid, &n)) { - return find_class_path(klass); - } - path = rb_str_dup(rb_id2str(SYM2ID((VALUE)n))); - OBJ_FREEZE(path); -- st_insert(RCLASS_IV_TBL(klass), (st_data_t)classpath, (st_data_t)path); -- n = classid; -- st_delete(RCLASS_IV_TBL(klass), &n, 0); -+ sa_insert(RCLASS_IV_TBL(klass), (sa_index_t)classpath, (st_data_t)path); -+ sa_delete(RCLASS_IV_TBL(klass), (sa_index_t)classid, 0); - } - else { - path = (VALUE)n; -@@ -192,8 +186,7 @@ rb_class_path(VALUE klass) - st_data_t n = (st_data_t)path; - - if (!NIL_P(path)) return path; -- if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass), -- (st_data_t)tmp_classpath, &n)) { -+ if (sa_lookup(RCLASS_IV_TBL(klass), (sa_index_t)tmp_classpath, &n)) { - return (VALUE)n; - } - else { -@@ -364,7 +357,7 @@ rb_global_entry(ID id) - struct global_entry *entry; - st_data_t data; - -- if (!st_lookup(rb_global_tbl, (st_data_t)id, &data)) { -+ if (!sa_lookup(&rb_global_tbl, (sa_index_t)id, &data)) { - struct global_variable *var; - entry = ALLOC(struct global_entry); - var = ALLOC(struct global_variable); -@@ -378,7 +371,7 @@ rb_global_entry(ID id) - - var->block_trace = 0; - var->trace = 0; -- st_add_direct(rb_global_tbl, id, (st_data_t)entry); -+ sa_insert(&rb_global_tbl, (sa_index_t)id, (st_data_t)entry); - } - else { - entry = (struct global_entry *)data; -@@ -454,8 +447,8 @@ readonly_setter(VALUE val, ID id, void *data, struct global_variable *gvar) - rb_name_error(id, "%s is a read-only variable", rb_id2name(id)); - } - --static int --mark_global_entry(ID key, struct global_entry *entry) -+static void -+mark_global_entry(struct global_entry *entry) - { - struct trace_var *trace; - struct global_variable *var = entry->var; -@@ -466,14 +459,14 @@ mark_global_entry(ID key, struct global_entry *entry) - if (trace->data) rb_gc_mark_maybe(trace->data); - trace = trace->next; - } -- return ST_CONTINUE; - } - - void - rb_gc_mark_global_tbl(void) - { -- if (rb_global_tbl) -- st_foreach_safe(rb_global_tbl, mark_global_entry, 0); -+ SA_FOREACH_START(&rb_global_tbl); -+ mark_global_entry((struct global_entry*) value); -+ SA_FOREACH_END(); - } - - static ID -@@ -635,7 +628,7 @@ rb_f_untrace_var(int argc, VALUE *argv) - rb_secure(4); - rb_scan_args(argc, argv, "11", &var, &cmd); - id = rb_to_id(var); -- if (!st_lookup(rb_global_tbl, (st_data_t)id, &data)) { -+ if (!sa_lookup(&rb_global_tbl, (sa_index_t)id, &data)) { - rb_name_error(id, "undefined global variable %s", rb_id2name(id)); - } - -@@ -742,13 +735,6 @@ rb_gvar_defined(struct global_entry *entry) - return Qtrue; - } - --static int --gvar_i(ID key, struct global_entry *entry, VALUE ary) --{ -- rb_ary_push(ary, ID2SYM(key)); -- return ST_CONTINUE; --} -- - /* - * call-seq: - * global_variables -> array -@@ -765,7 +751,9 @@ rb_f_global_variables(void) - char buf[2]; - int i; - -- st_foreach_safe(rb_global_tbl, gvar_i, ary); -+ SA_FOREACH_START(&rb_global_tbl); -+ rb_ary_push(ary, ID2SYM(entry->key)); -+ SA_FOREACH_END(); - buf[0] = '$'; - for (i = 1; i <= 9; ++i) { - buf[1] = (char)(i + '0'); -@@ -784,10 +772,10 @@ rb_alias_variable(ID name1, ID name2) - rb_raise(rb_eSecurityError, "Insecure: can't alias global variable"); - - entry2 = rb_global_entry(name2); -- if (!st_lookup(rb_global_tbl, (st_data_t)name1, &data1)) { -+ if (!sa_lookup(&rb_global_tbl, (sa_index_t)name1, &data1)) { - entry1 = ALLOC(struct global_entry); - entry1->id = name1; -- st_add_direct(rb_global_tbl, name1, (st_data_t)entry1); -+ sa_insert(&rb_global_tbl, (sa_index_t)name1, (st_data_t)entry1); - } - else if ((entry1 = (struct global_entry *)data1)->var != entry2->var) { - struct global_variable *var = entry1->var; -@@ -815,7 +803,7 @@ rb_alias_variable(ID name1, ID name2) - static int special_generic_ivar = 0; - static st_table *generic_iv_tbl; - --st_table* -+sa_table* - rb_generic_ivar_table(VALUE obj) - { - st_data_t tbl; -@@ -823,7 +811,7 @@ rb_generic_ivar_table(VALUE obj) - if (!FL_TEST(obj, FL_EXIVAR)) return 0; - if (!generic_iv_tbl) return 0; - if (!st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) return 0; -- return (st_table *)tbl; -+ return (sa_table *)tbl; - } - - static VALUE -@@ -833,7 +821,7 @@ generic_ivar_get(VALUE obj, ID id, int warn) - - if (generic_iv_tbl) { - if (st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) { -- if (st_lookup((st_table *)tbl, (st_data_t)id, &val)) { -+ if (sa_lookup((sa_table *)tbl, (sa_index_t)id, &val)) { - return (VALUE)val; - } - } -@@ -847,7 +835,6 @@ generic_ivar_get(VALUE obj, ID id, int warn) - static void - generic_ivar_set(VALUE obj, ID id, VALUE val) - { -- st_table *tbl; - st_data_t data; - - if (rb_special_const_p(obj)) { -@@ -859,24 +846,22 @@ generic_ivar_set(VALUE obj, ID id, VALUE val) - } - if (!st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) { - FL_SET(obj, FL_EXIVAR); -- tbl = st_init_numtable(); -- st_add_direct(generic_iv_tbl, (st_data_t)obj, (st_data_t)tbl); -- st_add_direct(tbl, (st_data_t)id, (st_data_t)val); -- return; -+ data = (st_data_t)sa_new_table(); -+ st_add_direct(generic_iv_tbl, (st_data_t)obj, data); - } -- st_insert((st_table *)data, (st_data_t)id, (st_data_t)val); -+ sa_insert((sa_table *)data, (sa_index_t)id, (st_data_t)val); - } - - static VALUE - generic_ivar_defined(VALUE obj, ID id) - { -- st_table *tbl; -+ sa_table *tbl; - st_data_t data; - - if (!generic_iv_tbl) return Qfalse; - if (!st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) return Qfalse; -- tbl = (st_table *)data; -- if (st_lookup(tbl, (st_data_t)id, &data)) { -+ tbl = (sa_table *)data; -+ if (sa_lookup(tbl, (sa_index_t)id, &data)) { - return Qtrue; - } - return Qfalse; -@@ -885,18 +870,18 @@ generic_ivar_defined(VALUE obj, ID id) - static int - generic_ivar_remove(VALUE obj, ID id, st_data_t *valp) - { -- st_table *tbl; -+ sa_table *tbl; - st_data_t data, key = (st_data_t)id; - int status; - - if (!generic_iv_tbl) return 0; - if (!st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) return 0; -- tbl = (st_table *)data; -- status = st_delete(tbl, &key, valp); -+ tbl = (sa_table *)data; -+ status = sa_delete(tbl, (sa_index_t)id, valp); - if (tbl->num_entries == 0) { - key = (st_data_t)obj; - st_delete(generic_iv_tbl, &key, &data); -- st_free_table((st_table *)data); -+ sa_free_table(tbl); - } - return status; - } -@@ -908,22 +893,17 @@ rb_mark_generic_ivar(VALUE obj) - - if (!generic_iv_tbl) return; - if (st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) { -- rb_mark_tbl((st_table *)tbl); -+ rb_mark_sa_tbl((sa_table *)tbl); - } - } - - static int --givar_mark_i(ID key, VALUE value) --{ -- rb_gc_mark(value); -- return ST_CONTINUE; --} -- --static int --givar_i(VALUE obj, st_table *tbl) -+givar_i(VALUE obj, sa_table *tbl) - { - if (rb_special_const_p(obj)) { -- st_foreach_safe(tbl, givar_mark_i, 0); -+ SA_FOREACH_START(tbl); -+ rb_gc_mark((VALUE)value); -+ SA_FOREACH_END(); - } - return ST_CONTINUE; - } -@@ -943,7 +923,7 @@ rb_free_generic_ivar(VALUE obj) - - if (!generic_iv_tbl) return; - if (st_delete(generic_iv_tbl, &key, &tbl)) -- st_free_table((st_table *)tbl); -+ sa_free_table((sa_table *)tbl); - } - - RUBY_FUNC_EXPORTED size_t -@@ -951,7 +931,7 @@ rb_generic_ivar_memsize(VALUE obj) - { - st_data_t tbl; - if (st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) -- return st_memsize((st_table *)tbl); -+ return sa_memsize((sa_table *)tbl); - return 0; - } - -@@ -970,17 +950,17 @@ rb_copy_generic_ivar(VALUE clone, VALUE obj) - return; - } - if (st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) { -- st_table *tbl = (st_table *)data; -+ sa_table *tbl = (sa_table *)data; - - if (tbl->num_entries == 0) - goto clear; - - if (st_lookup(generic_iv_tbl, (st_data_t)clone, &data)) { -- st_free_table((st_table *)data); -- st_insert(generic_iv_tbl, (st_data_t)clone, (st_data_t)st_copy(tbl)); -+ sa_free_table((sa_table *)data); -+ st_insert(generic_iv_tbl, (st_data_t)clone, (st_data_t)sa_copy(tbl)); - } - else { -- st_add_direct(generic_iv_tbl, (st_data_t)clone, (st_data_t)st_copy(tbl)); -+ st_add_direct(generic_iv_tbl, (st_data_t)clone, (st_data_t)sa_copy(tbl)); - FL_SET(clone, FL_EXIVAR); - } - } -@@ -990,7 +970,7 @@ static VALUE - ivar_get(VALUE obj, ID id, int warn) - { - VALUE val, *ptr; -- struct st_table *iv_index_tbl; -+ sa_table *iv_index_tbl; - long len; - st_data_t index; - -@@ -1000,7 +980,7 @@ ivar_get(VALUE obj, ID id, int warn) - ptr = ROBJECT_IVPTR(obj); - iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); - if (!iv_index_tbl) break; -- if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break; -+ if (!sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) break; - if (len <= (long)index) break; - val = ptr[index]; - if (val != Qundef) -@@ -1008,7 +988,7 @@ ivar_get(VALUE obj, ID id, int warn) - break; - case T_CLASS: - case T_MODULE: -- if (RCLASS_IV_TBL(obj) && st_lookup(RCLASS_IV_TBL(obj), (st_data_t)id, &index)) -+ if (sa_lookup(RCLASS_IV_TBL(obj), (sa_index_t)id, &index)) - return (VALUE)index; - break; - default: -@@ -1037,7 +1017,7 @@ rb_attr_get(VALUE obj, ID id) - VALUE - rb_ivar_set(VALUE obj, ID id, VALUE val) - { -- struct st_table *iv_index_tbl; -+ struct sa_table *iv_index_tbl; - st_data_t index; - long i, len; - int ivar_extended; -@@ -1051,14 +1031,11 @@ rb_ivar_set(VALUE obj, ID id, VALUE val) - if (!iv_index_tbl) { - VALUE klass = rb_obj_class(obj); - iv_index_tbl = RCLASS_IV_INDEX_TBL(klass); -- if (!iv_index_tbl) { -- iv_index_tbl = RCLASS_IV_INDEX_TBL(klass) = st_init_numtable(); -- } - } - ivar_extended = 0; -- if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) { -+ if (!sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) { - index = iv_index_tbl->num_entries; -- st_add_direct(iv_index_tbl, (st_data_t)id, index); -+ sa_insert(iv_index_tbl, (sa_index_t)id, index); - ivar_extended = 1; - } - len = ROBJECT_NUMIV(obj); -@@ -1098,8 +1075,7 @@ rb_ivar_set(VALUE obj, ID id, VALUE val) - break; - case T_CLASS: - case T_MODULE: -- if (!RCLASS_IV_TBL(obj)) RCLASS_IV_TBL(obj) = st_init_numtable(); -- st_insert(RCLASS_IV_TBL(obj), (st_data_t)id, val); -+ sa_insert(RCLASS_IV_TBL(obj), (sa_index_t)id, val); - break; - default: - generic_ivar_set(obj, id, val); -@@ -1112,13 +1088,13 @@ VALUE - rb_ivar_defined(VALUE obj, ID id) - { - VALUE val; -- struct st_table *iv_index_tbl; -+ struct sa_table *iv_index_tbl; - st_data_t index; - switch (TYPE(obj)) { - case T_OBJECT: - iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); - if (!iv_index_tbl) break; -- if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break; -+ if (!sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) break; - if (ROBJECT_NUMIV(obj) <= (long)index) break; - val = ROBJECT_IVPTR(obj)[index]; - if (val != Qundef) -@@ -1126,7 +1102,7 @@ rb_ivar_defined(VALUE obj, ID id) - break; - case T_CLASS: - case T_MODULE: -- if (RCLASS_IV_TBL(obj) && st_lookup(RCLASS_IV_TBL(obj), (st_data_t)id, 0)) -+ if (sa_lookup(RCLASS_IV_TBL(obj), (sa_index_t)id, 0)) - return Qtrue; - break; - default: -@@ -1137,40 +1113,26 @@ rb_ivar_defined(VALUE obj, ID id) - return Qfalse; - } - --struct obj_ivar_tag { -- VALUE obj; -- int (*func)(ID key, VALUE val, st_data_t arg); -- st_data_t arg; --}; -- --static int --obj_ivar_i(st_data_t key, st_data_t index, st_data_t arg) --{ -- struct obj_ivar_tag *data = (struct obj_ivar_tag *)arg; -- if ((long)index < ROBJECT_NUMIV(data->obj)) { -- VALUE val = ROBJECT_IVPTR(data->obj)[(long)index]; -- if (val != Qundef) { -- return (data->func)((ID)key, val, data->arg); -- } -- } -- return ST_CONTINUE; --} -- - static void - obj_ivar_each(VALUE obj, int (*func)(ANYARGS), st_data_t arg) - { -- st_table *tbl; -- struct obj_ivar_tag data; -+ sa_table *tbl; -+ long numiv = ROBJECT_NUMIV(obj); -+ VALUE *vars = ROBJECT_IVPTR(obj); - - tbl = ROBJECT_IV_INDEX_TBL(obj); -- if (!tbl) -+ if (!tbl || !numiv) - return; - -- data.obj = obj; -- data.func = (int (*)(ID key, VALUE val, st_data_t arg))func; -- data.arg = arg; -- -- st_foreach_safe(tbl, obj_ivar_i, (st_data_t)&data); -+ SA_FOREACH_START(tbl); -+ if ((long)value < numiv) { -+ VALUE val = vars[value]; -+ if (val != Qundef) { -+ if (((sa_iter_func)func)(entry->key, val, arg) == SA_STOP) -+ break; -+ } -+ } -+ SA_FOREACH_END(); - } - - void -@@ -1182,9 +1144,7 @@ rb_ivar_foreach(VALUE obj, int (*func)(ANYARGS), st_data_t arg) - break; - case T_CLASS: - case T_MODULE: -- if (RCLASS_IV_TBL(obj)) { -- st_foreach_safe(RCLASS_IV_TBL(obj), func, arg); -- } -+ sa_foreach(RCLASS_IV_TBL(obj), func, arg); - break; - default: - if (!generic_iv_tbl) break; -@@ -1192,7 +1152,7 @@ rb_ivar_foreach(VALUE obj, int (*func)(ANYARGS), st_data_t arg) - st_data_t tbl; - - if (st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) { -- st_foreach_safe((st_table *)tbl, func, arg); -+ sa_foreach((sa_table *)tbl, func, arg); - } - } - break; -@@ -1202,11 +1162,11 @@ rb_ivar_foreach(VALUE obj, int (*func)(ANYARGS), st_data_t arg) - st_index_t - rb_ivar_count(VALUE obj) - { -- st_table *tbl; -+ sa_table *tbl; - switch (TYPE(obj)) { - case T_OBJECT: - if ((tbl = ROBJECT_IV_INDEX_TBL(obj)) != 0) { -- st_index_t i, count, num = tbl->num_entries; -+ sa_index_t i, count, num = tbl->num_entries; - const VALUE *const ivptr = ROBJECT_IVPTR(obj); - for (i = count = 0; i < num; ++i) { - if (ivptr[i] != Qundef) { -@@ -1228,7 +1188,7 @@ rb_ivar_count(VALUE obj) - st_data_t data; - - if (st_lookup(generic_iv_tbl, (st_data_t)obj, &data) && -- (tbl = (st_table *)data) != 0) { -+ (tbl = (sa_table *)data) != 0) { - return tbl->num_entries; - } - } -@@ -1238,7 +1198,7 @@ rb_ivar_count(VALUE obj) - } - - static int --ivar_i(ID key, VALUE val, VALUE ary) -+ivar_i(sa_index_t key, VALUE val, VALUE ary) - { - if (rb_is_instance_id(key)) { - rb_ary_push(ary, ID2SYM(key)); -@@ -1301,7 +1261,7 @@ rb_obj_remove_instance_variable(VALUE obj, VALUE name) - VALUE val = Qnil; - const ID id = rb_to_id(name); - st_data_t n, v; -- struct st_table *iv_index_tbl; -+ struct sa_table *iv_index_tbl; - st_data_t index; - - if (!OBJ_UNTRUSTED(obj) && rb_safe_level() >= 4) -@@ -1315,7 +1275,7 @@ rb_obj_remove_instance_variable(VALUE obj, VALUE name) - case T_OBJECT: - iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); - if (!iv_index_tbl) break; -- if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break; -+ if (!sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) break; - if (ROBJECT_NUMIV(obj) <= (long)index) break; - val = ROBJECT_IVPTR(obj)[index]; - if (val != Qundef) { -@@ -1326,14 +1286,14 @@ rb_obj_remove_instance_variable(VALUE obj, VALUE name) - case T_CLASS: - case T_MODULE: - n = id; -- if (RCLASS_IV_TBL(obj) && st_delete(RCLASS_IV_TBL(obj), &n, &v)) { -+ if (sa_delete(RCLASS_IV_TBL(obj), (sa_index_t)id, &v)) { - return (VALUE)v; - } - break; - default: - if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) { - v = val; -- if (generic_ivar_remove(obj, (st_data_t)id, &v)) { -+ if (generic_ivar_remove(obj, id, &v)) { - return (VALUE)v; - } - } -@@ -1410,20 +1370,20 @@ rb_mod_const_missing(VALUE klass, VALUE name) - static void - autoload_mark(void *ptr) - { -- rb_mark_tbl((st_table *)ptr); -+ rb_mark_sa_tbl((sa_table *)ptr); - } - - static void - autoload_free(void *ptr) - { -- st_free_table((st_table *)ptr); -+ sa_free_table((sa_table *)ptr); - } - - static size_t - autoload_memsize(const void *ptr) - { -- const st_table *tbl = ptr; -- return st_memsize(tbl); -+ const sa_table *tbl = ptr; -+ return sa_memsize(tbl); - } - - static const rb_data_type_t autoload_data_type = { -@@ -1432,14 +1392,14 @@ static const rb_data_type_t autoload_data_type = { - }; - - #define check_autoload_table(av) \ -- (struct st_table *)rb_check_typeddata((av), &autoload_data_type) -+ (struct sa_table *)rb_check_typeddata((av), &autoload_data_type) - - void - rb_autoload(VALUE mod, ID id, const char *file) - { - st_data_t av; - VALUE fn; -- struct st_table *tbl; -+ struct sa_table *tbl; - - if (!rb_is_const_id(id)) { - rb_raise(rb_eNameError, "autoload must be constant name: %s", rb_id2name(id)); -@@ -1448,43 +1408,41 @@ rb_autoload(VALUE mod, ID id, const char *file) - rb_raise(rb_eArgError, "empty file name"); - } - -- if ((tbl = RCLASS_CONST_TBL(mod)) && st_lookup(tbl, (st_data_t)id, &av) && ((rb_const_entry_t*)av)->value != Qundef) -+ if (sa_lookup(RCLASS_CONST_TBL(mod), (sa_index_t)id, &av) && ((rb_const_entry_t*)av)->value != Qundef) - return; - - rb_const_set(mod, id, Qundef); - tbl = RCLASS_IV_TBL(mod); -- if (tbl && st_lookup(tbl, (st_data_t)autoload, &av)) { -+ if (sa_lookup(tbl, (sa_index_t)autoload, &av)) { - tbl = check_autoload_table((VALUE)av); - } - else { -- if (!tbl) tbl = RCLASS_IV_TBL(mod) = st_init_numtable(); - av = (st_data_t)TypedData_Wrap_Struct(0, &autoload_data_type, 0); -- st_add_direct(tbl, (st_data_t)autoload, av); -- DATA_PTR(av) = tbl = st_init_numtable(); -+ sa_insert(tbl, (sa_index_t)autoload, av); -+ DATA_PTR(av) = tbl = sa_new_table(); - } - fn = rb_str_new2(file); - FL_UNSET(fn, FL_TAINT); - OBJ_FREEZE(fn); -- st_insert(tbl, (st_data_t)id, (st_data_t)rb_node_newnode(NODE_MEMO, fn, rb_safe_level(), 0)); -+ sa_insert(tbl, (sa_index_t)id, (st_data_t)rb_node_newnode(NODE_MEMO, fn, rb_safe_level(), 0)); - } - - static NODE* - autoload_delete(VALUE mod, ID id) - { -- st_data_t val, load = 0, n = id; -+ st_data_t val, load = 0; - rb_const_entry_t *ce; - -- st_delete(RCLASS_CONST_TBL(mod), &n, &val); -+ sa_delete(RCLASS_CONST_TBL(mod), (sa_index_t)id, &val); - ce = (rb_const_entry_t*)val; - if (ce) xfree(ce); -- if (st_lookup(RCLASS_IV_TBL(mod), (st_data_t)autoload, &val)) { -- struct st_table *tbl = check_autoload_table((VALUE)val); -+ if (sa_lookup(RCLASS_IV_TBL(mod), (sa_index_t)autoload, &val)) { -+ struct sa_table *tbl = check_autoload_table((VALUE)val); - -- st_delete(tbl, &n, &load); -+ sa_delete(tbl, (sa_index_t)id, &load); - - if (tbl->num_entries == 0) { -- n = autoload; -- st_delete(RCLASS_IV_TBL(mod), &n, &val); -+ sa_delete(RCLASS_IV_TBL(mod), (sa_index_t)autoload, &val); - } - } - -@@ -1509,14 +1467,14 @@ static NODE * - autoload_node(VALUE mod, ID id, const char **loadingpath) - { - VALUE file; -- struct st_table *tbl; -+ struct sa_table *tbl; - st_data_t val; - NODE *load; - const char *loading; - int safe; - -- if (!st_lookup(RCLASS_IV_TBL(mod), autoload, &val) || -- !(tbl = check_autoload_table((VALUE)val)) || !st_lookup(tbl, (st_data_t)id, &val)) { -+ if (!sa_lookup(RCLASS_IV_TBL(mod), (sa_index_t)autoload, &val) || -+ !(tbl = check_autoload_table((VALUE)val)) || !sa_lookup(tbl, (sa_index_t)id, &val)) { - return 0; - } - load = (NODE *)val; -@@ -1541,10 +1499,10 @@ autoload_node(VALUE mod, ID id, const char **loadingpath) - static int - autoload_node_id(VALUE mod, ID id) - { -- struct st_table *tbl = RCLASS_CONST_TBL(mod); -+ struct sa_table *tbl = RCLASS_CONST_TBL(mod); - st_data_t val; - -- if (!tbl || !st_lookup(tbl, (st_data_t)id, &val) || ((rb_const_entry_t*)val)->value != Qundef) { -+ if (!tbl || !sa_lookup(tbl, (sa_index_t)id, &val) || ((rb_const_entry_t*)val)->value != Qundef) { - return 0; - } - return 1; -@@ -1593,7 +1551,7 @@ rb_const_get_0(VALUE klass, ID id, int exclude, int recurse, int visibility) - while (RTEST(tmp)) { - VALUE am = 0; - st_data_t data; -- while (RCLASS_CONST_TBL(tmp) && st_lookup(RCLASS_CONST_TBL(tmp), (st_data_t)id, &data)) { -+ while (sa_lookup(RCLASS_CONST_TBL(tmp), (sa_index_t)id, &data)) { - rb_const_entry_t *ce = (rb_const_entry_t *)data; - if (visibility && ce->flag == CONST_PRIVATE) { - rb_name_error(id, "private constant %s::%s referenced", rb_class2name(klass), rb_id2name(id)); -@@ -1686,12 +1644,12 @@ VALUE - rb_const_remove(VALUE mod, ID id) - { - VALUE val; -- st_data_t v, n = id; -+ st_data_t v; - - if (!OBJ_UNTRUSTED(mod) && rb_safe_level() >= 4) - rb_raise(rb_eSecurityError, "Insecure: can't remove constant"); - rb_check_frozen(mod); -- if (!RCLASS_CONST_TBL(mod) || !st_delete(RCLASS_CONST_TBL(mod), &n, &v)) { -+ if (!sa_delete(RCLASS_CONST_TBL(mod), (sa_index_t)id, &v)) { - if (rb_const_defined_at(mod, id)) { - rb_name_error(id, "cannot remove %s::%s", - rb_class2name(mod), rb_id2name(id)); -@@ -1711,27 +1669,20 @@ rb_const_remove(VALUE mod, ID id) - return val; - } - --static int --sv_i(ID key, rb_const_entry_t *ce, st_table *tbl) --{ -- if (rb_is_const_id(key)) { -- if (!st_lookup(tbl, (st_data_t)key, 0)) { -- st_insert(tbl, (st_data_t)key, (st_data_t)ce); -- } -- } -- return ST_CONTINUE; --} -- - void* - rb_mod_const_at(VALUE mod, void *data) - { -- st_table *tbl = data; -+ sa_table *tbl = data; - if (!tbl) { -- tbl = st_init_numtable(); -+ tbl = sa_new_table(); - } -- if (RCLASS_CONST_TBL(mod)) { -- st_foreach_safe(RCLASS_CONST_TBL(mod), sv_i, (st_data_t)tbl); -+ SA_FOREACH_START(RCLASS_CONST_TBL(mod)); -+ if (rb_is_const_id(entry->key)) { -+ if (!sa_lookup(tbl, entry->key, 0)) { -+ sa_insert(tbl, entry->key, value); -+ } - } -+ SA_FOREACH_END(); - return tbl; - } - -@@ -1748,25 +1699,21 @@ rb_mod_const_of(VALUE mod, void *data) - return data; - } - --static int --list_i(st_data_t key, st_data_t value, VALUE ary) --{ -- ID sym = (ID)key; -- rb_const_entry_t *ce = (rb_const_entry_t *)value; -- if (ce->flag != CONST_PRIVATE) rb_ary_push(ary, ID2SYM(sym)); -- return ST_CONTINUE; --} -- - VALUE - rb_const_list(void *data) - { -- st_table *tbl = data; -+ sa_table *tbl = data; - VALUE ary; - - if (!tbl) return rb_ary_new2(0); - ary = rb_ary_new2(tbl->num_entries); -- st_foreach_safe(tbl, list_i, ary); -- st_free_table(tbl); -+ -+ SA_FOREACH_START(tbl); -+ rb_const_entry_t *ce = (rb_const_entry_t *)value; -+ if (ce->flag != CONST_PRIVATE) rb_ary_push(ary, ID2SYM(entry->key)); -+ SA_FOREACH_END(); -+ -+ sa_free_table(tbl); - - return ary; - } -@@ -1790,7 +1737,7 @@ VALUE - rb_mod_constants(int argc, VALUE *argv, VALUE mod) - { - VALUE inherit; -- st_table *tbl; -+ sa_table *tbl; - - if (argc == 0) { - inherit = Qtrue; -@@ -1817,7 +1764,7 @@ rb_const_defined_0(VALUE klass, ID id, int exclude, int recurse, int visibility) - tmp = klass; - retry: - while (tmp) { -- if (RCLASS_CONST_TBL(tmp) && st_lookup(RCLASS_CONST_TBL(tmp), (st_data_t)id, &value)) { -+ if (sa_lookup(RCLASS_CONST_TBL(tmp), (sa_index_t)id, &value)) { - rb_const_entry_t *ce = (rb_const_entry_t *)value; - if (visibility && ce->flag == CONST_PRIVATE) { - return (int)Qfalse; -@@ -1885,6 +1832,7 @@ void - rb_const_set(VALUE klass, ID id, VALUE val) - { - rb_const_entry_t *ce; -+ st_data_t value; - VALUE visibility = CONST_PUBLIC; - - if (NIL_P(klass)) { -@@ -1893,21 +1841,14 @@ rb_const_set(VALUE klass, ID id, VALUE val) - } - - check_before_mod_set(klass, id, val, "constant"); -- if (!RCLASS_CONST_TBL(klass)) { -- RCLASS_CONST_TBL(klass) = st_init_numtable(); -- } -- else { -- st_data_t value; -- -- if (st_lookup(RCLASS_CONST_TBL(klass), (st_data_t)id, &value)) { -- rb_const_entry_t *ce = (rb_const_entry_t*)value; -- if (ce->value == Qundef) -- autoload_delete(klass, id); -- else { -- visibility = ce->flag; -- rb_warn("already initialized constant %s", rb_id2name(id)); -- } -- } -+ if (sa_lookup(RCLASS_CONST_TBL(klass), (sa_index_t)id, &value)) { -+ rb_const_entry_t *ce = (rb_const_entry_t*)value; -+ if (ce->value == Qundef) -+ autoload_delete(klass, id); -+ else { -+ visibility = ce->flag; -+ rb_warn("already initialized constant %s", rb_id2name(id)); -+ } - } - - rb_vm_change_state(); -@@ -1916,7 +1857,7 @@ rb_const_set(VALUE klass, ID id, VALUE val) - ce->flag = (rb_const_flag_t)visibility; - ce->value = val; - -- st_insert(RCLASS_CONST_TBL(klass), (st_data_t)id, (st_data_t)ce); -+ sa_insert(RCLASS_CONST_TBL(klass), (sa_index_t)id, (st_data_t)ce); - } - - void -@@ -1958,8 +1899,7 @@ set_const_visibility(VALUE mod, int argc, VALUE *argv, rb_const_flag_t flag) - for (i = 0; i < argc; i++) { - VALUE val = argv[i]; - id = rb_to_id(val); -- if (RCLASS_CONST_TBL(mod) && -- st_lookup(RCLASS_CONST_TBL(mod), (st_data_t)id, &v)) { -+ if (sa_lookup(RCLASS_CONST_TBL(mod), (sa_index_t)id, &v)) { - ((rb_const_entry_t*)v)->flag = flag; - } - else { -@@ -2008,7 +1948,7 @@ original_module(VALUE c) - } - - #define CVAR_LOOKUP(v,r) do {\ -- if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass),(st_data_t)id,(v))) {\ -+ if (sa_lookup(RCLASS_IV_TBL(klass),(sa_index_t)id,(v))) {\ - r;\ - }\ - if (FL_TEST(klass, FL_SINGLETON) ) {\ -@@ -2027,7 +1967,7 @@ original_module(VALUE c) - klass = RCLASS_SUPER(klass);\ - }\ - while (klass) {\ -- if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass),(st_data_t)id,(v))) {\ -+ if (sa_lookup(RCLASS_IV_TBL(klass),(sa_index_t)id,(v))) {\ - r;\ - }\ - klass = RCLASS_SUPER(klass);\ -@@ -2043,15 +1983,13 @@ rb_cvar_set(VALUE klass, ID id, VALUE val) - CVAR_LOOKUP(0, {if (!front) front = klass; target = klass;}); - if (target) { - if (front && target != front) { -- st_data_t did = id; -- - if (RTEST(ruby_verbose)) { - rb_warning("class variable %s of %s is overtaken by %s", - rb_id2name(id), rb_class2name(original_module(front)), - rb_class2name(original_module(target))); - } - if (BUILTIN_TYPE(front) == T_CLASS) { -- st_delete(RCLASS_IV_TBL(front),&did,0); -+ sa_delete(RCLASS_IV_TBL(front),(sa_index_t)id,0); - } - } - } -@@ -2060,11 +1998,7 @@ rb_cvar_set(VALUE klass, ID id, VALUE val) - } - - check_before_mod_set(target, id, val, "class variable"); -- if (!RCLASS_IV_TBL(target)) { -- RCLASS_IV_TBL(target) = st_init_numtable(); -- } -- -- st_insert(RCLASS_IV_TBL(target), (st_data_t)id, (st_data_t)val); -+ sa_insert(RCLASS_IV_TBL(target), (sa_index_t)id, (st_data_t)val); - } - - VALUE -@@ -2080,15 +2014,13 @@ rb_cvar_get(VALUE klass, ID id) - rb_id2name(id), rb_class2name(tmp)); - } - if (front && target != front) { -- st_data_t did = id; -- - if (RTEST(ruby_verbose)) { - rb_warning("class variable %s of %s is overtaken by %s", - rb_id2name(id), rb_class2name(original_module(front)), - rb_class2name(original_module(target))); - } - if (BUILTIN_TYPE(front) == T_CLASS) { -- st_delete(RCLASS_IV_TBL(front),&did,0); -+ sa_delete(RCLASS_IV_TBL(front),(sa_index_t)id,0); - } - } - return (VALUE)value; -@@ -2134,7 +2066,7 @@ rb_define_class_variable(VALUE klass, const char *name, VALUE val) - } - - static int --cv_i(ID key, VALUE value, VALUE ary) -+cv_i(sa_index_t key, VALUE value, VALUE ary) - { - if (rb_is_class_id(key)) { - VALUE kval = ID2SYM(key); -@@ -2167,7 +2099,7 @@ rb_mod_class_variables(VALUE obj) - VALUE ary = rb_ary_new(); - - if (RCLASS_IV_TBL(obj)) { -- st_foreach_safe(RCLASS_IV_TBL(obj), cv_i, ary); -+ sa_foreach(RCLASS_IV_TBL(obj), cv_i, ary); - } - return ary; - } -@@ -2196,7 +2128,7 @@ VALUE - rb_mod_remove_cvar(VALUE mod, VALUE name) - { - const ID id = rb_to_id(name); -- st_data_t val, n = id; -+ st_data_t val; - - if (!rb_is_class_id(id)) { - rb_name_error(id, "wrong class variable name %s", rb_id2name(id)); -@@ -2204,7 +2136,7 @@ rb_mod_remove_cvar(VALUE mod, VALUE name) - if (!OBJ_UNTRUSTED(mod) && rb_safe_level() >= 4) - rb_raise(rb_eSecurityError, "Insecure: can't remove class variable"); - rb_check_frozen(mod); -- if (RCLASS_IV_TBL(mod) && st_delete(RCLASS_IV_TBL(mod), &n, &val)) { -+ if (RCLASS_IV_TBL(mod) && sa_delete(RCLASS_IV_TBL(mod), (sa_index_t)id, &val)) { - return (VALUE)val; - } - if (rb_cvar_defined(mod, id)) { -diff --git a/vm.c b/vm.c -index 5a721d0..7bc007a 100644 ---- a/vm.c -+++ b/vm.c -@@ -1055,7 +1055,7 @@ static void - add_opt_method(VALUE klass, ID mid, VALUE bop) - { - rb_method_entry_t *me; -- if (st_lookup(RCLASS_M_TBL(klass), mid, (void *)&me) && me->def && -+ if (sa_lookup(RCLASS_M_TBL(klass), (sa_index_t)mid, (void *)&me) && me->def && - me->def->type == VM_METHOD_TYPE_CFUNC) { - st_insert(vm_opt_method_table, (st_data_t)me, (st_data_t)bop); - } -diff --git a/vm_insnhelper.c b/vm_insnhelper.c -index 5f7d1ee..ade417e 100644 ---- a/vm_insnhelper.c -+++ b/vm_insnhelper.c -@@ -1179,7 +1179,7 @@ vm_get_ev_const(rb_thread_t *th, const rb_iseq_t *iseq, - st_data_t data; - search_continue: - if (RCLASS_CONST_TBL(klass) && -- st_lookup(RCLASS_CONST_TBL(klass), id, &data)) { -+ sa_lookup(RCLASS_CONST_TBL(klass), (sa_index_t)id, &data)) { - val = ((rb_const_entry_t*)data)->value; - if (val == Qundef) { - if (am == klass) break; -@@ -1289,10 +1289,10 @@ vm_getivar(VALUE obj, ID id, IC ic) - st_data_t index; - long len = ROBJECT_NUMIV(obj); - VALUE *ptr = ROBJECT_IVPTR(obj); -- struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); -+ struct sa_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); - - if (iv_index_tbl) { -- if (st_lookup(iv_index_tbl, id, &index)) { -+ if (sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) { - if ((long)index < len) { - val = ptr[index]; - } -@@ -1342,9 +1342,9 @@ vm_setivar(VALUE obj, ID id, VALUE val, IC ic) - } - } - else { -- struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); -+ struct sa_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); - -- if (iv_index_tbl && st_lookup(iv_index_tbl, (st_data_t)id, &index)) { -+ if (iv_index_tbl && sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) { - ic->ic_class = klass; - ic->ic_value.index = index; - ic->ic_vmstat = GET_VM_STATE_VERSION(); -diff --git a/vm_method.c b/vm_method.c -index 85cb30c..d45df81 100644 ---- a/vm_method.c -+++ b/vm_method.c -@@ -162,7 +162,7 @@ rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type, - rb_method_definition_t *def, rb_method_flag_t noex) - { - rb_method_entry_t *me; -- st_table *mtbl; -+ sa_table *mtbl; - st_data_t data; - - if (NIL_P(klass)) { -@@ -190,7 +190,7 @@ rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type, - mtbl = RCLASS_M_TBL(klass); - - /* check re-definition */ -- if (st_lookup(mtbl, mid, &data)) { -+ if (sa_lookup(mtbl, (sa_index_t)mid, &data)) { - rb_method_entry_t *old_me = (rb_method_entry_t *)data; - rb_method_definition_t *old_def = old_me->def; - -@@ -248,7 +248,7 @@ rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type, - } - } - -- st_insert(mtbl, mid, (st_data_t) me); -+ sa_insert(mtbl, (sa_index_t)mid, (st_data_t) me); - - return me; - } -@@ -371,7 +371,7 @@ search_method(VALUE klass, ID id) - return 0; - } - -- while (!st_lookup(RCLASS_M_TBL(klass), id, &body)) { -+ while (!sa_lookup(RCLASS_M_TBL(klass), (sa_index_t)id, &body)) { - klass = RCLASS_SUPER(klass); - if (!klass) { - return 0; -@@ -429,7 +429,7 @@ rb_method_entry(VALUE klass, ID id) - static void - remove_method(VALUE klass, ID mid) - { -- st_data_t key, data; -+ st_data_t data; - rb_method_entry_t *me = 0; - - if (klass == rb_cObject) { -@@ -443,14 +443,13 @@ remove_method(VALUE klass, ID mid) - rb_warn("removing `%s' may cause serious problems", rb_id2name(mid)); - } - -- if (!st_lookup(RCLASS_M_TBL(klass), mid, &data) || -+ if (!sa_lookup(RCLASS_M_TBL(klass), (sa_index_t)mid, &data) || - !(me = (rb_method_entry_t *)data) || - (!me->def || me->def->type == VM_METHOD_TYPE_UNDEF)) { - rb_name_error(mid, "method `%s' not defined in %s", - rb_id2name(mid), rb_class2name(klass)); - } -- key = (st_data_t)mid; -- st_delete(RCLASS_M_TBL(klass), &key, &data); -+ sa_delete(RCLASS_M_TBL(klass), (sa_index_t)mid, &data); - - rb_vm_check_redefinition_opt_method(me); - rb_clear_cache_for_undef(klass, mid); diff --git a/patches/ruby/1.9.3/head/railsexpress/12-falcon-array-queue.patch b/patches/ruby/1.9.3/head/railsexpress/12-falcon-array-queue.patch deleted file mode 100644 index cdd40e123c..0000000000 --- a/patches/ruby/1.9.3/head/railsexpress/12-falcon-array-queue.patch +++ /dev/null @@ -1,301 +0,0 @@ -diff --git a/array.c b/array.c -index c33d106..747da0e 100644 ---- a/array.c -+++ b/array.c -@@ -255,15 +255,24 @@ rb_ary_modify(VALUE ary) - rb_ary_modify_check(ary); - if (ARY_SHARED_P(ary)) { - long len = RARRAY_LEN(ary); -+ VALUE shared = ARY_SHARED(ary); - if (len <= RARRAY_EMBED_LEN_MAX) { - VALUE *ptr = ARY_HEAP_PTR(ary); -- VALUE shared = ARY_SHARED(ary); - FL_UNSET_SHARED(ary); - FL_SET_EMBED(ary); - MEMCPY(ARY_EMBED_PTR(ary), ptr, VALUE, len); - rb_ary_decrement_share(shared); - ARY_SET_EMBED_LEN(ary, len); - } -+ else if (ARY_SHARED_NUM(shared) == 1 && len > RARRAY_LEN(shared)>>1) { -+ long shift = RARRAY_PTR(ary) - RARRAY_PTR(shared); -+ ARY_SET_PTR(ary, RARRAY_PTR(shared)); -+ ARY_SET_CAPA(ary, RARRAY_LEN(shared)); -+ MEMMOVE(RARRAY_PTR(ary), RARRAY_PTR(ary)+shift, VALUE, len); -+ FL_UNSET_SHARED(ary); -+ FL_SET_EMBED(shared); -+ rb_ary_decrement_share(shared); -+ } - else { - VALUE *ptr = ALLOC_N(VALUE, len); - MEMCPY(ptr, RARRAY_PTR(ary), VALUE, len); -@@ -274,6 +283,38 @@ rb_ary_modify(VALUE ary) - } - } - -+static void -+ary_ensure_room_for_push(VALUE ary, long add_len) -+{ -+ long new_len = RARRAY_LEN(ary) + add_len; -+ long capa; -+ -+ if (ARY_SHARED_P(ary)) { -+ if (new_len > RARRAY_EMBED_LEN_MAX) { -+ VALUE shared = ARY_SHARED(ary); -+ if (ARY_SHARED_NUM(shared) == 1) { -+ if (RARRAY_PTR(ary) - RARRAY_PTR(shared) + new_len <= RARRAY_LEN(shared)) { -+ rb_ary_modify_check(ary); -+ } -+ else { -+ /* if array is shared, than it is likely it participate in push/shift pattern */ -+ rb_ary_modify(ary); -+ capa = ARY_CAPA(ary); -+ if (new_len > capa - (capa >> 6)) { -+ ary_double_capa(ary, new_len); -+ } -+ } -+ return; -+ } -+ } -+ } -+ rb_ary_modify(ary); -+ capa = ARY_CAPA(ary); -+ if (new_len > capa) { -+ ary_double_capa(ary, new_len); -+ } -+} -+ - VALUE - rb_ary_freeze(VALUE ary) - { -@@ -446,8 +487,9 @@ ary_make_shared(VALUE ary) - OBJSETUP(shared, 0, T_ARRAY); - FL_UNSET_EMBED(shared); - -- ARY_SET_LEN((VALUE)shared, RARRAY_LEN(ary)); -+ ARY_SET_LEN((VALUE)shared, ARY_CAPA(ary)); - ARY_SET_PTR((VALUE)shared, RARRAY_PTR(ary)); -+ rb_mem_clear(RARRAY_PTR(shared) + RARRAY_LEN(ary), ARY_CAPA(ary) - RARRAY_LEN(ary)); - FL_SET_SHARED_ROOT(shared); - ARY_SET_SHARED_NUM((VALUE)shared, 1); - FL_SET_SHARED(ary); -@@ -737,8 +779,6 @@ ary_take_first_or_last(int argc, VALUE *argv, VALUE ary, enum ary_take_pos_flags - return ary_make_partial(ary, rb_cArray, offset, n); - } - --static VALUE rb_ary_push_1(VALUE ary, VALUE item); -- - /* - * call-seq: - * ary << obj -> ary -@@ -755,8 +795,12 @@ static VALUE rb_ary_push_1(VALUE ary, VALUE item); - VALUE - rb_ary_push(VALUE ary, VALUE item) - { -- rb_ary_modify(ary); -- return rb_ary_push_1(ary, item); -+ long idx = RARRAY_LEN(ary); -+ -+ ary_ensure_room_for_push(ary, 1); -+ RARRAY_PTR(ary)[idx] = item; -+ ARY_SET_LEN(ary, idx + 1); -+ return ary; - } - - static VALUE -@@ -772,6 +816,18 @@ rb_ary_push_1(VALUE ary, VALUE item) - return ary; - } - -+static VALUE -+rb_ary_cat(VALUE ary, const VALUE *ptr, long len) -+{ -+ long oldlen = RARRAY_LEN(ary); -+ -+ ary_ensure_room_for_push(ary, len); -+copy: -+ MEMCPY(RARRAY_PTR(ary) + oldlen, ptr, VALUE, len); -+ ARY_SET_LEN(ary, oldlen + len); -+ return ary; -+} -+ - /* - * call-seq: - * ary.push(obj, ... ) -> ary -@@ -788,11 +844,7 @@ rb_ary_push_1(VALUE ary, VALUE item) - static VALUE - rb_ary_push_m(int argc, VALUE *argv, VALUE ary) - { -- rb_ary_modify(ary); -- while (argc--) { -- rb_ary_push_1(ary, *argv++); -- } -- return ary; -+ return rb_ary_cat(ary, argv, argc); - } - - VALUE -@@ -920,6 +972,55 @@ rb_ary_shift_m(int argc, VALUE *argv, VALUE ary) - return result; - } - -+static void -+ary_ensure_room_for_unshift(VALUE ary, int argc) -+{ -+ long len = RARRAY_LEN(ary); -+ long new_len = len + argc; -+ long capa; -+ VALUE *head, *sharedp; -+ -+ if (ARY_SHARED_P(ary)) { -+ VALUE shared = ARY_SHARED(ary); -+ capa = RARRAY_LEN(shared); -+ if (ARY_SHARED_NUM(shared) == 1 && capa > new_len) { -+ head = RARRAY_PTR(ary); -+ sharedp = RARRAY_PTR(shared); -+ goto makeroom_if_need; -+ } -+ } -+ -+ rb_ary_modify(ary); -+ capa = ARY_CAPA(ary); -+ if (capa - (capa >> 6) <= new_len) { -+ ary_double_capa(ary, new_len); -+ } -+ -+ /* use shared array for big "queues" */ -+ if (new_len > ARY_DEFAULT_SIZE * 4) { -+ /* make a room for unshifted items */ -+ capa = ARY_CAPA(ary); -+ ary_make_shared(ary); -+ -+ head = sharedp = RARRAY_PTR(ary); -+ goto makeroom; -+makeroom_if_need: -+ if (head - sharedp < argc) { -+ long room; -+makeroom: -+ room = capa - new_len; -+ room -= room >> 4; -+ MEMMOVE(sharedp + argc + room, head, VALUE, len); -+ head = sharedp + argc + room; -+ } -+ ARY_SET_PTR(ary, head - argc); -+ } -+ else { -+ /* sliding items */ -+ MEMMOVE(RARRAY_PTR(ary) + argc, RARRAY_PTR(ary), VALUE, len); -+ } -+} -+ - /* - * call-seq: - * ary.unshift(obj, ...) -> ary -@@ -935,19 +1036,16 @@ rb_ary_shift_m(int argc, VALUE *argv, VALUE ary) - static VALUE - rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary) - { -- long len; -+ long len = RARRAY_LEN(ary); - -- rb_ary_modify(ary); -- if (argc == 0) return ary; -- if (ARY_CAPA(ary) <= (len = RARRAY_LEN(ary)) + argc) { -- ary_double_capa(ary, len + argc); -+ if (argc == 0) { -+ rb_ary_modify_check(ary); -+ return ary; - } - -- /* sliding items */ -- MEMMOVE(RARRAY_PTR(ary) + argc, RARRAY_PTR(ary), VALUE, len); -+ ary_ensure_room_for_unshift(ary, argc); - MEMCPY(RARRAY_PTR(ary), argv, VALUE, argc); -- ARY_INCREASE_LEN(ary, argc); -- -+ ARY_SET_LEN(ary, len + argc); - return ary; - } - -@@ -1309,15 +1407,12 @@ rb_ary_splice(VALUE ary, long beg, long len, VALUE rpl) - rpl = rb_ary_to_ary(rpl); - rlen = RARRAY_LEN(rpl); - } -- rb_ary_modify(ary); - if (beg >= RARRAY_LEN(ary)) { - if (beg > ARY_MAX_SIZE - rlen) { - rb_raise(rb_eIndexError, "index %ld too big", beg); - } -+ ary_ensure_room_for_push(ary, rlen-len); /* len is 0 or negative */ - len = beg + rlen; -- if (len >= ARY_CAPA(ary)) { -- ary_double_capa(ary, len); -- } - rb_mem_clear(RARRAY_PTR(ary) + RARRAY_LEN(ary), beg - RARRAY_LEN(ary)); - if (rlen > 0) { - MEMCPY(RARRAY_PTR(ary) + beg, RARRAY_PTR(rpl), VALUE, rlen); -@@ -1327,6 +1422,7 @@ rb_ary_splice(VALUE ary, long beg, long len, VALUE rpl) - else { - long alen; - -+ rb_ary_modify(ary); - alen = RARRAY_LEN(ary) + rlen - len; - if (alen >= ARY_CAPA(ary)) { - ary_double_capa(ary, alen); -@@ -2116,12 +2212,13 @@ rb_ary_sort_bang(VALUE ary) - if (RARRAY_LEN(ary) > 1) { - VALUE tmp = ary_make_substitution(ary); /* only ary refers tmp */ - struct ary_sort_data data; -+ long len = RARRAY_LEN(ary); - - RBASIC(tmp)->klass = 0; - data.ary = tmp; - data.opt_methods = 0; - data.opt_inited = 0; -- ruby_qsort(RARRAY_PTR(tmp), RARRAY_LEN(tmp), sizeof(VALUE), -+ ruby_qsort(RARRAY_PTR(tmp), len, sizeof(VALUE), - rb_block_given_p()?sort_1:sort_2, &data); - - if (ARY_EMBED_P(tmp)) { -@@ -2138,7 +2235,7 @@ rb_ary_sort_bang(VALUE ary) - if (ARY_HEAP_PTR(ary) == ARY_HEAP_PTR(tmp)) { - assert(!ARY_EMBED_P(ary)); - FL_UNSET_SHARED(ary); -- ARY_SET_CAPA(ary, ARY_CAPA(tmp)); -+ ARY_SET_CAPA(ary, RARRAY_LEN(tmp)); - } - else { - assert(!ARY_SHARED_P(tmp)); -@@ -2153,8 +2250,8 @@ rb_ary_sort_bang(VALUE ary) - xfree(ARY_HEAP_PTR(ary)); - } - ARY_SET_PTR(ary, RARRAY_PTR(tmp)); -- ARY_SET_HEAP_LEN(ary, RARRAY_LEN(tmp)); -- ARY_SET_CAPA(ary, ARY_CAPA(tmp)); -+ ARY_SET_HEAP_LEN(ary, len); -+ ARY_SET_CAPA(ary, RARRAY_LEN(tmp)); - } - /* tmp was lost ownership for the ptr */ - FL_UNSET(tmp, FL_FREEZE); -diff --git a/test/ruby/test_array.rb b/test/ruby/test_array.rb -index 28d3e41..bcad2c0 100644 ---- a/test/ruby/test_array.rb -+++ b/test/ruby/test_array.rb -@@ -414,6 +414,18 @@ class TestArray < Test::Unit::TestCase - a = @cls[1, 2, 3] - a[-1, 0] = a - assert_equal([1, 2, 1, 2, 3, 3], a) -+ -+ a = @cls[] -+ a[5,0] = [5] -+ assert_equal([nil, nil, nil, nil, nil, 5], a) -+ -+ a = @cls[1] -+ a[1,0] = [2] -+ assert_equal([1, 2], a) -+ -+ a = @cls[1] -+ a[1,1] = [2] -+ assert_equal([1, 2], a) - end - - def test_assoc diff --git a/patches/ruby/1.9.3/head/railsexpress/13-railsbench-gc-fixes.patch b/patches/ruby/1.9.3/head/railsexpress/13-railsbench-gc-fixes.patch deleted file mode 100644 index 0ff3abfe64..0000000000 --- a/patches/ruby/1.9.3/head/railsexpress/13-railsbench-gc-fixes.patch +++ /dev/null @@ -1,257 +0,0 @@ -diff --git a/gc.c b/gc.c -index 56f0217..6e3714d 100644 ---- a/gc.c -+++ b/gc.c -@@ -108,11 +108,6 @@ ruby_gc_params_t initial_params = { - #define LONG_LONG long - #endif - --static int heap_min_slots = 10000; --static int heap_slots_increment = 10000; --static int initial_heap_slots_increment = 10000; --static double heap_slots_growth_factor = 1.8; -- - #define nomem_error GET_VM()->special_exceptions[ruby_error_nomemory] - - #if SIZEOF_LONG == SIZEOF_VOIDP -@@ -321,6 +316,28 @@ typedef struct RVALUE { - #endif - } RVALUE; - -+ -+/* tiny heap size */ -+/* 32KB */ -+/*#define HEAP_SIZE 0x8000 */ -+/* 128KB */ -+/*#define HEAP_SIZE 0x20000 */ -+/* 64KB */ -+/*#define HEAP_SIZE 0x10000 */ -+/* 16KB */ -+#define HEAP_SIZE 0x4000 -+/* 8KB */ -+/*#define HEAP_SIZE 0x2000 */ -+/* 4KB */ -+/*#define HEAP_SIZE 0x1000 */ -+/* 2KB */ -+/*#define HEAP_SIZE 0x800 */ -+ -+#define HEAP_OBJ_LIMIT (unsigned int)(HEAP_SIZE / sizeof(struct RVALUE)) -+ -+static int heap_slots_increment = 10000 / HEAP_OBJ_LIMIT; -+static double heap_slots_growth_factor = 1.8; -+ - #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__) - #pragma pack(pop) - #endif -@@ -535,17 +552,6 @@ rb_gc_set_params(void) - - if (rb_safe_level() > 0) return; - -- envp = getenv("RUBY_GC_STATS"); -- if (envp != NULL) { -- int i = atoi(envp); -- if (i > 0) { -- verbose_gc_stats = 1; -- fprintf(stderr, "RUBY_GC_STATS=%d\n", verbose_gc_stats); -- } -- /* child processes should not inherit RUBY_GC_STATS */ -- ruby_unsetenv("RUBY_GC_STATS"); -- } -- - envp = getenv("RUBY_GC_DATA_FILE"); - if (envp != NULL) { - FILE* data_file = fopen(envp, "w"); -@@ -559,6 +565,18 @@ rb_gc_set_params(void) - ruby_unsetenv("RUBY_GC_DATA_FILE"); - } - -+ envp = getenv("RUBY_GC_STATS"); -+ if (envp != NULL) { -+ int i = atoi(envp); -+ if (i > 0) { -+ /* gc_statistics = 1; */ -+ verbose_gc_stats = 1; -+ fprintf(gc_data_file, "RUBY_GC_STATS=%d\n", verbose_gc_stats); -+ } -+ /* child processes should not inherit RUBY_GC_STATS */ -+ ruby_unsetenv("RUBY_GC_STATS"); -+ } -+ - envp = getenv("RUBY_GC_MALLOC_LIMIT"); - if (envp != NULL) { - int malloc_limit_i = atoi(envp); -@@ -570,7 +588,7 @@ rb_gc_set_params(void) - malloc_limit_i, initial_malloc_limit); - if (malloc_limit_i > 0) { - initial_malloc_limit = malloc_limit_i; -- // malloc_limit = initial_malloc_limit; -+ malloc_limit = initial_malloc_limit; - } - } - -@@ -609,8 +627,7 @@ rb_gc_set_params(void) - if (verbose_gc_stats) { - fprintf(gc_data_file, "RUBY_HEAP_SLOTS_INCREMENT=%s\n", envp); - } -- heap_slots_increment = i; -- initial_heap_slots_increment = heap_slots_increment; -+ heap_slots_increment = i / HEAP_OBJ_LIMIT; - } - - envp = getenv("RUBY_HEAP_SLOTS_GROWTH_FACTOR"); -@@ -670,24 +687,6 @@ rb_objspace_free(rb_objspace_t *objspace) - } - #endif - --/* tiny heap size */ --/* 32KB */ --/*#define HEAP_SIZE 0x8000 */ --/* 128KB */ --/*#define HEAP_SIZE 0x20000 */ --/* 64KB */ --/*#define HEAP_SIZE 0x10000 */ --/* 16KB */ --#define HEAP_SIZE 0x4000 --/* 8KB */ --/*#define HEAP_SIZE 0x2000 */ --/* 4KB */ --/*#define HEAP_SIZE 0x1000 */ --/* 2KB */ --/*#define HEAP_SIZE 0x800 */ -- --#define HEAP_OBJ_LIMIT (unsigned int)(HEAP_SIZE / sizeof(struct RVALUE)) -- - extern sa_table rb_class_tbl; - - int ruby_disable_gc_stress = 0; -@@ -1520,7 +1519,6 @@ rb_gc_dump_file_and_line_info(int argc, VALUE *argv) - rb_objspace_t *objspace = &rb_objspace; - VALUE filename, str, include_classnames = Qnil; - char *fname = NULL; -- char *klass = NULL; - FILE* f = NULL; - size_t i = 0; - -@@ -1778,17 +1776,15 @@ aligned_free(void *ptr) - static void - assign_heap_slot(rb_objspace_t *objspace) - { -- /* -- if (gc_statistics & verbose_gc_stats) { -- fprintf(gc_data_file, "assigning heap slot\n"); -- } -- */ -- - RVALUE *p, *pend, *membase; - struct heaps_slot *slot; - size_t hi, lo, mid; - size_t objs; -- -+ /* -+ if (gc_statistics & verbose_gc_stats) { -+ fprintf(gc_data_file, "assigning heap slot: %d\n", heaps_inc); -+ } -+ */ - objs = HEAP_OBJ_LIMIT; - p = (RVALUE*)malloc(HEAP_SIZE); - if (p == 0) { -@@ -1903,13 +1899,17 @@ static void - set_heaps_increment(rb_objspace_t *objspace) - { - size_t next_heaps_length = (size_t)(heaps_used * heap_slots_growth_factor); -+ size_t next_heaps_length_alt = heaps_used + heap_slots_increment; - -- if (next_heaps_length == heaps_used) { -- next_heaps_length++; -+ if (next_heaps_length < next_heaps_length_alt) { -+ next_heaps_length = next_heaps_length_alt; - } - - heaps_inc = next_heaps_length - heaps_used; -- -+ /* -+ if (gc_statistics & verbose_gc_stats) -+ fprintf(gc_data_file, "heaps_inc:%lu, slots_inc: %lu\n", heaps_inc, heaps_inc * HEAP_OBJ_LIMIT); -+ */ - if (next_heaps_length > heaps_length) { - allocate_sorted_heaps(objspace, next_heaps_length); - } -@@ -2527,7 +2527,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr) - - #ifdef GC_DEBUG - if (obj->file && obj->file != Qnil && is_pointer_to_heap(objspace, (void*)obj->file)) { -- gc_mark(objspace, obj->file, lev); -+ gc_mark(objspace, obj->file); - } - #endif - -@@ -2543,7 +2543,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr) - - #ifdef GC_DEBUG - if (obj->file && obj->file != Qnil && is_pointer_to_heap(objspace, (void*)obj->file)) { -- gc_mark(objspace, obj->file, lev); -+ gc_mark(objspace, obj->file); - } - #endif - -@@ -3028,14 +3028,14 @@ before_gc_sweep(rb_objspace_t *objspace) - MEMZERO((void*)live_counts, unsigned long, T_MASK+1); - } - -- objspace->heap.max_blocks_to_free = heaps_used - (heap_min_slots / HEAP_OBJ_LIMIT); -+ objspace->heap.max_blocks_to_free = heaps_used - (initial_heap_min_slots / HEAP_OBJ_LIMIT); - objspace->heap.freed_blocks = 0; - - freelist = 0; - objspace->heap.do_heap_free = (size_t)((heaps_used * HEAP_OBJ_LIMIT) * 0.65); - objspace->heap.free_min = (size_t)((heaps_used * HEAP_OBJ_LIMIT) * 0.2); - if (objspace->heap.free_min < initial_free_min) { -- objspace->heap.do_heap_free = heaps_used * HEAP_OBJ_LIMIT; -+ /* objspace->heap.do_heap_free = heaps_used * HEAP_OBJ_LIMIT; */ - objspace->heap.free_min = initial_free_min; - } - objspace->heap.sweep_slots = heaps; -@@ -3067,7 +3067,11 @@ after_gc_sweep(rb_objspace_t *objspace) - if (malloc_limit < initial_malloc_limit) malloc_limit = initial_malloc_limit; - } - malloc_increase = 0; -- -+ /* -+ if (verbose_gc_stats) -+ fprintf(gc_data_file, "heap size before freeing unused heaps: %7lu\n", -+ (unsigned long)heaps_used*HEAP_OBJ_LIMIT); -+ */ - free_unused_heaps(objspace); - - if (gc_statistics) { -@@ -3076,6 +3080,7 @@ after_gc_sweep(rb_objspace_t *objspace) - if (verbose_gc_stats) { - /* log gc stats if requested */ - fprintf(gc_data_file, "GC time: %lu musec\n", (unsigned long)(gc_time_accumulator-gc_time_accumulator_before_gc)); -+ fprintf(gc_data_file, "heap size : %7lu\n", (unsigned long)heaps_used*HEAP_OBJ_LIMIT); - fprintf(gc_data_file, "objects processed: %7lu\n", (unsigned long)processed); - fprintf(gc_data_file, "live objects : %7lu\n", (unsigned long)live_after_last_mark_phase); - fprintf(gc_data_file, "freelist objects : %7lu\n", (unsigned long)freelist_size); -@@ -3125,7 +3130,7 @@ rest_sweep(rb_objspace_t *objspace) - - static void gc_marks(rb_objspace_t *objspace); - --/* only called from rb_new_obj */ -+/* only called from rb_newobj */ - static int - gc_lazy_sweep(rb_objspace_t *objspace) - { -@@ -3412,13 +3417,11 @@ gc_marks(rb_objspace_t *objspace) - struct gc_list *list; - rb_thread_t *th = GET_THREAD(); - GC_PROF_MARK_TIMER_START; -- - /* - if (gc_statistics & verbose_gc_stats) { - fprintf(gc_data_file, "Marking objects\n"); - } - */ -- - objspace->heap.live_num = 0; - objspace->count++; - live_objects = 0; diff --git a/patches/ruby/1.9.3/head/railsexpress/14-show-full-backtrace-on-stack-overflow.patch b/patches/ruby/1.9.3/head/railsexpress/14-show-full-backtrace-on-stack-overflow.patch deleted file mode 100644 index 897e1bd980..0000000000 --- a/patches/ruby/1.9.3/head/railsexpress/14-show-full-backtrace-on-stack-overflow.patch +++ /dev/null @@ -1,14 +0,0 @@ -diff --git a/eval.c b/eval.c -index 9ceb833..fb5afc0 100644 ---- a/eval.c -+++ b/eval.c -@@ -380,8 +380,7 @@ setup_exception(rb_thread_t *th, int tag, volatile VALUE mesg) - if (file) line = rb_sourceline(); - if (file && !NIL_P(mesg)) { - if (mesg == sysstack_error) { -- at = rb_enc_sprintf(rb_usascii_encoding(), "%s:%d", file, line); -- at = rb_ary_new3(1, at); -+ at = rb_make_backtrace(); - rb_iv_set(mesg, "bt", at); - } - else { diff --git a/patches/ruby/1.9.3/p125/railsexpress/01-merge-revision-s-34719-34720-b.patch b/patches/ruby/1.9.3/p125/railsexpress/01-merge-revision-s-34719-34720-b.patch deleted file mode 100644 index 6386db9b2b..0000000000 --- a/patches/ruby/1.9.3/p125/railsexpress/01-merge-revision-s-34719-34720-b.patch +++ /dev/null @@ -1,76 +0,0 @@ -diff --git a/gc.c b/gc.c -index c53bfd9..e65d0ec 100644 ---- a/gc.c -+++ b/gc.c -@@ -464,13 +464,12 @@ rb_gc_set_params(void) - #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE - static void gc_sweep(rb_objspace_t *); - static void slot_sweep(rb_objspace_t *, struct heaps_slot *); --static void gc_clear_mark_on_sweep_slots(rb_objspace_t *); -+static void rest_sweep(rb_objspace_t *); - - void - rb_objspace_free(rb_objspace_t *objspace) - { -- gc_clear_mark_on_sweep_slots(objspace); -- gc_sweep(objspace); -+ rest_sweep(objspace); - if (objspace->profile.record) { - free(objspace->profile.record); - objspace->profile.record = 0; -@@ -2430,28 +2429,6 @@ mark_current_machine_context(rb_objspace_t *objspace, rb_thread_t *th) - } - - static void --gc_clear_mark_on_sweep_slots(rb_objspace_t *objspace) --{ -- struct heaps_slot *scan; -- RVALUE *p, *pend; -- -- if (objspace->heap.sweep_slots) { -- while (heaps_increment(objspace)); -- while (objspace->heap.sweep_slots) { -- scan = objspace->heap.sweep_slots; -- p = scan->slot; pend = p + scan->limit; -- while (p < pend) { -- if (p->as.free.flags & FL_MARK && BUILTIN_TYPE(p) != T_ZOMBIE) { -- p->as.basic.flags &= ~FL_MARK; -- } -- p++; -- } -- objspace->heap.sweep_slots = objspace->heap.sweep_slots->next; -- } -- } --} -- --static void - gc_marks(rb_objspace_t *objspace) - { - struct gc_list *list; -@@ -2462,8 +2439,6 @@ gc_marks(rb_objspace_t *objspace) - objspace->count++; - - -- gc_clear_mark_on_sweep_slots(objspace); -- - SET_STACK_END; - - init_mark_stack(objspace); -@@ -2520,6 +2495,8 @@ garbage_collect(rb_objspace_t *objspace) - - GC_PROF_TIMER_START; - -+ rest_sweep(objspace); -+ - during_gc++; - gc_marks(objspace); - -@@ -3025,7 +3002,7 @@ rb_objspace_call_finalizer(rb_objspace_t *objspace) - size_t i; - - /* run finalizers */ -- gc_clear_mark_on_sweep_slots(objspace); -+ rest_sweep(objspace); - - do { - /* XXX: this loop will make no sense */ diff --git a/patches/ruby/1.9.3/p125/railsexpress/02-railsbench-gc.patch b/patches/ruby/1.9.3/p125/railsexpress/02-railsbench-gc.patch deleted file mode 100644 index 4223909f5c..0000000000 --- a/patches/ruby/1.9.3/p125/railsexpress/02-railsbench-gc.patch +++ /dev/null @@ -1,1241 +0,0 @@ -diff --git a/configure.in b/configure.in -index d645aa7..e153d1c 100644 ---- a/configure.in -+++ b/configure.in -@@ -2453,6 +2453,10 @@ if test "$EXEEXT" = .exe; then - AC_SUBST(EXECUTABLE_EXTS) - fi - -+dnl enable gc debugging -+AC_ARG_ENABLE(gcdebug, -+ AS_HELP_STRING([--enable-gcdebug], [build garbage collector with debugging enabled]), -+ [AC_DEFINE(GC_DEBUG,1)]) - dnl } - dnl build section { - -diff --git a/gc.c b/gc.c -index e65d0ec..74ebec6 100644 ---- a/gc.c -+++ b/gc.c -@@ -96,6 +96,17 @@ ruby_gc_params_t initial_params = { - #endif - }; - -+#ifndef HAVE_LONG_LONG -+#define LONG_LONG long -+#endif -+ -+static size_t heap_free_min = 4096; -+static int heap_min_slots = 10000; -+static int heap_slots_increment = 10000; -+static int initial_heap_slots_increment = 10000; -+static double heap_slots_growth_factor = 1.8; -+static size_t initial_malloc_limit = GC_MALLOC_LIMIT; -+ - #define nomem_error GET_VM()->special_exceptions[ruby_error_nomemory] - - #define MARK_STACK_MAX 1024 -@@ -291,7 +302,7 @@ typedef struct RVALUE { - struct RComplex complex; - } as; - #ifdef GC_DEBUG -- const char *file; -+ VALUE file; - int line; - #endif - } RVALUE; -@@ -345,11 +356,25 @@ typedef struct rb_objspace { - size_t free_min; - size_t final_num; - size_t do_heap_free; -+ unsigned long max_blocks_to_free; -+ unsigned long freed_blocks; - } heap; - struct { -+ unsigned long processed; -+ unsigned long freed_objects; -+ unsigned long freelist_size; -+ unsigned long zombies; -+ unsigned long free_counts[T_MASK+1]; -+ unsigned long live_counts[T_MASK+1]; -+ unsigned long gc_time_accumulator_before_gc; -+ unsigned long live_after_last_mark_phase; -+ } stats; -+ struct { - int dont_gc; - int dont_lazy_sweep; - int during_gc; -+ int gc_statistics; -+ int verbose_gc_stats; - } flags; - struct { - st_table *table; -@@ -370,6 +395,14 @@ typedef struct rb_objspace { - struct gc_list *global_list; - size_t count; - int gc_stress; -+ long heap_size; -+ unsigned LONG_LONG gc_time_accumulator; -+ FILE* gc_data_file; -+ long gc_collections; -+ unsigned LONG_LONG gc_allocated_size; -+ unsigned LONG_LONG gc_num_allocations; -+ unsigned long live_objects; -+ unsigned LONG_LONG allocated_objects; - } rb_objspace_t; - - #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE -@@ -392,6 +425,16 @@ int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress; - #define heaps_freed objspace->heap.freed - #define dont_gc objspace->flags.dont_gc - #define during_gc objspace->flags.during_gc -+#define gc_statistics objspace->flags.gc_statistics -+#define verbose_gc_stats objspace->flags.verbose_gc_stats -+#define heap_size objspace->heap_size -+#define gc_time_accumulator objspace->gc_time_accumulator -+#define gc_data_file objspace->gc_data_file -+#define gc_collections objspace->gc_collections -+#define gc_allocated_size objspace->gc_allocated_size -+#define gc_num_allocations objspace->gc_num_allocations -+#define live_objects objspace->live_objects -+#define allocated_objects objspace->allocated_objects - #define finalizer_table objspace->final.table - #define deferred_final_list objspace->final.deferred - #define mark_stack objspace->markstack.buffer -@@ -402,6 +445,14 @@ int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress; - #define initial_malloc_limit initial_params.initial_malloc_limit - #define initial_heap_min_slots initial_params.initial_heap_min_slots - #define initial_free_min initial_params.initial_free_min -+#define free_counts objspace->stats.free_counts -+#define live_counts objspace->stats.live_counts -+#define processed objspace->stats.processed -+#define zombies objspace->stats.zombies -+#define freelist_size objspace->stats.freelist_size -+#define freed_objects objspace->stats.freed_objects -+#define gc_time_accumulator_before_gc objspace->stats.gc_time_accumulator_before_gc -+#define live_after_last_mark_phase objspace->stats.live_after_last_mark_phase - - static void rb_objspace_call_finalizer(rb_objspace_t *objspace); - -@@ -423,42 +474,106 @@ static void initial_expand_heap(rb_objspace_t *objspace); - void - rb_gc_set_params(void) - { -- char *malloc_limit_ptr, *heap_min_slots_ptr, *free_min_ptr; -+ char *envp; -+ -+ rb_objspace_t *objspace = &rb_objspace; -+ -+ gc_data_file = stderr; - - if (rb_safe_level() > 0) return; - -- malloc_limit_ptr = getenv("RUBY_GC_MALLOC_LIMIT"); -- if (malloc_limit_ptr != NULL) { -- int malloc_limit_i = atoi(malloc_limit_ptr); -+ envp = getenv("RUBY_GC_STATS"); -+ if (envp != NULL) { -+ int i = atoi(envp); -+ if (i > 0) { -+ verbose_gc_stats = 1; -+ fprintf(stderr, "RUBY_GC_STATS=%d\n", verbose_gc_stats); -+ } -+ /* child processes should not inherit RUBY_GC_STATS */ -+ ruby_unsetenv("RUBY_GC_STATS"); -+ } -+ -+ envp = getenv("RUBY_GC_DATA_FILE"); -+ if (envp != NULL) { -+ FILE* data_file = fopen(envp, "w"); -+ if (data_file != NULL) { -+ gc_data_file = data_file; -+ } -+ else { -+ fprintf(stderr, "can't open gc log file %s for writing, using default\n", envp); -+ } -+ /* child processes should not inherit RUBY_GC_DATA_FILE to avoid clobbering */ -+ ruby_unsetenv("RUBY_GC_DATA_FILE"); -+ } -+ -+ envp = getenv("RUBY_GC_MALLOC_LIMIT"); -+ if (envp != NULL) { -+ int malloc_limit_i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_GC_MALLOC_LIMIT=%s\n", envp); -+ } - if (RTEST(ruby_verbose)) - fprintf(stderr, "malloc_limit=%d (%d)\n", - malloc_limit_i, initial_malloc_limit); - if (malloc_limit_i > 0) { - initial_malloc_limit = malloc_limit_i; -+ // malloc_limit = initial_malloc_limit; - } - } - -- heap_min_slots_ptr = getenv("RUBY_HEAP_MIN_SLOTS"); -- if (heap_min_slots_ptr != NULL) { -- int heap_min_slots_i = atoi(heap_min_slots_ptr); -+ envp = getenv("RUBY_HEAP_MIN_SLOTS"); -+ if (envp != NULL) { -+ int heap_min_slots_i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_MIN_SLOTS=%s\n", envp); -+ } - if (RTEST(ruby_verbose)) - fprintf(stderr, "heap_min_slots=%d (%d)\n", - heap_min_slots_i, initial_heap_min_slots); - if (heap_min_slots_i > 0) { - initial_heap_min_slots = heap_min_slots_i; - initial_expand_heap(&rb_objspace); -+ // heap_min_slots = i; - } - } - -- free_min_ptr = getenv("RUBY_FREE_MIN"); -- if (free_min_ptr != NULL) { -- int free_min_i = atoi(free_min_ptr); -+ if (!(envp = getenv("RUBY_FREE_MIN"))) -+ envp = getenv("RUBY_HEAP_FREE_MIN"); -+ if (envp != NULL) { -+ int free_min_i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_FREE_MIN=%s\n", envp); -+ } - if (RTEST(ruby_verbose)) - fprintf(stderr, "free_min=%d (%d)\n", free_min_i, initial_free_min); - if (free_min_i > 0) { - initial_free_min = free_min_i; -+ // heap_free_min = i; - } - } -+ -+ envp = getenv("RUBY_HEAP_SLOTS_INCREMENT"); -+ if (envp != NULL) { -+ int i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_INCREMENT=%s\n", envp); -+ } -+ heap_slots_increment = i; -+ initial_heap_slots_increment = heap_slots_increment; -+ } -+ -+ envp = getenv("RUBY_HEAP_SLOTS_GROWTH_FACTOR"); -+ if (envp != NULL) { -+ double d = atof(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_GROWTH_FACTOR=%s\n", envp); -+ } -+ if (d > 0) { -+ heap_slots_growth_factor = d; -+ } -+ } -+ -+ fflush(gc_data_file); - } - - #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE -@@ -753,6 +868,11 @@ vm_malloc_fixup(rb_objspace_t *objspace, void *mem, size_t size) - mem = (size_t *)mem + 1; - #endif - -+ if (gc_statistics) { -+ gc_allocated_size += size; -+ gc_num_allocations += 1; -+ } -+ - return mem; - } - -@@ -813,6 +933,13 @@ vm_xrealloc(rb_objspace_t *objspace, void *ptr, size_t size) - mem = (size_t *)mem + 1; - #endif - -+ /* TODO: we can't count correctly unless we store old size on heap -+ if (gc_statistics) { -+ gc_allocated_size += size; -+ gc_num_allocations += 1; -+ } -+ */ -+ - return mem; - } - -@@ -894,7 +1021,6 @@ ruby_xfree(void *x) - vm_xfree(&rb_objspace, x); - } - -- - /* - * call-seq: - * GC.enable -> true or false -@@ -940,6 +1066,455 @@ rb_gc_disable(void) - return old ? Qtrue : Qfalse; - } - -+/* -+ * call-seq: -+ * GC.enable_stats => true or false -+ * -+ * Enables garbage collection statistics, returning true if garbage -+ * collection statistics was already enabled. -+ * -+ * GC.enable_stats #=> false or true -+ * GC.enable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = gc_statistics; -+ gc_statistics = 1; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_stats => true or false -+ * -+ * Disables garbage collection statistics, returning true if garbage -+ * collection statistics was already disabled. -+ * -+ * GC.disable_stats #=> false or true -+ * GC.disable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = gc_statistics; -+ gc_statistics = 0; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.stats_enabled? => true or false -+ * -+ * Check whether GC stats have been enabled. -+ * -+ * GC.stats_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_stats_enabled() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return gc_statistics ? Qtrue : Qfalse; -+} -+ -+ -+/* -+ * call-seq: -+ * GC.clear_stats => nil -+ * -+ * Clears garbage collection statistics, returning nil. This resets the number -+ * of collections (GC.collections) and the time used (GC.time) to 0. -+ * -+ * GC.clear_stats #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_clear_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ gc_collections = 0; -+ gc_time_accumulator = 0; -+ gc_time_accumulator_before_gc = 0; -+ gc_allocated_size = 0; -+ gc_num_allocations = 0; -+ return Qnil; -+} -+ -+/* -+ * call-seq: -+ * GC.allocated_size => Integer -+ * -+ * Returns the size of memory (in bytes) allocated since GC statistics collection -+ * was enabled. -+ * -+ * GC.allocated_size #=> 35 -+ * -+ */ -+ -+VALUE -+rb_gc_allocated_size() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_allocated_size); -+#else -+ return ULONG2NUM(gc_allocated_size); -+#endif -+} -+ -+/* -+ * call-seq: -+ * GC.num_allocations => Integer -+ * -+ * Returns the number of memory allocations since GC statistics collection -+ * was enabled. -+ * -+ * GC.num_allocations #=> 150 -+ * -+ */ -+VALUE -+rb_gc_num_allocations() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_num_allocations); -+#else -+ return ULONG2NUM(gc_num_allocations); -+#endif -+} -+ -+/* -+ * call-seq: -+ * GC.enable_trace => true or false -+ * -+ * Enables garbage collection tracing, returning true if garbage -+ * collection tracing was already enabled. -+ * -+ * GC.enable_trace #=> false or true -+ * GC.enable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_trace() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = verbose_gc_stats; -+ verbose_gc_stats = 1; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_trace => true or false -+ * -+ * Disables garbage collection tracing, returning true if garbage -+ * collection tracing was already disabled. -+ * -+ * GC.disable_trace #=> false or true -+ * GC.disable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_trace() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = verbose_gc_stats; -+ verbose_gc_stats = 0; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.trace_enabled? => true or false -+ * -+ * Check whether GC tracing has been enabled. -+ * -+ * GC.trace_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_trace_enabled() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return verbose_gc_stats ? Qtrue : Qfalse; -+} -+ -+ -+const char* GC_LOGFILE_IVAR = "@gc_logfile_name"; -+ -+/* -+ * call-seq: -+ * GC.log_file(filename=nil, mode="w") => boolean -+ * -+ * Changes the GC data log file. Closes the currently open logfile. -+ * Returns true if the file was successfully opened for -+ * writing. Returns false if the file could not be opened for -+ * writing. Returns the name of the current logfile (or nil) if no -+ * parameter is given. Restores logging to stderr when given nil as -+ * an argument. -+ * -+ * GC.log_file #=> nil -+ * GC.log_file "/tmp/gc.log" #=> true -+ * GC.log_file #=> "/tmp/gc.log" -+ * GC.log_file nil #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_log_file(int argc, VALUE *argv, VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ VALUE filename = Qnil; -+ VALUE mode_str = Qnil; -+ FILE* f = NULL; -+ const char* mode = "w"; -+ -+ VALUE current_logfile_name = rb_iv_get(rb_mGC, GC_LOGFILE_IVAR); -+ -+ if (argc==0) -+ return current_logfile_name; -+ -+ rb_scan_args(argc, argv, "02", &filename, &mode_str); -+ -+ if (filename == Qnil) { -+ /* close current logfile and reset logfile to stderr */ -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+ } -+ return Qtrue; -+ } -+ -+ /* we have a real logfile name */ -+ filename = StringValue(filename); -+ -+ if (rb_equal(current_logfile_name, filename) == Qtrue) { -+ /* do nothing if we get the file name we're already logging to */ -+ return Qtrue; -+ } -+ -+ /* get mode for file opening */ -+ if (mode_str != Qnil) -+ { -+ mode = RSTRING_PTR(StringValue(mode_str)); -+ } -+ -+ /* try to open file in given mode */ -+ if (f = fopen(RSTRING_PTR(filename), mode)) { -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ } -+ gc_data_file = f; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, filename); -+ } else { -+ return Qfalse; -+ } -+ return Qtrue; -+} -+ -+/* -+ * call-seq: -+ * GC.log String => String -+ * -+ * Logs string to the GC data file and returns it. -+ * -+ * GC.log "manual GC call" #=> "manual GC call" -+ * -+ */ -+ -+VALUE -+rb_gc_log(self, original_str) -+ VALUE self, original_str; -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ if (original_str == Qnil) { -+ fprintf(gc_data_file, "\n"); -+ } -+ else { -+ VALUE str = StringValue(original_str); -+ char *p = RSTRING_PTR(str); -+ fprintf(gc_data_file, "%s\n", p); -+ } -+ return original_str; -+} -+ -+/* -+ * call-seq: -+ * GC.dump => nil -+ * -+ * dumps information about the current GC data structures to the GC log file -+ * -+ * GC.dump #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_dump() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ size_t i; -+ -+ for (i = 0; i < heaps_used; i++) { -+ size_t limit = objspace->heap.sorted[i].slot->limit; -+ fprintf(gc_data_file, "HEAP[%2lu]: size=%7lu\n", (unsigned long)i, (unsigned long)limit); -+ } -+ -+ return Qnil; -+} -+ -+static const char* obj_type(VALUE tp); -+ -+#ifdef GC_DEBUG -+/* -+ * call-seq: -+ * GC.dump_file_and_line_info(String, boolean) => nil -+ * -+ * dumps information on which currently allocated object was created by which file and on which line -+ * -+ * GC.dump_file_and_line_info(String, boolean) #=> nil -+ * -+ * The second parameter specifies whether class names should be included in the dump. -+ * Note that including class names will allocate additional string objects on the heap. -+ * -+ */ -+ -+VALUE -+rb_gc_dump_file_and_line_info(int argc, VALUE *argv) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ VALUE filename, str, include_classnames = Qnil; -+ char *fname = NULL; -+ char *klass = NULL; -+ FILE* f = NULL; -+ size_t i = 0; -+ -+ rb_scan_args(argc, argv, "11", &filename, &include_classnames); -+ -+ str = StringValue(filename); -+ fname = RSTRING_PTR(str); -+ f = fopen(fname, "w"); -+ -+ for (i = 0; i < heaps_used; i++) { -+ RVALUE *p, *pend; -+ -+ p = objspace->heap.sorted[i].start; pend = objspace->heap.sorted[i].end; -+ for (;p < pend; p++) { -+ if (p->as.basic.flags) { -+ const char *src_filename = (p->file && p->file != Qnil )? RSTRING_PTR(p->file) : ""; -+ fprintf(f, "%s:%s:%d", obj_type(p->as.basic.flags & T_MASK), src_filename, (int)p->line); -+ // rb_obj_classname will create objects on the heap, we need a better solution -+ if (include_classnames == Qtrue) { -+ /* write the class */ -+ fprintf(f, ":"); -+ switch (BUILTIN_TYPE(p)) { -+ case T_NONE: -+ fprintf(f, "__none__"); -+ break; -+ case T_UNDEF: -+ fprintf(f, "__undef__"); -+ break; -+ case T_NODE: -+ fprintf(f, "__node__"); -+ break; -+ default: -+ if (!p->as.basic.klass) { -+ fprintf(f, "__unknown__"); -+ } else { -+ fprintf(f, "%s", rb_obj_classname((VALUE)p)); -+ } -+ } -+ /* print object size for some known object types */ -+ switch (BUILTIN_TYPE(p)) { -+ case T_STRING: -+ fprintf(f, ":%lu", RSTRING_LEN(p)); -+ break; -+ case T_ARRAY: -+ fprintf(f, ":%lu", RARRAY_LEN(p)); -+ break; -+ case T_HASH: -+ fprintf(f, ":%lu", (long unsigned int)RHASH_SIZE(p)); -+ break; -+ } -+ } -+ fprintf(f, "\n"); -+ } -+ } -+ } -+ fclose(f); -+ return Qnil; -+} -+#endif -+ -+/* -+ * call-seq: -+ * GC.heap_slots => Integer -+ * -+ * Returns the number of heap slots available for object allocations. -+ * -+ * GC.heap_slots #=> 10000 -+ * -+ */ -+VALUE -+rb_gc_heap_slots() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return LONG2NUM(heap_size); -+} -+ -+ -+/* -+ * call-seq: -+ * GC.collections => Integer -+ * -+ * Returns the number of garbage collections performed while GC statistics collection -+ * was enabled. -+ * -+ * GC.collections #=> 35 -+ * -+ */ -+ -+VALUE -+rb_gc_collections() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return LONG2NUM(gc_collections); -+} -+ -+/* -+ * call-seq: -+ * GC.time => Integer -+ * -+ * Returns the time spent during garbage collection while GC statistics collection -+ * was enabled (in micro seconds). -+ * -+ * GC.time #=> 20000 -+ * -+ */ -+ -+VALUE -+rb_gc_time() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return LL2NUM(gc_time_accumulator); -+#else -+ return LONG2NUM(gc_time_accumulator); -+#endif -+} -+ - VALUE rb_mGC; - - void -@@ -1011,6 +1586,12 @@ allocate_sorted_heaps(rb_objspace_t *objspace, size_t next_heaps_length) - static void - assign_heap_slot(rb_objspace_t *objspace) - { -+ /* -+ if (gc_statistics & verbose_gc_stats) { -+ fprintf(gc_data_file, "assigning heap slot\n"); -+ } -+ */ -+ - RVALUE *p, *pend, *membase; - struct heaps_slot *slot; - size_t hi, lo, mid; -@@ -1072,6 +1653,7 @@ assign_heap_slot(rb_objspace_t *objspace) - if (lomem == 0 || lomem > p) lomem = p; - if (himem < pend) himem = pend; - heaps_used++; -+ heap_size += objs; - - while (p < pend) { - p->as.free.flags = 0; -@@ -1127,7 +1709,7 @@ initial_expand_heap(rb_objspace_t *objspace) - static void - set_heaps_increment(rb_objspace_t *objspace) - { -- size_t next_heaps_length = (size_t)(heaps_used * 1.8); -+ size_t next_heaps_length = (size_t)(heaps_used * heap_slots_growth_factor); - - if (next_heaps_length == heaps_used) { - next_heaps_length++; -@@ -1160,6 +1742,22 @@ rb_during_gc(void) - - #define RANY(o) ((RVALUE*)(o)) - -+#ifdef GC_DEBUG -+static VALUE -+_rb_sourcefile(void) -+{ -+ rb_thread_t *th = GET_THREAD(); -+ rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp); -+ -+ if (cfp) { -+ return cfp->iseq->filename; -+ } -+ else { -+ return Qnil; -+ } -+} -+#endif -+ - VALUE - rb_newobj(void) - { -@@ -1191,9 +1789,11 @@ rb_newobj(void) - - MEMZERO((void*)obj, RVALUE, 1); - #ifdef GC_DEBUG -- RANY(obj)->file = rb_sourcefile(); -+ RANY(obj)->file = _rb_sourcefile(); - RANY(obj)->line = rb_sourceline(); - #endif -+ live_objects++; -+ allocated_objects++; - GC_PROF_INC_LIVE_NUM; - - return obj; -@@ -1660,6 +2260,12 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev) - { - register RVALUE *obj = RANY(ptr); - -+#ifdef GC_DEBUG -+ if (obj->file && obj->file != Qnil && is_pointer_to_heap(objspace, (void*)obj->file)) { -+ gc_mark(objspace, obj->file, lev); -+ } -+#endif -+ - goto marking; /* skip */ - - again: -@@ -1670,6 +2276,12 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev) - obj->as.basic.flags |= FL_MARK; - objspace->heap.live_num++; - -+#ifdef GC_DEBUG -+ if (obj->file && obj->file != Qnil && is_pointer_to_heap(objspace, (void*)obj->file)) { -+ gc_mark(objspace, obj->file, lev); -+ } -+#endif -+ - marking: - if (FL_TEST(obj, FL_EXIVAR)) { - rb_mark_generic_ivar(ptr); -@@ -2012,6 +2624,25 @@ free_unused_heaps(rb_objspace_t *objspace) - } - } - -+static inline unsigned long -+elapsed_musecs(struct timeval since) -+{ -+ struct timeval now; -+ struct timeval temp; -+ -+ gettimeofday(&now, NULL); -+ -+ if ((now.tv_usec-since.tv_usec)<0) { -+ temp.tv_sec = now.tv_sec-since.tv_sec-1; -+ temp.tv_usec = 1000000+now.tv_usec-since.tv_usec; -+ } else { -+ temp.tv_sec = now.tv_sec-since.tv_sec; -+ temp.tv_usec = now.tv_usec-since.tv_usec; -+ } -+ -+ return temp.tv_sec*1000000 + temp.tv_usec; -+} -+ - static void - slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - { -@@ -2019,14 +2650,23 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - RVALUE *p, *pend; - RVALUE *free = freelist, *final = deferred_final_list; - int deferred; -+ int do_gc_stats = gc_statistics & verbose_gc_stats; -+ -+ struct timeval tv1; -+ if (gc_statistics) gettimeofday(&tv1, NULL); - - p = sweep_slot->slot; pend = p + sweep_slot->limit; - while (p < pend) { - if (!(p->as.basic.flags & FL_MARK)) { -+ if (do_gc_stats && !p->as.basic.flags) { -+ /* slot was free before GC */ -+ freelist_size++; -+ } - if (p->as.basic.flags && - ((deferred = obj_free(objspace, (VALUE)p)) || - (FL_TEST(p, FL_FINALIZE)))) { - if (!deferred) { -+ if (do_gc_stats) zombies++; - p->as.free.flags = T_ZOMBIE; - RDATA(p)->dfree = 0; - } -@@ -2036,6 +2676,10 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - final_num++; - } - else { -+ if (do_gc_stats) { -+ VALUE obt = p->as.basic.flags & T_MASK; -+ if (obt) free_counts[obt]++; -+ } - add_freelist(objspace, p); - free_num++; - } -@@ -2043,13 +2687,22 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - else if (BUILTIN_TYPE(p) == T_ZOMBIE) { - /* objects to be finalized */ - /* do nothing remain marked */ -+ if (do_gc_stats) zombies++; - } - else { - RBASIC(p)->flags &= ~FL_MARK; -+ if (do_gc_stats) { -+ live_counts[p->as.basic.flags & T_MASK]++; -+ } - } - p++; -+ processed++; - } -- if (final_num + free_num == sweep_slot->limit && -+ -+ freed_objects += free_num; -+ -+ if (objspace->heap.freed_blocks < objspace->heap.max_blocks_to_free && -+ final_num + free_num == sweep_slot->limit && - objspace->heap.free_num > objspace->heap.do_heap_free) { - RVALUE *pp; - -@@ -2060,6 +2713,8 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - sweep_slot->limit = final_num; - freelist = free; /* cancel this page from freelist */ - unlink_heap_slot(objspace, sweep_slot); -+ objspace->heap.freed_blocks += 1; -+ heap_size -= final_num + free_num; - } - else { - objspace->heap.free_num += free_num; -@@ -2072,6 +2727,10 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - RUBY_VM_SET_FINALIZER_INTERRUPT(th); - } - } -+ -+ if (gc_statistics) { -+ gc_time_accumulator += elapsed_musecs(tv1); -+ } - } - - static int -@@ -2092,6 +2751,21 @@ ready_to_gc(rb_objspace_t *objspace) - static void - before_gc_sweep(rb_objspace_t *objspace) - { -+ if (gc_statistics & verbose_gc_stats) { -+ /* -+ fprintf(gc_data_file, "Sweep started\n"); -+ */ -+ freed_objects = 0; -+ processed = 0; -+ zombies = 0; -+ freelist_size = 0; -+ MEMZERO((void*)free_counts, unsigned long, T_MASK+1); -+ MEMZERO((void*)live_counts, unsigned long, T_MASK+1); -+ } -+ -+ objspace->heap.max_blocks_to_free = heaps_used - (heap_min_slots / HEAP_OBJ_LIMIT); -+ objspace->heap.freed_blocks = 0; -+ - freelist = 0; - objspace->heap.do_heap_free = (size_t)((heaps_used * HEAP_OBJ_LIMIT) * 0.65); - objspace->heap.free_min = (size_t)((heaps_used * HEAP_OBJ_LIMIT) * 0.2); -@@ -2111,8 +2785,13 @@ before_gc_sweep(rb_objspace_t *objspace) - static void - after_gc_sweep(rb_objspace_t *objspace) - { -+ int i; -+ struct timeval tv1; -+ - GC_PROF_SET_MALLOC_INFO; - -+ if (gc_statistics) gettimeofday(&tv1, NULL); -+ - if (objspace->heap.free_num < objspace->heap.free_min) { - set_heaps_increment(objspace); - heaps_increment(objspace); -@@ -2125,6 +2804,29 @@ after_gc_sweep(rb_objspace_t *objspace) - malloc_increase = 0; - - free_unused_heaps(objspace); -+ -+ if (gc_statistics) { -+ gc_time_accumulator += elapsed_musecs(tv1); -+ -+ if (verbose_gc_stats) { -+ /* log gc stats if requested */ -+ fprintf(gc_data_file, "GC time: %lu musec\n", (unsigned long)(gc_time_accumulator-gc_time_accumulator_before_gc)); -+ fprintf(gc_data_file, "objects processed: %7lu\n", (unsigned long)processed); -+ fprintf(gc_data_file, "live objects : %7lu\n", (unsigned long)live_after_last_mark_phase); -+ fprintf(gc_data_file, "freelist objects : %7lu\n", (unsigned long)freelist_size); -+ fprintf(gc_data_file, "freed objects : %7lu\n", (unsigned long)freed_objects); -+ fprintf(gc_data_file, "zombies : %7lu\n", (unsigned long)zombies); -+ for(i=0; i0 || live_counts[i]>0) { -+ fprintf(gc_data_file, -+ "kept %7lu / freed %7lu objects of type %s\n", -+ (unsigned long)live_counts[i], (unsigned long)free_counts[i], obj_type((int)i)); -+ } -+ } -+ rb_gc_dump(); -+ fflush(gc_data_file); -+ } -+ } - } - - static int -@@ -2158,9 +2860,11 @@ rest_sweep(rb_objspace_t *objspace) - - static void gc_marks(rb_objspace_t *objspace); - -+/* only called from rb_new_obj */ - static int - gc_lazy_sweep(rb_objspace_t *objspace) - { -+ struct timeval gctv1; - int res; - INIT_GC_PROF_PARAMS; - -@@ -2182,7 +2886,6 @@ gc_lazy_sweep(rb_objspace_t *objspace) - GC_PROF_TIMER_STOP(Qfalse); - return res; - } -- after_gc_sweep(objspace); - } - else { - if (heaps_increment(objspace)) { -@@ -2190,6 +2893,18 @@ gc_lazy_sweep(rb_objspace_t *objspace) - return TRUE; - } - } -+ after_gc_sweep(objspace); -+ -+ if (gc_statistics) { -+ gc_time_accumulator_before_gc = gc_time_accumulator; -+ gc_collections++; -+ gettimeofday(&gctv1, NULL); -+ /* -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "Garbage collection started (gc_lazy_sweep)\n"); -+ } -+ */ -+ } - - gc_marks(objspace); - -@@ -2198,6 +2913,10 @@ gc_lazy_sweep(rb_objspace_t *objspace) - set_heaps_increment(objspace); - } - -+ if (gc_statistics) { -+ gc_time_accumulator += elapsed_musecs(gctv1); -+ } -+ - GC_PROF_SWEEP_TIMER_START; - if(!(res = lazy_sweep(objspace))) { - after_gc_sweep(objspace); -@@ -2209,6 +2928,7 @@ gc_lazy_sweep(rb_objspace_t *objspace) - GC_PROF_SWEEP_TIMER_STOP; - - GC_PROF_TIMER_STOP(Qtrue); -+ - return res; - } - -@@ -2435,9 +3155,15 @@ gc_marks(rb_objspace_t *objspace) - rb_thread_t *th = GET_THREAD(); - GC_PROF_MARK_TIMER_START; - -+ /* -+ if (gc_statistics & verbose_gc_stats) { -+ fprintf(gc_data_file, "Marking objects\n"); -+ } -+ */ -+ - objspace->heap.live_num = 0; - objspace->count++; -- -+ live_objects = 0; - - SET_STACK_END; - -@@ -2477,11 +3203,15 @@ gc_marks(rb_objspace_t *objspace) - } - } - GC_PROF_MARK_TIMER_STOP; -+ -+ live_after_last_mark_phase = objspace->heap.live_num; - } - - static int - garbage_collect(rb_objspace_t *objspace) - { -+ struct timeval gctv1; -+ - INIT_GC_PROF_PARAMS; - - if (GC_NOTIFY) printf("start garbage_collect()\n"); -@@ -2497,15 +3227,31 @@ garbage_collect(rb_objspace_t *objspace) - - rest_sweep(objspace); - -+ if (gc_statistics) { -+ gc_time_accumulator_before_gc = gc_time_accumulator; -+ gc_collections++; -+ gettimeofday(&gctv1, NULL); -+ /* -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "Garbage collection started (garbage_collect)\n"); -+ } -+ */ -+ } -+ - during_gc++; - gc_marks(objspace); - -+ if (gc_statistics) { -+ gc_time_accumulator += elapsed_musecs(gctv1); -+ } -+ - GC_PROF_SWEEP_TIMER_START; - gc_sweep(objspace); - GC_PROF_SWEEP_TIMER_STOP; - - GC_PROF_TIMER_STOP(Qtrue); - if (GC_NOTIFY) printf("end garbage_collect()\n"); -+ - return TRUE; - } - -@@ -2994,6 +3740,39 @@ rb_gc_call_finalizer_at_exit(void) - rb_objspace_call_finalizer(&rb_objspace); - } - -+static const char* obj_type(VALUE type) -+{ -+ switch (type) { -+ case T_NIL : return "NIL"; -+ case T_OBJECT : return "OBJECT"; -+ case T_CLASS : return "CLASS"; -+ case T_ICLASS : return "ICLASS"; -+ case T_MODULE : return "MODULE"; -+ case T_FLOAT : return "FLOAT"; -+ case T_COMPLEX: return "COMPLEX"; -+ case T_RATIONAL: return "RATIONAL"; -+ case T_STRING : return "STRING"; -+ case T_REGEXP : return "REGEXP"; -+ case T_ARRAY : return "ARRAY"; -+ case T_FIXNUM : return "FIXNUM"; -+ case T_HASH : return "HASH"; -+ case T_STRUCT : return "STRUCT"; -+ case T_BIGNUM : return "BIGNUM"; -+ case T_FILE : return "FILE"; -+ -+ case T_TRUE : return "TRUE"; -+ case T_FALSE : return "FALSE"; -+ case T_DATA : return "DATA"; -+ case T_MATCH : return "MATCH"; -+ case T_SYMBOL : return "SYMBOL"; -+ case T_ZOMBIE : return "ZOMBIE"; -+ -+ case T_UNDEF : return "UNDEF"; -+ case T_NODE : return "NODE"; -+ default: return "____"; -+ } -+} -+ - static void - rb_objspace_call_finalizer(rb_objspace_t *objspace) - { -@@ -3307,6 +4086,49 @@ count_objects(int argc, VALUE *argv, VALUE os) - return hash; - } - -+/* call-seq: -+ * ObjectSpace.live_objects => number -+ * -+ * Returns the count of objects currently allocated in the system. This goes -+ * down after the garbage collector runs. -+ */ -+static -+VALUE os_live_objects(VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return ULONG2NUM(live_objects); -+} -+ -+unsigned long rb_os_live_objects() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return live_objects; -+} -+ -+/* call-seq: -+ * ObjectSpace.allocated_objects => number -+ * -+ * Returns the count of objects allocated since the Ruby interpreter has -+ * started. This number can only increase. To know how many objects are -+ * currently allocated, use ObjectSpace::live_objects -+ */ -+static -+VALUE os_allocated_objects(VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if defined(HAVE_LONG_LONG) -+ return ULL2NUM(allocated_objects); -+#else -+ return ULONG2NUM(allocated_objects); -+#endif -+} -+ -+unsigned LONG_LONG rb_os_allocated_objects() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return allocated_objects; -+} -+ - /* - * call-seq: - * GC.count -> Integer -@@ -3599,6 +4421,28 @@ Init_GC(void) - rb_define_singleton_method(rb_mGC, "stat", gc_stat, -1); - rb_define_method(rb_mGC, "garbage_collect", rb_gc_start, 0); - -+ rb_define_singleton_method(rb_mGC, "enable_stats", rb_gc_enable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "disable_stats", rb_gc_disable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "stats_enabled?", rb_gc_stats_enabled, 0); -+ rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0); -+ rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); -+ rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); -+ -+ rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); -+ rb_define_singleton_method(rb_mGC, "log_file", rb_gc_log_file, -1); -+ rb_define_singleton_method(rb_mGC, "enable_trace", rb_gc_enable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "disable_trace", rb_gc_disable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "trace_enabled?", rb_gc_trace_enabled, 0); -+ -+ rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); -+ rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); -+ rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); -+#ifdef GC_DEBUG -+ rb_define_singleton_method(rb_mGC, "dump_file_and_line_info", rb_gc_dump_file_and_line_info, -1); -+#endif -+ - 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); -@@ -3612,6 +4456,9 @@ Init_GC(void) - rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1); - rb_define_module_function(rb_mObSpace, "garbage_collect", rb_gc_start, 0); - -+ rb_define_module_function(rb_mObSpace, "live_objects", os_live_objects, 0); -+ rb_define_module_function(rb_mObSpace, "allocated_objects", os_allocated_objects, 0); -+ - rb_define_module_function(rb_mObSpace, "define_finalizer", define_final, -1); - rb_define_module_function(rb_mObSpace, "undefine_finalizer", undefine_final, 1); - diff --git a/patches/ruby/1.9.3/p125/railsexpress/03-display-more-detailed-stack-trace.patch b/patches/ruby/1.9.3/p125/railsexpress/03-display-more-detailed-stack-trace.patch deleted file mode 100644 index 5c7ad30352..0000000000 --- a/patches/ruby/1.9.3/p125/railsexpress/03-display-more-detailed-stack-trace.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/eval_error.c b/eval_error.c -index fd06adf..69c3b48 100644 ---- a/eval_error.c -+++ b/eval_error.c -@@ -164,8 +164,8 @@ error_print(void) - int skip = eclass == rb_eSysStackError; - - #define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5) --#define TRACE_HEAD 8 --#define TRACE_TAIL 5 -+#define TRACE_HEAD 100 -+#define TRACE_TAIL 100 - - for (i = 1; i < len; i++) { - if (TYPE(ptr[i]) == T_STRING) { diff --git a/patches/ruby/1.9.3/p125/railsexpress/04-fork-support-for-gc-logging.patch b/patches/ruby/1.9.3/p125/railsexpress/04-fork-support-for-gc-logging.patch deleted file mode 100644 index 5228c185bd..0000000000 --- a/patches/ruby/1.9.3/p125/railsexpress/04-fork-support-for-gc-logging.patch +++ /dev/null @@ -1,68 +0,0 @@ -diff --git a/gc.c b/gc.c -index 74ebec6..8e1501e 100644 ---- a/gc.c -+++ b/gc.c -@@ -1326,6 +1326,34 @@ rb_gc_log_file(int argc, VALUE *argv, VALUE self) - } - - /* -+ * Called from process.c before a fork. Flushes the gc log file to -+ * avoid writing the buffered output twice (once in the parent, and -+ * once in the child). -+ */ -+void -+rb_gc_before_fork() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ fflush(gc_data_file); -+} -+ -+/* -+ * Called from process.c after a fork in the child process. Turns off -+ * logging, disables GC stats and resets all gc counters and timing -+ * information. -+ */ -+void -+rb_gc_after_fork() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ rb_gc_disable_stats(); -+ rb_gc_clear_stats(); -+ rb_gc_disable_trace(); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+} -+ -+/* - * call-seq: - * GC.log String => String - * -diff --git a/include/ruby/intern.h b/include/ruby/intern.h -index 50451f3..3988869 100644 ---- a/include/ruby/intern.h -+++ b/include/ruby/intern.h -@@ -431,6 +431,8 @@ void rb_gc_call_finalizer_at_exit(void); - VALUE rb_gc_enable(void); - VALUE rb_gc_disable(void); - VALUE rb_gc_start(void); -+void rb_gc_before_fork _((void)); -+void rb_gc_after_fork _((void)); - #define Init_stack(addr) ruby_init_stack(addr) - void rb_gc_set_params(void); - /* hash.c */ -diff --git a/process.c b/process.c -index 2a16757..8a6013c 100644 ---- a/process.c -+++ b/process.c -@@ -2782,9 +2782,11 @@ rb_f_fork(VALUE obj) - rb_pid_t pid; - - rb_secure(2); -+ rb_gc_before_fork(); - - switch (pid = rb_fork(0, 0, 0, Qnil)) { - case 0: -+ rb_gc_after_fork(); - rb_thread_atfork(); - if (rb_block_given_p()) { - int status; diff --git a/patches/ruby/1.9.3/p125/railsexpress/05-track-live-dataset-size.patch b/patches/ruby/1.9.3/p125/railsexpress/05-track-live-dataset-size.patch deleted file mode 100644 index 4df3c80c40..0000000000 --- a/patches/ruby/1.9.3/p125/railsexpress/05-track-live-dataset-size.patch +++ /dev/null @@ -1,69 +0,0 @@ -diff --git a/gc.c b/gc.c -index 8e1501e..e526125 100644 ---- a/gc.c -+++ b/gc.c -@@ -272,7 +272,6 @@ getrusage_time(void) - #define GC_PROF_DEC_LIVE_NUM - #endif - -- - #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__) - #pragma pack(push, 1) /* magic for reducing sizeof(RVALUE): 24 -> 20 */ - #endif -@@ -403,6 +402,7 @@ typedef struct rb_objspace { - unsigned LONG_LONG gc_num_allocations; - unsigned long live_objects; - unsigned LONG_LONG allocated_objects; -+ unsigned long heap_slots_live_after_last_gc; - } rb_objspace_t; - - #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE -@@ -435,6 +435,7 @@ int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress; - #define gc_num_allocations objspace->gc_num_allocations - #define live_objects objspace->live_objects - #define allocated_objects objspace->allocated_objects -+#define heap_slots_live_after_last_gc objspace->heap_slots_live_after_last_gc - #define finalizer_table objspace->final.table - #define deferred_final_list objspace->final.deferred - #define mark_stack objspace->markstack.buffer -@@ -1543,6 +1544,24 @@ rb_gc_time() - #endif - } - -+/* -+ * call-seq: -+ * GC.heap_slots_live_after_last_gc => Integer -+ * -+ * Returns the number of heap slots which were live after the last garbage collection. -+ * -+ * GC.heap_slots_live_after_last_gc #=> 231223 -+ * -+ */ -+VALUE -+rb_gc_heap_slots_live_after_last_gc() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return ULONG2NUM(heap_slots_live_after_last_gc); -+} -+ -+ -+ - VALUE rb_mGC; - - void -@@ -3233,6 +3252,7 @@ gc_marks(rb_objspace_t *objspace) - GC_PROF_MARK_TIMER_STOP; - - live_after_last_mark_phase = objspace->heap.live_num; -+ heap_slots_live_after_last_gc = objspace->heap.live_num; - } - - static int -@@ -4456,6 +4476,7 @@ Init_GC(void) - rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); - rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); - rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots_live_after_last_gc", rb_gc_heap_slots_live_after_last_gc, 0); - rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); - - rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); diff --git a/patches/ruby/1.9.3/p125/railsexpress/06-export-some-symbols-for-rubyprof.patch b/patches/ruby/1.9.3/p125/railsexpress/06-export-some-symbols-for-rubyprof.patch deleted file mode 100644 index 45c0fd2ebe..0000000000 --- a/patches/ruby/1.9.3/p125/railsexpress/06-export-some-symbols-for-rubyprof.patch +++ /dev/null @@ -1,52 +0,0 @@ -diff --git a/gc.c b/gc.c -index e526125..0a8ee3a 100644 ---- a/gc.c -+++ b/gc.c -@@ -1161,6 +1161,7 @@ rb_gc_clear_stats() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_allocated_size() - { -@@ -1182,6 +1183,7 @@ rb_gc_allocated_size() - * GC.num_allocations #=> 150 - * - */ -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_num_allocations() - { -@@ -1515,6 +1517,7 @@ rb_gc_heap_slots() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_collections() - { -@@ -1533,6 +1536,7 @@ rb_gc_collections() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_time() - { -@@ -4147,6 +4151,7 @@ VALUE os_live_objects(VALUE self) - return ULONG2NUM(live_objects); - } - -+RUBY_FUNC_EXPORTED - unsigned long rb_os_live_objects() - { - rb_objspace_t *objspace = &rb_objspace; -@@ -4171,6 +4176,7 @@ VALUE os_allocated_objects(VALUE self) - #endif - } - -+RUBY_FUNC_EXPORTED - unsigned LONG_LONG rb_os_allocated_objects() - { - rb_objspace_t *objspace = &rb_objspace; diff --git a/patches/ruby/1.9.3/p125/railsexpress/07-revert-f6b49243eb0c21bea1c4198cdd52a549e6ead075.patch b/patches/ruby/1.9.3/p125/railsexpress/07-revert-f6b49243eb0c21bea1c4198cdd52a549e6ead075.patch deleted file mode 100644 index dcb393f3bc..0000000000 --- a/patches/ruby/1.9.3/p125/railsexpress/07-revert-f6b49243eb0c21bea1c4198cdd52a549e6ead075.patch +++ /dev/null @@ -1,24 +0,0 @@ -diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb -index 920caa6..1f94d97 100644 ---- a/ext/openssl/extconf.rb -+++ b/ext/openssl/extconf.rb -@@ -43,14 +43,11 @@ if $mingw - have_library("wsock32") - have_library("gdi32") - end -- --result = pkg_config("openssl") && have_header("openssl/ssl.h") -- --unless result -- result = have_header("openssl/ssl.h") -- result &&= %w[crypto libeay32].any? {|lib| have_library(lib, "OpenSSL_add_all_digests")} -- result &&= %w[ssl ssleay32].any? {|lib| have_library(lib, "SSL_library_init")} -- unless result -+result = have_header("openssl/ssl.h") -+result &&= %w[crypto libeay32].any? {|lib| have_library(lib, "OpenSSL_add_all_digests")} -+result &&= %w[ssl ssleay32].any? {|lib| have_library(lib, "SSL_library_init")} -+if !result -+ unless pkg_config("openssl") and have_header("openssl/ssl.h") - message "=== Checking for required stuff failed. ===\n" - message "Makefile wasn't created. Fix the errors above.\n" - exit 1 diff --git a/patches/ruby/1.9.3/p125/railsexpress/08-backport-c2086cc7ff1142b14c95c.patch b/patches/ruby/1.9.3/p125/railsexpress/08-backport-c2086cc7ff1142b14c95c.patch deleted file mode 100644 index 8d56d06f0d..0000000000 --- a/patches/ruby/1.9.3/p125/railsexpress/08-backport-c2086cc7ff1142b14c95c.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/lib/drb/ssl.rb b/lib/drb/ssl.rb -index 17e2a73..cc81d8c 100644 ---- a/lib/drb/ssl.rb -+++ b/lib/drb/ssl.rb -@@ -54,7 +54,7 @@ module DRb - return - end - -- rsa = OpenSSL::PKey::RSA.new(512){|p, n| -+ rsa = OpenSSL::PKey::RSA.new(1024){|p, n| - next unless self[:verbose] - case p - when 0; $stderr.putc "." # BN_generate_prime diff --git a/patches/ruby/1.9.3/p125/railsexpress/09-webrick_204_304_keep_alive_fix.patch b/patches/ruby/1.9.3/p125/railsexpress/09-webrick_204_304_keep_alive_fix.patch deleted file mode 100644 index 34d9b78133..0000000000 --- a/patches/ruby/1.9.3/p125/railsexpress/09-webrick_204_304_keep_alive_fix.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/lib/webrick/httpresponse.rb b/lib/webrick/httpresponse.rb -index 0d36c07..ce72b3f 100644 ---- a/lib/webrick/httpresponse.rb -+++ b/lib/webrick/httpresponse.rb -@@ -202,7 +202,7 @@ module WEBrick - if @header['connection'] == "close" - @keep_alive = false - elsif keep_alive? -- if chunked? || @header['content-length'] -+ if chunked? || @header['content-length'] || @status == 304 || @status == 204 - @header['connection'] = "Keep-Alive" - else - msg = "Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true" diff --git a/patches/ruby/1.9.3/p194/railsexpress/01-revert-f6b49243eb0c21bea1c4198cdd52a549e6ead075.patch b/patches/ruby/1.9.3/p194/railsexpress/01-revert-f6b49243eb0c21bea1c4198cdd52a549e6ead075.patch deleted file mode 100644 index dcb393f3bc..0000000000 --- a/patches/ruby/1.9.3/p194/railsexpress/01-revert-f6b49243eb0c21bea1c4198cdd52a549e6ead075.patch +++ /dev/null @@ -1,24 +0,0 @@ -diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb -index 920caa6..1f94d97 100644 ---- a/ext/openssl/extconf.rb -+++ b/ext/openssl/extconf.rb -@@ -43,14 +43,11 @@ if $mingw - have_library("wsock32") - have_library("gdi32") - end -- --result = pkg_config("openssl") && have_header("openssl/ssl.h") -- --unless result -- result = have_header("openssl/ssl.h") -- result &&= %w[crypto libeay32].any? {|lib| have_library(lib, "OpenSSL_add_all_digests")} -- result &&= %w[ssl ssleay32].any? {|lib| have_library(lib, "SSL_library_init")} -- unless result -+result = have_header("openssl/ssl.h") -+result &&= %w[crypto libeay32].any? {|lib| have_library(lib, "OpenSSL_add_all_digests")} -+result &&= %w[ssl ssleay32].any? {|lib| have_library(lib, "SSL_library_init")} -+if !result -+ unless pkg_config("openssl") and have_header("openssl/ssl.h") - message "=== Checking for required stuff failed. ===\n" - message "Makefile wasn't created. Fix the errors above.\n" - exit 1 diff --git a/patches/ruby/1.9.3/p194/railsexpress/02-backport-c2086cc7ff1142b14c95c8758af24b8689b78ffc.patch b/patches/ruby/1.9.3/p194/railsexpress/02-backport-c2086cc7ff1142b14c95c8758af24b8689b78ffc.patch deleted file mode 100644 index 8d56d06f0d..0000000000 --- a/patches/ruby/1.9.3/p194/railsexpress/02-backport-c2086cc7ff1142b14c95c8758af24b8689b78ffc.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/lib/drb/ssl.rb b/lib/drb/ssl.rb -index 17e2a73..cc81d8c 100644 ---- a/lib/drb/ssl.rb -+++ b/lib/drb/ssl.rb -@@ -54,7 +54,7 @@ module DRb - return - end - -- rsa = OpenSSL::PKey::RSA.new(512){|p, n| -+ rsa = OpenSSL::PKey::RSA.new(1024){|p, n| - next unless self[:verbose] - case p - when 0; $stderr.putc "." # BN_generate_prime diff --git a/patches/ruby/1.9.3/p194/railsexpress/03-railsbench-gc.patch b/patches/ruby/1.9.3/p194/railsexpress/03-railsbench-gc.patch deleted file mode 100644 index 7cbb240c0c..0000000000 --- a/patches/ruby/1.9.3/p194/railsexpress/03-railsbench-gc.patch +++ /dev/null @@ -1,1241 +0,0 @@ -diff --git a/configure.in b/configure.in -index 6d24689..2e85528 100644 ---- a/configure.in -+++ b/configure.in -@@ -2457,6 +2457,10 @@ if test "$EXEEXT" = .exe; then - AC_SUBST(EXECUTABLE_EXTS) - fi - -+dnl enable gc debugging -+AC_ARG_ENABLE(gcdebug, -+ AS_HELP_STRING([--enable-gcdebug], [build garbage collector with debugging enabled]), -+ [AC_DEFINE(GC_DEBUG,1)]) - dnl } - dnl build section { - -diff --git a/gc.c b/gc.c -index e65d0ec..4f4a9c1 100644 ---- a/gc.c -+++ b/gc.c -@@ -96,6 +96,17 @@ ruby_gc_params_t initial_params = { - #endif - }; - -+#ifndef HAVE_LONG_LONG -+#define LONG_LONG long -+#endif -+ -+static size_t heap_free_min = 4096; -+static int heap_min_slots = 10000; -+static int heap_slots_increment = 10000; -+static int initial_heap_slots_increment = 10000; -+static double heap_slots_growth_factor = 1.8; -+static size_t initial_malloc_limit = GC_MALLOC_LIMIT; -+ - #define nomem_error GET_VM()->special_exceptions[ruby_error_nomemory] - - #define MARK_STACK_MAX 1024 -@@ -291,7 +302,7 @@ typedef struct RVALUE { - struct RComplex complex; - } as; - #ifdef GC_DEBUG -- const char *file; -+ VALUE file; - int line; - #endif - } RVALUE; -@@ -345,11 +356,25 @@ typedef struct rb_objspace { - size_t free_min; - size_t final_num; - size_t do_heap_free; -+ unsigned long max_blocks_to_free; -+ unsigned long freed_blocks; - } heap; - struct { -+ unsigned long processed; -+ unsigned long freed_objects; -+ unsigned long freelist_size; -+ unsigned long zombies; -+ unsigned long free_counts[T_MASK+1]; -+ unsigned long live_counts[T_MASK+1]; -+ unsigned long gc_time_accumulator_before_gc; -+ unsigned long live_after_last_mark_phase; -+ } stats; -+ struct { - int dont_gc; - int dont_lazy_sweep; - int during_gc; -+ int gc_statistics; -+ int verbose_gc_stats; - } flags; - struct { - st_table *table; -@@ -370,6 +395,14 @@ typedef struct rb_objspace { - struct gc_list *global_list; - size_t count; - int gc_stress; -+ long heap_size; -+ unsigned LONG_LONG gc_time_accumulator; -+ FILE* gc_data_file; -+ long gc_collections; -+ unsigned LONG_LONG gc_allocated_size; -+ unsigned LONG_LONG gc_num_allocations; -+ unsigned long live_objects; -+ unsigned LONG_LONG allocated_objects; - } rb_objspace_t; - - #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE -@@ -392,6 +425,16 @@ int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress; - #define heaps_freed objspace->heap.freed - #define dont_gc objspace->flags.dont_gc - #define during_gc objspace->flags.during_gc -+#define gc_statistics objspace->flags.gc_statistics -+#define verbose_gc_stats objspace->flags.verbose_gc_stats -+#define heap_size objspace->heap_size -+#define gc_time_accumulator objspace->gc_time_accumulator -+#define gc_data_file objspace->gc_data_file -+#define gc_collections objspace->gc_collections -+#define gc_allocated_size objspace->gc_allocated_size -+#define gc_num_allocations objspace->gc_num_allocations -+#define live_objects objspace->live_objects -+#define allocated_objects objspace->allocated_objects - #define finalizer_table objspace->final.table - #define deferred_final_list objspace->final.deferred - #define mark_stack objspace->markstack.buffer -@@ -402,6 +445,14 @@ int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress; - #define initial_malloc_limit initial_params.initial_malloc_limit - #define initial_heap_min_slots initial_params.initial_heap_min_slots - #define initial_free_min initial_params.initial_free_min -+#define free_counts objspace->stats.free_counts -+#define live_counts objspace->stats.live_counts -+#define processed objspace->stats.processed -+#define zombies objspace->stats.zombies -+#define freelist_size objspace->stats.freelist_size -+#define freed_objects objspace->stats.freed_objects -+#define gc_time_accumulator_before_gc objspace->stats.gc_time_accumulator_before_gc -+#define live_after_last_mark_phase objspace->stats.live_after_last_mark_phase - - static void rb_objspace_call_finalizer(rb_objspace_t *objspace); - -@@ -423,13 +474,43 @@ static void initial_expand_heap(rb_objspace_t *objspace); - void - rb_gc_set_params(void) - { -- char *malloc_limit_ptr, *heap_min_slots_ptr, *free_min_ptr; -+ char *envp; -+ -+ rb_objspace_t *objspace = &rb_objspace; -+ -+ gc_data_file = stderr; - - if (rb_safe_level() > 0) return; - -- malloc_limit_ptr = getenv("RUBY_GC_MALLOC_LIMIT"); -- if (malloc_limit_ptr != NULL) { -- int malloc_limit_i = atoi(malloc_limit_ptr); -+ envp = getenv("RUBY_GC_STATS"); -+ if (envp != NULL) { -+ int i = atoi(envp); -+ if (i > 0) { -+ verbose_gc_stats = 1; -+ } -+ /* child processes should not inherit RUBY_GC_STATS */ -+ ruby_unsetenv("RUBY_GC_STATS"); -+ } -+ -+ envp = getenv("RUBY_GC_DATA_FILE"); -+ if (envp != NULL) { -+ FILE* data_file = fopen(envp, "w"); -+ if (data_file != NULL) { -+ gc_data_file = data_file; -+ } -+ else { -+ fprintf(stderr, "can't open gc log file %s for writing, using default\n", envp); -+ } -+ /* child processes should not inherit RUBY_GC_DATA_FILE to avoid clobbering */ -+ ruby_unsetenv("RUBY_GC_DATA_FILE"); -+ } -+ -+ envp = getenv("RUBY_GC_MALLOC_LIMIT"); -+ if (envp != NULL) { -+ int malloc_limit_i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_GC_MALLOC_LIMIT=%s\n", envp); -+ } - if (RTEST(ruby_verbose)) - fprintf(stderr, "malloc_limit=%d (%d)\n", - malloc_limit_i, initial_malloc_limit); -@@ -438,9 +519,12 @@ rb_gc_set_params(void) - } - } - -- heap_min_slots_ptr = getenv("RUBY_HEAP_MIN_SLOTS"); -- if (heap_min_slots_ptr != NULL) { -- int heap_min_slots_i = atoi(heap_min_slots_ptr); -+ envp = getenv("RUBY_HEAP_MIN_SLOTS"); -+ if (envp != NULL) { -+ int heap_min_slots_i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_MIN_SLOTS=%s\n", envp); -+ } - if (RTEST(ruby_verbose)) - fprintf(stderr, "heap_min_slots=%d (%d)\n", - heap_min_slots_i, initial_heap_min_slots); -@@ -450,15 +534,42 @@ rb_gc_set_params(void) - } - } - -- free_min_ptr = getenv("RUBY_FREE_MIN"); -- if (free_min_ptr != NULL) { -- int free_min_i = atoi(free_min_ptr); -+ if (!(envp = getenv("RUBY_FREE_MIN"))) -+ envp = getenv("RUBY_HEAP_FREE_MIN"); -+ if (envp != NULL) { -+ int free_min_i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_FREE_MIN=%s\n", envp); -+ } - if (RTEST(ruby_verbose)) - fprintf(stderr, "free_min=%d (%d)\n", free_min_i, initial_free_min); - if (free_min_i > 0) { - initial_free_min = free_min_i; - } - } -+ -+ envp = getenv("RUBY_HEAP_SLOTS_INCREMENT"); -+ if (envp != NULL) { -+ int i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_INCREMENT=%s\n", envp); -+ } -+ heap_slots_increment = i; -+ initial_heap_slots_increment = heap_slots_increment; -+ } -+ -+ envp = getenv("RUBY_HEAP_SLOTS_GROWTH_FACTOR"); -+ if (envp != NULL) { -+ double d = atof(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_GROWTH_FACTOR=%s\n", envp); -+ } -+ if (d > 0) { -+ heap_slots_growth_factor = d; -+ } -+ } -+ -+ fflush(gc_data_file); - } - - #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE -@@ -753,6 +864,11 @@ vm_malloc_fixup(rb_objspace_t *objspace, void *mem, size_t size) - mem = (size_t *)mem + 1; - #endif - -+ if (gc_statistics) { -+ gc_allocated_size += size; -+ gc_num_allocations += 1; -+ } -+ - return mem; - } - -@@ -813,6 +929,13 @@ vm_xrealloc(rb_objspace_t *objspace, void *ptr, size_t size) - mem = (size_t *)mem + 1; - #endif - -+ /* TODO: we can't count correctly unless we store old size on heap -+ if (gc_statistics) { -+ gc_allocated_size += size; -+ gc_num_allocations += 1; -+ } -+ */ -+ - return mem; - } - -@@ -894,7 +1017,6 @@ ruby_xfree(void *x) - vm_xfree(&rb_objspace, x); - } - -- - /* - * call-seq: - * GC.enable -> true or false -@@ -940,6 +1062,460 @@ rb_gc_disable(void) - return old ? Qtrue : Qfalse; - } - -+/* -+ * call-seq: -+ * GC.enable_stats => true or false -+ * -+ * Enables garbage collection statistics, returning true if garbage -+ * collection statistics was already enabled. -+ * -+ * GC.enable_stats #=> false or true -+ * GC.enable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = gc_statistics; -+ gc_statistics = 1; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_stats => true or false -+ * -+ * Disables garbage collection statistics, returning true if garbage -+ * collection statistics was already disabled. -+ * -+ * GC.disable_stats #=> false or true -+ * GC.disable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = gc_statistics; -+ gc_statistics = 0; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.stats_enabled? => true or false -+ * -+ * Check whether GC stats have been enabled. -+ * -+ * GC.stats_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_stats_enabled() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return gc_statistics ? Qtrue : Qfalse; -+} -+ -+ -+/* -+ * call-seq: -+ * GC.clear_stats => nil -+ * -+ * Clears garbage collection statistics, returning nil. This resets the number -+ * of collections (GC.collections) and the time used (GC.time) to 0. -+ * -+ * GC.clear_stats #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_clear_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ gc_collections = 0; -+ gc_time_accumulator = 0; -+ gc_time_accumulator_before_gc = 0; -+ gc_allocated_size = 0; -+ gc_num_allocations = 0; -+ return Qnil; -+} -+ -+/* -+ * call-seq: -+ * GC.allocated_size => Integer -+ * -+ * Returns the size of memory (in bytes) allocated since GC statistics collection -+ * was enabled. -+ * -+ * GC.allocated_size #=> 35 -+ * -+ */ -+ -+RUBY_FUNC_EXPORTED -+VALUE -+rb_gc_allocated_size() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_allocated_size); -+#else -+ return ULONG2NUM(gc_allocated_size); -+#endif -+} -+ -+/* -+ * call-seq: -+ * GC.num_allocations => Integer -+ * -+ * Returns the number of memory allocations since GC statistics collection -+ * was enabled. -+ * -+ * GC.num_allocations #=> 150 -+ * -+ */ -+ -+RUBY_FUNC_EXPORTED -+VALUE -+rb_gc_num_allocations() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_num_allocations); -+#else -+ return ULONG2NUM(gc_num_allocations); -+#endif -+} -+ -+/* -+ * call-seq: -+ * GC.enable_trace => true or false -+ * -+ * Enables garbage collection tracing, returning true if garbage -+ * collection tracing was already enabled. -+ * -+ * GC.enable_trace #=> false or true -+ * GC.enable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_trace() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = verbose_gc_stats; -+ verbose_gc_stats = 1; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_trace => true or false -+ * -+ * Disables garbage collection tracing, returning true if garbage -+ * collection tracing was already disabled. -+ * -+ * GC.disable_trace #=> false or true -+ * GC.disable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_trace() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = verbose_gc_stats; -+ verbose_gc_stats = 0; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.trace_enabled? => true or false -+ * -+ * Check whether GC tracing has been enabled. -+ * -+ * GC.trace_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_trace_enabled() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return verbose_gc_stats ? Qtrue : Qfalse; -+} -+ -+ -+const char* GC_LOGFILE_IVAR = "@gc_logfile_name"; -+ -+/* -+ * call-seq: -+ * GC.log_file(filename=nil, mode="w") => boolean -+ * -+ * Changes the GC data log file. Closes the currently open logfile. -+ * Returns true if the file was successfully opened for -+ * writing. Returns false if the file could not be opened for -+ * writing. Returns the name of the current logfile (or nil) if no -+ * parameter is given. Restores logging to stderr when given nil as -+ * an argument. -+ * -+ * GC.log_file #=> nil -+ * GC.log_file "/tmp/gc.log" #=> true -+ * GC.log_file #=> "/tmp/gc.log" -+ * GC.log_file nil #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_log_file(int argc, VALUE *argv, VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ VALUE filename = Qnil; -+ VALUE mode_str = Qnil; -+ FILE* f = NULL; -+ const char* mode = "w"; -+ -+ VALUE current_logfile_name = rb_iv_get(rb_mGC, GC_LOGFILE_IVAR); -+ -+ if (argc==0) -+ return current_logfile_name; -+ -+ rb_scan_args(argc, argv, "02", &filename, &mode_str); -+ -+ if (filename == Qnil) { -+ /* close current logfile and reset logfile to stderr */ -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+ } -+ return Qtrue; -+ } -+ -+ /* we have a real logfile name */ -+ filename = StringValue(filename); -+ -+ if (rb_equal(current_logfile_name, filename) == Qtrue) { -+ /* do nothing if we get the file name we're already logging to */ -+ return Qtrue; -+ } -+ -+ /* get mode for file opening */ -+ if (mode_str != Qnil) -+ { -+ mode = RSTRING_PTR(StringValue(mode_str)); -+ } -+ -+ /* try to open file in given mode */ -+ if (f = fopen(RSTRING_PTR(filename), mode)) { -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ } -+ gc_data_file = f; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, filename); -+ } else { -+ return Qfalse; -+ } -+ return Qtrue; -+} -+ -+/* -+ * call-seq: -+ * GC.log String => String -+ * -+ * Logs string to the GC data file and returns it. -+ * -+ * GC.log "manual GC call" #=> "manual GC call" -+ * -+ */ -+ -+VALUE -+rb_gc_log(self, original_str) -+ VALUE self, original_str; -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ if (original_str == Qnil) { -+ fprintf(gc_data_file, "\n"); -+ } -+ else { -+ VALUE str = StringValue(original_str); -+ char *p = RSTRING_PTR(str); -+ fprintf(gc_data_file, "%s\n", p); -+ } -+ return original_str; -+} -+ -+/* -+ * call-seq: -+ * GC.dump => nil -+ * -+ * dumps information about the current GC data structures to the GC log file -+ * -+ * GC.dump #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_dump() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ size_t i; -+ -+ for (i = 0; i < heaps_used; i++) { -+ size_t limit = objspace->heap.sorted[i].slot->limit; -+ fprintf(gc_data_file, "HEAP[%2lu]: size=%7lu\n", (unsigned long)i, (unsigned long)limit); -+ } -+ -+ return Qnil; -+} -+ -+static const char* obj_type(VALUE tp); -+ -+#ifdef GC_DEBUG -+/* -+ * call-seq: -+ * GC.dump_file_and_line_info(String, boolean) => nil -+ * -+ * dumps information on which currently allocated object was created by which file and on which line -+ * -+ * GC.dump_file_and_line_info(String, boolean) #=> nil -+ * -+ * The second parameter specifies whether class names should be included in the dump. -+ * Note that including class names will allocate additional string objects on the heap. -+ * -+ */ -+ -+VALUE -+rb_gc_dump_file_and_line_info(int argc, VALUE *argv) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ VALUE filename, str, include_classnames = Qnil; -+ char *fname = NULL; -+ char *klass = NULL; -+ FILE* f = NULL; -+ size_t i = 0; -+ -+ rb_scan_args(argc, argv, "11", &filename, &include_classnames); -+ -+ str = StringValue(filename); -+ fname = RSTRING_PTR(str); -+ f = fopen(fname, "w"); -+ -+ for (i = 0; i < heaps_used; i++) { -+ RVALUE *p, *pend; -+ -+ p = objspace->heap.sorted[i].start; pend = objspace->heap.sorted[i].end; -+ for (;p < pend; p++) { -+ if (p->as.basic.flags) { -+ const char *src_filename = (p->file && p->file != Qnil )? RSTRING_PTR(p->file) : ""; -+ fprintf(f, "%s:%s:%d", obj_type(p->as.basic.flags & T_MASK), src_filename, (int)p->line); -+ // rb_obj_classname will create objects on the heap, we need a better solution -+ if (include_classnames == Qtrue) { -+ /* write the class */ -+ fprintf(f, ":"); -+ switch (BUILTIN_TYPE(p)) { -+ case T_NONE: -+ fprintf(f, "__none__"); -+ break; -+ case T_UNDEF: -+ fprintf(f, "__undef__"); -+ break; -+ case T_NODE: -+ fprintf(f, "__node__"); -+ break; -+ default: -+ if (!p->as.basic.klass) { -+ fprintf(f, "__unknown__"); -+ } else { -+ fprintf(f, "%s", rb_obj_classname((VALUE)p)); -+ } -+ } -+ /* print object size for some known object types */ -+ switch (BUILTIN_TYPE(p)) { -+ case T_STRING: -+ fprintf(f, ":%lu", RSTRING_LEN(p)); -+ break; -+ case T_ARRAY: -+ fprintf(f, ":%lu", RARRAY_LEN(p)); -+ break; -+ case T_HASH: -+ fprintf(f, ":%lu", (long unsigned int)RHASH_SIZE(p)); -+ break; -+ } -+ } -+ fprintf(f, "\n"); -+ } -+ } -+ } -+ fclose(f); -+ return Qnil; -+} -+#endif -+ -+/* -+ * call-seq: -+ * GC.heap_slots => Integer -+ * -+ * Returns the number of heap slots available for object allocations. -+ * -+ * GC.heap_slots #=> 10000 -+ * -+ */ -+VALUE -+rb_gc_heap_slots() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return LONG2NUM(heap_size); -+} -+ -+ -+/* -+ * call-seq: -+ * GC.collections => Integer -+ * -+ * Returns the number of garbage collections performed while GC statistics collection -+ * was enabled. -+ * -+ * GC.collections #=> 35 -+ * -+ */ -+ -+RUBY_FUNC_EXPORTED -+VALUE -+rb_gc_collections() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return LONG2NUM(gc_collections); -+} -+ -+/* -+ * call-seq: -+ * GC.time => Integer -+ * -+ * Returns the time spent during garbage collection while GC statistics collection -+ * was enabled (in micro seconds). -+ * -+ * GC.time #=> 20000 -+ * -+ */ -+ -+RUBY_FUNC_EXPORTED -+VALUE -+rb_gc_time() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return LL2NUM(gc_time_accumulator); -+#else -+ return LONG2NUM(gc_time_accumulator); -+#endif -+} -+ - VALUE rb_mGC; - - void -@@ -1011,6 +1587,12 @@ allocate_sorted_heaps(rb_objspace_t *objspace, size_t next_heaps_length) - static void - assign_heap_slot(rb_objspace_t *objspace) - { -+ /* -+ if (gc_statistics & verbose_gc_stats) { -+ fprintf(gc_data_file, "assigning heap slot\n"); -+ } -+ */ -+ - RVALUE *p, *pend, *membase; - struct heaps_slot *slot; - size_t hi, lo, mid; -@@ -1072,6 +1654,7 @@ assign_heap_slot(rb_objspace_t *objspace) - if (lomem == 0 || lomem > p) lomem = p; - if (himem < pend) himem = pend; - heaps_used++; -+ heap_size += objs; - - while (p < pend) { - p->as.free.flags = 0; -@@ -1127,7 +1710,7 @@ initial_expand_heap(rb_objspace_t *objspace) - static void - set_heaps_increment(rb_objspace_t *objspace) - { -- size_t next_heaps_length = (size_t)(heaps_used * 1.8); -+ size_t next_heaps_length = (size_t)(heaps_used * heap_slots_growth_factor); - - if (next_heaps_length == heaps_used) { - next_heaps_length++; -@@ -1160,6 +1743,22 @@ rb_during_gc(void) - - #define RANY(o) ((RVALUE*)(o)) - -+#ifdef GC_DEBUG -+static VALUE -+_rb_sourcefile(void) -+{ -+ rb_thread_t *th = GET_THREAD(); -+ rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp); -+ -+ if (cfp) { -+ return cfp->iseq->filename; -+ } -+ else { -+ return Qnil; -+ } -+} -+#endif -+ - VALUE - rb_newobj(void) - { -@@ -1191,9 +1790,11 @@ rb_newobj(void) - - MEMZERO((void*)obj, RVALUE, 1); - #ifdef GC_DEBUG -- RANY(obj)->file = rb_sourcefile(); -+ RANY(obj)->file = _rb_sourcefile(); - RANY(obj)->line = rb_sourceline(); - #endif -+ live_objects++; -+ allocated_objects++; - GC_PROF_INC_LIVE_NUM; - - return obj; -@@ -1660,6 +2261,12 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev) - { - register RVALUE *obj = RANY(ptr); - -+#ifdef GC_DEBUG -+ if (obj->file && obj->file != Qnil && is_pointer_to_heap(objspace, (void*)obj->file)) { -+ gc_mark(objspace, obj->file, lev); -+ } -+#endif -+ - goto marking; /* skip */ - - again: -@@ -1670,6 +2277,12 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev) - obj->as.basic.flags |= FL_MARK; - objspace->heap.live_num++; - -+#ifdef GC_DEBUG -+ if (obj->file && obj->file != Qnil && is_pointer_to_heap(objspace, (void*)obj->file)) { -+ gc_mark(objspace, obj->file, lev); -+ } -+#endif -+ - marking: - if (FL_TEST(obj, FL_EXIVAR)) { - rb_mark_generic_ivar(ptr); -@@ -2012,6 +2625,25 @@ free_unused_heaps(rb_objspace_t *objspace) - } - } - -+static inline unsigned long -+elapsed_musecs(struct timeval since) -+{ -+ struct timeval now; -+ struct timeval temp; -+ -+ gettimeofday(&now, NULL); -+ -+ if ((now.tv_usec-since.tv_usec)<0) { -+ temp.tv_sec = now.tv_sec-since.tv_sec-1; -+ temp.tv_usec = 1000000+now.tv_usec-since.tv_usec; -+ } else { -+ temp.tv_sec = now.tv_sec-since.tv_sec; -+ temp.tv_usec = now.tv_usec-since.tv_usec; -+ } -+ -+ return temp.tv_sec*1000000 + temp.tv_usec; -+} -+ - static void - slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - { -@@ -2019,14 +2651,23 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - RVALUE *p, *pend; - RVALUE *free = freelist, *final = deferred_final_list; - int deferred; -+ int do_gc_stats = gc_statistics & verbose_gc_stats; -+ -+ struct timeval tv1; -+ if (gc_statistics) gettimeofday(&tv1, NULL); - - p = sweep_slot->slot; pend = p + sweep_slot->limit; - while (p < pend) { - if (!(p->as.basic.flags & FL_MARK)) { -+ if (do_gc_stats && !p->as.basic.flags) { -+ /* slot was free before GC */ -+ freelist_size++; -+ } - if (p->as.basic.flags && - ((deferred = obj_free(objspace, (VALUE)p)) || - (FL_TEST(p, FL_FINALIZE)))) { - if (!deferred) { -+ if (do_gc_stats) zombies++; - p->as.free.flags = T_ZOMBIE; - RDATA(p)->dfree = 0; - } -@@ -2036,6 +2677,10 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - final_num++; - } - else { -+ if (do_gc_stats) { -+ VALUE obt = p->as.basic.flags & T_MASK; -+ if (obt) free_counts[obt]++; -+ } - add_freelist(objspace, p); - free_num++; - } -@@ -2043,13 +2688,22 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - else if (BUILTIN_TYPE(p) == T_ZOMBIE) { - /* objects to be finalized */ - /* do nothing remain marked */ -+ if (do_gc_stats) zombies++; - } - else { - RBASIC(p)->flags &= ~FL_MARK; -+ if (do_gc_stats) { -+ live_counts[p->as.basic.flags & T_MASK]++; -+ } - } - p++; -+ processed++; - } -- if (final_num + free_num == sweep_slot->limit && -+ -+ freed_objects += free_num; -+ -+ if (objspace->heap.freed_blocks < objspace->heap.max_blocks_to_free && -+ final_num + free_num == sweep_slot->limit && - objspace->heap.free_num > objspace->heap.do_heap_free) { - RVALUE *pp; - -@@ -2060,6 +2714,8 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - sweep_slot->limit = final_num; - freelist = free; /* cancel this page from freelist */ - unlink_heap_slot(objspace, sweep_slot); -+ objspace->heap.freed_blocks += 1; -+ heap_size -= final_num + free_num; - } - else { - objspace->heap.free_num += free_num; -@@ -2072,6 +2728,10 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - RUBY_VM_SET_FINALIZER_INTERRUPT(th); - } - } -+ -+ if (gc_statistics) { -+ gc_time_accumulator += elapsed_musecs(tv1); -+ } - } - - static int -@@ -2092,6 +2752,21 @@ ready_to_gc(rb_objspace_t *objspace) - static void - before_gc_sweep(rb_objspace_t *objspace) - { -+ if (gc_statistics & verbose_gc_stats) { -+ /* -+ fprintf(gc_data_file, "Sweep started\n"); -+ */ -+ freed_objects = 0; -+ processed = 0; -+ zombies = 0; -+ freelist_size = 0; -+ MEMZERO((void*)free_counts, unsigned long, T_MASK+1); -+ MEMZERO((void*)live_counts, unsigned long, T_MASK+1); -+ } -+ -+ objspace->heap.max_blocks_to_free = heaps_used - (heap_min_slots / HEAP_OBJ_LIMIT); -+ objspace->heap.freed_blocks = 0; -+ - freelist = 0; - objspace->heap.do_heap_free = (size_t)((heaps_used * HEAP_OBJ_LIMIT) * 0.65); - objspace->heap.free_min = (size_t)((heaps_used * HEAP_OBJ_LIMIT) * 0.2); -@@ -2111,8 +2786,13 @@ before_gc_sweep(rb_objspace_t *objspace) - static void - after_gc_sweep(rb_objspace_t *objspace) - { -+ int i; -+ struct timeval tv1; -+ - GC_PROF_SET_MALLOC_INFO; - -+ if (gc_statistics) gettimeofday(&tv1, NULL); -+ - if (objspace->heap.free_num < objspace->heap.free_min) { - set_heaps_increment(objspace); - heaps_increment(objspace); -@@ -2125,6 +2805,29 @@ after_gc_sweep(rb_objspace_t *objspace) - malloc_increase = 0; - - free_unused_heaps(objspace); -+ -+ if (gc_statistics) { -+ gc_time_accumulator += elapsed_musecs(tv1); -+ -+ if (verbose_gc_stats) { -+ /* log gc stats if requested */ -+ fprintf(gc_data_file, "GC time: %lu musec\n", (unsigned long)(gc_time_accumulator-gc_time_accumulator_before_gc)); -+ fprintf(gc_data_file, "objects processed: %7lu\n", (unsigned long)processed); -+ fprintf(gc_data_file, "live objects : %7lu\n", (unsigned long)live_after_last_mark_phase); -+ fprintf(gc_data_file, "freelist objects : %7lu\n", (unsigned long)freelist_size); -+ fprintf(gc_data_file, "freed objects : %7lu\n", (unsigned long)freed_objects); -+ fprintf(gc_data_file, "zombies : %7lu\n", (unsigned long)zombies); -+ for(i=0; i0 || live_counts[i]>0) { -+ fprintf(gc_data_file, -+ "kept %7lu / freed %7lu objects of type %s\n", -+ (unsigned long)live_counts[i], (unsigned long)free_counts[i], obj_type((int)i)); -+ } -+ } -+ rb_gc_dump(); -+ fflush(gc_data_file); -+ } -+ } - } - - static int -@@ -2158,9 +2861,11 @@ rest_sweep(rb_objspace_t *objspace) - - static void gc_marks(rb_objspace_t *objspace); - -+/* only called from rb_new_obj */ - static int - gc_lazy_sweep(rb_objspace_t *objspace) - { -+ struct timeval gctv1; - int res; - INIT_GC_PROF_PARAMS; - -@@ -2182,7 +2887,6 @@ gc_lazy_sweep(rb_objspace_t *objspace) - GC_PROF_TIMER_STOP(Qfalse); - return res; - } -- after_gc_sweep(objspace); - } - else { - if (heaps_increment(objspace)) { -@@ -2190,6 +2894,18 @@ gc_lazy_sweep(rb_objspace_t *objspace) - return TRUE; - } - } -+ after_gc_sweep(objspace); -+ -+ if (gc_statistics) { -+ gc_time_accumulator_before_gc = gc_time_accumulator; -+ gc_collections++; -+ gettimeofday(&gctv1, NULL); -+ /* -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "Garbage collection started (gc_lazy_sweep)\n"); -+ } -+ */ -+ } - - gc_marks(objspace); - -@@ -2198,6 +2914,10 @@ gc_lazy_sweep(rb_objspace_t *objspace) - set_heaps_increment(objspace); - } - -+ if (gc_statistics) { -+ gc_time_accumulator += elapsed_musecs(gctv1); -+ } -+ - GC_PROF_SWEEP_TIMER_START; - if(!(res = lazy_sweep(objspace))) { - after_gc_sweep(objspace); -@@ -2209,6 +2929,7 @@ gc_lazy_sweep(rb_objspace_t *objspace) - GC_PROF_SWEEP_TIMER_STOP; - - GC_PROF_TIMER_STOP(Qtrue); -+ - return res; - } - -@@ -2435,9 +3156,15 @@ gc_marks(rb_objspace_t *objspace) - rb_thread_t *th = GET_THREAD(); - GC_PROF_MARK_TIMER_START; - -+ /* -+ if (gc_statistics & verbose_gc_stats) { -+ fprintf(gc_data_file, "Marking objects\n"); -+ } -+ */ -+ - objspace->heap.live_num = 0; - objspace->count++; -- -+ live_objects = 0; - - SET_STACK_END; - -@@ -2477,11 +3204,15 @@ gc_marks(rb_objspace_t *objspace) - } - } - GC_PROF_MARK_TIMER_STOP; -+ -+ live_after_last_mark_phase = objspace->heap.live_num; - } - - static int - garbage_collect(rb_objspace_t *objspace) - { -+ struct timeval gctv1; -+ - INIT_GC_PROF_PARAMS; - - if (GC_NOTIFY) printf("start garbage_collect()\n"); -@@ -2497,15 +3228,31 @@ garbage_collect(rb_objspace_t *objspace) - - rest_sweep(objspace); - -+ if (gc_statistics) { -+ gc_time_accumulator_before_gc = gc_time_accumulator; -+ gc_collections++; -+ gettimeofday(&gctv1, NULL); -+ /* -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "Garbage collection started (garbage_collect)\n"); -+ } -+ */ -+ } -+ - during_gc++; - gc_marks(objspace); - -+ if (gc_statistics) { -+ gc_time_accumulator += elapsed_musecs(gctv1); -+ } -+ - GC_PROF_SWEEP_TIMER_START; - gc_sweep(objspace); - GC_PROF_SWEEP_TIMER_STOP; - - GC_PROF_TIMER_STOP(Qtrue); - if (GC_NOTIFY) printf("end garbage_collect()\n"); -+ - return TRUE; - } - -@@ -2994,6 +3741,39 @@ rb_gc_call_finalizer_at_exit(void) - rb_objspace_call_finalizer(&rb_objspace); - } - -+static const char* obj_type(VALUE type) -+{ -+ switch (type) { -+ case T_NIL : return "NIL"; -+ case T_OBJECT : return "OBJECT"; -+ case T_CLASS : return "CLASS"; -+ case T_ICLASS : return "ICLASS"; -+ case T_MODULE : return "MODULE"; -+ case T_FLOAT : return "FLOAT"; -+ case T_COMPLEX: return "COMPLEX"; -+ case T_RATIONAL: return "RATIONAL"; -+ case T_STRING : return "STRING"; -+ case T_REGEXP : return "REGEXP"; -+ case T_ARRAY : return "ARRAY"; -+ case T_FIXNUM : return "FIXNUM"; -+ case T_HASH : return "HASH"; -+ case T_STRUCT : return "STRUCT"; -+ case T_BIGNUM : return "BIGNUM"; -+ case T_FILE : return "FILE"; -+ -+ case T_TRUE : return "TRUE"; -+ case T_FALSE : return "FALSE"; -+ case T_DATA : return "DATA"; -+ case T_MATCH : return "MATCH"; -+ case T_SYMBOL : return "SYMBOL"; -+ case T_ZOMBIE : return "ZOMBIE"; -+ -+ case T_UNDEF : return "UNDEF"; -+ case T_NODE : return "NODE"; -+ default: return "____"; -+ } -+} -+ - static void - rb_objspace_call_finalizer(rb_objspace_t *objspace) - { -@@ -3307,6 +4087,51 @@ count_objects(int argc, VALUE *argv, VALUE os) - return hash; - } - -+/* call-seq: -+ * ObjectSpace.live_objects => number -+ * -+ * Returns the count of objects currently allocated in the system. This goes -+ * down after the garbage collector runs. -+ */ -+static -+VALUE os_live_objects(VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return ULONG2NUM(live_objects); -+} -+ -+RUBY_FUNC_EXPORTED -+unsigned long rb_os_live_objects() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return live_objects; -+} -+ -+/* call-seq: -+ * ObjectSpace.allocated_objects => number -+ * -+ * Returns the count of objects allocated since the Ruby interpreter has -+ * started. This number can only increase. To know how many objects are -+ * currently allocated, use ObjectSpace::live_objects -+ */ -+static -+VALUE os_allocated_objects(VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if defined(HAVE_LONG_LONG) -+ return ULL2NUM(allocated_objects); -+#else -+ return ULONG2NUM(allocated_objects); -+#endif -+} -+ -+RUBY_FUNC_EXPORTED -+unsigned LONG_LONG rb_os_allocated_objects() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return allocated_objects; -+} -+ - /* - * call-seq: - * GC.count -> Integer -@@ -3599,6 +4424,28 @@ Init_GC(void) - rb_define_singleton_method(rb_mGC, "stat", gc_stat, -1); - rb_define_method(rb_mGC, "garbage_collect", rb_gc_start, 0); - -+ rb_define_singleton_method(rb_mGC, "enable_stats", rb_gc_enable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "disable_stats", rb_gc_disable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "stats_enabled?", rb_gc_stats_enabled, 0); -+ rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0); -+ rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); -+ rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); -+ -+ rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); -+ rb_define_singleton_method(rb_mGC, "log_file", rb_gc_log_file, -1); -+ rb_define_singleton_method(rb_mGC, "enable_trace", rb_gc_enable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "disable_trace", rb_gc_disable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "trace_enabled?", rb_gc_trace_enabled, 0); -+ -+ rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); -+ rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); -+ rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); -+#ifdef GC_DEBUG -+ rb_define_singleton_method(rb_mGC, "dump_file_and_line_info", rb_gc_dump_file_and_line_info, -1); -+#endif -+ - 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); -@@ -3612,6 +4459,9 @@ Init_GC(void) - rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1); - rb_define_module_function(rb_mObSpace, "garbage_collect", rb_gc_start, 0); - -+ rb_define_module_function(rb_mObSpace, "live_objects", os_live_objects, 0); -+ rb_define_module_function(rb_mObSpace, "allocated_objects", os_allocated_objects, 0); -+ - rb_define_module_function(rb_mObSpace, "define_finalizer", define_final, -1); - rb_define_module_function(rb_mObSpace, "undefine_finalizer", undefine_final, 1); - diff --git a/patches/ruby/1.9.3/p194/railsexpress/04-display-more-detailed-stack-trace.patch b/patches/ruby/1.9.3/p194/railsexpress/04-display-more-detailed-stack-trace.patch deleted file mode 100644 index 5c7ad30352..0000000000 --- a/patches/ruby/1.9.3/p194/railsexpress/04-display-more-detailed-stack-trace.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/eval_error.c b/eval_error.c -index fd06adf..69c3b48 100644 ---- a/eval_error.c -+++ b/eval_error.c -@@ -164,8 +164,8 @@ error_print(void) - int skip = eclass == rb_eSysStackError; - - #define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5) --#define TRACE_HEAD 8 --#define TRACE_TAIL 5 -+#define TRACE_HEAD 100 -+#define TRACE_TAIL 100 - - for (i = 1; i < len; i++) { - if (TYPE(ptr[i]) == T_STRING) { diff --git a/patches/ruby/1.9.3/p194/railsexpress/05-fork-support-for-gc-logging.patch b/patches/ruby/1.9.3/p194/railsexpress/05-fork-support-for-gc-logging.patch deleted file mode 100644 index b525e54fd8..0000000000 --- a/patches/ruby/1.9.3/p194/railsexpress/05-fork-support-for-gc-logging.patch +++ /dev/null @@ -1,68 +0,0 @@ -diff --git a/gc.c b/gc.c -index 4f4a9c1..7c6e443 100644 ---- a/gc.c -+++ b/gc.c -@@ -1325,6 +1325,34 @@ rb_gc_log_file(int argc, VALUE *argv, VALUE self) - } - - /* -+ * Called from process.c before a fork. Flushes the gc log file to -+ * avoid writing the buffered output twice (once in the parent, and -+ * once in the child). -+ */ -+void -+rb_gc_before_fork() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ fflush(gc_data_file); -+} -+ -+/* -+ * Called from process.c after a fork in the child process. Turns off -+ * logging, disables GC stats and resets all gc counters and timing -+ * information. -+ */ -+void -+rb_gc_after_fork() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ rb_gc_disable_stats(); -+ rb_gc_clear_stats(); -+ rb_gc_disable_trace(); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+} -+ -+/* - * call-seq: - * GC.log String => String - * -diff --git a/include/ruby/intern.h b/include/ruby/intern.h -index 50451f3..3988869 100644 ---- a/include/ruby/intern.h -+++ b/include/ruby/intern.h -@@ -431,6 +431,8 @@ void rb_gc_call_finalizer_at_exit(void); - VALUE rb_gc_enable(void); - VALUE rb_gc_disable(void); - VALUE rb_gc_start(void); -+void rb_gc_before_fork _((void)); -+void rb_gc_after_fork _((void)); - #define Init_stack(addr) ruby_init_stack(addr) - void rb_gc_set_params(void); - /* hash.c */ -diff --git a/process.c b/process.c -index 99cfc69..8bee602 100644 ---- a/process.c -+++ b/process.c -@@ -2804,9 +2804,11 @@ rb_f_fork(VALUE obj) - rb_pid_t pid; - - rb_secure(2); -+ rb_gc_before_fork(); - - switch (pid = rb_fork(0, 0, 0, Qnil)) { - case 0: -+ rb_gc_after_fork(); - rb_thread_atfork(); - if (rb_block_given_p()) { - int status; diff --git a/patches/ruby/1.9.3/p194/railsexpress/06-track-live-dataset-size.patch b/patches/ruby/1.9.3/p194/railsexpress/06-track-live-dataset-size.patch deleted file mode 100644 index 190f6d57c6..0000000000 --- a/patches/ruby/1.9.3/p194/railsexpress/06-track-live-dataset-size.patch +++ /dev/null @@ -1,69 +0,0 @@ -diff --git a/gc.c b/gc.c -index 7c6e443..9b5d588 100644 ---- a/gc.c -+++ b/gc.c -@@ -272,7 +272,6 @@ getrusage_time(void) - #define GC_PROF_DEC_LIVE_NUM - #endif - -- - #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__) - #pragma pack(push, 1) /* magic for reducing sizeof(RVALUE): 24 -> 20 */ - #endif -@@ -403,6 +402,7 @@ typedef struct rb_objspace { - unsigned LONG_LONG gc_num_allocations; - unsigned long live_objects; - unsigned LONG_LONG allocated_objects; -+ unsigned long heap_slots_live_after_last_gc; - } rb_objspace_t; - - #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE -@@ -435,6 +435,7 @@ int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress; - #define gc_num_allocations objspace->gc_num_allocations - #define live_objects objspace->live_objects - #define allocated_objects objspace->allocated_objects -+#define heap_slots_live_after_last_gc objspace->heap_slots_live_after_last_gc - #define finalizer_table objspace->final.table - #define deferred_final_list objspace->final.deferred - #define mark_stack objspace->markstack.buffer -@@ -1544,6 +1545,24 @@ rb_gc_time() - #endif - } - -+/* -+ * call-seq: -+ * GC.heap_slots_live_after_last_gc => Integer -+ * -+ * Returns the number of heap slots which were live after the last garbage collection. -+ * -+ * GC.heap_slots_live_after_last_gc #=> 231223 -+ * -+ */ -+VALUE -+rb_gc_heap_slots_live_after_last_gc() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return ULONG2NUM(heap_slots_live_after_last_gc); -+} -+ -+ -+ - VALUE rb_mGC; - - void -@@ -3234,6 +3253,7 @@ gc_marks(rb_objspace_t *objspace) - GC_PROF_MARK_TIMER_STOP; - - live_after_last_mark_phase = objspace->heap.live_num; -+ heap_slots_live_after_last_gc = objspace->heap.live_num; - } - - static int -@@ -4459,6 +4479,7 @@ Init_GC(void) - rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); - rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); - rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots_live_after_last_gc", rb_gc_heap_slots_live_after_last_gc, 0); - rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); - - rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); diff --git a/patches/ruby/1.9.3/p194/railsexpress/07-webrick_204_304_keep_alive_fix.patch b/patches/ruby/1.9.3/p194/railsexpress/07-webrick_204_304_keep_alive_fix.patch deleted file mode 100644 index 34d9b78133..0000000000 --- a/patches/ruby/1.9.3/p194/railsexpress/07-webrick_204_304_keep_alive_fix.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/lib/webrick/httpresponse.rb b/lib/webrick/httpresponse.rb -index 0d36c07..ce72b3f 100644 ---- a/lib/webrick/httpresponse.rb -+++ b/lib/webrick/httpresponse.rb -@@ -202,7 +202,7 @@ module WEBrick - if @header['connection'] == "close" - @keep_alive = false - elsif keep_alive? -- if chunked? || @header['content-length'] -+ if chunked? || @header['content-length'] || @status == 304 || @status == 204 - @header['connection'] = "Keep-Alive" - else - msg = "Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true" diff --git a/patches/ruby/1.9.3/p194/railsexpress/08-export-a-few-more-symbols-for-ruby-prof.patch b/patches/ruby/1.9.3/p194/railsexpress/08-export-a-few-more-symbols-for-ruby-prof.patch deleted file mode 100644 index 1c60dc6705..0000000000 --- a/patches/ruby/1.9.3/p194/railsexpress/08-export-a-few-more-symbols-for-ruby-prof.patch +++ /dev/null @@ -1,84 +0,0 @@ -diff --git a/gc.c b/gc.c -index 9b5d588..e1144ff 100644 ---- a/gc.c -+++ b/gc.c -@@ -1031,6 +1031,7 @@ ruby_xfree(void *x) - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_enable(void) - { -@@ -1053,6 +1054,7 @@ rb_gc_enable(void) - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_disable(void) - { -@@ -1075,6 +1077,7 @@ rb_gc_disable(void) - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_enable_stats() - { -@@ -1096,6 +1099,7 @@ rb_gc_enable_stats() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_disable_stats() - { -@@ -1115,6 +1119,7 @@ rb_gc_disable_stats() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_stats_enabled() - { -@@ -1134,6 +1139,7 @@ rb_gc_stats_enabled() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_clear_stats() - { -@@ -1204,6 +1210,7 @@ rb_gc_num_allocations() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_enable_trace() - { -@@ -1225,6 +1232,7 @@ rb_gc_enable_trace() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_disable_trace() - { -@@ -1244,6 +1252,7 @@ rb_gc_disable_trace() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_trace_enabled() - { -@@ -1272,6 +1281,7 @@ const char* GC_LOGFILE_IVAR = "@gc_logfile_name"; - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_log_file(int argc, VALUE *argv, VALUE self) - { diff --git a/patches/ruby/1.9.3/p194/railsexpress/09-avoid-using-broken-ffi-headers.patch b/patches/ruby/1.9.3/p194/railsexpress/09-avoid-using-broken-ffi-headers.patch deleted file mode 100644 index f026ef50fa..0000000000 --- a/patches/ruby/1.9.3/p194/railsexpress/09-avoid-using-broken-ffi-headers.patch +++ /dev/null @@ -1,24 +0,0 @@ -diff --git a/ext/fiddle/extconf.rb b/ext/fiddle/extconf.rb -index 03b0ac2..4b8c4cf 100644 ---- a/ext/fiddle/extconf.rb -+++ b/ext/fiddle/extconf.rb -@@ -4,11 +4,16 @@ require 'mkmf' - - dir_config 'libffi' - --pkg_config("libffi") --unless have_header('ffi.h') -+def have_ffi_headers -+ return true if have_header('ffi.h') - if have_header('ffi/ffi.h') - $defs.push(format('-DUSE_HEADER_HACKS')) -- else -+ end -+end -+ -+unless have_ffi_headers -+ pkg_config('libffi') -+ unless have_ffi_headers - abort "ffi.h is missing. Please install libffi." - end - end diff --git a/patches/ruby/1.9.3/p286/railsexpress/01-railsbench-gc.patch b/patches/ruby/1.9.3/p286/railsexpress/01-railsbench-gc.patch deleted file mode 100644 index eb2e6df82c..0000000000 --- a/patches/ruby/1.9.3/p286/railsexpress/01-railsbench-gc.patch +++ /dev/null @@ -1,1234 +0,0 @@ -diff --git a/configure.in b/configure.in -index 1d727e4..0c2b661 100644 ---- a/configure.in -+++ b/configure.in -@@ -2465,6 +2465,10 @@ if test "$EXEEXT" = .exe; then - AC_SUBST(EXECUTABLE_EXTS) - fi - -+dnl enable gc debugging -+AC_ARG_ENABLE(gcdebug, -+ AS_HELP_STRING([--enable-gcdebug], [build garbage collector with debugging enabled]), -+ [AC_DEFINE(GC_DEBUG,1)]) - dnl } - dnl build section { - -diff --git a/gc.c b/gc.c -index e65d0ec..551e4c1 100644 ---- a/gc.c -+++ b/gc.c -@@ -96,6 +96,15 @@ ruby_gc_params_t initial_params = { - #endif - }; - -+#ifndef HAVE_LONG_LONG -+#define LONG_LONG long -+#endif -+ -+static int heap_min_slots = 10000; -+static int heap_slots_increment = 10000; -+static int initial_heap_slots_increment = 10000; -+static double heap_slots_growth_factor = 1.8; -+ - #define nomem_error GET_VM()->special_exceptions[ruby_error_nomemory] - - #define MARK_STACK_MAX 1024 -@@ -291,7 +300,7 @@ typedef struct RVALUE { - struct RComplex complex; - } as; - #ifdef GC_DEBUG -- const char *file; -+ VALUE file; - int line; - #endif - } RVALUE; -@@ -345,11 +354,25 @@ typedef struct rb_objspace { - size_t free_min; - size_t final_num; - size_t do_heap_free; -+ unsigned long max_blocks_to_free; -+ unsigned long freed_blocks; - } heap; - struct { -+ unsigned long processed; -+ unsigned long freed_objects; -+ unsigned long freelist_size; -+ unsigned long zombies; -+ unsigned long free_counts[T_MASK+1]; -+ unsigned long live_counts[T_MASK+1]; -+ unsigned long gc_time_accumulator_before_gc; -+ unsigned long live_after_last_mark_phase; -+ } stats; -+ struct { - int dont_gc; - int dont_lazy_sweep; - int during_gc; -+ int gc_statistics; -+ int verbose_gc_stats; - } flags; - struct { - st_table *table; -@@ -370,6 +393,14 @@ typedef struct rb_objspace { - struct gc_list *global_list; - size_t count; - int gc_stress; -+ long heap_size; -+ unsigned LONG_LONG gc_time_accumulator; -+ FILE* gc_data_file; -+ long gc_collections; -+ unsigned LONG_LONG gc_allocated_size; -+ unsigned LONG_LONG gc_num_allocations; -+ unsigned long live_objects; -+ unsigned LONG_LONG allocated_objects; - } rb_objspace_t; - - #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE -@@ -392,6 +423,16 @@ int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress; - #define heaps_freed objspace->heap.freed - #define dont_gc objspace->flags.dont_gc - #define during_gc objspace->flags.during_gc -+#define gc_statistics objspace->flags.gc_statistics -+#define verbose_gc_stats objspace->flags.verbose_gc_stats -+#define heap_size objspace->heap_size -+#define gc_time_accumulator objspace->gc_time_accumulator -+#define gc_data_file objspace->gc_data_file -+#define gc_collections objspace->gc_collections -+#define gc_allocated_size objspace->gc_allocated_size -+#define gc_num_allocations objspace->gc_num_allocations -+#define live_objects objspace->live_objects -+#define allocated_objects objspace->allocated_objects - #define finalizer_table objspace->final.table - #define deferred_final_list objspace->final.deferred - #define mark_stack objspace->markstack.buffer -@@ -402,6 +443,14 @@ int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress; - #define initial_malloc_limit initial_params.initial_malloc_limit - #define initial_heap_min_slots initial_params.initial_heap_min_slots - #define initial_free_min initial_params.initial_free_min -+#define free_counts objspace->stats.free_counts -+#define live_counts objspace->stats.live_counts -+#define processed objspace->stats.processed -+#define zombies objspace->stats.zombies -+#define freelist_size objspace->stats.freelist_size -+#define freed_objects objspace->stats.freed_objects -+#define gc_time_accumulator_before_gc objspace->stats.gc_time_accumulator_before_gc -+#define live_after_last_mark_phase objspace->stats.live_after_last_mark_phase - - static void rb_objspace_call_finalizer(rb_objspace_t *objspace); - -@@ -423,24 +472,59 @@ static void initial_expand_heap(rb_objspace_t *objspace); - void - rb_gc_set_params(void) - { -- char *malloc_limit_ptr, *heap_min_slots_ptr, *free_min_ptr; -+ char *envp; -+ -+ rb_objspace_t *objspace = &rb_objspace; -+ -+ gc_data_file = stderr; - - if (rb_safe_level() > 0) return; - -- malloc_limit_ptr = getenv("RUBY_GC_MALLOC_LIMIT"); -- if (malloc_limit_ptr != NULL) { -- int malloc_limit_i = atoi(malloc_limit_ptr); -+ envp = getenv("RUBY_GC_STATS"); -+ if (envp != NULL) { -+ int i = atoi(envp); -+ if (i > 0) { -+ verbose_gc_stats = 1; -+ fprintf(stderr, "RUBY_GC_STATS=%d\n", verbose_gc_stats); -+ } -+ /* child processes should not inherit RUBY_GC_STATS */ -+ ruby_unsetenv("RUBY_GC_STATS"); -+ } -+ -+ envp = getenv("RUBY_GC_DATA_FILE"); -+ if (envp != NULL) { -+ FILE* data_file = fopen(envp, "w"); -+ if (data_file != NULL) { -+ gc_data_file = data_file; -+ } -+ else { -+ fprintf(stderr, "can't open gc log file %s for writing, using default\n", envp); -+ } -+ /* child processes should not inherit RUBY_GC_DATA_FILE to avoid clobbering */ -+ ruby_unsetenv("RUBY_GC_DATA_FILE"); -+ } -+ -+ envp = getenv("RUBY_GC_MALLOC_LIMIT"); -+ if (envp != NULL) { -+ int malloc_limit_i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_GC_MALLOC_LIMIT=%s\n", envp); -+ } - if (RTEST(ruby_verbose)) - fprintf(stderr, "malloc_limit=%d (%d)\n", - malloc_limit_i, initial_malloc_limit); - if (malloc_limit_i > 0) { - initial_malloc_limit = malloc_limit_i; -+ // malloc_limit = initial_malloc_limit; - } - } - -- heap_min_slots_ptr = getenv("RUBY_HEAP_MIN_SLOTS"); -- if (heap_min_slots_ptr != NULL) { -- int heap_min_slots_i = atoi(heap_min_slots_ptr); -+ envp = getenv("RUBY_HEAP_MIN_SLOTS"); -+ if (envp != NULL) { -+ int heap_min_slots_i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_MIN_SLOTS=%s\n", envp); -+ } - if (RTEST(ruby_verbose)) - fprintf(stderr, "heap_min_slots=%d (%d)\n", - heap_min_slots_i, initial_heap_min_slots); -@@ -450,15 +534,42 @@ rb_gc_set_params(void) - } - } - -- free_min_ptr = getenv("RUBY_FREE_MIN"); -- if (free_min_ptr != NULL) { -- int free_min_i = atoi(free_min_ptr); -+ if (!(envp = getenv("RUBY_FREE_MIN"))) -+ envp = getenv("RUBY_HEAP_FREE_MIN"); -+ if (envp != NULL) { -+ int free_min_i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_FREE_MIN=%s\n", envp); -+ } - if (RTEST(ruby_verbose)) - fprintf(stderr, "free_min=%d (%d)\n", free_min_i, initial_free_min); - if (free_min_i > 0) { - initial_free_min = free_min_i; - } - } -+ -+ envp = getenv("RUBY_HEAP_SLOTS_INCREMENT"); -+ if (envp != NULL) { -+ int i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_INCREMENT=%s\n", envp); -+ } -+ heap_slots_increment = i; -+ initial_heap_slots_increment = heap_slots_increment; -+ } -+ -+ envp = getenv("RUBY_HEAP_SLOTS_GROWTH_FACTOR"); -+ if (envp != NULL) { -+ double d = atof(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_GROWTH_FACTOR=%s\n", envp); -+ } -+ if (d > 0) { -+ heap_slots_growth_factor = d; -+ } -+ } -+ -+ fflush(gc_data_file); - } - - #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE -@@ -753,6 +864,11 @@ vm_malloc_fixup(rb_objspace_t *objspace, void *mem, size_t size) - mem = (size_t *)mem + 1; - #endif - -+ if (gc_statistics) { -+ gc_allocated_size += size; -+ gc_num_allocations += 1; -+ } -+ - return mem; - } - -@@ -813,6 +929,13 @@ vm_xrealloc(rb_objspace_t *objspace, void *ptr, size_t size) - mem = (size_t *)mem + 1; - #endif - -+ /* TODO: we can't count correctly unless we store old size on heap -+ if (gc_statistics) { -+ gc_allocated_size += size; -+ gc_num_allocations += 1; -+ } -+ */ -+ - return mem; - } - -@@ -894,7 +1017,6 @@ ruby_xfree(void *x) - vm_xfree(&rb_objspace, x); - } - -- - /* - * call-seq: - * GC.enable -> true or false -@@ -940,6 +1062,454 @@ rb_gc_disable(void) - return old ? Qtrue : Qfalse; - } - -+/* -+ * call-seq: -+ * GC.enable_stats => true or false -+ * -+ * Enables garbage collection statistics, returning true if garbage -+ * collection statistics was already enabled. -+ * -+ * GC.enable_stats #=> false or true -+ * GC.enable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = gc_statistics; -+ gc_statistics = 1; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_stats => true or false -+ * -+ * Disables garbage collection statistics, returning true if garbage -+ * collection statistics was already disabled. -+ * -+ * GC.disable_stats #=> false or true -+ * GC.disable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = gc_statistics; -+ gc_statistics = 0; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.stats_enabled? => true or false -+ * -+ * Check whether GC stats have been enabled. -+ * -+ * GC.stats_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_stats_enabled() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return gc_statistics ? Qtrue : Qfalse; -+} -+ -+ -+/* -+ * call-seq: -+ * GC.clear_stats => nil -+ * -+ * Clears garbage collection statistics, returning nil. This resets the number -+ * of collections (GC.collections) and the time used (GC.time) to 0. -+ * -+ * GC.clear_stats #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_clear_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ gc_collections = 0; -+ gc_time_accumulator = 0; -+ gc_time_accumulator_before_gc = 0; -+ gc_allocated_size = 0; -+ gc_num_allocations = 0; -+ return Qnil; -+} -+ -+/* -+ * call-seq: -+ * GC.allocated_size => Integer -+ * -+ * Returns the size of memory (in bytes) allocated since GC statistics collection -+ * was enabled. -+ * -+ * GC.allocated_size #=> 35 -+ * -+ */ -+ -+VALUE -+rb_gc_allocated_size() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_allocated_size); -+#else -+ return ULONG2NUM(gc_allocated_size); -+#endif -+} -+ -+/* -+ * call-seq: -+ * GC.num_allocations => Integer -+ * -+ * Returns the number of memory allocations since GC statistics collection -+ * was enabled. -+ * -+ * GC.num_allocations #=> 150 -+ * -+ */ -+VALUE -+rb_gc_num_allocations() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_num_allocations); -+#else -+ return ULONG2NUM(gc_num_allocations); -+#endif -+} -+ -+/* -+ * call-seq: -+ * GC.enable_trace => true or false -+ * -+ * Enables garbage collection tracing, returning true if garbage -+ * collection tracing was already enabled. -+ * -+ * GC.enable_trace #=> false or true -+ * GC.enable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_trace() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = verbose_gc_stats; -+ verbose_gc_stats = 1; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_trace => true or false -+ * -+ * Disables garbage collection tracing, returning true if garbage -+ * collection tracing was already disabled. -+ * -+ * GC.disable_trace #=> false or true -+ * GC.disable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_trace() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = verbose_gc_stats; -+ verbose_gc_stats = 0; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.trace_enabled? => true or false -+ * -+ * Check whether GC tracing has been enabled. -+ * -+ * GC.trace_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_trace_enabled() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return verbose_gc_stats ? Qtrue : Qfalse; -+} -+ -+ -+const char* GC_LOGFILE_IVAR = "@gc_logfile_name"; -+ -+/* -+ * call-seq: -+ * GC.log_file(filename=nil, mode="w") => boolean -+ * -+ * Changes the GC data log file. Closes the currently open logfile. -+ * Returns true if the file was successfully opened for -+ * writing. Returns false if the file could not be opened for -+ * writing. Returns the name of the current logfile (or nil) if no -+ * parameter is given. Restores logging to stderr when given nil as -+ * an argument. -+ * -+ * GC.log_file #=> nil -+ * GC.log_file "/tmp/gc.log" #=> true -+ * GC.log_file #=> "/tmp/gc.log" -+ * GC.log_file nil #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_log_file(int argc, VALUE *argv, VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ VALUE filename = Qnil; -+ VALUE mode_str = Qnil; -+ FILE* f = NULL; -+ const char* mode = "w"; -+ -+ VALUE current_logfile_name = rb_iv_get(rb_mGC, GC_LOGFILE_IVAR); -+ -+ if (argc==0) -+ return current_logfile_name; -+ -+ rb_scan_args(argc, argv, "02", &filename, &mode_str); -+ -+ if (filename == Qnil) { -+ /* close current logfile and reset logfile to stderr */ -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+ } -+ return Qtrue; -+ } -+ -+ /* we have a real logfile name */ -+ filename = StringValue(filename); -+ -+ if (rb_equal(current_logfile_name, filename) == Qtrue) { -+ /* do nothing if we get the file name we're already logging to */ -+ return Qtrue; -+ } -+ -+ /* get mode for file opening */ -+ if (mode_str != Qnil) -+ { -+ mode = RSTRING_PTR(StringValue(mode_str)); -+ } -+ -+ /* try to open file in given mode */ -+ if (f = fopen(RSTRING_PTR(filename), mode)) { -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ } -+ gc_data_file = f; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, filename); -+ } else { -+ return Qfalse; -+ } -+ return Qtrue; -+} -+ -+/* -+ * call-seq: -+ * GC.log String => String -+ * -+ * Logs string to the GC data file and returns it. -+ * -+ * GC.log "manual GC call" #=> "manual GC call" -+ * -+ */ -+ -+VALUE -+rb_gc_log(self, original_str) -+ VALUE self, original_str; -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ if (original_str == Qnil) { -+ fprintf(gc_data_file, "\n"); -+ } -+ else { -+ VALUE str = StringValue(original_str); -+ char *p = RSTRING_PTR(str); -+ fprintf(gc_data_file, "%s\n", p); -+ } -+ return original_str; -+} -+ -+/* -+ * call-seq: -+ * GC.dump => nil -+ * -+ * dumps information about the current GC data structures to the GC log file -+ * -+ * GC.dump #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_dump() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ size_t i; -+ -+ for (i = 0; i < heaps_used; i++) { -+ size_t limit = objspace->heap.sorted[i].slot->limit; -+ fprintf(gc_data_file, "HEAP[%2lu]: size=%7lu\n", (unsigned long)i, (unsigned long)limit); -+ } -+ -+ return Qnil; -+} -+ -+static const char* obj_type(VALUE tp); -+ -+#ifdef GC_DEBUG -+/* -+ * call-seq: -+ * GC.dump_file_and_line_info(String, boolean) => nil -+ * -+ * dumps information on which currently allocated object was created by which file and on which line -+ * -+ * GC.dump_file_and_line_info(String, boolean) #=> nil -+ * -+ * The second parameter specifies whether class names should be included in the dump. -+ * Note that including class names will allocate additional string objects on the heap. -+ * -+ */ -+ -+VALUE -+rb_gc_dump_file_and_line_info(int argc, VALUE *argv) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ VALUE filename, str, include_classnames = Qnil; -+ char *fname = NULL; -+ FILE* f = NULL; -+ size_t i = 0; -+ -+ rb_scan_args(argc, argv, "11", &filename, &include_classnames); -+ -+ str = StringValue(filename); -+ fname = RSTRING_PTR(str); -+ f = fopen(fname, "w"); -+ -+ for (i = 0; i < heaps_used; i++) { -+ RVALUE *p, *pend; -+ -+ p = objspace->heap.sorted[i].start; pend = objspace->heap.sorted[i].end; -+ for (;p < pend; p++) { -+ if (p->as.basic.flags) { -+ const char *src_filename = (p->file && p->file != Qnil )? RSTRING_PTR(p->file) : ""; -+ fprintf(f, "%s:%s:%d", obj_type(p->as.basic.flags & T_MASK), src_filename, (int)p->line); -+ // rb_obj_classname will create objects on the heap, we need a better solution -+ if (include_classnames == Qtrue) { -+ /* write the class */ -+ fprintf(f, ":"); -+ switch (BUILTIN_TYPE(p)) { -+ case T_NONE: -+ fprintf(f, "__none__"); -+ break; -+ case T_UNDEF: -+ fprintf(f, "__undef__"); -+ break; -+ case T_NODE: -+ fprintf(f, "__node__"); -+ break; -+ default: -+ if (!p->as.basic.klass) { -+ fprintf(f, "__unknown__"); -+ } else { -+ fprintf(f, "%s", rb_obj_classname((VALUE)p)); -+ } -+ } -+ /* print object size for some known object types */ -+ switch (BUILTIN_TYPE(p)) { -+ case T_STRING: -+ fprintf(f, ":%lu", RSTRING_LEN(p)); -+ break; -+ case T_ARRAY: -+ fprintf(f, ":%lu", RARRAY_LEN(p)); -+ break; -+ case T_HASH: -+ fprintf(f, ":%lu", (long unsigned int)RHASH_SIZE(p)); -+ break; -+ } -+ } -+ fprintf(f, "\n"); -+ } -+ } -+ } -+ fclose(f); -+ return Qnil; -+} -+#endif -+ -+/* -+ * call-seq: -+ * GC.heap_slots => Integer -+ * -+ * Returns the number of heap slots available for object allocations. -+ * -+ * GC.heap_slots #=> 10000 -+ * -+ */ -+VALUE -+rb_gc_heap_slots() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return LONG2NUM(heap_size); -+} -+ -+ -+/* -+ * call-seq: -+ * GC.collections => Integer -+ * -+ * Returns the number of garbage collections performed while GC statistics collection -+ * was enabled. -+ * -+ * GC.collections #=> 35 -+ * -+ */ -+ -+VALUE -+rb_gc_collections() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return LONG2NUM(gc_collections); -+} -+ -+/* -+ * call-seq: -+ * GC.time => Integer -+ * -+ * Returns the time spent during garbage collection while GC statistics collection -+ * was enabled (in micro seconds). -+ * -+ * GC.time #=> 20000 -+ * -+ */ -+ -+VALUE -+rb_gc_time() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return LL2NUM(gc_time_accumulator); -+#else -+ return LONG2NUM(gc_time_accumulator); -+#endif -+} -+ - VALUE rb_mGC; - - void -@@ -1011,6 +1581,12 @@ allocate_sorted_heaps(rb_objspace_t *objspace, size_t next_heaps_length) - static void - assign_heap_slot(rb_objspace_t *objspace) - { -+ /* -+ if (gc_statistics & verbose_gc_stats) { -+ fprintf(gc_data_file, "assigning heap slot\n"); -+ } -+ */ -+ - RVALUE *p, *pend, *membase; - struct heaps_slot *slot; - size_t hi, lo, mid; -@@ -1072,6 +1648,7 @@ assign_heap_slot(rb_objspace_t *objspace) - if (lomem == 0 || lomem > p) lomem = p; - if (himem < pend) himem = pend; - heaps_used++; -+ heap_size += objs; - - while (p < pend) { - p->as.free.flags = 0; -@@ -1127,7 +1704,7 @@ initial_expand_heap(rb_objspace_t *objspace) - static void - set_heaps_increment(rb_objspace_t *objspace) - { -- size_t next_heaps_length = (size_t)(heaps_used * 1.8); -+ size_t next_heaps_length = (size_t)(heaps_used * heap_slots_growth_factor); - - if (next_heaps_length == heaps_used) { - next_heaps_length++; -@@ -1160,6 +1737,22 @@ rb_during_gc(void) - - #define RANY(o) ((RVALUE*)(o)) - -+#ifdef GC_DEBUG -+static VALUE -+_rb_sourcefile(void) -+{ -+ rb_thread_t *th = GET_THREAD(); -+ rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp); -+ -+ if (cfp) { -+ return cfp->iseq->filename; -+ } -+ else { -+ return Qnil; -+ } -+} -+#endif -+ - VALUE - rb_newobj(void) - { -@@ -1191,9 +1784,11 @@ rb_newobj(void) - - MEMZERO((void*)obj, RVALUE, 1); - #ifdef GC_DEBUG -- RANY(obj)->file = rb_sourcefile(); -+ RANY(obj)->file = _rb_sourcefile(); - RANY(obj)->line = rb_sourceline(); - #endif -+ live_objects++; -+ allocated_objects++; - GC_PROF_INC_LIVE_NUM; - - return obj; -@@ -1660,6 +2255,12 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev) - { - register RVALUE *obj = RANY(ptr); - -+#ifdef GC_DEBUG -+ if (obj->file && obj->file != Qnil && is_pointer_to_heap(objspace, (void*)obj->file)) { -+ gc_mark(objspace, obj->file, lev); -+ } -+#endif -+ - goto marking; /* skip */ - - again: -@@ -1670,6 +2271,12 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev) - obj->as.basic.flags |= FL_MARK; - objspace->heap.live_num++; - -+#ifdef GC_DEBUG -+ if (obj->file && obj->file != Qnil && is_pointer_to_heap(objspace, (void*)obj->file)) { -+ gc_mark(objspace, obj->file, lev); -+ } -+#endif -+ - marking: - if (FL_TEST(obj, FL_EXIVAR)) { - rb_mark_generic_ivar(ptr); -@@ -2012,6 +2619,25 @@ free_unused_heaps(rb_objspace_t *objspace) - } - } - -+static inline unsigned long -+elapsed_musecs(struct timeval since) -+{ -+ struct timeval now; -+ struct timeval temp; -+ -+ gettimeofday(&now, NULL); -+ -+ if ((now.tv_usec-since.tv_usec)<0) { -+ temp.tv_sec = now.tv_sec-since.tv_sec-1; -+ temp.tv_usec = 1000000+now.tv_usec-since.tv_usec; -+ } else { -+ temp.tv_sec = now.tv_sec-since.tv_sec; -+ temp.tv_usec = now.tv_usec-since.tv_usec; -+ } -+ -+ return temp.tv_sec*1000000 + temp.tv_usec; -+} -+ - static void - slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - { -@@ -2019,14 +2645,23 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - RVALUE *p, *pend; - RVALUE *free = freelist, *final = deferred_final_list; - int deferred; -+ int do_gc_stats = gc_statistics & verbose_gc_stats; -+ -+ struct timeval tv1; -+ if (gc_statistics) gettimeofday(&tv1, NULL); - - p = sweep_slot->slot; pend = p + sweep_slot->limit; - while (p < pend) { - if (!(p->as.basic.flags & FL_MARK)) { -+ if (do_gc_stats && !p->as.basic.flags) { -+ /* slot was free before GC */ -+ freelist_size++; -+ } - if (p->as.basic.flags && - ((deferred = obj_free(objspace, (VALUE)p)) || - (FL_TEST(p, FL_FINALIZE)))) { - if (!deferred) { -+ if (do_gc_stats) zombies++; - p->as.free.flags = T_ZOMBIE; - RDATA(p)->dfree = 0; - } -@@ -2036,6 +2671,10 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - final_num++; - } - else { -+ if (do_gc_stats) { -+ VALUE obt = p->as.basic.flags & T_MASK; -+ if (obt) free_counts[obt]++; -+ } - add_freelist(objspace, p); - free_num++; - } -@@ -2043,13 +2682,22 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - else if (BUILTIN_TYPE(p) == T_ZOMBIE) { - /* objects to be finalized */ - /* do nothing remain marked */ -+ if (do_gc_stats) zombies++; - } - else { - RBASIC(p)->flags &= ~FL_MARK; -+ if (do_gc_stats) { -+ live_counts[p->as.basic.flags & T_MASK]++; -+ } - } - p++; -+ processed++; - } -- if (final_num + free_num == sweep_slot->limit && -+ -+ freed_objects += free_num; -+ -+ if (objspace->heap.freed_blocks < objspace->heap.max_blocks_to_free && -+ final_num + free_num == sweep_slot->limit && - objspace->heap.free_num > objspace->heap.do_heap_free) { - RVALUE *pp; - -@@ -2060,6 +2708,8 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - sweep_slot->limit = final_num; - freelist = free; /* cancel this page from freelist */ - unlink_heap_slot(objspace, sweep_slot); -+ objspace->heap.freed_blocks += 1; -+ heap_size -= final_num + free_num; - } - else { - objspace->heap.free_num += free_num; -@@ -2072,6 +2722,10 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - RUBY_VM_SET_FINALIZER_INTERRUPT(th); - } - } -+ -+ if (gc_statistics) { -+ gc_time_accumulator += elapsed_musecs(tv1); -+ } - } - - static int -@@ -2092,6 +2746,21 @@ ready_to_gc(rb_objspace_t *objspace) - static void - before_gc_sweep(rb_objspace_t *objspace) - { -+ if (gc_statistics & verbose_gc_stats) { -+ /* -+ fprintf(gc_data_file, "Sweep started\n"); -+ */ -+ freed_objects = 0; -+ processed = 0; -+ zombies = 0; -+ freelist_size = 0; -+ MEMZERO((void*)free_counts, unsigned long, T_MASK+1); -+ MEMZERO((void*)live_counts, unsigned long, T_MASK+1); -+ } -+ -+ objspace->heap.max_blocks_to_free = heaps_used - (heap_min_slots / HEAP_OBJ_LIMIT); -+ objspace->heap.freed_blocks = 0; -+ - freelist = 0; - objspace->heap.do_heap_free = (size_t)((heaps_used * HEAP_OBJ_LIMIT) * 0.65); - objspace->heap.free_min = (size_t)((heaps_used * HEAP_OBJ_LIMIT) * 0.2); -@@ -2111,8 +2780,13 @@ before_gc_sweep(rb_objspace_t *objspace) - static void - after_gc_sweep(rb_objspace_t *objspace) - { -+ int i; -+ struct timeval tv1; -+ - GC_PROF_SET_MALLOC_INFO; - -+ if (gc_statistics) gettimeofday(&tv1, NULL); -+ - if (objspace->heap.free_num < objspace->heap.free_min) { - set_heaps_increment(objspace); - heaps_increment(objspace); -@@ -2125,6 +2799,29 @@ after_gc_sweep(rb_objspace_t *objspace) - malloc_increase = 0; - - free_unused_heaps(objspace); -+ -+ if (gc_statistics) { -+ gc_time_accumulator += elapsed_musecs(tv1); -+ -+ if (verbose_gc_stats) { -+ /* log gc stats if requested */ -+ fprintf(gc_data_file, "GC time: %lu musec\n", (unsigned long)(gc_time_accumulator-gc_time_accumulator_before_gc)); -+ fprintf(gc_data_file, "objects processed: %7lu\n", (unsigned long)processed); -+ fprintf(gc_data_file, "live objects : %7lu\n", (unsigned long)live_after_last_mark_phase); -+ fprintf(gc_data_file, "freelist objects : %7lu\n", (unsigned long)freelist_size); -+ fprintf(gc_data_file, "freed objects : %7lu\n", (unsigned long)freed_objects); -+ fprintf(gc_data_file, "zombies : %7lu\n", (unsigned long)zombies); -+ for(i=0; i0 || live_counts[i]>0) { -+ fprintf(gc_data_file, -+ "kept %7lu / freed %7lu objects of type %s\n", -+ (unsigned long)live_counts[i], (unsigned long)free_counts[i], obj_type((int)i)); -+ } -+ } -+ rb_gc_dump(); -+ fflush(gc_data_file); -+ } -+ } - } - - static int -@@ -2158,9 +2855,11 @@ rest_sweep(rb_objspace_t *objspace) - - static void gc_marks(rb_objspace_t *objspace); - -+/* only called from rb_new_obj */ - static int - gc_lazy_sweep(rb_objspace_t *objspace) - { -+ struct timeval gctv1; - int res; - INIT_GC_PROF_PARAMS; - -@@ -2182,7 +2881,6 @@ gc_lazy_sweep(rb_objspace_t *objspace) - GC_PROF_TIMER_STOP(Qfalse); - return res; - } -- after_gc_sweep(objspace); - } - else { - if (heaps_increment(objspace)) { -@@ -2190,6 +2888,18 @@ gc_lazy_sweep(rb_objspace_t *objspace) - return TRUE; - } - } -+ after_gc_sweep(objspace); -+ -+ if (gc_statistics) { -+ gc_time_accumulator_before_gc = gc_time_accumulator; -+ gc_collections++; -+ gettimeofday(&gctv1, NULL); -+ /* -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "Garbage collection started (gc_lazy_sweep)\n"); -+ } -+ */ -+ } - - gc_marks(objspace); - -@@ -2198,6 +2908,10 @@ gc_lazy_sweep(rb_objspace_t *objspace) - set_heaps_increment(objspace); - } - -+ if (gc_statistics) { -+ gc_time_accumulator += elapsed_musecs(gctv1); -+ } -+ - GC_PROF_SWEEP_TIMER_START; - if(!(res = lazy_sweep(objspace))) { - after_gc_sweep(objspace); -@@ -2209,6 +2923,7 @@ gc_lazy_sweep(rb_objspace_t *objspace) - GC_PROF_SWEEP_TIMER_STOP; - - GC_PROF_TIMER_STOP(Qtrue); -+ - return res; - } - -@@ -2435,9 +3150,15 @@ gc_marks(rb_objspace_t *objspace) - rb_thread_t *th = GET_THREAD(); - GC_PROF_MARK_TIMER_START; - -+ /* -+ if (gc_statistics & verbose_gc_stats) { -+ fprintf(gc_data_file, "Marking objects\n"); -+ } -+ */ -+ - objspace->heap.live_num = 0; - objspace->count++; -- -+ live_objects = 0; - - SET_STACK_END; - -@@ -2477,11 +3198,15 @@ gc_marks(rb_objspace_t *objspace) - } - } - GC_PROF_MARK_TIMER_STOP; -+ -+ live_after_last_mark_phase = objspace->heap.live_num; - } - - static int - garbage_collect(rb_objspace_t *objspace) - { -+ struct timeval gctv1; -+ - INIT_GC_PROF_PARAMS; - - if (GC_NOTIFY) printf("start garbage_collect()\n"); -@@ -2497,15 +3222,31 @@ garbage_collect(rb_objspace_t *objspace) - - rest_sweep(objspace); - -+ if (gc_statistics) { -+ gc_time_accumulator_before_gc = gc_time_accumulator; -+ gc_collections++; -+ gettimeofday(&gctv1, NULL); -+ /* -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "Garbage collection started (garbage_collect)\n"); -+ } -+ */ -+ } -+ - during_gc++; - gc_marks(objspace); - -+ if (gc_statistics) { -+ gc_time_accumulator += elapsed_musecs(gctv1); -+ } -+ - GC_PROF_SWEEP_TIMER_START; - gc_sweep(objspace); - GC_PROF_SWEEP_TIMER_STOP; - - GC_PROF_TIMER_STOP(Qtrue); - if (GC_NOTIFY) printf("end garbage_collect()\n"); -+ - return TRUE; - } - -@@ -2994,6 +3735,39 @@ rb_gc_call_finalizer_at_exit(void) - rb_objspace_call_finalizer(&rb_objspace); - } - -+static const char* obj_type(VALUE type) -+{ -+ switch (type) { -+ case T_NIL : return "NIL"; -+ case T_OBJECT : return "OBJECT"; -+ case T_CLASS : return "CLASS"; -+ case T_ICLASS : return "ICLASS"; -+ case T_MODULE : return "MODULE"; -+ case T_FLOAT : return "FLOAT"; -+ case T_COMPLEX: return "COMPLEX"; -+ case T_RATIONAL: return "RATIONAL"; -+ case T_STRING : return "STRING"; -+ case T_REGEXP : return "REGEXP"; -+ case T_ARRAY : return "ARRAY"; -+ case T_FIXNUM : return "FIXNUM"; -+ case T_HASH : return "HASH"; -+ case T_STRUCT : return "STRUCT"; -+ case T_BIGNUM : return "BIGNUM"; -+ case T_FILE : return "FILE"; -+ -+ case T_TRUE : return "TRUE"; -+ case T_FALSE : return "FALSE"; -+ case T_DATA : return "DATA"; -+ case T_MATCH : return "MATCH"; -+ case T_SYMBOL : return "SYMBOL"; -+ case T_ZOMBIE : return "ZOMBIE"; -+ -+ case T_UNDEF : return "UNDEF"; -+ case T_NODE : return "NODE"; -+ default: return "____"; -+ } -+} -+ - static void - rb_objspace_call_finalizer(rb_objspace_t *objspace) - { -@@ -3307,6 +4081,49 @@ count_objects(int argc, VALUE *argv, VALUE os) - return hash; - } - -+/* call-seq: -+ * ObjectSpace.live_objects => number -+ * -+ * Returns the count of objects currently allocated in the system. This goes -+ * down after the garbage collector runs. -+ */ -+static -+VALUE os_live_objects(VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return ULONG2NUM(live_objects); -+} -+ -+unsigned long rb_os_live_objects() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return live_objects; -+} -+ -+/* call-seq: -+ * ObjectSpace.allocated_objects => number -+ * -+ * Returns the count of objects allocated since the Ruby interpreter has -+ * started. This number can only increase. To know how many objects are -+ * currently allocated, use ObjectSpace::live_objects -+ */ -+static -+VALUE os_allocated_objects(VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if defined(HAVE_LONG_LONG) -+ return ULL2NUM(allocated_objects); -+#else -+ return ULONG2NUM(allocated_objects); -+#endif -+} -+ -+unsigned LONG_LONG rb_os_allocated_objects() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return allocated_objects; -+} -+ - /* - * call-seq: - * GC.count -> Integer -@@ -3599,6 +4416,28 @@ Init_GC(void) - rb_define_singleton_method(rb_mGC, "stat", gc_stat, -1); - rb_define_method(rb_mGC, "garbage_collect", rb_gc_start, 0); - -+ rb_define_singleton_method(rb_mGC, "enable_stats", rb_gc_enable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "disable_stats", rb_gc_disable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "stats_enabled?", rb_gc_stats_enabled, 0); -+ rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0); -+ rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); -+ rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); -+ -+ rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); -+ rb_define_singleton_method(rb_mGC, "log_file", rb_gc_log_file, -1); -+ rb_define_singleton_method(rb_mGC, "enable_trace", rb_gc_enable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "disable_trace", rb_gc_disable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "trace_enabled?", rb_gc_trace_enabled, 0); -+ -+ rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); -+ rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); -+ rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); -+#ifdef GC_DEBUG -+ rb_define_singleton_method(rb_mGC, "dump_file_and_line_info", rb_gc_dump_file_and_line_info, -1); -+#endif -+ - 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); -@@ -3612,6 +4451,9 @@ Init_GC(void) - rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1); - rb_define_module_function(rb_mObSpace, "garbage_collect", rb_gc_start, 0); - -+ rb_define_module_function(rb_mObSpace, "live_objects", os_live_objects, 0); -+ rb_define_module_function(rb_mObSpace, "allocated_objects", os_allocated_objects, 0); -+ - rb_define_module_function(rb_mObSpace, "define_finalizer", define_final, -1); - rb_define_module_function(rb_mObSpace, "undefine_finalizer", undefine_final, 1); - diff --git a/patches/ruby/1.9.3/p286/railsexpress/02-display-more-detailed-stack-trace.patch b/patches/ruby/1.9.3/p286/railsexpress/02-display-more-detailed-stack-trace.patch deleted file mode 100644 index 5c7ad30352..0000000000 --- a/patches/ruby/1.9.3/p286/railsexpress/02-display-more-detailed-stack-trace.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/eval_error.c b/eval_error.c -index fd06adf..69c3b48 100644 ---- a/eval_error.c -+++ b/eval_error.c -@@ -164,8 +164,8 @@ error_print(void) - int skip = eclass == rb_eSysStackError; - - #define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5) --#define TRACE_HEAD 8 --#define TRACE_TAIL 5 -+#define TRACE_HEAD 100 -+#define TRACE_TAIL 100 - - for (i = 1; i < len; i++) { - if (TYPE(ptr[i]) == T_STRING) { diff --git a/patches/ruby/1.9.3/p286/railsexpress/03-fork-support-for-gc-logging.patch b/patches/ruby/1.9.3/p286/railsexpress/03-fork-support-for-gc-logging.patch deleted file mode 100644 index 08fb35a80d..0000000000 --- a/patches/ruby/1.9.3/p286/railsexpress/03-fork-support-for-gc-logging.patch +++ /dev/null @@ -1,68 +0,0 @@ -diff --git a/gc.c b/gc.c -index 551e4c1..1d707fd 100644 ---- a/gc.c -+++ b/gc.c -@@ -1322,6 +1322,34 @@ rb_gc_log_file(int argc, VALUE *argv, VALUE self) - } - - /* -+ * Called from process.c before a fork. Flushes the gc log file to -+ * avoid writing the buffered output twice (once in the parent, and -+ * once in the child). -+ */ -+void -+rb_gc_before_fork() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ fflush(gc_data_file); -+} -+ -+/* -+ * Called from process.c after a fork in the child process. Turns off -+ * logging, disables GC stats and resets all gc counters and timing -+ * information. -+ */ -+void -+rb_gc_after_fork() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ rb_gc_disable_stats(); -+ rb_gc_clear_stats(); -+ rb_gc_disable_trace(); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+} -+ -+/* - * call-seq: - * GC.log String => String - * -diff --git a/include/ruby/intern.h b/include/ruby/intern.h -index 6dec838..559088a 100644 ---- a/include/ruby/intern.h -+++ b/include/ruby/intern.h -@@ -431,6 +431,8 @@ void rb_gc_call_finalizer_at_exit(void); - VALUE rb_gc_enable(void); - VALUE rb_gc_disable(void); - VALUE rb_gc_start(void); -+void rb_gc_before_fork _((void)); -+void rb_gc_after_fork _((void)); - #define Init_stack(addr) ruby_init_stack(addr) - void rb_gc_set_params(void); - /* hash.c */ -diff --git a/process.c b/process.c -index 99cfc69..8bee602 100644 ---- a/process.c -+++ b/process.c -@@ -2804,9 +2804,11 @@ rb_f_fork(VALUE obj) - rb_pid_t pid; - - rb_secure(2); -+ rb_gc_before_fork(); - - switch (pid = rb_fork(0, 0, 0, Qnil)) { - case 0: -+ rb_gc_after_fork(); - rb_thread_atfork(); - if (rb_block_given_p()) { - int status; diff --git a/patches/ruby/1.9.3/p286/railsexpress/04-track-live-dataset-size.patch b/patches/ruby/1.9.3/p286/railsexpress/04-track-live-dataset-size.patch deleted file mode 100644 index 61b4bfc108..0000000000 --- a/patches/ruby/1.9.3/p286/railsexpress/04-track-live-dataset-size.patch +++ /dev/null @@ -1,45 +0,0 @@ -diff --git a/gc.c b/gc.c -index 1d707fd..9eeeb4d 100644 ---- a/gc.c -+++ b/gc.c -@@ -270,7 +270,6 @@ getrusage_time(void) - #define GC_PROF_DEC_LIVE_NUM - #endif - -- - #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__) - #pragma pack(push, 1) /* magic for reducing sizeof(RVALUE): 24 -> 20 */ - #endif -@@ -1538,6 +1537,24 @@ rb_gc_time() - #endif - } - -+/* -+ * call-seq: -+ * GC.heap_slots_live_after_last_gc => Integer -+ * -+ * Returns the number of heap slots which were live after the last garbage collection. -+ * -+ * GC.heap_slots_live_after_last_gc #=> 231223 -+ * -+ */ -+VALUE -+rb_gc_heap_slots_live_after_last_gc() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return ULONG2NUM(live_after_last_mark_phase); -+} -+ -+ -+ - VALUE rb_mGC; - - void -@@ -4451,6 +4468,7 @@ Init_GC(void) - rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); - rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); - rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots_live_after_last_gc", rb_gc_heap_slots_live_after_last_gc, 0); - rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); - - rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); diff --git a/patches/ruby/1.9.3/p286/railsexpress/05-webrick_204_304_keep_alive_fix.patch b/patches/ruby/1.9.3/p286/railsexpress/05-webrick_204_304_keep_alive_fix.patch deleted file mode 100644 index 34d9b78133..0000000000 --- a/patches/ruby/1.9.3/p286/railsexpress/05-webrick_204_304_keep_alive_fix.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/lib/webrick/httpresponse.rb b/lib/webrick/httpresponse.rb -index 0d36c07..ce72b3f 100644 ---- a/lib/webrick/httpresponse.rb -+++ b/lib/webrick/httpresponse.rb -@@ -202,7 +202,7 @@ module WEBrick - if @header['connection'] == "close" - @keep_alive = false - elsif keep_alive? -- if chunked? || @header['content-length'] -+ if chunked? || @header['content-length'] || @status == 304 || @status == 204 - @header['connection'] = "Keep-Alive" - else - msg = "Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true" diff --git a/patches/ruby/1.9.3/p286/railsexpress/06-export-a-few-more-symbols-for-ruby-prof.patch b/patches/ruby/1.9.3/p286/railsexpress/06-export-a-few-more-symbols-for-ruby-prof.patch deleted file mode 100644 index a420df91f2..0000000000 --- a/patches/ruby/1.9.3/p286/railsexpress/06-export-a-few-more-symbols-for-ruby-prof.patch +++ /dev/null @@ -1,84 +0,0 @@ -diff --git a/gc.c b/gc.c -index 9eeeb4d..06e6655 100644 ---- a/gc.c -+++ b/gc.c -@@ -1029,6 +1029,7 @@ ruby_xfree(void *x) - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_enable(void) - { -@@ -1051,6 +1052,7 @@ rb_gc_enable(void) - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_disable(void) - { -@@ -1073,6 +1075,7 @@ rb_gc_disable(void) - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_enable_stats() - { -@@ -1094,6 +1097,7 @@ rb_gc_enable_stats() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_disable_stats() - { -@@ -1113,6 +1117,7 @@ rb_gc_disable_stats() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_stats_enabled() - { -@@ -1132,6 +1137,7 @@ rb_gc_stats_enabled() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_clear_stats() - { -@@ -1199,6 +1205,7 @@ rb_gc_num_allocations() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_enable_trace() - { -@@ -1220,6 +1227,7 @@ rb_gc_enable_trace() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_disable_trace() - { -@@ -1239,6 +1247,7 @@ rb_gc_disable_trace() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_trace_enabled() - { -@@ -1267,6 +1276,7 @@ const char* GC_LOGFILE_IVAR = "@gc_logfile_name"; - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_log_file(int argc, VALUE *argv, VALUE self) - { diff --git a/patches/ruby/1.9.3/p286/railsexpress/07-thread-variables.patch b/patches/ruby/1.9.3/p286/railsexpress/07-thread-variables.patch deleted file mode 100644 index 8cd6501249..0000000000 --- a/patches/ruby/1.9.3/p286/railsexpress/07-thread-variables.patch +++ /dev/null @@ -1,319 +0,0 @@ -diff --git a/NEWS b/NEWS -index 30fec33..9f6c172 100644 ---- a/NEWS -+++ b/NEWS -@@ -103,6 +103,16 @@ with all sufficient information, see the ChangeLog file. - * String#prepend - * String#byteslice - -+ * Thread -+ * added method: -+ * added Thread#thread_variable_get for getting thread local variables -+ (these are different than Fiber local variables). -+ * added Thread#thread_variable_set for setting thread local variables. -+ * added Thread#thread_variables for getting a list of the thread local -+ variable keys. -+ * added Thread#thread_variable? for testing to see if a particular thread -+ variable has been set. -+ - * Time - * extended method: - * Time#strftime supports %:z and %::z. -diff --git a/test/ruby/test_thread.rb b/test/ruby/test_thread.rb -index e8cb3b1..9ff491d 100644 ---- a/test/ruby/test_thread.rb -+++ b/test/ruby/test_thread.rb -@@ -27,6 +27,79 @@ class TestThread < Test::Unit::TestCase - end - end - -+ def test_main_thread_variable_in_enumerator -+ assert_equal Thread.main, Thread.current -+ -+ Thread.current.thread_variable_set :foo, "bar" -+ -+ thread, value = Fiber.new { -+ Fiber.yield [Thread.current, Thread.current.thread_variable_get(:foo)] -+ }.resume -+ -+ assert_equal Thread.current, thread -+ assert_equal Thread.current.thread_variable_get(:foo), value -+ end -+ -+ def test_thread_variable_in_enumerator -+ Thread.new { -+ Thread.current.thread_variable_set :foo, "bar" -+ -+ thread, value = Fiber.new { -+ Fiber.yield [Thread.current, Thread.current.thread_variable_get(:foo)] -+ }.resume -+ -+ assert_equal Thread.current, thread -+ assert_equal Thread.current.thread_variable_get(:foo), value -+ }.join -+ end -+ -+ def test_thread_variables -+ assert_equal [], Thread.new { Thread.current.thread_variables }.join.value -+ -+ t = Thread.new { -+ Thread.current.thread_variable_set(:foo, "bar") -+ Thread.current.thread_variables -+ } -+ assert_equal [:foo], t.join.value -+ end -+ -+ def test_thread_variable? -+ refute Thread.new { Thread.current.thread_variable?("foo") }.join.value -+ t = Thread.new { -+ Thread.current.thread_variable_set("foo", "bar") -+ }.join -+ -+ assert t.thread_variable?("foo") -+ assert t.thread_variable?(:foo) -+ refute t.thread_variable?(:bar) -+ end -+ -+ def test_thread_variable_strings_and_symbols_are_the_same_key -+ t = Thread.new {}.join -+ t.thread_variable_set("foo", "bar") -+ assert_equal "bar", t.thread_variable_get(:foo) -+ end -+ -+ def test_thread_variable_frozen -+ t = Thread.new { }.join -+ t.freeze -+ assert_raises(RuntimeError) do -+ t.thread_variable_set(:foo, "bar") -+ end -+ end -+ -+ def test_thread_variable_security -+ t = Thread.new { sleep } -+ -+ assert_raises(SecurityError) do -+ Thread.new { $SAFE = 4; t.thread_variable_get(:foo) }.join -+ end -+ -+ assert_raises(SecurityError) do -+ Thread.new { $SAFE = 4; t.thread_variable_set(:foo, :baz) }.join -+ end -+ end -+ - def test_mutex_synchronize - m = Mutex.new - r = 0 -diff --git a/thread.c b/thread.c -index eb0be9f..a8721c4 100644 ---- a/thread.c -+++ b/thread.c -@@ -2112,7 +2112,9 @@ rb_thread_local_aset(VALUE thread, ID id, VALUE val) - * thr[sym] = obj -> obj - * - * Attribute Assignment---Sets or creates the value of a thread-local variable, -- * using either a symbol or a string. See also Thread#[]. -+ * using either a symbol or a string. See also Thread#[]. For -+ * thread-local variables, please see Thread#thread_variable_set -+ * and Thread#thread_variable_get. - */ - - static VALUE -@@ -2123,6 +2125,80 @@ rb_thread_aset(VALUE self, VALUE id, VALUE val) - - /* - * call-seq: -+ * thr.thread_variable_get(key) -> obj or nil -+ * -+ * Returns the value of a thread local variable that has been set. Note that -+ * these are different than fiber local values. For fiber local values, -+ * please see Thread#[] and Thread#[]=. -+ * -+ * Thread local values are carried along with threads, and do not respect -+ * fibers. For example: -+ * -+ * Thread.new { -+ * Thread.current.thread_variable_set("foo", "bar") # set a thread local -+ * Thread.current["foo"] = "bar" # set a fiber local -+ * -+ * Fiber.new { -+ * Fiber.yield [ -+ * Thread.current.thread_variable_get("foo"), # get the thread local -+ * Thread.current["foo"], # get the fiber local -+ * ] -+ * }.resume -+ * }.join.value # => ['bar', nil] -+ * -+ * The value "bar" is returned for the thread local, where nil is returned -+ * for the fiber local. The fiber is executed in the same thread, so the -+ * thread local values are available. -+ * -+ * See also Thread#[] -+ */ -+ -+static VALUE -+rb_thread_variable_get(VALUE thread, VALUE id) -+{ -+ VALUE locals; -+ rb_thread_t *th; -+ -+ GetThreadPtr(thread, th); -+ -+ if (rb_safe_level() >= 4 && th != GET_THREAD()) { -+ rb_raise(rb_eSecurityError, "Insecure: can't access thread locals"); -+ } -+ -+ locals = rb_iv_get(thread, "locals"); -+ return rb_hash_aref(locals, ID2SYM(rb_to_id(id))); -+} -+ -+/* -+ * call-seq: -+ * thr.thread_variable_set(key, value) -+ * -+ * Sets a thread local with +key+ to +value+. Note that these are local to -+ * threads, and not to fibers. Please see Thread#thread_variable_get and -+ * Thread#[] for more information. -+ */ -+ -+static VALUE -+rb_thread_variable_set(VALUE thread, VALUE id, VALUE val) -+{ -+ VALUE locals; -+ rb_thread_t *th; -+ -+ GetThreadPtr(thread, th); -+ -+ if (rb_safe_level() >= 4 && th != GET_THREAD()) { -+ rb_raise(rb_eSecurityError, "Insecure: can't modify thread locals"); -+ } -+ if (OBJ_FROZEN(thread)) { -+ rb_error_frozen("thread locals"); -+ } -+ -+ locals = rb_iv_get(thread, "locals"); -+ return rb_hash_aset(locals, ID2SYM(rb_to_id(id)), val); -+} -+ -+/* -+ * call-seq: - * thr.key?(sym) -> true or false - * - * Returns true if the given string (or symbol) exists as a -@@ -2993,6 +3069,9 @@ rb_gc_save_machine_context(rb_thread_t *th) - - /* - * -+ * For thread-local variables, please see Thread#thread_local_get -+ * and Thread#thread_local_set. -+ * - */ - - void -@@ -3195,6 +3274,76 @@ thgroup_list_i(st_data_t key, st_data_t val, st_data_t data) - return ST_CONTINUE; - } - -+static int -+keys_i(VALUE key, VALUE value, VALUE ary) -+{ -+ rb_ary_push(ary, key); -+ return ST_CONTINUE; -+} -+ -+/* -+ * call-seq: -+ * thr.thread_variables -> array -+ * -+ * Returns an an array of the names of the thread-local variables (as Symbols). -+ * -+ * thr = Thread.new do -+ * Thread.current.thread_variable_set(:cat, 'meow') -+ * Thread.current.thread_variable_set("dog", 'woof') -+ * end -+ * thr.join #=> # -+ * thr.thread_variables #=> [:dog, :cat] -+ * -+ * Note that these are not fiber local variables. Please see Thread#[] and -+ * Thread#thread_variable_get for more details. -+ */ -+ -+static VALUE -+rb_thread_variables(VALUE thread) -+{ -+ VALUE locals; -+ VALUE ary; -+ -+ locals = rb_iv_get(thread, "locals"); -+ ary = rb_ary_new(); -+ rb_hash_foreach(locals, keys_i, ary); -+ -+ return ary; -+} -+ -+/* -+ * call-seq: -+ * thr.thread_variable?(key) -> true or false -+ * -+ * Returns true if the given string (or symbol) exists as a -+ * thread-local variable. -+ * -+ * me = Thread.current -+ * me.thread_variable_set(:oliver, "a") -+ * me.thread_variable?(:oliver) #=> true -+ * me.thread_variable?(:stanley) #=> false -+ * -+ * Note that these are not fiber local variables. Please see Thread#[] and -+ * Thread#thread_variable_get for more details. -+ */ -+ -+static VALUE -+rb_thread_variable_p(VALUE thread, VALUE key) -+{ -+ VALUE locals; -+ -+ locals = rb_iv_get(thread, "locals"); -+ -+ if (!RHASH(locals)->ntbl) -+ return Qfalse; -+ -+ if (st_lookup(RHASH(locals)->ntbl, ID2SYM(rb_to_id(key)), 0)) { -+ return Qtrue; -+ } -+ -+ return Qfalse; -+} -+ - /* - * call-seq: - * thgrp.list -> array -@@ -4670,6 +4819,10 @@ Init_Thread(void) - rb_define_method(rb_cThread, "priority", rb_thread_priority, 0); - rb_define_method(rb_cThread, "priority=", rb_thread_priority_set, 1); - rb_define_method(rb_cThread, "status", rb_thread_status, 0); -+ rb_define_method(rb_cThread, "thread_variable_get", rb_thread_variable_get, 1); -+ rb_define_method(rb_cThread, "thread_variable_set", rb_thread_variable_set, 2); -+ rb_define_method(rb_cThread, "thread_variables", rb_thread_variables, 0); -+ rb_define_method(rb_cThread, "thread_variable?", rb_thread_variable_p, 1); - rb_define_method(rb_cThread, "alive?", rb_thread_alive_p, 0); - rb_define_method(rb_cThread, "stop?", rb_thread_stop_p, 0); - rb_define_method(rb_cThread, "abort_on_exception", rb_thread_abort_exc, 0); -diff --git a/vm.c b/vm.c -index 3d7b76e..48796bc 100644 ---- a/vm.c -+++ b/vm.c -@@ -1896,6 +1896,7 @@ ruby_thread_init(VALUE self) - GetThreadPtr(self, th); - - th_init(th, self); -+ rb_iv_set(self, "locals", rb_hash_new()); - th->vm = vm; - - th->top_wrapper = 0; -@@ -2164,6 +2165,7 @@ Init_VM(void) - - /* create main thread */ - th_self = th->self = TypedData_Wrap_Struct(rb_cThread, &thread_data_type, th); -+ rb_iv_set(th_self, "locals", rb_hash_new()); - vm->main_thread = th; - vm->running_thread = th; - th->vm = vm; diff --git a/patches/ruby/1.9.3/p327/railsexpress/01-fix-make-clean.patch b/patches/ruby/1.9.3/p327/railsexpress/01-fix-make-clean.patch deleted file mode 100644 index 8886e47473..0000000000 --- a/patches/ruby/1.9.3/p327/railsexpress/01-fix-make-clean.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/lib/mkmf.rb b/lib/mkmf.rb -index f4f84a6..f73f7ed 100644 ---- a/lib/mkmf.rb -+++ b/lib/mkmf.rb -@@ -2191,7 +2191,7 @@ def init_mkmf(config = CONFIG, rbconfig = RbConfig::CONFIG) - $LOCAL_LIBS = "" - - $cleanfiles = config_string('CLEANFILES') {|s| Shellwords.shellwords(s)} || [] -- $cleanfiles << "mkmf.log" -+ $cleanfiles << "mkmf.log .*.time" - $distcleanfiles = config_string('DISTCLEANFILES') {|s| Shellwords.shellwords(s)} || [] - $distcleandirs = config_string('DISTCLEANDIRS') {|s| Shellwords.shellwords(s)} || [] - diff --git a/patches/ruby/1.9.3/p327/railsexpress/02-railsbench-gc.patch b/patches/ruby/1.9.3/p327/railsexpress/02-railsbench-gc.patch deleted file mode 100644 index 49a4f41209..0000000000 --- a/patches/ruby/1.9.3/p327/railsexpress/02-railsbench-gc.patch +++ /dev/null @@ -1,1235 +0,0 @@ -diff --git a/configure.in b/configure.in -index b006a01..af5acc4 100644 ---- a/configure.in -+++ b/configure.in -@@ -2473,6 +2473,10 @@ if test "$EXEEXT" = .exe; then - AC_SUBST(EXECUTABLE_EXTS) - fi - -+dnl enable gc debugging -+AC_ARG_ENABLE(gcdebug, -+ AS_HELP_STRING([--enable-gcdebug], [build garbage collector with debugging enabled]), -+ [AC_DEFINE(GC_DEBUG,1)]) - dnl } - dnl build section { - -diff --git a/gc.c b/gc.c -index e65d0ec..169dfab 100644 ---- a/gc.c -+++ b/gc.c -@@ -96,6 +96,15 @@ ruby_gc_params_t initial_params = { - #endif - }; - -+#ifndef HAVE_LONG_LONG -+#define LONG_LONG long -+#endif -+ -+static int heap_min_slots = 10000; -+static int heap_slots_increment = 10000; -+static int initial_heap_slots_increment = 10000; -+static double heap_slots_growth_factor = 1.8; -+ - #define nomem_error GET_VM()->special_exceptions[ruby_error_nomemory] - - #define MARK_STACK_MAX 1024 -@@ -291,7 +300,7 @@ typedef struct RVALUE { - struct RComplex complex; - } as; - #ifdef GC_DEBUG -- const char *file; -+ VALUE file; - int line; - #endif - } RVALUE; -@@ -345,11 +354,25 @@ typedef struct rb_objspace { - size_t free_min; - size_t final_num; - size_t do_heap_free; -+ unsigned long max_blocks_to_free; -+ unsigned long freed_blocks; - } heap; - struct { -+ unsigned long processed; -+ unsigned long freed_objects; -+ unsigned long freelist_size; -+ unsigned long zombies; -+ unsigned long free_counts[T_MASK+1]; -+ unsigned long live_counts[T_MASK+1]; -+ unsigned long gc_time_accumulator_before_gc; -+ unsigned long live_after_last_mark_phase; -+ } stats; -+ struct { - int dont_gc; - int dont_lazy_sweep; - int during_gc; -+ int gc_statistics; -+ int verbose_gc_stats; - } flags; - struct { - st_table *table; -@@ -370,6 +393,14 @@ typedef struct rb_objspace { - struct gc_list *global_list; - size_t count; - int gc_stress; -+ long heap_size; -+ unsigned LONG_LONG gc_time_accumulator; -+ FILE* gc_data_file; -+ long gc_collections; -+ unsigned LONG_LONG gc_allocated_size; -+ unsigned LONG_LONG gc_num_allocations; -+ unsigned long live_objects; -+ unsigned LONG_LONG allocated_objects; - } rb_objspace_t; - - #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE -@@ -392,6 +423,16 @@ int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress; - #define heaps_freed objspace->heap.freed - #define dont_gc objspace->flags.dont_gc - #define during_gc objspace->flags.during_gc -+#define gc_statistics objspace->flags.gc_statistics -+#define verbose_gc_stats objspace->flags.verbose_gc_stats -+#define heap_size objspace->heap_size -+#define gc_time_accumulator objspace->gc_time_accumulator -+#define gc_data_file objspace->gc_data_file -+#define gc_collections objspace->gc_collections -+#define gc_allocated_size objspace->gc_allocated_size -+#define gc_num_allocations objspace->gc_num_allocations -+#define live_objects objspace->live_objects -+#define allocated_objects objspace->allocated_objects - #define finalizer_table objspace->final.table - #define deferred_final_list objspace->final.deferred - #define mark_stack objspace->markstack.buffer -@@ -402,6 +443,14 @@ int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress; - #define initial_malloc_limit initial_params.initial_malloc_limit - #define initial_heap_min_slots initial_params.initial_heap_min_slots - #define initial_free_min initial_params.initial_free_min -+#define free_counts objspace->stats.free_counts -+#define live_counts objspace->stats.live_counts -+#define processed objspace->stats.processed -+#define zombies objspace->stats.zombies -+#define freelist_size objspace->stats.freelist_size -+#define freed_objects objspace->stats.freed_objects -+#define gc_time_accumulator_before_gc objspace->stats.gc_time_accumulator_before_gc -+#define live_after_last_mark_phase objspace->stats.live_after_last_mark_phase - - static void rb_objspace_call_finalizer(rb_objspace_t *objspace); - -@@ -423,24 +472,59 @@ static void initial_expand_heap(rb_objspace_t *objspace); - void - rb_gc_set_params(void) - { -- char *malloc_limit_ptr, *heap_min_slots_ptr, *free_min_ptr; -+ char *envp; -+ -+ rb_objspace_t *objspace = &rb_objspace; -+ -+ gc_data_file = stderr; - - if (rb_safe_level() > 0) return; - -- malloc_limit_ptr = getenv("RUBY_GC_MALLOC_LIMIT"); -- if (malloc_limit_ptr != NULL) { -- int malloc_limit_i = atoi(malloc_limit_ptr); -+ envp = getenv("RUBY_GC_STATS"); -+ if (envp != NULL) { -+ int i = atoi(envp); -+ if (i > 0) { -+ verbose_gc_stats = 1; -+ fprintf(stderr, "RUBY_GC_STATS=%d\n", verbose_gc_stats); -+ } -+ /* child processes should not inherit RUBY_GC_STATS */ -+ ruby_unsetenv("RUBY_GC_STATS"); -+ } -+ -+ envp = getenv("RUBY_GC_DATA_FILE"); -+ if (envp != NULL) { -+ FILE* data_file = fopen(envp, "w"); -+ if (data_file != NULL) { -+ gc_data_file = data_file; -+ } -+ else { -+ fprintf(stderr, "can't open gc log file %s for writing, using default\n", envp); -+ } -+ /* child processes should not inherit RUBY_GC_DATA_FILE to avoid clobbering */ -+ ruby_unsetenv("RUBY_GC_DATA_FILE"); -+ } -+ -+ envp = getenv("RUBY_GC_MALLOC_LIMIT"); -+ if (envp != NULL) { -+ int malloc_limit_i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_GC_MALLOC_LIMIT=%s\n", envp); -+ } - if (RTEST(ruby_verbose)) - fprintf(stderr, "malloc_limit=%d (%d)\n", - malloc_limit_i, initial_malloc_limit); - if (malloc_limit_i > 0) { - initial_malloc_limit = malloc_limit_i; -+ // malloc_limit = initial_malloc_limit; - } - } - -- heap_min_slots_ptr = getenv("RUBY_HEAP_MIN_SLOTS"); -- if (heap_min_slots_ptr != NULL) { -- int heap_min_slots_i = atoi(heap_min_slots_ptr); -+ envp = getenv("RUBY_HEAP_MIN_SLOTS"); -+ if (envp != NULL) { -+ int heap_min_slots_i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_MIN_SLOTS=%s\n", envp); -+ } - if (RTEST(ruby_verbose)) - fprintf(stderr, "heap_min_slots=%d (%d)\n", - heap_min_slots_i, initial_heap_min_slots); -@@ -450,15 +534,42 @@ rb_gc_set_params(void) - } - } - -- free_min_ptr = getenv("RUBY_FREE_MIN"); -- if (free_min_ptr != NULL) { -- int free_min_i = atoi(free_min_ptr); -+ if (!(envp = getenv("RUBY_FREE_MIN"))) -+ envp = getenv("RUBY_HEAP_FREE_MIN"); -+ if (envp != NULL) { -+ int free_min_i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_FREE_MIN=%s\n", envp); -+ } - if (RTEST(ruby_verbose)) - fprintf(stderr, "free_min=%d (%d)\n", free_min_i, initial_free_min); - if (free_min_i > 0) { - initial_free_min = free_min_i; - } - } -+ -+ envp = getenv("RUBY_HEAP_SLOTS_INCREMENT"); -+ if (envp != NULL) { -+ int i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_INCREMENT=%s\n", envp); -+ } -+ heap_slots_increment = i; -+ initial_heap_slots_increment = heap_slots_increment; -+ } -+ -+ envp = getenv("RUBY_HEAP_SLOTS_GROWTH_FACTOR"); -+ if (envp != NULL) { -+ double d = atof(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_GROWTH_FACTOR=%s\n", envp); -+ } -+ if (d > 0) { -+ heap_slots_growth_factor = d; -+ } -+ } -+ -+ fflush(gc_data_file); - } - - #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE -@@ -753,6 +864,11 @@ vm_malloc_fixup(rb_objspace_t *objspace, void *mem, size_t size) - mem = (size_t *)mem + 1; - #endif - -+ if (gc_statistics) { -+ gc_allocated_size += size; -+ gc_num_allocations += 1; -+ } -+ - return mem; - } - -@@ -813,6 +929,13 @@ vm_xrealloc(rb_objspace_t *objspace, void *ptr, size_t size) - mem = (size_t *)mem + 1; - #endif - -+ /* TODO: we can't count correctly unless we store old size on heap -+ if (gc_statistics) { -+ gc_allocated_size += size; -+ gc_num_allocations += 1; -+ } -+ */ -+ - return mem; - } - -@@ -894,7 +1017,6 @@ ruby_xfree(void *x) - vm_xfree(&rb_objspace, x); - } - -- - /* - * call-seq: - * GC.enable -> true or false -@@ -940,6 +1062,455 @@ rb_gc_disable(void) - return old ? Qtrue : Qfalse; - } - -+/* -+ * call-seq: -+ * GC.enable_stats => true or false -+ * -+ * Enables garbage collection statistics, returning true if garbage -+ * collection statistics was already enabled. -+ * -+ * GC.enable_stats #=> false or true -+ * GC.enable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = gc_statistics; -+ gc_statistics = 1; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_stats => true or false -+ * -+ * Disables garbage collection statistics, returning true if garbage -+ * collection statistics was already disabled. -+ * -+ * GC.disable_stats #=> false or true -+ * GC.disable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = gc_statistics; -+ gc_statistics = 0; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.stats_enabled? => true or false -+ * -+ * Check whether GC stats have been enabled. -+ * -+ * GC.stats_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_stats_enabled() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return gc_statistics ? Qtrue : Qfalse; -+} -+ -+ -+/* -+ * call-seq: -+ * GC.clear_stats => nil -+ * -+ * Clears garbage collection statistics, returning nil. This resets the number -+ * of collections (GC.collections) and the time used (GC.time) to 0. -+ * -+ * GC.clear_stats #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_clear_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ gc_collections = 0; -+ gc_time_accumulator = 0; -+ gc_time_accumulator_before_gc = 0; -+ gc_allocated_size = 0; -+ gc_num_allocations = 0; -+ return Qnil; -+} -+ -+/* -+ * call-seq: -+ * GC.allocated_size => Integer -+ * -+ * Returns the size of memory (in bytes) allocated since GC statistics collection -+ * was enabled. -+ * -+ * GC.allocated_size #=> 35 -+ * -+ */ -+ -+VALUE -+rb_gc_allocated_size() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_allocated_size); -+#else -+ return ULONG2NUM(gc_allocated_size); -+#endif -+} -+ -+/* -+ * call-seq: -+ * GC.num_allocations => Integer -+ * -+ * Returns the number of memory allocations since GC statistics collection -+ * was enabled. -+ * -+ * GC.num_allocations #=> 150 -+ * -+ */ -+VALUE -+rb_gc_num_allocations() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_num_allocations); -+#else -+ return ULONG2NUM(gc_num_allocations); -+#endif -+} -+ -+/* -+ * call-seq: -+ * GC.enable_trace => true or false -+ * -+ * Enables garbage collection tracing, returning true if garbage -+ * collection tracing was already enabled. -+ * -+ * GC.enable_trace #=> false or true -+ * GC.enable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_trace() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = verbose_gc_stats; -+ verbose_gc_stats = 1; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_trace => true or false -+ * -+ * Disables garbage collection tracing, returning true if garbage -+ * collection tracing was already disabled. -+ * -+ * GC.disable_trace #=> false or true -+ * GC.disable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_trace() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = verbose_gc_stats; -+ verbose_gc_stats = 0; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.trace_enabled? => true or false -+ * -+ * Check whether GC tracing has been enabled. -+ * -+ * GC.trace_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_trace_enabled() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return verbose_gc_stats ? Qtrue : Qfalse; -+} -+ -+ -+const char* GC_LOGFILE_IVAR = "@gc_logfile_name"; -+ -+/* -+ * call-seq: -+ * GC.log_file(filename=nil, mode="w") => boolean -+ * -+ * Changes the GC data log file. Closes the currently open logfile. -+ * Returns true if the file was successfully opened for -+ * writing. Returns false if the file could not be opened for -+ * writing. Returns the name of the current logfile (or nil) if no -+ * parameter is given. Restores logging to stderr when given nil as -+ * an argument. -+ * -+ * GC.log_file #=> nil -+ * GC.log_file "/tmp/gc.log" #=> true -+ * GC.log_file #=> "/tmp/gc.log" -+ * GC.log_file nil #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_log_file(int argc, VALUE *argv, VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ VALUE filename = Qnil; -+ VALUE mode_str = Qnil; -+ FILE* f = NULL; -+ const char* mode = "w"; -+ -+ VALUE current_logfile_name = rb_iv_get(rb_mGC, GC_LOGFILE_IVAR); -+ -+ if (argc==0) -+ return current_logfile_name; -+ -+ rb_scan_args(argc, argv, "02", &filename, &mode_str); -+ -+ if (filename == Qnil) { -+ /* close current logfile and reset logfile to stderr */ -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+ } -+ return Qtrue; -+ } -+ -+ /* we have a real logfile name */ -+ filename = StringValue(filename); -+ -+ if (rb_equal(current_logfile_name, filename) == Qtrue) { -+ /* do nothing if we get the file name we're already logging to */ -+ return Qtrue; -+ } -+ -+ /* get mode for file opening */ -+ if (mode_str != Qnil) -+ { -+ mode = RSTRING_PTR(StringValue(mode_str)); -+ } -+ -+ /* try to open file in given mode */ -+ if (f = fopen(RSTRING_PTR(filename), mode)) { -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ } -+ gc_data_file = f; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, filename); -+ } else { -+ return Qfalse; -+ } -+ return Qtrue; -+} -+ -+/* -+ * call-seq: -+ * GC.log String => String -+ * -+ * Logs string to the GC data file and returns it. -+ * -+ * GC.log "manual GC call" #=> "manual GC call" -+ * -+ */ -+ -+VALUE -+rb_gc_log(self, original_str) -+ VALUE self, original_str; -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ if (original_str == Qnil) { -+ fprintf(gc_data_file, "\n"); -+ } -+ else { -+ VALUE str = StringValue(original_str); -+ char *p = RSTRING_PTR(str); -+ fprintf(gc_data_file, "%s\n", p); -+ } -+ return original_str; -+} -+ -+/* -+ * call-seq: -+ * GC.dump => nil -+ * -+ * dumps information about the current GC data structures to the GC log file -+ * -+ * GC.dump #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_dump() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ size_t i; -+ -+ for (i = 0; i < heaps_used; i++) { -+ size_t limit = objspace->heap.sorted[i].slot->limit; -+ fprintf(gc_data_file, "HEAP[%2lu]: size=%7lu\n", (unsigned long)i, (unsigned long)limit); -+ } -+ -+ return Qnil; -+} -+ -+static const char* obj_type(VALUE tp); -+ -+#ifdef GC_DEBUG -+/* -+ * call-seq: -+ * GC.dump_file_and_line_info(String, boolean) => nil -+ * -+ * dumps information on which currently allocated object was created by which file and on which line -+ * -+ * GC.dump_file_and_line_info(String, boolean) #=> nil -+ * -+ * The second parameter specifies whether class names should be included in the dump. -+ * Note that including class names will allocate additional string objects on the heap. -+ * -+ */ -+ -+VALUE -+rb_gc_dump_file_and_line_info(int argc, VALUE *argv) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ VALUE filename, str, include_classnames = Qnil; -+ char *fname = NULL; -+ char *klass = NULL; -+ FILE* f = NULL; -+ size_t i = 0; -+ -+ rb_scan_args(argc, argv, "11", &filename, &include_classnames); -+ -+ str = StringValue(filename); -+ fname = RSTRING_PTR(str); -+ f = fopen(fname, "w"); -+ -+ for (i = 0; i < heaps_used; i++) { -+ RVALUE *p, *pend; -+ -+ p = objspace->heap.sorted[i].start; pend = objspace->heap.sorted[i].end; -+ for (;p < pend; p++) { -+ if (p->as.basic.flags) { -+ const char *src_filename = (p->file && p->file != Qnil )? RSTRING_PTR(p->file) : ""; -+ fprintf(f, "%s:%s:%d", obj_type(p->as.basic.flags & T_MASK), src_filename, (int)p->line); -+ // rb_obj_classname will create objects on the heap, we need a better solution -+ if (include_classnames == Qtrue) { -+ /* write the class */ -+ fprintf(f, ":"); -+ switch (BUILTIN_TYPE(p)) { -+ case T_NONE: -+ fprintf(f, "__none__"); -+ break; -+ case T_UNDEF: -+ fprintf(f, "__undef__"); -+ break; -+ case T_NODE: -+ fprintf(f, "__node__"); -+ break; -+ default: -+ if (!p->as.basic.klass) { -+ fprintf(f, "__unknown__"); -+ } else { -+ fprintf(f, "%s", rb_obj_classname((VALUE)p)); -+ } -+ } -+ /* print object size for some known object types */ -+ switch (BUILTIN_TYPE(p)) { -+ case T_STRING: -+ fprintf(f, ":%lu", RSTRING_LEN(p)); -+ break; -+ case T_ARRAY: -+ fprintf(f, ":%lu", RARRAY_LEN(p)); -+ break; -+ case T_HASH: -+ fprintf(f, ":%lu", (long unsigned int)RHASH_SIZE(p)); -+ break; -+ } -+ } -+ fprintf(f, "\n"); -+ } -+ } -+ } -+ fclose(f); -+ return Qnil; -+} -+#endif -+ -+/* -+ * call-seq: -+ * GC.heap_slots => Integer -+ * -+ * Returns the number of heap slots available for object allocations. -+ * -+ * GC.heap_slots #=> 10000 -+ * -+ */ -+VALUE -+rb_gc_heap_slots() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return LONG2NUM(heap_size); -+} -+ -+ -+/* -+ * call-seq: -+ * GC.collections => Integer -+ * -+ * Returns the number of garbage collections performed while GC statistics collection -+ * was enabled. -+ * -+ * GC.collections #=> 35 -+ * -+ */ -+ -+VALUE -+rb_gc_collections() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return LONG2NUM(gc_collections); -+} -+ -+/* -+ * call-seq: -+ * GC.time => Integer -+ * -+ * Returns the time spent during garbage collection while GC statistics collection -+ * was enabled (in micro seconds). -+ * -+ * GC.time #=> 20000 -+ * -+ */ -+ -+VALUE -+rb_gc_time() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return LL2NUM(gc_time_accumulator); -+#else -+ return LONG2NUM(gc_time_accumulator); -+#endif -+} -+ - VALUE rb_mGC; - - void -@@ -1011,6 +1582,12 @@ allocate_sorted_heaps(rb_objspace_t *objspace, size_t next_heaps_length) - static void - assign_heap_slot(rb_objspace_t *objspace) - { -+ /* -+ if (gc_statistics & verbose_gc_stats) { -+ fprintf(gc_data_file, "assigning heap slot\n"); -+ } -+ */ -+ - RVALUE *p, *pend, *membase; - struct heaps_slot *slot; - size_t hi, lo, mid; -@@ -1072,6 +1649,7 @@ assign_heap_slot(rb_objspace_t *objspace) - if (lomem == 0 || lomem > p) lomem = p; - if (himem < pend) himem = pend; - heaps_used++; -+ heap_size += objs; - - while (p < pend) { - p->as.free.flags = 0; -@@ -1127,7 +1705,7 @@ initial_expand_heap(rb_objspace_t *objspace) - static void - set_heaps_increment(rb_objspace_t *objspace) - { -- size_t next_heaps_length = (size_t)(heaps_used * 1.8); -+ size_t next_heaps_length = (size_t)(heaps_used * heap_slots_growth_factor); - - if (next_heaps_length == heaps_used) { - next_heaps_length++; -@@ -1160,6 +1738,22 @@ rb_during_gc(void) - - #define RANY(o) ((RVALUE*)(o)) - -+#ifdef GC_DEBUG -+static VALUE -+_rb_sourcefile(void) -+{ -+ rb_thread_t *th = GET_THREAD(); -+ rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp); -+ -+ if (cfp) { -+ return cfp->iseq->filename; -+ } -+ else { -+ return Qnil; -+ } -+} -+#endif -+ - VALUE - rb_newobj(void) - { -@@ -1191,9 +1785,11 @@ rb_newobj(void) - - MEMZERO((void*)obj, RVALUE, 1); - #ifdef GC_DEBUG -- RANY(obj)->file = rb_sourcefile(); -+ RANY(obj)->file = _rb_sourcefile(); - RANY(obj)->line = rb_sourceline(); - #endif -+ live_objects++; -+ allocated_objects++; - GC_PROF_INC_LIVE_NUM; - - return obj; -@@ -1660,6 +2256,12 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev) - { - register RVALUE *obj = RANY(ptr); - -+#ifdef GC_DEBUG -+ if (obj->file && obj->file != Qnil && is_pointer_to_heap(objspace, (void*)obj->file)) { -+ gc_mark(objspace, obj->file, lev); -+ } -+#endif -+ - goto marking; /* skip */ - - again: -@@ -1670,6 +2272,12 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev) - obj->as.basic.flags |= FL_MARK; - objspace->heap.live_num++; - -+#ifdef GC_DEBUG -+ if (obj->file && obj->file != Qnil && is_pointer_to_heap(objspace, (void*)obj->file)) { -+ gc_mark(objspace, obj->file, lev); -+ } -+#endif -+ - marking: - if (FL_TEST(obj, FL_EXIVAR)) { - rb_mark_generic_ivar(ptr); -@@ -2012,6 +2620,25 @@ free_unused_heaps(rb_objspace_t *objspace) - } - } - -+static inline unsigned long -+elapsed_musecs(struct timeval since) -+{ -+ struct timeval now; -+ struct timeval temp; -+ -+ gettimeofday(&now, NULL); -+ -+ if ((now.tv_usec-since.tv_usec)<0) { -+ temp.tv_sec = now.tv_sec-since.tv_sec-1; -+ temp.tv_usec = 1000000+now.tv_usec-since.tv_usec; -+ } else { -+ temp.tv_sec = now.tv_sec-since.tv_sec; -+ temp.tv_usec = now.tv_usec-since.tv_usec; -+ } -+ -+ return temp.tv_sec*1000000 + temp.tv_usec; -+} -+ - static void - slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - { -@@ -2019,14 +2646,23 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - RVALUE *p, *pend; - RVALUE *free = freelist, *final = deferred_final_list; - int deferred; -+ int do_gc_stats = gc_statistics & verbose_gc_stats; -+ -+ struct timeval tv1; -+ if (gc_statistics) gettimeofday(&tv1, NULL); - - p = sweep_slot->slot; pend = p + sweep_slot->limit; - while (p < pend) { - if (!(p->as.basic.flags & FL_MARK)) { -+ if (do_gc_stats && !p->as.basic.flags) { -+ /* slot was free before GC */ -+ freelist_size++; -+ } - if (p->as.basic.flags && - ((deferred = obj_free(objspace, (VALUE)p)) || - (FL_TEST(p, FL_FINALIZE)))) { - if (!deferred) { -+ if (do_gc_stats) zombies++; - p->as.free.flags = T_ZOMBIE; - RDATA(p)->dfree = 0; - } -@@ -2036,6 +2672,10 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - final_num++; - } - else { -+ if (do_gc_stats) { -+ VALUE obt = p->as.basic.flags & T_MASK; -+ if (obt) free_counts[obt]++; -+ } - add_freelist(objspace, p); - free_num++; - } -@@ -2043,13 +2683,22 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - else if (BUILTIN_TYPE(p) == T_ZOMBIE) { - /* objects to be finalized */ - /* do nothing remain marked */ -+ if (do_gc_stats) zombies++; - } - else { - RBASIC(p)->flags &= ~FL_MARK; -+ if (do_gc_stats) { -+ live_counts[p->as.basic.flags & T_MASK]++; -+ } - } - p++; -+ processed++; - } -- if (final_num + free_num == sweep_slot->limit && -+ -+ freed_objects += free_num; -+ -+ if (objspace->heap.freed_blocks < objspace->heap.max_blocks_to_free && -+ final_num + free_num == sweep_slot->limit && - objspace->heap.free_num > objspace->heap.do_heap_free) { - RVALUE *pp; - -@@ -2060,6 +2709,8 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - sweep_slot->limit = final_num; - freelist = free; /* cancel this page from freelist */ - unlink_heap_slot(objspace, sweep_slot); -+ objspace->heap.freed_blocks += 1; -+ heap_size -= final_num + free_num; - } - else { - objspace->heap.free_num += free_num; -@@ -2072,6 +2723,10 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - RUBY_VM_SET_FINALIZER_INTERRUPT(th); - } - } -+ -+ if (gc_statistics) { -+ gc_time_accumulator += elapsed_musecs(tv1); -+ } - } - - static int -@@ -2092,6 +2747,21 @@ ready_to_gc(rb_objspace_t *objspace) - static void - before_gc_sweep(rb_objspace_t *objspace) - { -+ if (gc_statistics & verbose_gc_stats) { -+ /* -+ fprintf(gc_data_file, "Sweep started\n"); -+ */ -+ freed_objects = 0; -+ processed = 0; -+ zombies = 0; -+ freelist_size = 0; -+ MEMZERO((void*)free_counts, unsigned long, T_MASK+1); -+ MEMZERO((void*)live_counts, unsigned long, T_MASK+1); -+ } -+ -+ objspace->heap.max_blocks_to_free = heaps_used - (heap_min_slots / HEAP_OBJ_LIMIT); -+ objspace->heap.freed_blocks = 0; -+ - freelist = 0; - objspace->heap.do_heap_free = (size_t)((heaps_used * HEAP_OBJ_LIMIT) * 0.65); - objspace->heap.free_min = (size_t)((heaps_used * HEAP_OBJ_LIMIT) * 0.2); -@@ -2111,8 +2781,13 @@ before_gc_sweep(rb_objspace_t *objspace) - static void - after_gc_sweep(rb_objspace_t *objspace) - { -+ int i; -+ struct timeval tv1; -+ - GC_PROF_SET_MALLOC_INFO; - -+ if (gc_statistics) gettimeofday(&tv1, NULL); -+ - if (objspace->heap.free_num < objspace->heap.free_min) { - set_heaps_increment(objspace); - heaps_increment(objspace); -@@ -2125,6 +2800,29 @@ after_gc_sweep(rb_objspace_t *objspace) - malloc_increase = 0; - - free_unused_heaps(objspace); -+ -+ if (gc_statistics) { -+ gc_time_accumulator += elapsed_musecs(tv1); -+ -+ if (verbose_gc_stats) { -+ /* log gc stats if requested */ -+ fprintf(gc_data_file, "GC time: %lu musec\n", (unsigned long)(gc_time_accumulator-gc_time_accumulator_before_gc)); -+ fprintf(gc_data_file, "objects processed: %7lu\n", (unsigned long)processed); -+ fprintf(gc_data_file, "live objects : %7lu\n", (unsigned long)live_after_last_mark_phase); -+ fprintf(gc_data_file, "freelist objects : %7lu\n", (unsigned long)freelist_size); -+ fprintf(gc_data_file, "freed objects : %7lu\n", (unsigned long)freed_objects); -+ fprintf(gc_data_file, "zombies : %7lu\n", (unsigned long)zombies); -+ for(i=0; i0 || live_counts[i]>0) { -+ fprintf(gc_data_file, -+ "kept %7lu / freed %7lu objects of type %s\n", -+ (unsigned long)live_counts[i], (unsigned long)free_counts[i], obj_type((int)i)); -+ } -+ } -+ rb_gc_dump(); -+ fflush(gc_data_file); -+ } -+ } - } - - static int -@@ -2158,9 +2856,11 @@ rest_sweep(rb_objspace_t *objspace) - - static void gc_marks(rb_objspace_t *objspace); - -+/* only called from rb_new_obj */ - static int - gc_lazy_sweep(rb_objspace_t *objspace) - { -+ struct timeval gctv1; - int res; - INIT_GC_PROF_PARAMS; - -@@ -2182,7 +2882,6 @@ gc_lazy_sweep(rb_objspace_t *objspace) - GC_PROF_TIMER_STOP(Qfalse); - return res; - } -- after_gc_sweep(objspace); - } - else { - if (heaps_increment(objspace)) { -@@ -2190,6 +2889,18 @@ gc_lazy_sweep(rb_objspace_t *objspace) - return TRUE; - } - } -+ after_gc_sweep(objspace); -+ -+ if (gc_statistics) { -+ gc_time_accumulator_before_gc = gc_time_accumulator; -+ gc_collections++; -+ gettimeofday(&gctv1, NULL); -+ /* -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "Garbage collection started (gc_lazy_sweep)\n"); -+ } -+ */ -+ } - - gc_marks(objspace); - -@@ -2198,6 +2909,10 @@ gc_lazy_sweep(rb_objspace_t *objspace) - set_heaps_increment(objspace); - } - -+ if (gc_statistics) { -+ gc_time_accumulator += elapsed_musecs(gctv1); -+ } -+ - GC_PROF_SWEEP_TIMER_START; - if(!(res = lazy_sweep(objspace))) { - after_gc_sweep(objspace); -@@ -2209,6 +2924,7 @@ gc_lazy_sweep(rb_objspace_t *objspace) - GC_PROF_SWEEP_TIMER_STOP; - - GC_PROF_TIMER_STOP(Qtrue); -+ - return res; - } - -@@ -2435,9 +3151,15 @@ gc_marks(rb_objspace_t *objspace) - rb_thread_t *th = GET_THREAD(); - GC_PROF_MARK_TIMER_START; - -+ /* -+ if (gc_statistics & verbose_gc_stats) { -+ fprintf(gc_data_file, "Marking objects\n"); -+ } -+ */ -+ - objspace->heap.live_num = 0; - objspace->count++; -- -+ live_objects = 0; - - SET_STACK_END; - -@@ -2477,11 +3199,15 @@ gc_marks(rb_objspace_t *objspace) - } - } - GC_PROF_MARK_TIMER_STOP; -+ -+ live_after_last_mark_phase = objspace->heap.live_num; - } - - static int - garbage_collect(rb_objspace_t *objspace) - { -+ struct timeval gctv1; -+ - INIT_GC_PROF_PARAMS; - - if (GC_NOTIFY) printf("start garbage_collect()\n"); -@@ -2497,15 +3223,31 @@ garbage_collect(rb_objspace_t *objspace) - - rest_sweep(objspace); - -+ if (gc_statistics) { -+ gc_time_accumulator_before_gc = gc_time_accumulator; -+ gc_collections++; -+ gettimeofday(&gctv1, NULL); -+ /* -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "Garbage collection started (garbage_collect)\n"); -+ } -+ */ -+ } -+ - during_gc++; - gc_marks(objspace); - -+ if (gc_statistics) { -+ gc_time_accumulator += elapsed_musecs(gctv1); -+ } -+ - GC_PROF_SWEEP_TIMER_START; - gc_sweep(objspace); - GC_PROF_SWEEP_TIMER_STOP; - - GC_PROF_TIMER_STOP(Qtrue); - if (GC_NOTIFY) printf("end garbage_collect()\n"); -+ - return TRUE; - } - -@@ -2994,6 +3736,39 @@ rb_gc_call_finalizer_at_exit(void) - rb_objspace_call_finalizer(&rb_objspace); - } - -+static const char* obj_type(VALUE type) -+{ -+ switch (type) { -+ case T_NIL : return "NIL"; -+ case T_OBJECT : return "OBJECT"; -+ case T_CLASS : return "CLASS"; -+ case T_ICLASS : return "ICLASS"; -+ case T_MODULE : return "MODULE"; -+ case T_FLOAT : return "FLOAT"; -+ case T_COMPLEX: return "COMPLEX"; -+ case T_RATIONAL: return "RATIONAL"; -+ case T_STRING : return "STRING"; -+ case T_REGEXP : return "REGEXP"; -+ case T_ARRAY : return "ARRAY"; -+ case T_FIXNUM : return "FIXNUM"; -+ case T_HASH : return "HASH"; -+ case T_STRUCT : return "STRUCT"; -+ case T_BIGNUM : return "BIGNUM"; -+ case T_FILE : return "FILE"; -+ -+ case T_TRUE : return "TRUE"; -+ case T_FALSE : return "FALSE"; -+ case T_DATA : return "DATA"; -+ case T_MATCH : return "MATCH"; -+ case T_SYMBOL : return "SYMBOL"; -+ case T_ZOMBIE : return "ZOMBIE"; -+ -+ case T_UNDEF : return "UNDEF"; -+ case T_NODE : return "NODE"; -+ default: return "____"; -+ } -+} -+ - static void - rb_objspace_call_finalizer(rb_objspace_t *objspace) - { -@@ -3307,6 +4082,49 @@ count_objects(int argc, VALUE *argv, VALUE os) - return hash; - } - -+/* call-seq: -+ * ObjectSpace.live_objects => number -+ * -+ * Returns the count of objects currently allocated in the system. This goes -+ * down after the garbage collector runs. -+ */ -+static -+VALUE os_live_objects(VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return ULONG2NUM(live_objects); -+} -+ -+unsigned long rb_os_live_objects() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return live_objects; -+} -+ -+/* call-seq: -+ * ObjectSpace.allocated_objects => number -+ * -+ * Returns the count of objects allocated since the Ruby interpreter has -+ * started. This number can only increase. To know how many objects are -+ * currently allocated, use ObjectSpace::live_objects -+ */ -+static -+VALUE os_allocated_objects(VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if defined(HAVE_LONG_LONG) -+ return ULL2NUM(allocated_objects); -+#else -+ return ULONG2NUM(allocated_objects); -+#endif -+} -+ -+unsigned LONG_LONG rb_os_allocated_objects() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return allocated_objects; -+} -+ - /* - * call-seq: - * GC.count -> Integer -@@ -3599,6 +4417,28 @@ Init_GC(void) - rb_define_singleton_method(rb_mGC, "stat", gc_stat, -1); - rb_define_method(rb_mGC, "garbage_collect", rb_gc_start, 0); - -+ rb_define_singleton_method(rb_mGC, "enable_stats", rb_gc_enable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "disable_stats", rb_gc_disable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "stats_enabled?", rb_gc_stats_enabled, 0); -+ rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0); -+ rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); -+ rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); -+ -+ rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); -+ rb_define_singleton_method(rb_mGC, "log_file", rb_gc_log_file, -1); -+ rb_define_singleton_method(rb_mGC, "enable_trace", rb_gc_enable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "disable_trace", rb_gc_disable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "trace_enabled?", rb_gc_trace_enabled, 0); -+ -+ rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); -+ rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); -+ rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); -+#ifdef GC_DEBUG -+ rb_define_singleton_method(rb_mGC, "dump_file_and_line_info", rb_gc_dump_file_and_line_info, -1); -+#endif -+ - 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); -@@ -3612,6 +4452,9 @@ Init_GC(void) - rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1); - rb_define_module_function(rb_mObSpace, "garbage_collect", rb_gc_start, 0); - -+ rb_define_module_function(rb_mObSpace, "live_objects", os_live_objects, 0); -+ rb_define_module_function(rb_mObSpace, "allocated_objects", os_allocated_objects, 0); -+ - rb_define_module_function(rb_mObSpace, "define_finalizer", define_final, -1); - rb_define_module_function(rb_mObSpace, "undefine_finalizer", undefine_final, 1); - diff --git a/patches/ruby/1.9.3/p327/railsexpress/03-display-more-detailed-stack-trace.patch b/patches/ruby/1.9.3/p327/railsexpress/03-display-more-detailed-stack-trace.patch deleted file mode 100644 index 5c7ad30352..0000000000 --- a/patches/ruby/1.9.3/p327/railsexpress/03-display-more-detailed-stack-trace.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/eval_error.c b/eval_error.c -index fd06adf..69c3b48 100644 ---- a/eval_error.c -+++ b/eval_error.c -@@ -164,8 +164,8 @@ error_print(void) - int skip = eclass == rb_eSysStackError; - - #define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5) --#define TRACE_HEAD 8 --#define TRACE_TAIL 5 -+#define TRACE_HEAD 100 -+#define TRACE_TAIL 100 - - for (i = 1; i < len; i++) { - if (TYPE(ptr[i]) == T_STRING) { diff --git a/patches/ruby/1.9.3/p327/railsexpress/04-fork-support-for-gc-logging.patch b/patches/ruby/1.9.3/p327/railsexpress/04-fork-support-for-gc-logging.patch deleted file mode 100644 index cc97b25aad..0000000000 --- a/patches/ruby/1.9.3/p327/railsexpress/04-fork-support-for-gc-logging.patch +++ /dev/null @@ -1,68 +0,0 @@ -diff --git a/gc.c b/gc.c -index 169dfab..629a73a 100644 ---- a/gc.c -+++ b/gc.c -@@ -1322,6 +1322,34 @@ rb_gc_log_file(int argc, VALUE *argv, VALUE self) - } - - /* -+ * Called from process.c before a fork. Flushes the gc log file to -+ * avoid writing the buffered output twice (once in the parent, and -+ * once in the child). -+ */ -+void -+rb_gc_before_fork() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ fflush(gc_data_file); -+} -+ -+/* -+ * Called from process.c after a fork in the child process. Turns off -+ * logging, disables GC stats and resets all gc counters and timing -+ * information. -+ */ -+void -+rb_gc_after_fork() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ rb_gc_disable_stats(); -+ rb_gc_clear_stats(); -+ rb_gc_disable_trace(); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+} -+ -+/* - * call-seq: - * GC.log String => String - * -diff --git a/include/ruby/intern.h b/include/ruby/intern.h -index 927b536..9da266e 100644 ---- a/include/ruby/intern.h -+++ b/include/ruby/intern.h -@@ -425,6 +425,8 @@ void rb_gc_call_finalizer_at_exit(void); - VALUE rb_gc_enable(void); - VALUE rb_gc_disable(void); - VALUE rb_gc_start(void); -+void rb_gc_before_fork _((void)); -+void rb_gc_after_fork _((void)); - #define Init_stack(addr) ruby_init_stack(addr) - void rb_gc_set_params(void); - /* hash.c */ -diff --git a/process.c b/process.c -index 99cfc69..8bee602 100644 ---- a/process.c -+++ b/process.c -@@ -2804,9 +2804,11 @@ rb_f_fork(VALUE obj) - rb_pid_t pid; - - rb_secure(2); -+ rb_gc_before_fork(); - - switch (pid = rb_fork(0, 0, 0, Qnil)) { - case 0: -+ rb_gc_after_fork(); - rb_thread_atfork(); - if (rb_block_given_p()) { - int status; diff --git a/patches/ruby/1.9.3/p327/railsexpress/05-track-live-dataset-size.patch b/patches/ruby/1.9.3/p327/railsexpress/05-track-live-dataset-size.patch deleted file mode 100644 index 555912f7fa..0000000000 --- a/patches/ruby/1.9.3/p327/railsexpress/05-track-live-dataset-size.patch +++ /dev/null @@ -1,45 +0,0 @@ -diff --git a/gc.c b/gc.c -index 629a73a..8ab287e 100644 ---- a/gc.c -+++ b/gc.c -@@ -270,7 +270,6 @@ getrusage_time(void) - #define GC_PROF_DEC_LIVE_NUM - #endif - -- - #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__) - #pragma pack(push, 1) /* magic for reducing sizeof(RVALUE): 24 -> 20 */ - #endif -@@ -1539,6 +1538,24 @@ rb_gc_time() - #endif - } - -+/* -+ * call-seq: -+ * GC.heap_slots_live_after_last_gc => Integer -+ * -+ * Returns the number of heap slots which were live after the last garbage collection. -+ * -+ * GC.heap_slots_live_after_last_gc #=> 231223 -+ * -+ */ -+VALUE -+rb_gc_heap_slots_live_after_last_gc() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return ULONG2NUM(live_after_last_mark_phase); -+} -+ -+ -+ - VALUE rb_mGC; - - void -@@ -4452,6 +4469,7 @@ Init_GC(void) - rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); - rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); - rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots_live_after_last_gc", rb_gc_heap_slots_live_after_last_gc, 0); - rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); - - rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); diff --git a/patches/ruby/1.9.3/p327/railsexpress/06-webrick_204_304_keep_alive_fix.patch b/patches/ruby/1.9.3/p327/railsexpress/06-webrick_204_304_keep_alive_fix.patch deleted file mode 100644 index 34d9b78133..0000000000 --- a/patches/ruby/1.9.3/p327/railsexpress/06-webrick_204_304_keep_alive_fix.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/lib/webrick/httpresponse.rb b/lib/webrick/httpresponse.rb -index 0d36c07..ce72b3f 100644 ---- a/lib/webrick/httpresponse.rb -+++ b/lib/webrick/httpresponse.rb -@@ -202,7 +202,7 @@ module WEBrick - if @header['connection'] == "close" - @keep_alive = false - elsif keep_alive? -- if chunked? || @header['content-length'] -+ if chunked? || @header['content-length'] || @status == 304 || @status == 204 - @header['connection'] = "Keep-Alive" - else - msg = "Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true" diff --git a/patches/ruby/1.9.3/p327/railsexpress/07-export-a-few-more-symbols-for-ruby-prof.patch b/patches/ruby/1.9.3/p327/railsexpress/07-export-a-few-more-symbols-for-ruby-prof.patch deleted file mode 100644 index c7e8492baa..0000000000 --- a/patches/ruby/1.9.3/p327/railsexpress/07-export-a-few-more-symbols-for-ruby-prof.patch +++ /dev/null @@ -1,125 +0,0 @@ -diff --git a/gc.c b/gc.c -index 8ab287e..91994aa 100644 ---- a/gc.c -+++ b/gc.c -@@ -1029,6 +1029,7 @@ ruby_xfree(void *x) - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_enable(void) - { -@@ -1051,6 +1052,7 @@ rb_gc_enable(void) - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_disable(void) - { -@@ -1073,6 +1075,7 @@ rb_gc_disable(void) - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_enable_stats() - { -@@ -1094,6 +1097,7 @@ rb_gc_enable_stats() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_disable_stats() - { -@@ -1113,6 +1117,7 @@ rb_gc_disable_stats() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_stats_enabled() - { -@@ -1132,6 +1137,7 @@ rb_gc_stats_enabled() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_clear_stats() - { -@@ -1155,6 +1161,7 @@ rb_gc_clear_stats() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_allocated_size() - { -@@ -1176,6 +1183,8 @@ rb_gc_allocated_size() - * GC.num_allocations #=> 150 - * - */ -+ -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_num_allocations() - { -@@ -1199,6 +1208,7 @@ rb_gc_num_allocations() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_enable_trace() - { -@@ -1220,6 +1230,7 @@ rb_gc_enable_trace() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_disable_trace() - { -@@ -1239,6 +1250,7 @@ rb_gc_disable_trace() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_trace_enabled() - { -@@ -1267,6 +1279,7 @@ const char* GC_LOGFILE_IVAR = "@gc_logfile_name"; - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_log_file(int argc, VALUE *argv, VALUE self) - { -@@ -1509,6 +1522,7 @@ rb_gc_heap_slots() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_collections() - { -@@ -1527,6 +1541,7 @@ rb_gc_collections() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_time() - { -@@ -4164,6 +4179,7 @@ VALUE os_allocated_objects(VALUE self) - #endif - } - -+RUBY_FUNC_EXPORTED - unsigned LONG_LONG rb_os_allocated_objects() - { - rb_objspace_t *objspace = &rb_objspace; diff --git a/patches/ruby/1.9.3/p327/railsexpress/08-thread-variables.patch b/patches/ruby/1.9.3/p327/railsexpress/08-thread-variables.patch deleted file mode 100644 index a71c027e51..0000000000 --- a/patches/ruby/1.9.3/p327/railsexpress/08-thread-variables.patch +++ /dev/null @@ -1,319 +0,0 @@ -diff --git a/NEWS b/NEWS -index 30fec33..9f6c172 100644 ---- a/NEWS -+++ b/NEWS -@@ -103,6 +103,16 @@ with all sufficient information, see the ChangeLog file. - * String#prepend - * String#byteslice - -+ * Thread -+ * added method: -+ * added Thread#thread_variable_get for getting thread local variables -+ (these are different than Fiber local variables). -+ * added Thread#thread_variable_set for setting thread local variables. -+ * added Thread#thread_variables for getting a list of the thread local -+ variable keys. -+ * added Thread#thread_variable? for testing to see if a particular thread -+ variable has been set. -+ - * Time - * extended method: - * Time#strftime supports %:z and %::z. -diff --git a/test/ruby/test_thread.rb b/test/ruby/test_thread.rb -index e8cb3b1..9ff491d 100644 ---- a/test/ruby/test_thread.rb -+++ b/test/ruby/test_thread.rb -@@ -27,6 +27,79 @@ class TestThread < Test::Unit::TestCase - end - end - -+ def test_main_thread_variable_in_enumerator -+ assert_equal Thread.main, Thread.current -+ -+ Thread.current.thread_variable_set :foo, "bar" -+ -+ thread, value = Fiber.new { -+ Fiber.yield [Thread.current, Thread.current.thread_variable_get(:foo)] -+ }.resume -+ -+ assert_equal Thread.current, thread -+ assert_equal Thread.current.thread_variable_get(:foo), value -+ end -+ -+ def test_thread_variable_in_enumerator -+ Thread.new { -+ Thread.current.thread_variable_set :foo, "bar" -+ -+ thread, value = Fiber.new { -+ Fiber.yield [Thread.current, Thread.current.thread_variable_get(:foo)] -+ }.resume -+ -+ assert_equal Thread.current, thread -+ assert_equal Thread.current.thread_variable_get(:foo), value -+ }.join -+ end -+ -+ def test_thread_variables -+ assert_equal [], Thread.new { Thread.current.thread_variables }.join.value -+ -+ t = Thread.new { -+ Thread.current.thread_variable_set(:foo, "bar") -+ Thread.current.thread_variables -+ } -+ assert_equal [:foo], t.join.value -+ end -+ -+ def test_thread_variable? -+ refute Thread.new { Thread.current.thread_variable?("foo") }.join.value -+ t = Thread.new { -+ Thread.current.thread_variable_set("foo", "bar") -+ }.join -+ -+ assert t.thread_variable?("foo") -+ assert t.thread_variable?(:foo) -+ refute t.thread_variable?(:bar) -+ end -+ -+ def test_thread_variable_strings_and_symbols_are_the_same_key -+ t = Thread.new {}.join -+ t.thread_variable_set("foo", "bar") -+ assert_equal "bar", t.thread_variable_get(:foo) -+ end -+ -+ def test_thread_variable_frozen -+ t = Thread.new { }.join -+ t.freeze -+ assert_raises(RuntimeError) do -+ t.thread_variable_set(:foo, "bar") -+ end -+ end -+ -+ def test_thread_variable_security -+ t = Thread.new { sleep } -+ -+ assert_raises(SecurityError) do -+ Thread.new { $SAFE = 4; t.thread_variable_get(:foo) }.join -+ end -+ -+ assert_raises(SecurityError) do -+ Thread.new { $SAFE = 4; t.thread_variable_set(:foo, :baz) }.join -+ end -+ end -+ - def test_mutex_synchronize - m = Mutex.new - r = 0 -diff --git a/thread.c b/thread.c -index eb0be9f..a8721c4 100644 ---- a/thread.c -+++ b/thread.c -@@ -2112,7 +2112,9 @@ rb_thread_local_aset(VALUE thread, ID id, VALUE val) - * thr[sym] = obj -> obj - * - * Attribute Assignment---Sets or creates the value of a thread-local variable, -- * using either a symbol or a string. See also Thread#[]. -+ * using either a symbol or a string. See also Thread#[]. For -+ * thread-local variables, please see Thread#thread_variable_set -+ * and Thread#thread_variable_get. - */ - - static VALUE -@@ -2123,6 +2125,80 @@ rb_thread_aset(VALUE self, VALUE id, VALUE val) - - /* - * call-seq: -+ * thr.thread_variable_get(key) -> obj or nil -+ * -+ * Returns the value of a thread local variable that has been set. Note that -+ * these are different than fiber local values. For fiber local values, -+ * please see Thread#[] and Thread#[]=. -+ * -+ * Thread local values are carried along with threads, and do not respect -+ * fibers. For example: -+ * -+ * Thread.new { -+ * Thread.current.thread_variable_set("foo", "bar") # set a thread local -+ * Thread.current["foo"] = "bar" # set a fiber local -+ * -+ * Fiber.new { -+ * Fiber.yield [ -+ * Thread.current.thread_variable_get("foo"), # get the thread local -+ * Thread.current["foo"], # get the fiber local -+ * ] -+ * }.resume -+ * }.join.value # => ['bar', nil] -+ * -+ * The value "bar" is returned for the thread local, where nil is returned -+ * for the fiber local. The fiber is executed in the same thread, so the -+ * thread local values are available. -+ * -+ * See also Thread#[] -+ */ -+ -+static VALUE -+rb_thread_variable_get(VALUE thread, VALUE id) -+{ -+ VALUE locals; -+ rb_thread_t *th; -+ -+ GetThreadPtr(thread, th); -+ -+ if (rb_safe_level() >= 4 && th != GET_THREAD()) { -+ rb_raise(rb_eSecurityError, "Insecure: can't access thread locals"); -+ } -+ -+ locals = rb_iv_get(thread, "locals"); -+ return rb_hash_aref(locals, ID2SYM(rb_to_id(id))); -+} -+ -+/* -+ * call-seq: -+ * thr.thread_variable_set(key, value) -+ * -+ * Sets a thread local with +key+ to +value+. Note that these are local to -+ * threads, and not to fibers. Please see Thread#thread_variable_get and -+ * Thread#[] for more information. -+ */ -+ -+static VALUE -+rb_thread_variable_set(VALUE thread, VALUE id, VALUE val) -+{ -+ VALUE locals; -+ rb_thread_t *th; -+ -+ GetThreadPtr(thread, th); -+ -+ if (rb_safe_level() >= 4 && th != GET_THREAD()) { -+ rb_raise(rb_eSecurityError, "Insecure: can't modify thread locals"); -+ } -+ if (OBJ_FROZEN(thread)) { -+ rb_error_frozen("thread locals"); -+ } -+ -+ locals = rb_iv_get(thread, "locals"); -+ return rb_hash_aset(locals, ID2SYM(rb_to_id(id)), val); -+} -+ -+/* -+ * call-seq: - * thr.key?(sym) -> true or false - * - * Returns true if the given string (or symbol) exists as a -@@ -2993,6 +3069,9 @@ rb_gc_save_machine_context(rb_thread_t *th) - - /* - * -+ * For thread-local variables, please see Thread#thread_local_get -+ * and Thread#thread_local_set. -+ * - */ - - void -@@ -3195,6 +3274,76 @@ thgroup_list_i(st_data_t key, st_data_t val, st_data_t data) - return ST_CONTINUE; - } - -+static int -+keys_i(VALUE key, VALUE value, VALUE ary) -+{ -+ rb_ary_push(ary, key); -+ return ST_CONTINUE; -+} -+ -+/* -+ * call-seq: -+ * thr.thread_variables -> array -+ * -+ * Returns an an array of the names of the thread-local variables (as Symbols). -+ * -+ * thr = Thread.new do -+ * Thread.current.thread_variable_set(:cat, 'meow') -+ * Thread.current.thread_variable_set("dog", 'woof') -+ * end -+ * thr.join #=> # -+ * thr.thread_variables #=> [:dog, :cat] -+ * -+ * Note that these are not fiber local variables. Please see Thread#[] and -+ * Thread#thread_variable_get for more details. -+ */ -+ -+static VALUE -+rb_thread_variables(VALUE thread) -+{ -+ VALUE locals; -+ VALUE ary; -+ -+ locals = rb_iv_get(thread, "locals"); -+ ary = rb_ary_new(); -+ rb_hash_foreach(locals, keys_i, ary); -+ -+ return ary; -+} -+ -+/* -+ * call-seq: -+ * thr.thread_variable?(key) -> true or false -+ * -+ * Returns true if the given string (or symbol) exists as a -+ * thread-local variable. -+ * -+ * me = Thread.current -+ * me.thread_variable_set(:oliver, "a") -+ * me.thread_variable?(:oliver) #=> true -+ * me.thread_variable?(:stanley) #=> false -+ * -+ * Note that these are not fiber local variables. Please see Thread#[] and -+ * Thread#thread_variable_get for more details. -+ */ -+ -+static VALUE -+rb_thread_variable_p(VALUE thread, VALUE key) -+{ -+ VALUE locals; -+ -+ locals = rb_iv_get(thread, "locals"); -+ -+ if (!RHASH(locals)->ntbl) -+ return Qfalse; -+ -+ if (st_lookup(RHASH(locals)->ntbl, ID2SYM(rb_to_id(key)), 0)) { -+ return Qtrue; -+ } -+ -+ return Qfalse; -+} -+ - /* - * call-seq: - * thgrp.list -> array -@@ -4670,6 +4819,10 @@ Init_Thread(void) - rb_define_method(rb_cThread, "priority", rb_thread_priority, 0); - rb_define_method(rb_cThread, "priority=", rb_thread_priority_set, 1); - rb_define_method(rb_cThread, "status", rb_thread_status, 0); -+ rb_define_method(rb_cThread, "thread_variable_get", rb_thread_variable_get, 1); -+ rb_define_method(rb_cThread, "thread_variable_set", rb_thread_variable_set, 2); -+ rb_define_method(rb_cThread, "thread_variables", rb_thread_variables, 0); -+ rb_define_method(rb_cThread, "thread_variable?", rb_thread_variable_p, 1); - rb_define_method(rb_cThread, "alive?", rb_thread_alive_p, 0); - rb_define_method(rb_cThread, "stop?", rb_thread_stop_p, 0); - rb_define_method(rb_cThread, "abort_on_exception", rb_thread_abort_exc, 0); -diff --git a/vm.c b/vm.c -index 63141ba..553f180 100644 ---- a/vm.c -+++ b/vm.c -@@ -1896,6 +1896,7 @@ ruby_thread_init(VALUE self) - GetThreadPtr(self, th); - - th_init(th, self); -+ rb_iv_set(self, "locals", rb_hash_new()); - th->vm = vm; - - th->top_wrapper = 0; -@@ -2164,6 +2165,7 @@ Init_VM(void) - - /* create main thread */ - th_self = th->self = TypedData_Wrap_Struct(rb_cThread, &thread_data_type, th); -+ rb_iv_set(th_self, "locals", rb_hash_new()); - vm->main_thread = th; - vm->running_thread = th; - th->vm = vm; diff --git a/patches/ruby/1.9.3/p327/railsexpress/09-faster-loading.patch b/patches/ruby/1.9.3/p327/railsexpress/09-faster-loading.patch deleted file mode 100644 index 0d1a1b5ef4..0000000000 --- a/patches/ruby/1.9.3/p327/railsexpress/09-faster-loading.patch +++ /dev/null @@ -1,747 +0,0 @@ -diff --git a/array.c b/array.c -index e427cb3..c33d106 100644 ---- a/array.c -+++ b/array.c -@@ -295,6 +295,22 @@ rb_ary_frozen_p(VALUE ary) - return Qfalse; - } - -+/* This can be used to take a snapshot of an array (with -+ e.g. rb_ary_replace) and check later whether the array has been -+ modified from the snapshot. The snapshot is cheap, though if -+ something does modify the array it will pay the cost of copying -+ it. */ -+VALUE -+rb_ary_shared_with_p(VALUE ary1, VALUE ary2) -+{ -+ if (!ARY_EMBED_P(ary1) && ARY_SHARED_P(ary1) -+ && !ARY_EMBED_P(ary2) && ARY_SHARED_P(ary2) -+ && RARRAY(ary1)->as.heap.aux.shared == RARRAY(ary2)->as.heap.aux.shared) { -+ return Qtrue; -+ } -+ return Qfalse; -+} -+ - static VALUE - ary_alloc(VALUE klass) - { -diff --git a/file.c b/file.c -index c1db6d7..a28eb6a 100644 ---- a/file.c -+++ b/file.c -@@ -148,23 +148,32 @@ file_path_convert(VALUE name) - return name; - } - --static VALUE --rb_get_path_check(VALUE obj, int level) -+VALUE -+rb_get_path_check_to_string(VALUE obj, int level) - { - VALUE tmp; - ID to_path; -- rb_encoding *enc; - - if (insecure_obj_p(obj, level)) { - rb_insecure_operation(); - } - -+ if (RB_TYPE_P(obj, T_STRING)) { -+ return obj; -+ } - CONST_ID(to_path, "to_path"); - tmp = rb_check_funcall(obj, to_path, 0, 0); - if (tmp == Qundef) { - tmp = obj; - } - StringValue(tmp); -+ return tmp; -+} -+ -+VALUE -+rb_get_path_check_convert(VALUE obj, VALUE tmp, int level) -+{ -+ rb_encoding *enc; - - tmp = file_path_convert(tmp); - if (obj != tmp && insecure_obj_p(tmp, level)) { -@@ -182,6 +191,13 @@ rb_get_path_check(VALUE obj, int level) - return rb_str_new4(tmp); - } - -+static VALUE -+rb_get_path_check(VALUE obj, int level) -+{ -+ VALUE tmp = rb_get_path_check_to_string(obj, level); -+ return rb_get_path_check_convert(obj, tmp, level); -+} -+ - VALUE - rb_get_path_no_checksafe(VALUE obj) - { -@@ -3249,7 +3265,6 @@ rb_file_expand_path(VALUE fname, VALUE dname) - VALUE - rb_file_expand_path_fast(VALUE fname, VALUE dname) - { -- check_expand_path_args(fname, dname); - return rb_file_expand_path_internal(fname, dname, 0, 0, EXPAND_PATH_BUFFER()); - } - -@@ -5237,7 +5252,7 @@ rb_find_file_ext_safe(VALUE *filep, const char *const *ext, int safe_level) - rb_raise(rb_eSecurityError, "loading from non-absolute path %s", f); - } - -- RB_GC_GUARD(load_path) = rb_get_load_path(); -+ RB_GC_GUARD(load_path) = rb_get_expanded_load_path(); - if (!load_path) return 0; - - fname = rb_str_dup(*filep); -@@ -5302,7 +5317,7 @@ rb_find_file_safe(VALUE path, int safe_level) - rb_raise(rb_eSecurityError, "loading from non-absolute path %s", f); - } - -- RB_GC_GUARD(load_path) = rb_get_load_path(); -+ RB_GC_GUARD(load_path) = rb_get_expanded_load_path(); - if (load_path) { - long i; - -diff --git a/hash.c b/hash.c -index fbd8237..8423558 100644 ---- a/hash.c -+++ b/hash.c -@@ -1087,7 +1087,7 @@ clear_i(VALUE key, VALUE value, VALUE dummy) - * - */ - --static VALUE -+VALUE - rb_hash_clear(VALUE hash) - { - rb_hash_modify_check(hash); -diff --git a/include/ruby/intern.h b/include/ruby/intern.h -index 9da266e..b82252a 100644 ---- a/include/ruby/intern.h -+++ b/include/ruby/intern.h -@@ -56,6 +56,7 @@ VALUE rb_ary_tmp_new(long); - void rb_ary_free(VALUE); - void rb_ary_modify(VALUE); - VALUE rb_ary_freeze(VALUE); -+VALUE rb_ary_shared_with_p(VALUE, VALUE); - VALUE rb_ary_aref(int, VALUE*, VALUE); - VALUE rb_ary_subseq(VALUE, long, long); - void rb_ary_store(VALUE, long, VALUE); -@@ -442,6 +443,7 @@ VALUE rb_hash_lookup(VALUE, VALUE); - VALUE rb_hash_lookup2(VALUE, VALUE, VALUE); - VALUE rb_hash_fetch(VALUE, VALUE); - VALUE rb_hash_aset(VALUE, VALUE, VALUE); -+VALUE rb_hash_clear(VALUE); - VALUE rb_hash_delete_if(VALUE); - VALUE rb_hash_delete(VALUE,VALUE); - typedef VALUE rb_hash_update_func(VALUE newkey, VALUE oldkey, VALUE value); -diff --git a/internal.h b/internal.h -index 59c9284..f5af903 100644 ---- a/internal.h -+++ b/internal.h -@@ -94,6 +94,8 @@ VALUE rb_home_dir(const char *user, VALUE result); - VALUE rb_realpath_internal(VALUE basedir, VALUE path, int strict); - VALUE rb_file_expand_path_fast(VALUE, VALUE); - VALUE rb_file_expand_path_internal(VALUE, VALUE, int, int, VALUE); -+VALUE rb_get_path_check_to_string(VALUE, int); -+VALUE rb_get_path_check_convert(VALUE, VALUE, int); - void Init_File(void); - - #ifdef _WIN32 -@@ -119,6 +121,7 @@ VALUE rb_iseq_clone(VALUE iseqval, VALUE newcbase); - - /* load.c */ - VALUE rb_get_load_path(void); -+VALUE rb_get_expanded_load_path(void); - - /* math.c */ - VALUE rb_math_atan2(VALUE, VALUE); -diff --git a/load.c b/load.c -index 163ec4c..e766880 100644 ---- a/load.c -+++ b/load.c -@@ -18,7 +18,6 @@ VALUE ruby_dln_librefs; - #define IS_DLEXT(e) (strcmp((e), DLEXT) == 0) - #endif - -- - static const char *const loadable_ext[] = { - ".rb", DLEXT, - #ifdef DLEXT2 -@@ -34,21 +33,120 @@ rb_get_load_path(void) - return load_path; - } - --VALUE --rb_get_expanded_load_path(void) -+enum expand_type { -+ EXPAND_ALL, -+ EXPAND_RELATIVE, -+ EXPAND_HOME, -+ EXPAND_NON_CACHE -+}; -+ -+/* Construct expanded load path and store it to cache. -+ We rebuild load path partially if the cache is invalid. -+ We don't cache non string object and expand it every times. We ensure that -+ string objects in $LOAD_PATH are frozen. -+ */ -+static void -+rb_construct_expanded_load_path(int type, int *has_relative, int *has_non_cache) - { -- VALUE load_path = rb_get_load_path(); -+ rb_vm_t *vm = GET_VM(); -+ VALUE load_path = vm->load_path; -+ VALUE expanded_load_path = vm->expanded_load_path; - VALUE ary; - long i; -+ int level = rb_safe_level(); - - ary = rb_ary_new2(RARRAY_LEN(load_path)); - for (i = 0; i < RARRAY_LEN(load_path); ++i) { -- VALUE path = rb_file_expand_path_fast(RARRAY_PTR(load_path)[i], Qnil); -- rb_str_freeze(path); -- rb_ary_push(ary, path); -+ VALUE path, as_str, expanded_path; -+ int is_string, non_cache; -+ char *as_cstr; -+ as_str = path = RARRAY_PTR(load_path)[i]; -+ is_string = RB_TYPE_P(path, T_STRING) ? 1 : 0; -+ non_cache = !is_string ? 1 : 0; -+ as_str = rb_get_path_check_to_string(path, level); -+ as_cstr = RSTRING_PTR(as_str); -+ -+ if (!non_cache) { -+ if ((type == EXPAND_RELATIVE && -+ rb_is_absolute_path(as_cstr)) || -+ (type == EXPAND_HOME && -+ (!as_cstr[0] || as_cstr[0] != '~')) || -+ (type == EXPAND_NON_CACHE)) { -+ /* Use cached expanded path. */ -+ rb_ary_push(ary, RARRAY_PTR(expanded_load_path)[i]); -+ continue; -+ } -+ } -+ if (!*has_relative && !rb_is_absolute_path(as_cstr)) -+ *has_relative = 1; -+ if (!*has_non_cache && non_cache) -+ *has_non_cache = 1; -+ /* Freeze only string object. We expand other objects every times. */ -+ if (is_string) -+ rb_str_freeze(path); -+ as_str = rb_get_path_check_convert(path, as_str, level); -+ expanded_path = rb_file_expand_path_fast(as_str, Qnil); -+ rb_str_freeze(expanded_path); -+ rb_ary_push(ary, expanded_path); - } - rb_obj_freeze(ary); -- return ary; -+ vm->expanded_load_path = ary; -+ rb_ary_replace(vm->load_path_snapshot, vm->load_path); -+} -+ -+static VALUE -+load_path_getcwd(void) -+{ -+ char *cwd = my_getcwd(); -+ VALUE cwd_str = rb_filesystem_str_new_cstr(cwd); -+ xfree(cwd); -+ return cwd_str; -+} -+ -+VALUE -+rb_get_expanded_load_path(void) -+{ -+ rb_vm_t *vm = GET_VM(); -+ const VALUE non_cache = Qtrue; -+ -+ if (!rb_ary_shared_with_p(vm->load_path_snapshot, vm->load_path)) { -+ /* The load path was modified. Rebuild the expanded load path. */ -+ int has_relative = 0, has_non_cache = 0; -+ rb_construct_expanded_load_path(EXPAND_ALL, &has_relative, &has_non_cache); -+ if (has_relative) { -+ vm->load_path_check_cache = load_path_getcwd(); -+ } -+ else if (has_non_cache) { -+ /* Non string object. */ -+ vm->load_path_check_cache = non_cache; -+ } -+ else { -+ vm->load_path_check_cache = 0; -+ } -+ } -+ else if (vm->load_path_check_cache == non_cache) { -+ int has_relative = 1, has_non_cache = 1; -+ /* Expand only non-cacheable objects. */ -+ rb_construct_expanded_load_path(EXPAND_NON_CACHE, -+ &has_relative, &has_non_cache); -+ } -+ else if (vm->load_path_check_cache) { -+ int has_relative = 1, has_non_cache = 1; -+ VALUE cwd = load_path_getcwd(); -+ if (!rb_str_equal(vm->load_path_check_cache, cwd)) { -+ /* Current working directory or filesystem encoding was changed. -+ Expand relative load path and non-cacheable objects again. */ -+ vm->load_path_check_cache = cwd; -+ rb_construct_expanded_load_path(EXPAND_RELATIVE, -+ &has_relative, &has_non_cache); -+ } -+ else { -+ /* Expand only tilde (User HOME) and non-cacheable objects. */ -+ rb_construct_expanded_load_path(EXPAND_HOME, -+ &has_relative, &has_non_cache); -+ } -+ } -+ return vm->expanded_load_path; - } - - static VALUE -@@ -63,12 +161,121 @@ get_loaded_features(void) - return GET_VM()->loaded_features; - } - -+static void -+reset_loaded_features_snapshot(void) -+{ -+ rb_vm_t *vm = GET_VM(); -+ rb_ary_replace(vm->loaded_features_snapshot, vm->loaded_features); -+} -+ -+static VALUE -+get_loaded_features_index_raw(void) -+{ -+ return GET_VM()->loaded_features_index; -+} -+ - static st_table * - get_loading_table(void) - { - return GET_VM()->loading_table; - } - -+static void -+features_index_add_single(VALUE short_feature, VALUE offset) -+{ -+ VALUE features_index, this_feature_index; -+ features_index = get_loaded_features_index_raw(); -+ if ((this_feature_index = rb_hash_lookup(features_index, short_feature)) == Qnil) { -+ this_feature_index = rb_ary_new(); -+ rb_hash_aset(features_index, short_feature, this_feature_index); -+ } -+ rb_ary_push(this_feature_index, offset); -+} -+ -+/* Add to the loaded-features index all the required entries for -+ `feature`, located at `offset` in $LOADED_FEATURES. We add an -+ index entry at each string `short_feature` for which -+ feature == "#{prefix}#{short_feature}#{e}" -+ where `e` is empty or matches %r{^\.[^./]*$}, and `prefix` is empty -+ or ends in '/'. This maintains the invariant that `rb_feature_p()` -+ relies on for its fast lookup. -+*/ -+static void -+features_index_add(VALUE feature, VALUE offset) -+{ -+ VALUE short_feature; -+ const char *feature_str, *feature_end, *ext, *p; -+ -+ feature_str = StringValuePtr(feature); -+ feature_end = feature_str + RSTRING_LEN(feature); -+ -+ for (ext = feature_end; ext > feature_str; ext--) -+ if (*ext == '.' || *ext == '/') -+ break; -+ if (*ext != '.') -+ ext = NULL; -+ /* Now `ext` points to the only string matching %r{^\.[^./]*$} that is -+ at the end of `feature`, or is NULL if there is no such string. */ -+ -+ p = ext ? ext : feature_end; -+ while (1) { -+ p--; -+ while (p >= feature_str && *p != '/') -+ p--; -+ if (p < feature_str) -+ break; -+ /* Now *p == '/'. We reach this point for every '/' in `feature`. */ -+ short_feature = rb_str_substr(feature, p + 1 - feature_str, feature_end - p - 1); -+ features_index_add_single(short_feature, offset); -+ if (ext) { -+ short_feature = rb_str_substr(feature, p + 1 - feature_str, ext - p - 1); -+ features_index_add_single(short_feature, offset); -+ } -+ } -+ features_index_add_single(feature, offset); -+ if (ext) { -+ short_feature = rb_str_substr(feature, 0, ext - feature_str); -+ features_index_add_single(short_feature, offset); -+ } -+} -+ -+static VALUE -+get_loaded_features_index(void) -+{ -+ VALUE features; -+ int i; -+ rb_vm_t *vm = GET_VM(); -+ -+ if (!rb_ary_shared_with_p(vm->loaded_features_snapshot, vm->loaded_features)) { -+ /* The sharing was broken; something (other than us in rb_provide_feature()) -+ modified loaded_features. Rebuild the index. */ -+ rb_hash_clear(vm->loaded_features_index); -+ features = vm->loaded_features; -+ for (i = 0; i < RARRAY_LEN(features); i++) { -+ VALUE entry, as_str; -+ as_str = entry = rb_ary_entry(features, i); -+ StringValue(as_str); -+ if (as_str != entry) -+ rb_ary_store(features, i, as_str); -+ rb_str_freeze(as_str); -+ features_index_add(as_str, INT2FIX(i)); -+ } -+ reset_loaded_features_snapshot(); -+ } -+ return vm->loaded_features_index; -+} -+ -+/* This searches `load_path` for a value such that -+ name == "#{load_path[i]}/#{feature}" -+ if `feature` is a suffix of `name`, or otherwise -+ name == "#{load_path[i]}/#{feature}#{ext}" -+ for an acceptable string `ext`. It returns -+ `load_path[i].to_str` if found, else 0. -+ -+ If type is 's', then `ext` is acceptable only if IS_DLEXT(ext); -+ if 'r', then only if IS_RBEXT(ext); otherwise `ext` may be absent -+ or have any value matching `%r{^\.[^./]*$}`. -+*/ - static VALUE - loaded_feature_path(const char *name, long vlen, const char *feature, long len, - int type, VALUE load_path) -@@ -77,7 +284,7 @@ loaded_feature_path(const char *name, long vlen, const char *feature, long len, - long plen; - const char *e; - -- if(vlen < len) return 0; -+ if (vlen < len+1) return 0; - if (!strncmp(name+(vlen-len),feature,len)){ - plen = vlen - len - 1; - } else { -@@ -88,23 +295,22 @@ loaded_feature_path(const char *name, long vlen, const char *feature, long len, - return 0; - plen = e - name - len - 1; - } -+ if (type == 's' && !IS_DLEXT(&name[plen+len+1]) -+ || type == 'r' && !IS_RBEXT(&name[plen+len+1]) -+ || name[plen] != '/') { -+ return 0; -+ } -+ /* Now name == "#{prefix}/#{feature}#{ext}" where ext is acceptable -+ (possibly empty) and prefix is some string of length plen. */ -+ - for (i = 0; i < RARRAY_LEN(load_path); ++i) { - VALUE p = RARRAY_PTR(load_path)[i]; - const char *s = StringValuePtr(p); - long n = RSTRING_LEN(p); - - if (n != plen ) continue; -- if (n && (strncmp(name, s, n) || name[n] != '/')) continue; -- switch (type) { -- case 's': -- if (IS_DLEXT(&name[n+len+1])) return p; -- break; -- case 'r': -- if (IS_RBEXT(&name[n+len+1])) return p; -- break; -- default: -- return p; -- } -+ if (n && strncmp(name, s, n)) continue; -+ return p; - } - return 0; - } -@@ -132,7 +338,7 @@ loaded_feature_path_i(st_data_t v, st_data_t b, st_data_t f) - static int - rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const char **fn) - { -- VALUE v, features, p, load_path = 0; -+ VALUE features, features_index, feature_val, this_feature_index, v, p, load_path = 0; - const char *f, *e; - long i, len, elen, n; - st_table *loading_tbl; -@@ -151,8 +357,39 @@ rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const c - type = 0; - } - features = get_loaded_features(); -- for (i = 0; i < RARRAY_LEN(features); ++i) { -- v = RARRAY_PTR(features)[i]; -+ features_index = get_loaded_features_index(); -+ -+ feature_val = rb_str_new(feature, len); -+ this_feature_index = rb_hash_lookup(features_index, feature_val); -+ /* We search `features` for an entry such that either -+ "#{features[i]}" == "#{load_path[j]}/#{feature}#{e}" -+ for some j, or -+ "#{features[i]}" == "#{feature}#{e}" -+ Here `e` is an "allowed" extension -- either empty or one -+ of the extensions accepted by IS_RBEXT, IS_SOEXT, or -+ IS_DLEXT. Further, if `ext && rb` then `IS_RBEXT(e)`, -+ and if `ext && !rb` then `IS_SOEXT(e) || IS_DLEXT(e)`. -+ -+ If `expanded`, then only the latter form (without load_path[j]) -+ is accepted. Otherwise either form is accepted, *unless* `ext` -+ is false and an otherwise-matching entry of the first form is -+ preceded by an entry of the form -+ "#{features[i2]}" == "#{load_path[j2]}/#{feature}#{e2}" -+ where `e2` matches %r{^\.[^./]*$} but is not an allowed extension. -+ After a "distractor" entry of this form, only entries of the -+ form "#{feature}#{e}" are accepted. -+ -+ In `rb_provide_feature()` and `get_loaded_features_index()` we -+ maintain an invariant that the array `this_feature_index` will -+ point to every entry in `features` which has the form -+ "#{prefix}#{feature}#{e}" -+ where `e` is empty or matches %r{^\.[^./]*$}, and `prefix` is empty -+ or ends in '/'. This includes both match forms above, as well -+ as any distractors, so we may ignore all other entries in `features`. -+ */ -+ for (i = 0; this_feature_index != Qnil && i < RARRAY_LEN(this_feature_index); i++) { -+ long index = FIX2LONG(rb_ary_entry(this_feature_index, i)); -+ v = RARRAY_PTR(features)[index]; - f = StringValuePtr(v); - if ((n = RSTRING_LEN(v)) < len) continue; - if (strncmp(f, feature, len) != 0) { -@@ -175,6 +412,7 @@ rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const c - return 'r'; - } - } -+ - loading_tbl = get_loading_table(); - if (loading_tbl) { - f = 0; -@@ -183,7 +421,7 @@ rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const c - fs.name = feature; - fs.len = len; - fs.type = type; -- fs.load_path = load_path ? load_path : rb_get_load_path(); -+ fs.load_path = load_path ? load_path : rb_get_expanded_load_path(); - fs.result = 0; - st_foreach(loading_tbl, loaded_feature_path_i, (st_data_t)&fs); - if ((f = fs.result) != 0) { -@@ -233,7 +471,7 @@ rb_feature_provided(const char *feature, const char **loading) - - if (*feature == '.' && - (feature[1] == '/' || strncmp(feature+1, "./", 2) == 0)) { -- fullpath = rb_file_expand_path_fast(rb_str_new2(feature), Qnil); -+ fullpath = rb_file_expand_path_fast(rb_get_path(rb_str_new2(feature)), Qnil); - feature = RSTRING_PTR(fullpath); - } - if (ext && !strchr(ext, '/')) { -@@ -254,11 +492,18 @@ rb_feature_provided(const char *feature, const char **loading) - static void - rb_provide_feature(VALUE feature) - { -- if (OBJ_FROZEN(get_loaded_features())) { -+ VALUE features; -+ -+ features = get_loaded_features(); -+ if (OBJ_FROZEN(features)) { - rb_raise(rb_eRuntimeError, - "$LOADED_FEATURES is frozen; cannot append feature"); - } -- rb_ary_push(get_loaded_features(), feature); -+ rb_str_freeze(feature); -+ -+ rb_ary_push(features, feature); -+ features_index_add(feature, INT2FIX(RARRAY_LEN(features)-1)); -+ reset_loaded_features_snapshot(); - } - - void -@@ -774,10 +1019,15 @@ Init_load() - rb_alias_variable(rb_intern("$-I"), id_load_path); - rb_alias_variable(rb_intern("$LOAD_PATH"), id_load_path); - vm->load_path = rb_ary_new(); -+ vm->expanded_load_path = rb_ary_new(); -+ vm->load_path_snapshot = rb_ary_new(); -+ vm->load_path_check_cache = 0; - - rb_define_virtual_variable("$\"", get_loaded_features, 0); - rb_define_virtual_variable("$LOADED_FEATURES", get_loaded_features, 0); - vm->loaded_features = rb_ary_new(); -+ vm->loaded_features_snapshot = rb_ary_new(); -+ vm->loaded_features_index = rb_hash_new(); - - rb_define_global_function("load", rb_f_load, -1); - rb_define_global_function("require", rb_f_require, 1); -diff --git a/ruby.c b/ruby.c -index 3ddd96c..7ffc78e 100644 ---- a/ruby.c -+++ b/ruby.c -@@ -1366,7 +1366,8 @@ process_options(int argc, char **argv, struct cmdline_options *opt) - long i; - VALUE load_path = GET_VM()->load_path; - for (i = 0; i < RARRAY_LEN(load_path); ++i) { -- rb_enc_associate(RARRAY_PTR(load_path)[i], lenc); -+ RARRAY_PTR(load_path)[i] = -+ rb_enc_associate(rb_str_dup(RARRAY_PTR(load_path)[i]), lenc); - } - } - if (!(opt->disable & DISABLE_BIT(gems))) { -diff --git a/test/ruby/test_require.rb b/test/ruby/test_require.rb -index 58a9ee2..ec75096 100644 ---- a/test/ruby/test_require.rb -+++ b/test/ruby/test_require.rb -@@ -356,4 +356,114 @@ class TestRequire < Test::Unit::TestCase - $:.replace(loadpath) - $".replace(features) - end -+ -+ def test_require_changed_current_dir -+ bug7158 = '[ruby-core:47970]' -+ Dir.mktmpdir {|tmp| -+ Dir.chdir(tmp) { -+ Dir.mkdir("a") -+ Dir.mkdir("b") -+ open(File.join("a", "foo.rb"), "w") {} -+ open(File.join("b", "bar.rb"), "w") {|f| -+ f.puts "p :ok" -+ } -+ assert_in_out_err([], <<-INPUT, %w(:ok), [], bug7158) -+ $: << "." -+ Dir.chdir("a") -+ require "foo" -+ Dir.chdir("../b") -+ p :ng unless require "bar" -+ Dir.chdir("..") -+ p :ng if require "b/bar" -+ INPUT -+ } -+ } -+ end -+ -+ def test_require_not_modified_load_path -+ bug7158 = '[ruby-core:47970]' -+ Dir.mktmpdir {|tmp| -+ Dir.chdir(tmp) { -+ open("foo.rb", "w") {} -+ assert_in_out_err([], <<-INPUT, %w(:ok), [], bug7158) -+ a = Object.new -+ def a.to_str -+ "#{tmp}" -+ end -+ $: << a -+ require "foo" -+ last_path = $:.pop -+ p :ok if last_path == a && last_path.class == Object -+ INPUT -+ } -+ } -+ end -+ -+ def test_require_changed_home -+ bug7158 = '[ruby-core:47970]' -+ Dir.mktmpdir {|tmp| -+ Dir.chdir(tmp) { -+ open("foo.rb", "w") {} -+ Dir.mkdir("a") -+ open(File.join("a", "bar.rb"), "w") {} -+ assert_in_out_err([], <<-INPUT, %w(:ok), [], bug7158) -+ $: << '~' -+ ENV['HOME'] = "#{tmp}" -+ require "foo" -+ ENV['HOME'] = "#{tmp}/a" -+ p :ok if require "bar" -+ INPUT -+ } -+ } -+ end -+ -+ def test_require_to_path_redefined_in_load_path -+ bug7158 = '[ruby-core:47970]' -+ Dir.mktmpdir {|tmp| -+ Dir.chdir(tmp) { -+ open("foo.rb", "w") {} -+ assert_in_out_err(["RUBYOPT"=>nil], <<-INPUT, %w(:ok), [], bug7158) -+ a = Object.new -+ def a.to_path -+ "bar" -+ end -+ $: << a -+ begin -+ require "foo" -+ p :ng -+ rescue LoadError -+ end -+ def a.to_path -+ "#{tmp}" -+ end -+ p :ok if require "foo" -+ INPUT -+ } -+ } -+ end -+ -+ def test_require_to_str_redefined_in_load_path -+ bug7158 = '[ruby-core:47970]' -+ Dir.mktmpdir {|tmp| -+ Dir.chdir(tmp) { -+ open("foo.rb", "w") {} -+ assert_in_out_err(["RUBYOPT"=>nil], <<-INPUT, %w(:ok), [], bug7158) -+ a = Object.new -+ def a.to_str -+ "foo" -+ end -+ $: << a -+ begin -+ require "foo" -+ p :ng -+ rescue LoadError -+ end -+ def a.to_str -+ "#{tmp}" -+ end -+ p :ok if require "foo" -+ INPUT -+ } -+ } -+ end - end -diff --git a/vm.c b/vm.c -index 553f180..3436898 100644 ---- a/vm.c -+++ b/vm.c -@@ -1578,7 +1578,12 @@ rb_vm_mark(void *ptr) - RUBY_MARK_UNLESS_NULL(vm->thgroup_default); - RUBY_MARK_UNLESS_NULL(vm->mark_object_ary); - RUBY_MARK_UNLESS_NULL(vm->load_path); -+ RUBY_MARK_UNLESS_NULL(vm->load_path_snapshot); -+ RUBY_MARK_UNLESS_NULL(vm->load_path_check_cache); -+ RUBY_MARK_UNLESS_NULL(vm->expanded_load_path); - RUBY_MARK_UNLESS_NULL(vm->loaded_features); -+ RUBY_MARK_UNLESS_NULL(vm->loaded_features_snapshot); -+ RUBY_MARK_UNLESS_NULL(vm->loaded_features_index); - RUBY_MARK_UNLESS_NULL(vm->top_self); - RUBY_MARK_UNLESS_NULL(vm->coverages); - rb_gc_mark_locations(vm->special_exceptions, vm->special_exceptions + ruby_special_error_count); -diff --git a/vm_core.h b/vm_core.h -index 60146f0..7b25806 100644 ---- a/vm_core.h -+++ b/vm_core.h -@@ -298,7 +298,12 @@ typedef struct rb_vm_struct { - /* load */ - VALUE top_self; - VALUE load_path; -+ VALUE load_path_snapshot; -+ VALUE load_path_check_cache; -+ VALUE expanded_load_path; - VALUE loaded_features; -+ VALUE loaded_features_snapshot; -+ VALUE loaded_features_index; - struct st_table *loading_table; - - /* signal */ diff --git a/patches/ruby/1.9.3/p327/railsexpress/10-falcon-st-opt.patch b/patches/ruby/1.9.3/p327/railsexpress/10-falcon-st-opt.patch deleted file mode 100644 index 33f85f56a3..0000000000 --- a/patches/ruby/1.9.3/p327/railsexpress/10-falcon-st-opt.patch +++ /dev/null @@ -1,2337 +0,0 @@ -diff --git a/common.mk b/common.mk -index c9ef641..56e52b6 100644 ---- a/common.mk -+++ b/common.mk -@@ -638,7 +638,8 @@ file.$(OBJEXT): {$(VPATH)}file.c $(RUBY_H_INCLUDES) {$(VPATH)}io.h \ - gc.$(OBJEXT): {$(VPATH)}gc.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \ - {$(VPATH)}regex.h $(ENCODING_H_INCLUDES) $(VM_CORE_H_INCLUDES) \ - {$(VPATH)}gc.h {$(VPATH)}io.h {$(VPATH)}eval_intern.h {$(VPATH)}util.h \ -- {$(VPATH)}debug.h {$(VPATH)}internal.h {$(VPATH)}constant.h -+ {$(VPATH)}debug.h {$(VPATH)}internal.h {$(VPATH)}constant.h \ -+ {$(VPATH)}pool_alloc.inc.h {$(VPATH)}pool_alloc.h - hash.$(OBJEXT): {$(VPATH)}hash.c $(RUBY_H_INCLUDES) {$(VPATH)}util.h \ - $(ENCODING_H_INCLUDES) - inits.$(OBJEXT): {$(VPATH)}inits.c $(RUBY_H_INCLUDES) \ -@@ -702,7 +703,7 @@ signal.$(OBJEXT): {$(VPATH)}signal.c $(RUBY_H_INCLUDES) \ - $(VM_CORE_H_INCLUDES) {$(VPATH)}debug.h - sprintf.$(OBJEXT): {$(VPATH)}sprintf.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \ - {$(VPATH)}regex.h {$(VPATH)}vsnprintf.c $(ENCODING_H_INCLUDES) --st.$(OBJEXT): {$(VPATH)}st.c $(RUBY_H_INCLUDES) -+st.$(OBJEXT): {$(VPATH)}st.c $(RUBY_H_INCLUDES) {$(VPATH)}pool_alloc.h - strftime.$(OBJEXT): {$(VPATH)}strftime.c $(RUBY_H_INCLUDES) \ - {$(VPATH)}timev.h - string.$(OBJEXT): {$(VPATH)}string.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \ -diff --git a/configure.in b/configure.in -index af5acc4..354b9f2 100644 ---- a/configure.in -+++ b/configure.in -@@ -1324,6 +1324,29 @@ main() { - CFLAGS="$save_CFLAGS"]) - AC_DEFINE_UNQUOTED(GC_MARK_STACKFRAME_WORD, $rb_cv_gc_mark_stackframe_word) - -+AS_CASE(["$target_os"], -+[openbsd*], [ -+ AC_CACHE_CHECK(for heap align log on openbsd, rb_cv_page_size_log, -+ [rb_cv_page_size_log=no -+ for page_log in 12 13; do -+ AC_TRY_RUN([ -+#include -+#include -+ -+int -+main() { -+ if ((int)log2((double)sysconf(_SC_PAGESIZE)) != $page_log) return 1; -+ return 0; -+} -+ ], -+ rb_cv_page_size_log="$page_log"; break) -+ done]) -+ if test $rb_cv_page_size_log != no; then -+ AC_DEFINE_UNQUOTED(HEAP_ALIGN_LOG, $rb_cv_page_size_log) -+ else -+ AC_DEFINE_UNQUOTED(HEAP_ALIGN_LOG, 12) -+ fi -+]) - - dnl Checks for library functions. - AC_TYPE_GETGROUPS -@@ -1424,7 +1447,8 @@ AC_CHECK_FUNCS(fmod killpg wait4 waitpid fork spawnv syscall __syscall chroot ge - setsid telldir seekdir fchmod cosh sinh tanh log2 round\ - setuid setgid daemon select_large_fdset setenv unsetenv\ - mktime timegm gmtime_r clock_gettime gettimeofday poll ppoll\ -- pread sendfile shutdown sigaltstack dl_iterate_phdr) -+ pread sendfile shutdown sigaltstack dl_iterate_phdr\ -+ dup3 pipe2 posix_memalign memalign) - - AC_CACHE_CHECK(for unsetenv returns a value, rb_cv_unsetenv_return_value, - [AC_TRY_COMPILE([ -diff --git a/ext/-test-/st/numhash/numhash.c b/ext/-test-/st/numhash/numhash.c -index e186cd4..53d9e1b 100644 ---- a/ext/-test-/st/numhash/numhash.c -+++ b/ext/-test-/st/numhash/numhash.c -@@ -54,7 +54,7 @@ numhash_i(st_data_t key, st_data_t value, st_data_t arg, int error) - static VALUE - numhash_each(VALUE self) - { -- return st_foreach((st_table *)DATA_PTR(self), numhash_i, self) ? Qtrue : Qfalse; -+ return st_foreach_check((st_table *)DATA_PTR(self), numhash_i, self, 0) ? Qtrue : Qfalse; - } - - void -diff --git a/gc.c b/gc.c -index 91994aa..13dd821 100644 ---- a/gc.c -+++ b/gc.c -@@ -20,10 +20,12 @@ - #include "vm_core.h" - #include "internal.h" - #include "gc.h" -+#include "pool_alloc.h" - #include "constant.h" - #include - #include - #include -+#include - - #ifdef HAVE_SYS_TIME_H - #include -@@ -35,7 +37,12 @@ - - #if defined _WIN32 || defined __CYGWIN__ - #include -+#elif defined(HAVE_POSIX_MEMALIGN) -+#elif defined(HAVE_MEMALIGN) -+#include - #endif -+static void aligned_free(void *); -+static void *aligned_malloc(size_t alignment, size_t size); - - #ifdef HAVE_VALGRIND_MEMCHECK_H - # include -@@ -329,6 +336,24 @@ struct gc_list { - - #define CALC_EXACT_MALLOC_SIZE 0 - -+#ifdef POOL_ALLOC_API -+/* POOL ALLOC API */ -+#define POOL_ALLOC_PART 1 -+#include "pool_alloc.inc.h" -+#undef POOL_ALLOC_PART -+ -+typedef struct pool_layout_t pool_layout_t; -+struct pool_layout_t { -+ pool_header -+ p6, /* st_table && st_table_entry */ -+ p11; /* st_table.bins init size */ -+} pool_layout = { -+ INIT_POOL(void*[6]), -+ INIT_POOL(void*[11]) -+}; -+static void pool_finalize_header(pool_header *header); -+#endif -+ - typedef struct rb_objspace { - struct { - size_t limit; -@@ -338,6 +363,9 @@ typedef struct rb_objspace { - size_t allocations; - #endif - } malloc_params; -+#ifdef POOL_ALLOC_API -+ pool_layout_t *pool_headers; -+#endif - struct { - size_t increment; - struct heaps_slot *ptr; -@@ -407,7 +435,11 @@ typedef struct rb_objspace { - #define ruby_initial_gc_stress initial_params.gc_stress - int *ruby_initial_gc_stress_ptr = &ruby_initial_gc_stress; - #else -+# ifdef POOL_ALLOC_API -+static rb_objspace_t rb_objspace = {{GC_MALLOC_LIMIT}, &pool_layout, {HEAP_MIN_SLOTS}}; -+# else - static rb_objspace_t rb_objspace = {{GC_MALLOC_LIMIT}, {HEAP_MIN_SLOTS}}; -+# endif - int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress; - #endif - #define malloc_limit objspace->malloc_params.limit -@@ -461,6 +493,10 @@ rb_objspace_alloc(void) - memset(objspace, 0, sizeof(*objspace)); - malloc_limit = initial_malloc_limit; - ruby_gc_stress = ruby_initial_gc_stress; -+#ifdef POOL_ALLOC_API -+ objspace->pool_headers = (pool_layout_t*) malloc(sizeof(pool_layout)); -+ memcpy(objspace->pool_headers, &pool_layout, sizeof(pool_layout)); -+#endif - - return objspace; - } -@@ -601,6 +637,13 @@ rb_objspace_free(rb_objspace_t *objspace) - heaps_used = 0; - heaps = 0; - } -+#ifdef POOL_ALLOC_API -+ if (objspace->pool_headers) { -+ pool_finalize_header(&objspace->pool_headers->p6); -+ pool_finalize_header(&objspace->pool_headers->p11); -+ free(objspace->pool_headers); -+ } -+#endif - free(objspace); - } - #endif -@@ -1125,6 +1168,27 @@ rb_gc_stats_enabled() - return gc_statistics ? Qtrue : Qfalse; - } - -+#ifdef POOL_ALLOC_API -+/* POOL ALLOC API */ -+#define POOL_ALLOC_PART 2 -+#include "pool_alloc.inc.h" -+#undef POOL_ALLOC_PART -+ -+void -+ruby_xpool_free(void *ptr) -+{ -+ pool_free_entry((void**)ptr); -+} -+ -+#define CONCRET_POOL_MALLOC(pnts) \ -+void * ruby_xpool_malloc_##pnts##p () { \ -+ return pool_alloc_entry(&rb_objspace.pool_headers->p##pnts ); \ -+} -+CONCRET_POOL_MALLOC(6) -+CONCRET_POOL_MALLOC(11) -+#undef CONCRET_POOL_MALLOC -+ -+#endif - - /* - * call-seq: -@@ -1639,6 +1703,55 @@ allocate_sorted_heaps(rb_objspace_t *objspace, size_t next_heaps_length) - heaps_length = next_heaps_length; - } - -+static void * -+aligned_malloc(size_t alignment, size_t size) -+{ -+ void *res; -+ -+#if defined __MINGW32__ -+ res = __mingw_aligned_malloc(size, alignment); -+#elif defined _WIN32 && !defined __CYGWIN__ -+ 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 -+ -+#if defined(_DEBUG) || defined(GC_DEBUG) -+ /* alignment must be a power of 2 */ -+ assert((alignment - 1) & alignment == 0); -+ assert(alignment % sizeof(void*) == 0); -+#endif -+ return res; -+} -+ -+static void -+aligned_free(void *ptr) -+{ -+#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 -+} -+ - static void - assign_heap_slot(rb_objspace_t *objspace) - { -diff --git a/hash.c b/hash.c -index 8423558..4cb2e2d 100644 ---- a/hash.c -+++ b/hash.c -@@ -44,7 +44,7 @@ rb_any_cmp(VALUE a, VALUE b) - if (FIXNUM_P(a) && FIXNUM_P(b)) { - return a != b; - } -- if (TYPE(a) == T_STRING && RBASIC(a)->klass == rb_cString && -+ if (RB_TYPE_P(a, T_STRING) && RBASIC(a)->klass == rb_cString && - TYPE(b) == T_STRING && RBASIC(b)->klass == rb_cString) { - return rb_str_hash_cmp(a, b); - } -@@ -80,20 +80,14 @@ rb_any_hash(VALUE a) - VALUE hval; - st_index_t hnum; - -- switch (TYPE(a)) { -- case T_FIXNUM: -- case T_SYMBOL: -- case T_NIL: -- case T_FALSE: -- case T_TRUE: -- hnum = rb_hash_end(rb_hash_start((unsigned int)a)); -- break; -- -- case T_STRING: -+ if (SPECIAL_CONST_P(a)) { -+ if (a == Qundef) return 0; -+ hnum = rb_hash_end(rb_hash_start((st_index_t)a)); -+ } -+ else if (BUILTIN_TYPE(a) == T_STRING) { - hnum = rb_str_hash(a); -- break; -- -- default: -+ } -+ else { - hval = rb_hash(a); - hnum = FIX2LONG(hval); - } -@@ -106,10 +100,8 @@ static const struct st_hash_type objhash = { - rb_any_hash, - }; - --static const struct st_hash_type identhash = { -- st_numcmp, -- st_numhash, --}; -+extern const struct st_hash_type st_hashtype_num; -+#define identhash st_hashtype_num - - typedef int st_foreach_func(st_data_t, st_data_t, st_data_t); - -@@ -124,7 +116,6 @@ foreach_safe_i(st_data_t key, st_data_t value, struct foreach_safe_arg *arg) - { - int status; - -- if (key == Qundef) return ST_CONTINUE; - status = (*arg->func)(key, value, arg->arg); - if (status == ST_CONTINUE) { - return ST_CHECK; -@@ -140,7 +131,7 @@ st_foreach_safe(st_table *table, int (*func)(ANYARGS), st_data_t a) - arg.tbl = table; - arg.func = (st_foreach_func *)func; - arg.arg = a; -- if (st_foreach(table, foreach_safe_i, (st_data_t)&arg)) { -+ if (st_foreach_check(table, foreach_safe_i, (st_data_t)&arg, 0)) { - rb_raise(rb_eRuntimeError, "hash modified during iteration"); - } - } -@@ -154,21 +145,21 @@ struct hash_foreach_arg { - }; - - static int --hash_foreach_iter(st_data_t key, st_data_t value, struct hash_foreach_arg *arg) -+hash_foreach_iter(st_data_t key, st_data_t value, st_data_t argp) - { -+ struct hash_foreach_arg *arg = (struct hash_foreach_arg *)argp; - int status; - st_table *tbl; - - tbl = RHASH(arg->hash)->ntbl; -- if ((VALUE)key == Qundef) return ST_CONTINUE; - status = (*arg->func)((VALUE)key, (VALUE)value, arg->arg); - if (RHASH(arg->hash)->ntbl != tbl) { - rb_raise(rb_eRuntimeError, "rehash occurred during iteration"); - } - switch (status) { - case ST_DELETE: -- st_delete_safe(tbl, &key, 0, Qundef); - FL_SET(arg->hash, HASH_DELETED); -+ return ST_DELETE; - case ST_CONTINUE: - break; - case ST_STOP: -@@ -184,7 +175,7 @@ hash_foreach_ensure(VALUE hash) - - if (RHASH(hash)->iter_lev == 0) { - if (FL_TEST(hash, HASH_DELETED)) { -- st_cleanup_safe(RHASH(hash)->ntbl, Qundef); -+ st_cleanup_safe(RHASH(hash)->ntbl, (st_data_t)Qundef); - FL_UNSET(hash, HASH_DELETED); - } - } -@@ -192,9 +183,10 @@ hash_foreach_ensure(VALUE hash) - } - - static VALUE --hash_foreach_call(struct hash_foreach_arg *arg) -+hash_foreach_call(VALUE arg) - { -- if (st_foreach(RHASH(arg->hash)->ntbl, hash_foreach_iter, (st_data_t)arg)) { -+ VALUE hash = ((struct hash_foreach_arg *)arg)->hash; -+ if (st_foreach_check(RHASH(hash)->ntbl, hash_foreach_iter, (st_data_t)arg, (st_data_t)Qundef)) { - rb_raise(rb_eRuntimeError, "hash modified during iteration"); - } - return Qnil; -@@ -447,7 +439,7 @@ rb_hash_rehash_i(VALUE key, VALUE value, VALUE arg) - { - st_table *tbl = (st_table *)arg; - -- if (key != Qundef) st_insert(tbl, key, value); -+ st_insert(tbl, (st_data_t)key, (st_data_t)value); - return ST_CONTINUE; - } - -@@ -490,6 +482,20 @@ rb_hash_rehash(VALUE hash) - return hash; - } - -+static VALUE -+hash_default_value(VALUE hash, VALUE key) -+{ -+ if (rb_method_basic_definition_p(CLASS_OF(hash), id_default)) { -+ VALUE ifnone = RHASH_IFNONE(hash); -+ if (!FL_TEST(hash, HASH_PROC_DEFAULT)) return ifnone; -+ if (key == Qundef) return Qnil; -+ return rb_funcall(ifnone, id_yield, 2, hash, key); -+ } -+ else { -+ return rb_funcall(hash, id_default, 1, key); -+ } -+} -+ - /* - * call-seq: - * hsh[key] -> value -@@ -510,13 +516,7 @@ rb_hash_aref(VALUE hash, VALUE key) - st_data_t val; - - if (!RHASH(hash)->ntbl || !st_lookup(RHASH(hash)->ntbl, key, &val)) { -- if (!FL_TEST(hash, HASH_PROC_DEFAULT) && -- rb_method_basic_definition_p(CLASS_OF(hash), id_default)) { -- return RHASH_IFNONE(hash); -- } -- else { -- return rb_funcall(hash, id_default, 1, key); -- } -+ return hash_default_value(hash, key); - } - return (VALUE)val; - } -@@ -659,7 +659,7 @@ rb_hash_default(int argc, VALUE *argv, VALUE hash) - static VALUE - rb_hash_set_default(VALUE hash, VALUE ifnone) - { -- rb_hash_modify(hash); -+ rb_hash_modify_check(hash); - RHASH_IFNONE(hash) = ifnone; - FL_UNSET(hash, HASH_PROC_DEFAULT); - return ifnone; -@@ -707,7 +707,7 @@ rb_hash_set_default_proc(VALUE hash, VALUE proc) - { - VALUE b; - -- rb_hash_modify(hash); -+ rb_hash_modify_check(hash); - b = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc"); - if (NIL_P(b) || !rb_obj_is_proc(b)) { - rb_raise(rb_eTypeError, -@@ -776,7 +776,7 @@ rb_hash_delete_key(VALUE hash, VALUE key) - if (!RHASH(hash)->ntbl) - return Qundef; - if (RHASH(hash)->iter_lev > 0) { -- if (st_delete_safe(RHASH(hash)->ntbl, &ktmp, &val, Qundef)) { -+ if (st_delete_safe(RHASH(hash)->ntbl, &ktmp, &val, (st_data_t)Qundef)) { - FL_SET(hash, HASH_DELETED); - return (VALUE)val; - } -@@ -809,7 +809,7 @@ rb_hash_delete(VALUE hash, VALUE key) - { - VALUE val; - -- rb_hash_modify(hash); -+ rb_hash_modify_check(hash); - val = rb_hash_delete_key(hash, key); - if (val != Qundef) return val; - if (rb_block_given_p()) { -@@ -828,7 +828,6 @@ shift_i(VALUE key, VALUE value, VALUE arg) - { - struct shift_var *var = (struct shift_var *)arg; - -- if (key == Qundef) return ST_CONTINUE; - if (var->key != Qundef) return ST_STOP; - var->key = key; - var->val = value; -@@ -840,7 +839,6 @@ shift_i_safe(VALUE key, VALUE value, VALUE arg) - { - struct shift_var *var = (struct shift_var *)arg; - -- if (key == Qundef) return ST_CONTINUE; - var->key = key; - var->val = value; - return ST_STOP; -@@ -864,29 +862,25 @@ rb_hash_shift(VALUE hash) - { - struct shift_var var; - -- rb_hash_modify(hash); -- var.key = Qundef; -- rb_hash_foreach(hash, RHASH(hash)->iter_lev > 0 ? shift_i_safe : shift_i, -- (VALUE)&var); -- -- if (var.key != Qundef) { -- if (RHASH(hash)->iter_lev > 0) { -- rb_hash_delete_key(hash, var.key); -+ rb_hash_modify_check(hash); -+ if (RHASH(hash)->ntbl) { -+ var.key = Qundef; -+ rb_hash_foreach(hash, RHASH(hash)->iter_lev > 0 ? shift_i_safe : shift_i, -+ (VALUE)&var); -+ -+ if (var.key != Qundef) { -+ if (RHASH(hash)->iter_lev > 0) { -+ rb_hash_delete_key(hash, var.key); -+ } -+ return rb_assoc_new(var.key, var.val); - } -- return rb_assoc_new(var.key, var.val); -- } -- else if (FL_TEST(hash, HASH_PROC_DEFAULT)) { -- return rb_funcall(RHASH_IFNONE(hash), id_yield, 2, hash, Qnil); -- } -- else { -- return RHASH_IFNONE(hash); - } -+ return hash_default_value(hash, Qnil); - } - - static int - delete_if_i(VALUE key, VALUE value, VALUE hash) - { -- if (key == Qundef) return ST_CONTINUE; - if (RTEST(rb_yield_values(2, key, value))) { - rb_hash_delete_key(hash, key); - } -@@ -912,8 +906,9 @@ VALUE - rb_hash_delete_if(VALUE hash) - { - RETURN_ENUMERATOR(hash, 0, 0); -- rb_hash_modify(hash); -- rb_hash_foreach(hash, delete_if_i, hash); -+ rb_hash_modify_check(hash); -+ if (RHASH(hash)->ntbl) -+ rb_hash_foreach(hash, delete_if_i, hash); - return hash; - } - -@@ -984,7 +979,6 @@ rb_hash_values_at(int argc, VALUE *argv, VALUE hash) - static int - select_i(VALUE key, VALUE value, VALUE result) - { -- if (key == Qundef) return ST_CONTINUE; - if (RTEST(rb_yield_values(2, key, value))) - rb_hash_aset(result, key, value); - return ST_CONTINUE; -@@ -1018,7 +1012,6 @@ rb_hash_select(VALUE hash) - static int - keep_if_i(VALUE key, VALUE value, VALUE hash) - { -- if (key == Qundef) return ST_CONTINUE; - if (!RTEST(rb_yield_values(2, key, value))) { - return ST_DELETE; - } -@@ -1040,7 +1033,7 @@ rb_hash_select_bang(VALUE hash) - st_index_t n; - - RETURN_ENUMERATOR(hash, 0, 0); -- rb_hash_modify(hash); -+ rb_hash_modify_check(hash); - if (!RHASH(hash)->ntbl) - return Qnil; - n = RHASH(hash)->ntbl->num_entries; -@@ -1065,8 +1058,9 @@ VALUE - rb_hash_keep_if(VALUE hash) - { - RETURN_ENUMERATOR(hash, 0, 0); -- rb_hash_modify(hash); -- rb_hash_foreach(hash, keep_if_i, hash); -+ rb_hash_modify_check(hash); -+ if (RHASH(hash)->ntbl) -+ rb_hash_foreach(hash, keep_if_i, hash); - return hash; - } - -@@ -1144,9 +1138,7 @@ rb_hash_aset(VALUE hash, VALUE key, VALUE val) - static int - replace_i(VALUE key, VALUE val, VALUE hash) - { -- if (key != Qundef) { -- rb_hash_aset(hash, key, val); -- } -+ rb_hash_aset(hash, key, val); - - return ST_CONTINUE; - } -@@ -1227,7 +1219,6 @@ rb_hash_empty_p(VALUE hash) - static int - each_value_i(VALUE key, VALUE value) - { -- if (key == Qundef) return ST_CONTINUE; - rb_yield(value); - return ST_CONTINUE; - } -@@ -1262,7 +1253,6 @@ rb_hash_each_value(VALUE hash) - static int - each_key_i(VALUE key, VALUE value) - { -- if (key == Qundef) return ST_CONTINUE; - rb_yield(key); - return ST_CONTINUE; - } -@@ -1296,7 +1286,6 @@ rb_hash_each_key(VALUE hash) - static int - each_pair_i(VALUE key, VALUE value) - { -- if (key == Qundef) return ST_CONTINUE; - rb_yield(rb_assoc_new(key, value)); - return ST_CONTINUE; - } -@@ -1334,7 +1323,6 @@ rb_hash_each_pair(VALUE hash) - static int - to_a_i(VALUE key, VALUE value, VALUE ary) - { -- if (key == Qundef) return ST_CONTINUE; - rb_ary_push(ary, rb_assoc_new(key, value)); - return ST_CONTINUE; - } -@@ -1367,7 +1355,6 @@ inspect_i(VALUE key, VALUE value, VALUE str) - { - VALUE str2; - -- if (key == Qundef) return ST_CONTINUE; - str2 = rb_inspect(key); - if (RSTRING_LEN(str) > 1) { - rb_str_cat2(str, ", "); -@@ -1434,7 +1421,6 @@ rb_hash_to_hash(VALUE hash) - static int - keys_i(VALUE key, VALUE value, VALUE ary) - { -- if (key == Qundef) return ST_CONTINUE; - rb_ary_push(ary, key); - return ST_CONTINUE; - } -@@ -1465,7 +1451,6 @@ rb_hash_keys(VALUE hash) - static int - values_i(VALUE key, VALUE value, VALUE ary) - { -- if (key == Qundef) return ST_CONTINUE; - rb_ary_push(ary, value); - return ST_CONTINUE; - } -@@ -1524,7 +1509,6 @@ rb_hash_search_value(VALUE key, VALUE value, VALUE arg) - { - VALUE *data = (VALUE *)arg; - -- if (key == Qundef) return ST_CONTINUE; - if (rb_equal(value, data[1])) { - data[0] = Qtrue; - return ST_STOP; -@@ -1568,7 +1552,6 @@ eql_i(VALUE key, VALUE val1, VALUE arg) - struct equal_data *data = (struct equal_data *)arg; - st_data_t val2; - -- if (key == Qundef) return ST_CONTINUE; - if (!st_lookup(data->tbl, key, &val2)) { - data->result = Qfalse; - return ST_STOP; -@@ -1599,7 +1582,7 @@ hash_equal(VALUE hash1, VALUE hash2, int eql) - struct equal_data data; - - if (hash1 == hash2) return Qtrue; -- if (TYPE(hash2) != T_HASH) { -+ if (!RB_TYPE_P(hash2, T_HASH)) { - if (!rb_respond_to(hash2, rb_intern("to_hash"))) { - return Qfalse; - } -@@ -1670,7 +1653,6 @@ hash_i(VALUE key, VALUE val, VALUE arg) - st_index_t *hval = (st_index_t *)arg; - st_index_t hdata[2]; - -- if (key == Qundef) return ST_CONTINUE; - hdata[0] = rb_hash(key); - hdata[1] = rb_hash(val); - *hval ^= st_hash(hdata, sizeof(hdata), 0); -@@ -1711,7 +1693,6 @@ rb_hash_hash(VALUE hash) - static int - rb_hash_invert_i(VALUE key, VALUE value, VALUE hash) - { -- if (key == Qundef) return ST_CONTINUE; - rb_hash_aset(hash, value, key); - return ST_CONTINUE; - } -@@ -1740,7 +1721,6 @@ rb_hash_invert(VALUE hash) - static int - rb_hash_update_i(VALUE key, VALUE value, VALUE hash) - { -- if (key == Qundef) return ST_CONTINUE; - hash_update(hash, key); - st_insert(RHASH(hash)->ntbl, key, value); - return ST_CONTINUE; -@@ -1749,7 +1729,6 @@ rb_hash_update_i(VALUE key, VALUE value, VALUE hash) - static int - rb_hash_update_block_i(VALUE key, VALUE value, VALUE hash) - { -- if (key == Qundef) return ST_CONTINUE; - if (rb_hash_has_key(hash, key)) { - value = rb_yield_values(3, key, rb_hash_aref(hash, key), value); - } -@@ -1806,7 +1785,6 @@ rb_hash_update_func_i(VALUE key, VALUE value, VALUE arg0) - struct update_arg *arg = (struct update_arg *)arg0; - VALUE hash = arg->hash; - -- if (key == Qundef) return ST_CONTINUE; - if (rb_hash_has_key(hash, key)) { - value = (*arg->func)(key, rb_hash_aref(hash, key), value); - } -@@ -1863,7 +1841,6 @@ assoc_i(VALUE key, VALUE val, VALUE arg) - { - VALUE *args = (VALUE *)arg; - -- if (key == Qundef) return ST_CONTINUE; - if (RTEST(rb_equal(args[0], key))) { - args[1] = rb_assoc_new(key, val); - return ST_STOP; -@@ -1901,7 +1878,6 @@ rassoc_i(VALUE key, VALUE val, VALUE arg) - { - VALUE *args = (VALUE *)arg; - -- if (key == Qundef) return ST_CONTINUE; - if (RTEST(rb_equal(args[0], val))) { - args[1] = rb_assoc_new(key, val); - return ST_STOP; -@@ -2198,7 +2174,7 @@ rb_env_path_tainted(void) - } - - #if defined(_WIN32) || (defined(HAVE_SETENV) && defined(HAVE_UNSETENV)) --#elif defined __sun__ -+#elif defined __sun - static int - in_origenv(const char *str) - { -@@ -2286,7 +2262,7 @@ ruby_setenv(const char *name, const char *value) - rb_sys_fail("unsetenv"); - #endif - } --#elif defined __sun__ -+#elif defined __sun - size_t len; - char **env_ptr, *str; - if (strchr(name, '=')) { -@@ -3084,11 +3060,9 @@ env_invert(void) - static int - env_replace_i(VALUE key, VALUE val, VALUE keys) - { -- if (key != Qundef) { -- env_aset(Qnil, key, val); -- if (rb_ary_includes(keys, key)) { -- rb_ary_delete(keys, key); -- } -+ env_aset(Qnil, key, val); -+ if (rb_ary_includes(keys, key)) { -+ rb_ary_delete(keys, key); - } - return ST_CONTINUE; - } -@@ -3120,12 +3094,10 @@ env_replace(VALUE env, VALUE hash) - static int - env_update_i(VALUE key, VALUE val) - { -- if (key != Qundef) { -- if (rb_block_given_p()) { -- val = rb_yield_values(3, key, rb_f_getenv(Qnil, key), val); -- } -- env_aset(Qnil, key, val); -+ if (rb_block_given_p()) { -+ val = rb_yield_values(3, key, rb_f_getenv(Qnil, key), val); - } -+ env_aset(Qnil, key, val); - return ST_CONTINUE; - } - -@@ -3150,15 +3122,116 @@ env_update(VALUE env, VALUE hash) - } - - /* -- * A Hash is a collection of key-value pairs. It is -- * similar to an Array, except that indexing is done via -- * arbitrary keys of any object type, not an integer index. Hashes enumerate -- * their values in the order that the corresponding keys were inserted. -+ * A Hash is a dictionary-like collection of unique keys and their values. -+ * Also called associative arrays, they are similar to Arrays, but where an -+ * Array uses integers as its index, a Hash allows you to use any object -+ * type. -+ * -+ * Hashes enumerate their values in the order that the corresponding keys -+ * were inserted. -+ * -+ * A Hash can be easily created by using its implicit form: -+ * -+ * grades = { "Jane Doe" => 10, "Jim Doe" => 6 } -+ * -+ * Hashes allow an alternate syntax form when your keys are always symbols. -+ * Instead of -+ * -+ * options = { :font_size => 10, :font_family => "Arial" } -+ * -+ * You could write it as: -+ * -+ * options = { font_size: 10, font_family: "Arial" } -+ * -+ * Each named key is a symbol you can access in hash: -+ * -+ * options[:font_size] # => 10 -+ * -+ * A Hash can also be created through its ::new method: -+ * -+ * grades = Hash.new -+ * grades["Dorothy Doe"] = 9 - * - * Hashes have a default value that is returned when accessing -- * keys that do not exist in the hash. By default, that value is -- * nil. -+ * keys that do not exist in the hash. If no default is set +nil+ is used. -+ * You can set the default value by sending it as an argument to Hash.new: -+ * -+ * grades = Hash.new(0) -+ * -+ * Or by using the #default= method: -+ * -+ * grades = {"Timmy Doe" => 8} -+ * grades.default = 0 -+ * -+ * Accessing a value in a Hash requires using its key: -+ * -+ * puts grades["Jane Doe"] # => 10 -+ * -+ * === Common Uses -+ * -+ * Hashes are an easy way to represent data structures, such as -+ * -+ * books = {} -+ * books[:matz] = "The Ruby Language" -+ * books[:black] = "The Well-Grounded Rubyist" -+ * -+ * Hashes are also commonly used as a way to have named parameters in -+ * functions. Note that no brackets are used below. If a hash is the last -+ * argument on a method call, no braces are needed, thus creating a really -+ * clean interface: -+ * -+ * Person.create(name: "John Doe", age: 27) -+ * -+ * def self.create(params) -+ * @name = params[:name] -+ * @age = params[:age] -+ * end -+ * -+ * === Hash Keys -+ * -+ * Two objects refer to the same hash key when their hash value -+ * is identical and the two objects are eql? to each other. -+ * -+ * A user-defined class may be used as a hash key if the hash -+ * and eql? methods are overridden to provide meaningful -+ * behavior. By default, separate instances refer to separate hash keys. -+ * -+ * A typical implementation of hash is based on the -+ * object's data while eql? is usually aliased to the overridden -+ * == method: -+ * -+ * class Book -+ * attr_reader :author, :title -+ * -+ * def initialize(author, title) -+ * @author = author -+ * @title = title -+ * end -+ * -+ * def ==(other) -+ * self.class === other and -+ * other.author == @author and -+ * other.title == @title -+ * end -+ * -+ * alias eql? == -+ * -+ * def hash -+ * @author.hash ^ @title.hash # XOR -+ * end -+ * end -+ * -+ * book1 = Book.new 'matz', 'Ruby in a Nutshell' -+ * book2 = Book.new 'matz', 'Ruby in a Nutshell' -+ * -+ * reviews = {} -+ * -+ * reviews[book1] = 'Great reference!' -+ * reviews[book2] = 'Nice and compact!' -+ * -+ * reviews.length #=> 1 - * -+ * See also Object#hash and Object#eql? - */ - - void -diff --git a/include/ruby/st.h b/include/ruby/st.h -index 50f2a75..119dfde 100644 ---- a/include/ruby/st.h -+++ b/include/ruby/st.h -@@ -36,7 +36,7 @@ typedef unsigned long st_data_t; - #elif SIZEOF_LONG_LONG == SIZEOF_VOIDP - typedef unsigned LONG_LONG st_data_t; - #else --# error ---->> st.c requires sizeof(void*) == sizeof(long) to be compiled. <<---- -+# error ---->> st.c requires sizeof(void*) == sizeof(long) or sizeof(LONG_LONG) to be compiled. <<---- - #endif - #define ST_DATA_T_DEFINED - -@@ -74,6 +74,11 @@ struct st_hash_type { - - #define ST_INDEX_BITS (sizeof(st_index_t) * CHAR_BIT) - -+typedef struct st_packed_entry { -+ st_index_t hash; -+ st_data_t key, val; -+} st_packed_entry; -+ - struct st_table { - const struct st_hash_type *type; - st_index_t num_bins; -@@ -91,8 +96,17 @@ struct st_table { - __extension__ - #endif - st_index_t num_entries : ST_INDEX_BITS - 1; -- struct st_table_entry **bins; -- struct st_table_entry *head, *tail; -+ union { -+ struct { -+ struct st_table_entry **bins; -+ struct st_table_entry *head, *tail; -+ } big; -+ struct { -+ struct st_packed_entry *entries; -+ st_index_t real_entries; -+ } packed; -+ st_packed_entry upacked; -+ } as; - }; - - #define st_is_member(table,key) st_lookup((table),(key),(st_data_t *)0) -@@ -114,6 +128,7 @@ int st_insert2(st_table *, st_data_t, st_data_t, st_data_t (*)(st_data_t)); - int st_lookup(st_table *, st_data_t, st_data_t *); - int st_get_key(st_table *, st_data_t, st_data_t *); - int st_foreach(st_table *, int (*)(ANYARGS), st_data_t); -+int st_foreach_check(st_table *, int (*)(ANYARGS), st_data_t, st_data_t); - int st_reverse_foreach(st_table *, int (*)(ANYARGS), st_data_t); - void st_add_direct(st_table *, st_data_t, st_data_t); - void st_free_table(st_table *); -diff --git a/pool_alloc.h b/pool_alloc.h -new file mode 100644 -index 0000000..957708e ---- /dev/null -+++ b/pool_alloc.h -@@ -0,0 +1,11 @@ -+#ifndef POOL_ALLOC_H -+#define POOL_ALLOC_H -+ -+#define POOL_ALLOC_API -+#ifdef POOL_ALLOC_API -+void ruby_xpool_free(void *ptr); -+void *ruby_xpool_malloc_6p(); -+void *ruby_xpool_malloc_11p(); -+#endif -+ -+#endif -diff --git a/pool_alloc.inc.h b/pool_alloc.inc.h -new file mode 100644 -index 0000000..a7879ab ---- /dev/null -+++ b/pool_alloc.inc.h -@@ -0,0 +1,156 @@ -+/* -+ * this is generic pool allocator -+ * you should define following macroses: -+ * ITEM_NAME - unique identifier, which allows to hold functions in a namespace -+ * ITEM_TYPEDEF(name) - passed to typedef to localize item type -+ * free_entry - desired name of function for free entry -+ * alloc_entry - defired name of function for allocate entry -+ */ -+ -+#if POOL_ALLOC_PART == 1 -+#ifdef HEAP_ALIGN_LOG -+#define DEFAULT_POOL_SIZE (1 << HEAP_ALIGN_LOG) -+#else -+#define DEFAULT_POOL_SIZE (sizeof(void*) * 2048) -+#endif -+typedef unsigned int pool_holder_counter; -+ -+typedef struct pool_entry_list pool_entry_list; -+typedef struct pool_holder pool_holder; -+ -+typedef struct pool_header { -+ pool_holder *first; -+ pool_holder *_black_magick; -+ pool_holder_counter size; // size of entry in sizeof(void*) items -+ pool_holder_counter total; // size of entry in sizeof(void*) items -+} pool_header; -+ -+struct pool_holder { -+ pool_holder_counter free, total; -+ pool_header *header; -+ void *freep; -+ pool_holder *fore, *back; -+ void *data[1]; -+}; -+#define POOL_DATA_SIZE(pool_size) (((pool_size) - sizeof(void*) * 6 - offsetof(pool_holder, data)) / sizeof(void*)) -+#define POOL_ENTRY_SIZE(item_type) ((sizeof(item_type) - 1) / sizeof(void*) + 1) -+#define POOL_HOLDER_COUNT(pool_size, item_type) (POOL_DATA_SIZE(pool_size)/POOL_ENTRY_SIZE(item_type)) -+#define INIT_POOL(item_type) {NULL, NULL, POOL_ENTRY_SIZE(item_type), POOL_HOLDER_COUNT(DEFAULT_POOL_SIZE, item_type)} -+ -+#elif POOL_ALLOC_PART == 2 -+static pool_holder * -+pool_holder_alloc(pool_header *header) -+{ -+ pool_holder *holder; -+ pool_holder_counter i, size, count; -+ register void **ptr; -+ -+ size_t sz = offsetof(pool_holder, data) + -+ header->size * header->total * sizeof(void*); -+#define objspace (&rb_objspace) -+ vm_malloc_prepare(objspace, DEFAULT_POOL_SIZE); -+ if (header->first != NULL) return header->first; -+ TRY_WITH_GC(holder = (pool_holder*) aligned_malloc(DEFAULT_POOL_SIZE, sz)); -+ malloc_increase += DEFAULT_POOL_SIZE; -+#if CALC_EXACT_MALLOC_SIZE -+ objspace->malloc_params.allocated_size += DEFAULT_POOL_SIZE; -+ objspace->malloc_params.allocations++; -+#endif -+#undef objspace -+ -+ size = header->size; -+ count = header->total; -+ holder->free = count; -+ holder->total = count; -+ holder->header = header; -+ holder->fore = NULL; -+ holder->back = NULL; -+ holder->freep = &holder->data; -+ ptr = holder->data; -+ for(i = count - 1; i; i-- ) { -+ ptr = *ptr = ptr + size; -+ } -+ *ptr = NULL; -+ header->first = holder; -+ return holder; -+} -+ -+static inline void -+pool_holder_unchaing(pool_header *header, pool_holder *holder) -+{ -+ register pool_holder *fore = holder->fore, *back = holder->back; -+ holder->fore = NULL; -+ holder->back = NULL; -+ if (fore != NULL) fore->back = back; -+ else header->_black_magick = back; -+ if (back != NULL) back->fore = fore; -+ else header->first = fore; -+} -+ -+static inline pool_holder * -+entry_holder(void **entry) -+{ -+ return (pool_holder*)(((uintptr_t)entry) & ~(DEFAULT_POOL_SIZE - 1)); -+} -+ -+static inline void -+pool_free_entry(void **entry) -+{ -+ pool_holder *holder = entry_holder(entry); -+ pool_header *header = holder->header; -+ -+ if (holder->free++ == 0) { -+ register pool_holder *first = header->first; -+ if (first == NULL) { -+ header->first = holder; -+ } else { -+ holder->back = first; -+ holder->fore = first->fore; -+ first->fore = holder; -+ if (holder->fore) -+ holder->fore->back = holder; -+ else -+ header->_black_magick = holder; -+ } -+ } else if (holder->free == holder->total && header->first != holder ) { -+ pool_holder_unchaing(header, holder); -+ aligned_free(holder); -+#if CALC_EXACT_MALLOC_SIZE -+ rb_objspace.malloc_params.allocated_size -= DEFAULT_POOL_SIZE; -+ rb_objspace.malloc_params.allocations--; -+#endif -+ return; -+ } -+ -+ *entry = holder->freep; -+ holder->freep = entry; -+} -+ -+static inline void* -+pool_alloc_entry(pool_header *header) -+{ -+ pool_holder *holder = header->first; -+ void **result; -+ if (holder == NULL) { -+ holder = pool_holder_alloc(header); -+ } -+ -+ result = holder->freep; -+ holder->freep = *result; -+ -+ if (--holder->free == 0) { -+ pool_holder_unchaing(header, holder); -+ } -+ -+ return result; -+} -+ -+static void -+pool_finalize_header(pool_header *header) -+{ -+ if (header->first) { -+ aligned_free(header->first); -+ header->first = NULL; -+ } -+} -+#endif -diff --git a/st.c b/st.c -index fda5784..20ec427 100644 ---- a/st.c -+++ b/st.c -@@ -7,6 +7,7 @@ - #include "st.h" - #else - #include "ruby/ruby.h" -+#include "pool_alloc.h" - #endif - - #include -@@ -25,8 +26,17 @@ struct st_table_entry { - st_table_entry *fore, *back; - }; - --#define ST_DEFAULT_MAX_DENSITY 5 -+#define STATIC_ASSERT(name, expr) typedef int static_assert_##name##_check[(expr) ? 1 : -1]; -+ -+#define ST_DEFAULT_MAX_DENSITY 2 - #define ST_DEFAULT_INIT_TABLE_SIZE 11 -+#define ST_DEFAULT_SECOND_TABLE_SIZE 19 -+#define ST_DEFAULT_PACKED_TABLE_SIZE 18 -+#define PACKED_UNIT (int)(sizeof(st_packed_entry) / sizeof(st_table_entry*)) -+#define MAX_PACKED_HASH (int)(ST_DEFAULT_PACKED_TABLE_SIZE * sizeof(st_table_entry*) / sizeof(st_packed_entry)) -+ -+STATIC_ASSERT(st_packed_entry, sizeof(st_packed_entry) == sizeof(st_table_entry*[PACKED_UNIT])) -+STATIC_ASSERT(st_packed_bins, sizeof(st_packed_entry[MAX_PACKED_HASH]) <= sizeof(st_table_entry*[ST_DEFAULT_PACKED_TABLE_SIZE])) - - /* - * DEFAULT_MAX_DENSITY is the default for the largest we allow the -@@ -38,7 +48,8 @@ struct st_table_entry { - * - */ - --static const struct st_hash_type type_numhash = { -+#define type_numhash st_hashtype_num -+const struct st_hash_type st_hashtype_num = { - st_numcmp, - st_numhash, - }; -@@ -61,20 +72,128 @@ static void rehash(st_table *); - #ifdef RUBY - #define malloc xmalloc - #define calloc xcalloc -+#define realloc xrealloc - #define free(x) xfree(x) - #endif - - #define numberof(array) (int)(sizeof(array) / sizeof((array)[0])) - --#define alloc(type) (type*)malloc((size_t)sizeof(type)) --#define Calloc(n,s) (char*)calloc((n),(s)) -- - #define EQUAL(table,x,y) ((x)==(y) || (*(table)->type->compare)((x),(y)) == 0) - --/* remove cast to unsigned int in the future */ --#define do_hash(key,table) (unsigned int)(st_index_t)(*(table)->type->hash)((key)) -+#define do_hash(key,table) (st_index_t)(*(table)->type->hash)((key)) - #define do_hash_bin(key,table) (do_hash((key), (table))%(table)->num_bins) - -+/* preparation for possible allocation improvements */ -+#ifdef POOL_ALLOC_API -+#define st_alloc_entry() (st_table_entry *)ruby_xpool_malloc_6p() -+#define st_free_entry(entry) ruby_xpool_free(entry) -+#define st_alloc_table() (st_table *)ruby_xpool_malloc_6p() -+#define st_dealloc_table(table) ruby_xpool_free(table) -+static inline st_table_entry ** -+st_alloc_bins(st_index_t size) -+{ -+ st_table_entry **result; -+ if (size == 11) { -+ result = (st_table_entry **) ruby_xpool_malloc_11p(); -+ memset(result, 0, 11 * sizeof(st_table_entry *)); -+ } -+ else -+ result = (st_table_entry **) ruby_xcalloc(size, sizeof(st_table_entry*)); -+ return result; -+} -+static inline void -+st_free_bins(st_table_entry **bins, st_index_t size) -+{ -+ if (size == 11) -+ ruby_xpool_free(bins); -+ else -+ ruby_xfree(bins); -+} -+static inline st_table_entry** -+st_realloc_bins(st_table_entry **bins, st_index_t newsize, st_index_t oldsize) -+{ -+ st_table_entry **new_bins = st_alloc_bins(newsize); -+ st_free_bins(bins, oldsize); -+ return new_bins; -+} -+#else -+#define st_alloc_entry() (st_table_entry *)malloc(sizeof(st_table_entry)) -+#define st_free_entry(entry) free(entry) -+#define st_alloc_table() (st_table *)malloc(sizeof(st_table)) -+#define st_dealloc_table(table) free(table) -+#define st_alloc_bins(size) (st_table_entry **)calloc(size, sizeof(st_table_entry *)) -+#define st_free_bins(bins, size) free(bins) -+static inline st_table_entry** -+st_realloc_bins(st_table_entry **bins, st_index_t newsize, st_index_t oldsize) -+{ -+ bins = (st_table_entry **)realloc(bins, newsize * sizeof(st_table_entry *)); -+ MEMZERO(bins, st_table_entry*, newsize); -+ return bins; -+} -+#endif -+ -+/* Shortage */ -+#define bins as.big.bins -+#define head as.big.head -+#define tail as.big.tail -+#define real_entries as.packed.real_entries -+ -+/* preparation for possible packing improvements */ -+#define PACKED_BINS(table) ((table)->as.packed.entries) -+#define PACKED_ENT(table, i) PACKED_BINS(table)[i] -+#define PKEY(table, i) PACKED_ENT((table), (i)).key -+#define PVAL(table, i) PACKED_ENT((table), (i)).val -+#define PHASH(table, i) PACKED_ENT((table), (i)).hash -+#define PKEY_SET(table, i, v) (PKEY((table), (i)) = (v)) -+#define PVAL_SET(table, i, v) (PVAL((table), (i)) = (v)) -+#define PHASH_SET(table, i, v) (PHASH((table), (i)) = (v)) -+ -+/* this function depends much on packed layout, so that it placed here */ -+static inline void -+remove_packed_entry(st_table *table, st_index_t i) -+{ -+ table->real_entries--; -+ table->num_entries--; -+ if (i < table->real_entries) { -+ MEMMOVE(&PACKED_ENT(table, i), &PACKED_ENT(table, i+1), -+ st_packed_entry, table->real_entries - i); -+ } -+} -+ -+static inline void -+remove_safe_packed_entry(st_table *table, st_index_t i, st_data_t never) -+{ -+ table->num_entries--; -+ PKEY_SET(table, i, never); -+ PVAL_SET(table, i, never); -+ PHASH_SET(table, i, 0); -+} -+ -+/* ultrapacking */ -+#define real_upacked num_bins -+#define MAX_UPACKED_HASH 1 -+#define ULTRAPACKED(table) ((table)->real_upacked <= 1) -+#define UPACKED_ENT(table) ((table)->as.upacked) -+#define UPKEY(table) UPACKED_ENT(table).key -+#define UPVAL(table) UPACKED_ENT(table).val -+#define UPHASH(table) UPACKED_ENT(table).hash -+#define UPKEY_SET(table, v) (UPACKED_ENT(table).key = (v)) -+#define UPVAL_SET(table, v) (UPACKED_ENT(table).val = (v)) -+#define UPHASH_SET(table, v) (UPACKED_ENT(table).hash = (v)) -+static inline void -+remove_upacked_entry(st_table *table) -+{ -+ table->real_upacked = table->num_entries = 0; -+} -+ -+static inline void -+remove_safe_upacked_entry(st_table *table, st_data_t never) -+{ -+ table->num_entries = 0; -+ UPKEY_SET(table, never); -+ UPVAL_SET(table, never); -+ UPHASH_SET(table, 0); -+} - /* - * MINSIZE is the minimum size of a dictionary. - */ -@@ -85,8 +204,8 @@ static void rehash(st_table *); - Table of prime numbers 2^n+a, 2<=n<=30. - */ - static const unsigned int primes[] = { -- 8 + 3, -- 16 + 3, -+ ST_DEFAULT_INIT_TABLE_SIZE, -+ ST_DEFAULT_SECOND_TABLE_SIZE, - 32 + 5, - 64 + 3, - 128 + 3, -@@ -161,8 +280,6 @@ stat_col(void) - } - #endif - --#define MAX_PACKED_NUMHASH (ST_DEFAULT_INIT_TABLE_SIZE/2) -- - st_table* - st_init_table_with_size(const struct st_hash_type *type, st_index_t size) - { -@@ -181,14 +298,19 @@ st_init_table_with_size(const struct st_hash_type *type, st_index_t size) - } - #endif - -- size = new_size(size); /* round up to prime number */ - -- tbl = alloc(st_table); -+ tbl = st_alloc_table(); - tbl->type = type; - tbl->num_entries = 0; -- tbl->entries_packed = type == &type_numhash && size/2 <= MAX_PACKED_NUMHASH; -+ tbl->entries_packed = size <= MAX_PACKED_HASH; -+ if (tbl->entries_packed) { -+ size = size <= MAX_UPACKED_HASH ? 0 : ST_DEFAULT_PACKED_TABLE_SIZE; -+ } -+ else { -+ size = new_size(size); /* round up to prime number */ -+ } - tbl->num_bins = size; -- tbl->bins = (st_table_entry **)Calloc(size, sizeof(st_table_entry*)); -+ tbl->bins = size ? st_alloc_bins(size) : 0; - tbl->head = 0; - tbl->tail = 0; - -@@ -243,17 +365,23 @@ st_clear(st_table *table) - register st_table_entry *ptr, *next; - st_index_t i; - -+ if (ULTRAPACKED(table)) { -+ remove_upacked_entry(table); -+ return; -+ } -+ - if (table->entries_packed) { - table->num_entries = 0; -+ table->real_entries = 0; - return; - } - -- for(i = 0; i < table->num_bins; i++) { -+ for (i = 0; i < table->num_bins; i++) { - ptr = table->bins[i]; - table->bins[i] = 0; - while (ptr != 0) { - next = ptr->next; -- free(ptr); -+ st_free_entry(ptr); - ptr = next; - } - } -@@ -266,14 +394,19 @@ void - st_free_table(st_table *table) - { - st_clear(table); -- free(table->bins); -- free(table); -+ if (!ULTRAPACKED(table)) { -+ st_free_bins(table->bins, table->num_bins); -+ } -+ st_dealloc_table(table); - } - - size_t - st_memsize(const st_table *table) - { -- if (table->entries_packed) { -+ if (ULTRAPACKED(table)) { -+ return sizeof(st_table); -+ } -+ else if (table->entries_packed) { - return table->num_bins * sizeof (void *) + sizeof(st_table); - } - else { -@@ -306,46 +439,77 @@ count_collision(const struct st_hash_type *type) - #define FOUND_ENTRY - #endif - --#define FIND_ENTRY(table, ptr, hash_val, bin_pos) do {\ -- (bin_pos) = (hash_val)%(table)->num_bins;\ -- (ptr) = (table)->bins[(bin_pos)];\ -- FOUND_ENTRY;\ -- if (PTR_NOT_EQUAL((table), (ptr), (hash_val), key)) {\ -- COLLISION;\ -- while (PTR_NOT_EQUAL((table), (ptr)->next, (hash_val), key)) {\ -- (ptr) = (ptr)->next;\ -- }\ -- (ptr) = (ptr)->next;\ -- }\ --} while (0) -+#define FIND_ENTRY(table, ptr, hash_val, bin_pos) \ -+ ((ptr) = find_entry((table), key, (hash_val), ((bin_pos) = (hash_val)%(table)->num_bins))) -+ -+static st_table_entry * -+find_entry(st_table *table, st_data_t key, st_index_t hash_val, st_index_t bin_pos) -+{ -+ register st_table_entry *ptr = table->bins[bin_pos]; -+ FOUND_ENTRY; -+ if (PTR_NOT_EQUAL(table, ptr, hash_val, key)) { -+ COLLISION; -+ while (PTR_NOT_EQUAL(table, ptr->next, hash_val, key)) { -+ ptr = ptr->next; -+ } -+ ptr = ptr->next; -+ } -+ return ptr; -+} -+ -+static inline st_index_t -+find_packed_index(st_table *table, st_index_t hash_val, st_data_t key) -+{ -+ st_index_t i = 0; -+ while (i < table->real_entries && -+ (PHASH(table, i) != hash_val || !EQUAL(table, key, PKEY(table, i)))) { -+ i++; -+ } -+ return i; -+} -+ -+static inline int -+check_upacked(st_table *table, st_index_t hash_val, st_data_t key) -+{ -+ return table->num_entries && -+ UPHASH(table) == hash_val && -+ EQUAL(table, key, UPKEY(table)); -+} - - #define collision_check 0 - - int - st_lookup(st_table *table, register st_data_t key, st_data_t *value) - { -- st_index_t hash_val, bin_pos; -+ st_index_t hash_val; - register st_table_entry *ptr; - -+ hash_val = do_hash(key, table); -+ -+ if (ULTRAPACKED(table)) { -+ if (check_upacked(table, hash_val, key)) { -+ if (value != 0) *value = UPVAL(table); -+ return 1; -+ } -+ return 0; -+ } -+ - if (table->entries_packed) { -- st_index_t i; -- for (i = 0; i < table->num_entries; i++) { -- if ((st_data_t)table->bins[i*2] == key) { -- if (value !=0) *value = (st_data_t)table->bins[i*2+1]; -- return 1; -- } -- } -+ st_index_t i = find_packed_index(table, hash_val, key); -+ if (i < table->real_entries) { -+ if (value != 0) *value = PVAL(table, i); -+ return 1; -+ } - return 0; - } - -- hash_val = do_hash(key, table); -- FIND_ENTRY(table, ptr, hash_val, bin_pos); -+ ptr = find_entry(table, key, hash_val, hash_val % table->num_bins); - - if (ptr == 0) { - return 0; - } - else { -- if (value != 0) *value = ptr->record; -+ if (value != 0) *value = ptr->record; - return 1; - } - } -@@ -353,22 +517,29 @@ st_lookup(st_table *table, register st_data_t key, st_data_t *value) - int - st_get_key(st_table *table, register st_data_t key, st_data_t *result) - { -- st_index_t hash_val, bin_pos; -+ st_index_t hash_val; - register st_table_entry *ptr; - -+ hash_val = do_hash(key, table); -+ -+ if (ULTRAPACKED(table)) { -+ if (check_upacked(table, hash_val, key)) { -+ if (result != 0) *result = UPKEY(table); -+ return 1; -+ } -+ return 0; -+ } -+ - if (table->entries_packed) { -- st_index_t i; -- for (i = 0; i < table->num_entries; i++) { -- if ((st_data_t)table->bins[i*2] == key) { -- if (result !=0) *result = (st_data_t)table->bins[i*2]; -- return 1; -- } -- } -+ st_index_t i = find_packed_index(table, hash_val, key); -+ if (i < table->real_entries) { -+ if (result != 0) *result = PKEY(table, i); -+ return 1; -+ } - return 0; - } - -- hash_val = do_hash(key, table); -- FIND_ENTRY(table, ptr, hash_val, bin_pos); -+ ptr = find_entry(table, key, hash_val, hash_val % table->num_bins); - - if (ptr == 0) { - return 0; -@@ -382,85 +553,151 @@ st_get_key(st_table *table, register st_data_t key, st_data_t *result) - #undef collision_check - #define collision_check 1 - --#define MORE_PACKABLE_P(table) \ -- ((st_index_t)((table)->num_entries+1) * 2 <= (table)->num_bins && \ -- (table)->num_entries+1 <= MAX_PACKED_NUMHASH) -- --#define ADD_DIRECT(table, key, value, hash_val, bin_pos)\ --do {\ -- st_table_entry *entry;\ -- if ((table)->num_entries > ST_DEFAULT_MAX_DENSITY * (table)->num_bins) {\ -- rehash(table);\ -- (bin_pos) = (hash_val) % (table)->num_bins;\ -- }\ -- \ -- entry = alloc(st_table_entry);\ -- \ -- entry->hash = (hash_val);\ -- entry->key = (key);\ -- entry->record = (value);\ -- entry->next = (table)->bins[(bin_pos)];\ -- if ((table)->head != 0) {\ -- entry->fore = 0;\ -- (entry->back = (table)->tail)->fore = entry;\ -- (table)->tail = entry;\ -- }\ -- else {\ -- (table)->head = (table)->tail = entry;\ -- entry->fore = entry->back = 0;\ -- }\ -- (table)->bins[(bin_pos)] = entry;\ -- (table)->num_entries++;\ --} while (0) -+static inline st_table_entry * -+new_entry(st_table * table, st_data_t key, st_data_t value, -+ st_index_t hash_val, register st_index_t bin_pos) -+{ -+ register st_table_entry *entry = st_alloc_entry(); -+ -+ entry->next = table->bins[bin_pos]; -+ table->bins[bin_pos] = entry; -+ entry->hash = hash_val; -+ entry->key = key; -+ entry->record = value; -+ -+ return entry; -+} -+ -+static inline void -+add_direct(st_table *table, st_data_t key, st_data_t value, -+ st_index_t hash_val, register st_index_t bin_pos) -+{ -+ register st_table_entry *entry; -+ if (table->num_entries > ST_DEFAULT_MAX_DENSITY * table->num_bins) { -+ rehash(table); -+ bin_pos = hash_val % table->num_bins; -+ } -+ -+ entry = new_entry(table, key, value, hash_val, bin_pos); -+ -+ if (table->head != 0) { -+ entry->fore = 0; -+ (entry->back = table->tail)->fore = entry; -+ table->tail = entry; -+ } -+ else { -+ table->head = table->tail = entry; -+ entry->fore = entry->back = 0; -+ } -+ table->num_entries++; -+} - - static void - unpack_entries(register st_table *table) - { - st_index_t i; -- struct st_table_entry *packed_bins[MAX_PACKED_NUMHASH*2]; -+ st_packed_entry packed_bins[MAX_PACKED_HASH]; -+ register st_table_entry *entry, *preventry = 0, **chain; - st_table tmp_table = *table; - -- memcpy(packed_bins, table->bins, sizeof(struct st_table_entry *) * table->num_entries*2); -- table->bins = packed_bins; -+ MEMCPY(packed_bins, PACKED_BINS(table), st_packed_entry, MAX_PACKED_HASH); -+ table->as.packed.entries = packed_bins; - tmp_table.entries_packed = 0; -- tmp_table.num_entries = 0; -- memset(tmp_table.bins, 0, sizeof(struct st_table_entry *) * tmp_table.num_bins); -- for (i = 0; i < table->num_entries; i++) { -- st_insert(&tmp_table, (st_data_t)packed_bins[i*2], (st_data_t)packed_bins[i*2+1]); -- } -+#if ST_DEFAULT_INIT_TABLE_SIZE == ST_DEFAULT_PACKED_TABLE_SIZE -+ MEMZERO(tmp_table.bins, st_table_entry*, tmp_table.num_bins); -+#else -+ tmp_table.bins = st_realloc_bins(tmp_table.bins, ST_DEFAULT_INIT_TABLE_SIZE, tmp_table.num_bins); -+ tmp_table.num_bins = ST_DEFAULT_INIT_TABLE_SIZE; -+#endif -+ i = 0; -+ chain = &tmp_table.head; -+ do { -+ st_data_t key = packed_bins[i].key; -+ st_data_t val = packed_bins[i].val; -+ st_index_t hash = packed_bins[i].hash; -+ entry = new_entry(&tmp_table, key, val, hash, -+ hash % ST_DEFAULT_INIT_TABLE_SIZE); -+ *chain = entry; -+ entry->back = preventry; -+ preventry = entry; -+ chain = &entry->fore; -+ } while (++i < MAX_PACKED_HASH); -+ *chain = NULL; -+ tmp_table.tail = entry; - *table = tmp_table; - } - -+static void -+add_packed_direct(st_table *table, st_data_t key, st_data_t value, st_index_t hash_val) -+{ -+ if (table->real_entries < MAX_PACKED_HASH) { -+ st_index_t i = table->real_entries++; -+ PKEY_SET(table, i, key); -+ PVAL_SET(table, i, value); -+ PHASH_SET(table, i, hash_val); -+ table->num_entries++; -+ } -+ else { -+ unpack_entries(table); -+ add_direct(table, key, value, hash_val, hash_val % table->num_bins); -+ } -+} -+ -+static void -+add_upacked_direct(register st_table *table, register st_data_t key, st_data_t value, st_index_t hash_val) -+{ -+ if (table->real_upacked) { -+ st_packed_entry *entries = (st_packed_entry *) st_alloc_bins(ST_DEFAULT_PACKED_TABLE_SIZE); -+ entries[0] = UPACKED_ENT(table); -+ entries[1].hash = hash_val; -+ entries[1].key = key; -+ entries[1].val = value; -+ table->num_bins = ST_DEFAULT_PACKED_TABLE_SIZE; -+ table->real_entries = 2; -+ table->num_entries++; -+ table->as.packed.entries = entries; -+ } -+ else { -+ table->real_upacked = 1; -+ table->num_entries = 1; -+ UPHASH_SET(table, hash_val); -+ UPKEY_SET(table, key); -+ UPVAL_SET(table, value); -+ } -+} -+ - int - st_insert(register st_table *table, register st_data_t key, st_data_t value) - { -- st_index_t hash_val, bin_pos; -+ st_index_t hash_val; -+ register st_index_t bin_pos; - register st_table_entry *ptr; - -+ hash_val = do_hash(key, table); -+ -+ if (ULTRAPACKED(table)) { -+ if (check_upacked(table, hash_val, key)) { -+ UPVAL_SET(table, value); -+ return 1; -+ } -+ add_upacked_direct(table, key, value, hash_val); -+ return 0; -+ } -+ - if (table->entries_packed) { -- st_index_t i; -- for (i = 0; i < table->num_entries; i++) { -- if ((st_data_t)table->bins[i*2] == key) { -- table->bins[i*2+1] = (struct st_table_entry*)value; -- return 1; -- } -- } -- if (MORE_PACKABLE_P(table)) { -- i = table->num_entries++; -- table->bins[i*2] = (struct st_table_entry*)key; -- table->bins[i*2+1] = (struct st_table_entry*)value; -- return 0; -- } -- else { -- unpack_entries(table); -+ st_index_t i = find_packed_index(table, hash_val, key); -+ if (i < table->real_entries) { -+ PVAL_SET(table, i, value); -+ return 1; - } -+ add_packed_direct(table, key, value, hash_val); -+ return 0; - } - -- hash_val = do_hash(key, table); - FIND_ENTRY(table, ptr, hash_val, bin_pos); - - if (ptr == 0) { -- ADD_DIRECT(table, key, value, hash_val, bin_pos); -+ add_direct(table, key, value, hash_val, bin_pos); - return 0; - } - else { -@@ -473,34 +710,38 @@ int - st_insert2(register st_table *table, register st_data_t key, st_data_t value, - st_data_t (*func)(st_data_t)) - { -- st_index_t hash_val, bin_pos; -+ st_index_t hash_val; -+ register st_index_t bin_pos; - register st_table_entry *ptr; - -+ hash_val = do_hash(key, table); -+ -+ if (ULTRAPACKED(table)) { -+ if (check_upacked(table, hash_val, key)) { -+ UPVAL_SET(table, value); -+ return 1; -+ } -+ key = (*func)(key); -+ add_upacked_direct(table, key, value, hash_val); -+ return 0; -+ } -+ - if (table->entries_packed) { -- st_index_t i; -- for (i = 0; i < table->num_entries; i++) { -- if ((st_data_t)table->bins[i*2] == key) { -- table->bins[i*2+1] = (struct st_table_entry*)value; -- return 1; -- } -- } -- if (MORE_PACKABLE_P(table)) { -- i = table->num_entries++; -- table->bins[i*2] = (struct st_table_entry*)key; -- table->bins[i*2+1] = (struct st_table_entry*)value; -- return 0; -- } -- else { -- unpack_entries(table); -- } -+ st_index_t i = find_packed_index(table, hash_val, key); -+ if (i < table->real_entries) { -+ PVAL_SET(table, i, value); -+ return 1; -+ } -+ key = (*func)(key); -+ add_packed_direct(table, key, value, hash_val); -+ return 0; - } - -- hash_val = do_hash(key, table); - FIND_ENTRY(table, ptr, hash_val, bin_pos); - - if (ptr == 0) { - key = (*func)(key); -- ADD_DIRECT(table, key, value, hash_val, bin_pos); -+ add_direct(table, key, value, hash_val, bin_pos); - return 0; - } - else { -@@ -512,36 +753,30 @@ st_insert2(register st_table *table, register st_data_t key, st_data_t value, - void - st_add_direct(st_table *table, st_data_t key, st_data_t value) - { -- st_index_t hash_val, bin_pos; -+ st_index_t hash_val; -+ -+ hash_val = do_hash(key, table); -+ if (ULTRAPACKED(table)) { -+ add_upacked_direct(table, key, value, hash_val); -+ return; -+ } - - if (table->entries_packed) { -- int i; -- if (MORE_PACKABLE_P(table)) { -- i = table->num_entries++; -- table->bins[i*2] = (struct st_table_entry*)key; -- table->bins[i*2+1] = (struct st_table_entry*)value; -- return; -- } -- else { -- unpack_entries(table); -- } -+ add_packed_direct(table, key, value, hash_val); -+ return; - } - -- hash_val = do_hash(key, table); -- bin_pos = hash_val % table->num_bins; -- ADD_DIRECT(table, key, value, hash_val, bin_pos); -+ add_direct(table, key, value, hash_val, hash_val % table->num_bins); - } - - static void - rehash(register st_table *table) - { - register st_table_entry *ptr, **new_bins; -- st_index_t i, new_num_bins, hash_val; -+ st_index_t new_num_bins, hash_val; - - new_num_bins = new_size(table->num_bins+1); -- new_bins = (st_table_entry**) -- xrealloc(table->bins, new_num_bins * sizeof(st_table_entry*)); -- for (i = 0; i < new_num_bins; ++i) new_bins[i] = 0; -+ new_bins = st_realloc_bins(table->bins, new_num_bins, table->num_bins); - table->num_bins = new_num_bins; - table->bins = new_bins; - -@@ -558,34 +793,37 @@ st_table* - st_copy(st_table *old_table) - { - st_table *new_table; -- st_table_entry *ptr, *entry, *prev, **tail; -+ st_table_entry *ptr, *entry, *prev, **tailp; - st_index_t num_bins = old_table->num_bins; - st_index_t hash_val; - -- new_table = alloc(st_table); -+ new_table = st_alloc_table(); - if (new_table == 0) { - return 0; - } - - *new_table = *old_table; -- new_table->bins = (st_table_entry**) -- Calloc((unsigned)num_bins, sizeof(st_table_entry*)); -+ if (ULTRAPACKED(old_table)) { -+ return new_table; -+ } -+ -+ new_table->bins = st_alloc_bins(num_bins); - - if (new_table->bins == 0) { -- free(new_table); -+ st_dealloc_table(new_table); - return 0; - } - - if (old_table->entries_packed) { -- memcpy(new_table->bins, old_table->bins, sizeof(struct st_table_entry *) * old_table->num_bins); -+ MEMCPY(new_table->bins, old_table->bins, st_table_entry*, old_table->num_bins); - return new_table; - } - - if ((ptr = old_table->head) != 0) { - prev = 0; -- tail = &new_table->head; -+ tailp = &new_table->head; - do { -- entry = alloc(st_table_entry); -+ entry = st_alloc_entry(); - if (entry == 0) { - st_free_table(new_table); - return 0; -@@ -595,8 +833,8 @@ st_copy(st_table *old_table) - entry->next = new_table->bins[hash_val]; - new_table->bins[hash_val] = entry; - entry->back = prev; -- *tail = prev = entry; -- tail = &entry->fore; -+ *tailp = prev = entry; -+ tailp = &entry->fore; - } while ((ptr = ptr->fore) != 0); - new_table->tail = prev; - } -@@ -604,21 +842,22 @@ st_copy(st_table *old_table) - return new_table; - } - --#define REMOVE_ENTRY(table, ptr) do \ -- { \ -- if ((ptr)->fore == 0 && (ptr)->back == 0) { \ -- (table)->head = 0; \ -- (table)->tail = 0; \ -- } \ -- else { \ -- st_table_entry *fore = (ptr)->fore, *back = (ptr)->back; \ -- if (fore) fore->back = back; \ -- if (back) back->fore = fore; \ -- if ((ptr) == (table)->head) (table)->head = fore; \ -- if ((ptr) == (table)->tail) (table)->tail = back; \ -- } \ -- (table)->num_entries--; \ -- } while (0) -+static inline void -+remove_entry(st_table *table, st_table_entry *ptr) -+{ -+ if (ptr->fore == 0 && ptr->back == 0) { -+ table->head = 0; -+ table->tail = 0; -+ } -+ else { -+ st_table_entry *fore = ptr->fore, *back = ptr->back; -+ if (fore) fore->back = back; -+ if (back) back->fore = fore; -+ if (ptr == table->head) table->head = fore; -+ if (ptr == table->tail) table->tail = back; -+ } -+ table->num_entries--; -+} - - int - st_delete(register st_table *table, register st_data_t *key, st_data_t *value) -@@ -627,30 +866,38 @@ st_delete(register st_table *table, register st_data_t *key, st_data_t *value) - st_table_entry **prev; - register st_table_entry *ptr; - -+ hash_val = do_hash(*key, table); -+ -+ if (ULTRAPACKED(table)) { -+ if (check_upacked(table, hash_val, *key)) { -+ if (value != 0) *value = UPVAL(table); -+ *key = UPKEY(table); -+ remove_upacked_entry(table); -+ return 1; -+ } -+ return 0; -+ } -+ - if (table->entries_packed) { -- st_index_t i; -- for (i = 0; i < table->num_entries; i++) { -- if ((st_data_t)table->bins[i*2] == *key) { -- if (value != 0) *value = (st_data_t)table->bins[i*2+1]; -- table->num_entries--; -- memmove(&table->bins[i*2], &table->bins[(i+1)*2], -- sizeof(struct st_table_entry*) * 2*(table->num_entries-i)); -- return 1; -- } -+ st_index_t i = find_packed_index(table, hash_val, *key); -+ if (i < table->real_entries) { -+ if (value != 0) *value = PVAL(table, i); -+ *key = PKEY(table, i); -+ remove_packed_entry(table, i); -+ return 1; - } - if (value != 0) *value = 0; - return 0; - } - -- hash_val = do_hash_bin(*key, table); -- -- for (prev = &table->bins[hash_val]; (ptr = *prev) != 0; prev = &ptr->next) { -+ prev = &table->bins[hash_val % table->num_bins]; -+ for (;(ptr = *prev) != 0; prev = &ptr->next) { - if (EQUAL(table, *key, ptr->key)) { - *prev = ptr->next; -- REMOVE_ENTRY(table, ptr); -+ remove_entry(table, ptr); - if (value != 0) *value = ptr->record; - *key = ptr->key; -- free(ptr); -+ st_free_entry(ptr); - return 1; - } - } -@@ -665,25 +912,36 @@ st_delete_safe(register st_table *table, register st_data_t *key, st_data_t *val - st_index_t hash_val; - register st_table_entry *ptr; - -+ hash_val = do_hash(*key, table); -+ -+ if (ULTRAPACKED(table)) { -+ if (check_upacked(table, hash_val, *key)) { -+ if (value != 0) *value = UPVAL(table); -+ *key = UPKEY(table); -+ remove_safe_upacked_entry(table, never); -+ return 1; -+ } -+ if (value != 0) *value = 0; -+ return 0; -+ } -+ - if (table->entries_packed) { -- st_index_t i; -- for (i = 0; i < table->num_entries; i++) { -- if ((st_data_t)table->bins[i*2] == *key) { -- if (value != 0) *value = (st_data_t)table->bins[i*2+1]; -- table->bins[i*2] = (void *)never; -- return 1; -- } -+ st_index_t i = find_packed_index(table, hash_val, *key); -+ if (i < table->real_entries) { -+ if (value != 0) *value = PVAL(table, i); -+ *key = PKEY(table, i); -+ remove_safe_packed_entry(table, i, never); -+ return 1; - } - if (value != 0) *value = 0; - return 0; - } - -- hash_val = do_hash_bin(*key, table); -- ptr = table->bins[hash_val]; -+ ptr = table->bins[hash_val % table->num_bins]; - - for (; ptr != 0; ptr = ptr->next) { - if ((ptr->key != never) && EQUAL(table, ptr->key, *key)) { -- REMOVE_ENTRY(table, ptr); -+ remove_entry(table, ptr); - *key = ptr->key; - if (value != 0) *value = ptr->record; - ptr->key = ptr->record = never; -@@ -701,17 +959,23 @@ st_cleanup_safe(st_table *table, st_data_t never) - st_table_entry *ptr, **last, *tmp; - st_index_t i; - -+ if (ULTRAPACKED(table)) { -+ table->real_upacked = table->num_entries; -+ return; -+ } -+ - if (table->entries_packed) { - st_index_t i = 0, j = 0; -- while ((st_data_t)table->bins[i*2] != never) { -- if (i++ == table->num_entries) return; -+ while (PKEY(table, i) != never) { -+ if (i++ == table->real_entries) return; - } -- for (j = i; ++i < table->num_entries;) { -- if ((st_data_t)table->bins[i*2] == never) continue; -- table->bins[j*2] = table->bins[i*2]; -- table->bins[j*2+1] = table->bins[i*2+1]; -+ for (j = i; ++i < table->real_entries;) { -+ if (PKEY(table, i) == never) continue; -+ PACKED_ENT(table, j) = PACKED_ENT(table, i); - j++; - } -+ table->real_entries = j; -+ /* table->num_entries really should be equal j at this moment, but let set it anyway */ - table->num_entries = j; - return; - } -@@ -722,7 +986,7 @@ st_cleanup_safe(st_table *table, st_data_t never) - if (ptr->key == never) { - tmp = ptr; - *last = ptr = ptr->next; -- free(tmp); -+ st_free_entry(tmp); - } - else { - ptr = *(last = &ptr->next); -@@ -732,50 +996,78 @@ st_cleanup_safe(st_table *table, st_data_t never) - } - - int --st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) -+st_foreach_check(st_table *table, int (*func)(ANYARGS), st_data_t arg, st_data_t never) - { - st_table_entry *ptr, **last, *tmp; - enum st_retval retval; -- st_index_t i; -+ st_data_t key, val; -+ st_index_t hash, i = 0; -+ -+ if (table->num_entries == 0) { -+ return 0; -+ } -+ -+ if (ULTRAPACKED(table)) { -+ key = UPKEY(table); -+ val = UPVAL(table); -+ hash = UPHASH(table); -+ if (key == never) return 0; -+ retval = (*func)(key, val, arg); -+ if (!ULTRAPACKED(table)) { -+ goto packed; -+ } -+ switch(retval) { -+ case ST_CHECK: -+ if (UPHASH(table) == 0 && UPKEY(table) == never) -+ break; -+ if (check_upacked(table, hash, key)) -+ break; -+ goto deleted; -+ case ST_DELETE: -+ remove_safe_upacked_entry(table, never); -+ case ST_CONTINUE: -+ case ST_STOP: -+ break; -+ } -+ return 0; -+ } - - if (table->entries_packed) { -- for (i = 0; i < table->num_entries; i++) { -- st_index_t j; -- st_data_t key, val; -- key = (st_data_t)table->bins[i*2]; -- val = (st_data_t)table->bins[i*2+1]; -- retval = (*func)(key, val, arg); -+ for (i = 0; i < table->real_entries; i++) { -+ key = PKEY(table, i); -+ val = PVAL(table, i); -+ hash = PHASH(table, i); -+ if (key == never) continue; -+ retval = (*func)(key, val, arg); -+ packed: - if (!table->entries_packed) { -- FIND_ENTRY(table, ptr, key, i); -+ FIND_ENTRY(table, ptr, hash, i); - if (retval == ST_CHECK) { - if (!ptr) goto deleted; - goto unpacked_continue; - } - goto unpacked; - } -- switch (retval) { -+ switch (retval) { - case ST_CHECK: /* check if hash is modified during iteration */ -- for (j = 0; j < table->num_entries; j++) { -- if ((st_data_t)table->bins[j*2] == key) -- break; -- } -- if (j == table->num_entries) { -+ if (PHASH(table, i) == 0 && PKEY(table, i) == never) { -+ break; -+ } -+ i = find_packed_index(table, hash, key); -+ if (i == table->real_entries) { - goto deleted; -- } -+ } - /* fall through */ - case ST_CONTINUE: - break; - case ST_STOP: - return 0; - case ST_DELETE: -- table->num_entries--; -- memmove(&table->bins[i*2], &table->bins[(i+1)*2], -- sizeof(struct st_table_entry*) * 2*(table->num_entries-i)); -- i--; -- break; -- } -- } -- return 0; -+ remove_safe_packed_entry(table, i, never); -+ break; -+ } -+ } -+ return 0; - } - else { - ptr = table->head; -@@ -783,6 +1075,8 @@ st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) - - if (ptr != 0) { - do { -+ if (ptr->key == never) -+ goto unpacked_continue; - i = ptr->hash % table->num_bins; - retval = (*func)(ptr->key, ptr->record, arg); - unpacked: -@@ -808,10 +1102,100 @@ st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) - for (; (tmp = *last) != 0; last = &tmp->next) { - if (ptr == tmp) { - tmp = ptr->fore; -+ remove_entry(table, ptr); -+ ptr->key = ptr->record = never; -+ ptr->hash = 0; -+ ptr = tmp; -+ break; -+ } -+ } -+ } -+ } while (ptr && table->head); -+ } -+ return 0; -+} -+ -+int -+st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) -+{ -+ st_table_entry *ptr, **last, *tmp; -+ enum st_retval retval; -+ st_data_t key, val; -+ st_index_t hash, i = 0; -+ -+ if (table->num_entries == 0) { -+ return 0; -+ } -+ -+ if (ULTRAPACKED(table)) { -+ key = UPKEY(table); -+ val = UPVAL(table); -+ hash = UPHASH(table); -+ retval = (*func)(key, val, arg); -+ if (!ULTRAPACKED(table)) { -+ goto packed; -+ } -+ switch (retval) { -+ case ST_DELETE: -+ remove_upacked_entry(table); -+ case ST_CONTINUE: -+ case ST_CHECK: -+ case ST_STOP: -+ break; -+ } -+ return 0; -+ } -+ -+ if (table->entries_packed) { -+ for (i = 0; i < table->real_entries; i++) { -+ key = PKEY(table, i); -+ val = PVAL(table, i); -+ hash = PHASH(table, i); -+ retval = (*func)(key, val, arg); -+ packed: -+ if (!table->entries_packed) { -+ FIND_ENTRY(table, ptr, hash, i); -+ if (!ptr) return 0; -+ goto unpacked; -+ } -+ switch (retval) { -+ case ST_CONTINUE: -+ break; -+ case ST_CHECK: -+ case ST_STOP: -+ return 0; -+ case ST_DELETE: -+ remove_packed_entry(table, i); -+ i--; -+ break; -+ } -+ } -+ return 0; -+ } -+ else { -+ ptr = table->head; -+ } -+ -+ if (ptr != 0) { -+ do { -+ i = ptr->hash % table->num_bins; -+ retval = (*func)(ptr->key, ptr->record, arg); -+ unpacked: -+ switch (retval) { -+ case ST_CONTINUE: -+ ptr = ptr->fore; -+ break; -+ case ST_CHECK: -+ case ST_STOP: -+ return 0; -+ case ST_DELETE: -+ last = &table->bins[ptr->hash % table->num_bins]; -+ for (; (tmp = *last) != 0; last = &tmp->next) { -+ if (ptr == tmp) { -+ tmp = ptr->fore; - *last = ptr->next; -- REMOVE_ENTRY(table, ptr); -- free(ptr); -- if (ptr == tmp) return 0; -+ remove_entry(table, ptr); -+ st_free_entry(ptr); - ptr = tmp; - break; - } -@@ -834,13 +1218,13 @@ st_reverse_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) - for (i = table->num_entries-1; 0 <= i; i--) { - int j; - st_data_t key, val; -- key = (st_data_t)table->bins[i*2]; -- val = (st_data_t)table->bins[i*2+1]; -+ key = PKEY(table, i); -+ val = PVAL(table, i); - retval = (*func)(key, val, arg); - switch (retval) { - case ST_CHECK: /* check if hash is modified during iteration */ - for (j = 0; j < table->num_entries; j++) { -- if ((st_data_t)table->bins[j*2] == key) -+ if (PKEY(table, j) == key) - break; - } - if (j == table->num_entries) { -@@ -854,9 +1238,7 @@ st_reverse_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) - case ST_STOP: - return 0; - case ST_DELETE: -- table->num_entries--; -- memmove(&table->bins[i*2], &table->bins[(i+1)*2], -- sizeof(struct st_table_entry*) * 2*(table->num_entries-i)); -+ remove_packed_entry(table, i); - break; - } - } -@@ -889,8 +1271,8 @@ st_reverse_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) - if (ptr == tmp) { - tmp = ptr->back; - *last = ptr->next; -- REMOVE_ENTRY(table, ptr); -- free(ptr); -+ remove_entry(table, ptr); -+ st_free_entry(ptr); - ptr = tmp; - break; - } diff --git a/patches/ruby/1.9.3/p327/railsexpress/11-falcon-array-queue.patch b/patches/ruby/1.9.3/p327/railsexpress/11-falcon-array-queue.patch deleted file mode 100644 index 3469efeedf..0000000000 --- a/patches/ruby/1.9.3/p327/railsexpress/11-falcon-array-queue.patch +++ /dev/null @@ -1,24173 +0,0 @@ -diff --git a/array.c b/array.c -index c33d106..a459a4a 100644 ---- a/array.c -+++ b/array.c -@@ -255,15 +255,24 @@ rb_ary_modify(VALUE ary) - rb_ary_modify_check(ary); - if (ARY_SHARED_P(ary)) { - long len = RARRAY_LEN(ary); -+ VALUE shared = ARY_SHARED(ary); - if (len <= RARRAY_EMBED_LEN_MAX) { - VALUE *ptr = ARY_HEAP_PTR(ary); -- VALUE shared = ARY_SHARED(ary); - FL_UNSET_SHARED(ary); - FL_SET_EMBED(ary); - MEMCPY(ARY_EMBED_PTR(ary), ptr, VALUE, len); - rb_ary_decrement_share(shared); - ARY_SET_EMBED_LEN(ary, len); - } -+ else if (ARY_SHARED_NUM(shared) == 1 && len > RARRAY_LEN(shared)>>1) { -+ long shift = RARRAY_PTR(ary) - RARRAY_PTR(shared); -+ ARY_SET_PTR(ary, RARRAY_PTR(shared)); -+ ARY_SET_CAPA(ary, RARRAY_LEN(shared)); -+ MEMMOVE(RARRAY_PTR(ary), RARRAY_PTR(ary)+shift, VALUE, len); -+ FL_UNSET_SHARED(ary); -+ FL_SET_EMBED(shared); -+ rb_ary_decrement_share(shared); -+ } - else { - VALUE *ptr = ALLOC_N(VALUE, len); - MEMCPY(ptr, RARRAY_PTR(ary), VALUE, len); -@@ -274,6 +283,38 @@ rb_ary_modify(VALUE ary) - } - } - -+static void -+ary_ensure_room_for_push(VALUE ary, long add_len) -+{ -+ long new_len = RARRAY_LEN(ary) + add_len; -+ long capa; -+ -+ if (ARY_SHARED_P(ary)) { -+ if (new_len > RARRAY_EMBED_LEN_MAX) { -+ VALUE shared = ARY_SHARED(ary); -+ if (ARY_SHARED_NUM(shared) == 1) { -+ if (RARRAY_PTR(ary) - RARRAY_PTR(shared) + new_len <= RARRAY_LEN(shared)) { -+ rb_ary_modify_check(ary); -+ } -+ else { -+ /* if array is shared, than it is likely it participate in push/shift pattern */ -+ rb_ary_modify(ary); -+ capa = ARY_CAPA(ary); -+ if (new_len > capa - (capa >> 6)) { -+ ary_double_capa(ary, new_len); -+ } -+ } -+ return; -+ } -+ } -+ } -+ rb_ary_modify(ary); -+ capa = ARY_CAPA(ary); -+ if (new_len > capa) { -+ ary_double_capa(ary, new_len); -+ } -+} -+ - VALUE - rb_ary_freeze(VALUE ary) - { -@@ -446,8 +487,9 @@ ary_make_shared(VALUE ary) - OBJSETUP(shared, 0, T_ARRAY); - FL_UNSET_EMBED(shared); - -- ARY_SET_LEN((VALUE)shared, RARRAY_LEN(ary)); -+ ARY_SET_LEN((VALUE)shared, ARY_CAPA(ary)); - ARY_SET_PTR((VALUE)shared, RARRAY_PTR(ary)); -+ rb_mem_clear(RARRAY_PTR(shared) + RARRAY_LEN(ary), ARY_CAPA(ary) - RARRAY_LEN(ary)); - FL_SET_SHARED_ROOT(shared); - ARY_SET_SHARED_NUM((VALUE)shared, 1); - FL_SET_SHARED(ary); -@@ -737,8 +779,6 @@ ary_take_first_or_last(int argc, VALUE *argv, VALUE ary, enum ary_take_pos_flags - return ary_make_partial(ary, rb_cArray, offset, n); - } - --static VALUE rb_ary_push_1(VALUE ary, VALUE item); -- - /* - * call-seq: - * ary << obj -> ary -@@ -755,8 +795,12 @@ static VALUE rb_ary_push_1(VALUE ary, VALUE item); - VALUE - rb_ary_push(VALUE ary, VALUE item) - { -- rb_ary_modify(ary); -- return rb_ary_push_1(ary, item); -+ long idx = RARRAY_LEN(ary); -+ -+ ary_ensure_room_for_push(ary, 1); -+ RARRAY_PTR(ary)[idx] = item; -+ ARY_SET_LEN(ary, idx + 1); -+ return ary; - } - - static VALUE -@@ -772,6 +816,18 @@ rb_ary_push_1(VALUE ary, VALUE item) - return ary; - } - -+static VALUE -+rb_ary_cat(VALUE ary, const VALUE *ptr, long len) -+{ -+ long oldlen = RARRAY_LEN(ary); -+ -+ ary_ensure_room_for_push(ary, len); -+ -+ MEMCPY(RARRAY_PTR(ary) + oldlen, ptr, VALUE, len); -+ ARY_SET_LEN(ary, oldlen + len); -+ return ary; -+} -+ - /* - * call-seq: - * ary.push(obj, ... ) -> ary -@@ -788,11 +844,7 @@ rb_ary_push_1(VALUE ary, VALUE item) - static VALUE - rb_ary_push_m(int argc, VALUE *argv, VALUE ary) - { -- rb_ary_modify(ary); -- while (argc--) { -- rb_ary_push_1(ary, *argv++); -- } -- return ary; -+ return rb_ary_cat(ary, argv, argc); - } - - VALUE -@@ -920,6 +972,55 @@ rb_ary_shift_m(int argc, VALUE *argv, VALUE ary) - return result; - } - -+static void -+ary_ensure_room_for_unshift(VALUE ary, int argc) -+{ -+ long len = RARRAY_LEN(ary); -+ long new_len = len + argc; -+ long capa; -+ VALUE *head, *sharedp; -+ -+ if (ARY_SHARED_P(ary)) { -+ VALUE shared = ARY_SHARED(ary); -+ capa = RARRAY_LEN(shared); -+ if (ARY_SHARED_NUM(shared) == 1 && capa > new_len) { -+ head = RARRAY_PTR(ary); -+ sharedp = RARRAY_PTR(shared); -+ goto makeroom_if_need; -+ } -+ } -+ -+ rb_ary_modify(ary); -+ capa = ARY_CAPA(ary); -+ if (capa - (capa >> 6) <= new_len) { -+ ary_double_capa(ary, new_len); -+ } -+ -+ /* use shared array for big "queues" */ -+ if (new_len > ARY_DEFAULT_SIZE * 4) { -+ /* make a room for unshifted items */ -+ capa = ARY_CAPA(ary); -+ ary_make_shared(ary); -+ -+ head = sharedp = RARRAY_PTR(ary); -+ goto makeroom; -+makeroom_if_need: -+ if (head - sharedp < argc) { -+ long room; -+makeroom: -+ room = capa - new_len; -+ room -= room >> 4; -+ MEMMOVE(sharedp + argc + room, head, VALUE, len); -+ head = sharedp + argc + room; -+ } -+ ARY_SET_PTR(ary, head - argc); -+ } -+ else { -+ /* sliding items */ -+ MEMMOVE(RARRAY_PTR(ary) + argc, RARRAY_PTR(ary), VALUE, len); -+ } -+} -+ - /* - * call-seq: - * ary.unshift(obj, ...) -> ary -@@ -935,19 +1036,16 @@ rb_ary_shift_m(int argc, VALUE *argv, VALUE ary) - static VALUE - rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary) - { -- long len; -+ long len = RARRAY_LEN(ary); - -- rb_ary_modify(ary); -- if (argc == 0) return ary; -- if (ARY_CAPA(ary) <= (len = RARRAY_LEN(ary)) + argc) { -- ary_double_capa(ary, len + argc); -+ if (argc == 0) { -+ rb_ary_modify_check(ary); -+ return ary; - } - -- /* sliding items */ -- MEMMOVE(RARRAY_PTR(ary) + argc, RARRAY_PTR(ary), VALUE, len); -+ ary_ensure_room_for_unshift(ary, argc); - MEMCPY(RARRAY_PTR(ary), argv, VALUE, argc); -- ARY_INCREASE_LEN(ary, argc); -- -+ ARY_SET_LEN(ary, len + argc); - return ary; - } - -@@ -1309,15 +1407,12 @@ rb_ary_splice(VALUE ary, long beg, long len, VALUE rpl) - rpl = rb_ary_to_ary(rpl); - rlen = RARRAY_LEN(rpl); - } -- rb_ary_modify(ary); - if (beg >= RARRAY_LEN(ary)) { - if (beg > ARY_MAX_SIZE - rlen) { - rb_raise(rb_eIndexError, "index %ld too big", beg); - } -+ ary_ensure_room_for_push(ary, rlen-len); /* len is 0 or negative */ - len = beg + rlen; -- if (len >= ARY_CAPA(ary)) { -- ary_double_capa(ary, len); -- } - rb_mem_clear(RARRAY_PTR(ary) + RARRAY_LEN(ary), beg - RARRAY_LEN(ary)); - if (rlen > 0) { - MEMCPY(RARRAY_PTR(ary) + beg, RARRAY_PTR(rpl), VALUE, rlen); -@@ -1327,6 +1422,7 @@ rb_ary_splice(VALUE ary, long beg, long len, VALUE rpl) - else { - long alen; - -+ rb_ary_modify(ary); - alen = RARRAY_LEN(ary) + rlen - len; - if (alen >= ARY_CAPA(ary)) { - ary_double_capa(ary, alen); -@@ -2116,12 +2212,13 @@ rb_ary_sort_bang(VALUE ary) - if (RARRAY_LEN(ary) > 1) { - VALUE tmp = ary_make_substitution(ary); /* only ary refers tmp */ - struct ary_sort_data data; -+ long len = RARRAY_LEN(ary); - - RBASIC(tmp)->klass = 0; - data.ary = tmp; - data.opt_methods = 0; - data.opt_inited = 0; -- ruby_qsort(RARRAY_PTR(tmp), RARRAY_LEN(tmp), sizeof(VALUE), -+ ruby_qsort(RARRAY_PTR(tmp), len, sizeof(VALUE), - rb_block_given_p()?sort_1:sort_2, &data); - - if (ARY_EMBED_P(tmp)) { -@@ -2138,7 +2235,7 @@ rb_ary_sort_bang(VALUE ary) - if (ARY_HEAP_PTR(ary) == ARY_HEAP_PTR(tmp)) { - assert(!ARY_EMBED_P(ary)); - FL_UNSET_SHARED(ary); -- ARY_SET_CAPA(ary, ARY_CAPA(tmp)); -+ ARY_SET_CAPA(ary, RARRAY_LEN(tmp)); - } - else { - assert(!ARY_SHARED_P(tmp)); -@@ -2153,8 +2250,8 @@ rb_ary_sort_bang(VALUE ary) - xfree(ARY_HEAP_PTR(ary)); - } - ARY_SET_PTR(ary, RARRAY_PTR(tmp)); -- ARY_SET_HEAP_LEN(ary, RARRAY_LEN(tmp)); -- ARY_SET_CAPA(ary, ARY_CAPA(tmp)); -+ ARY_SET_HEAP_LEN(ary, len); -+ ARY_SET_CAPA(ary, RARRAY_LEN(tmp)); - } - /* tmp was lost ownership for the ptr */ - FL_UNSET(tmp, FL_FREEZE); -diff --git a/enc/unicode/name2ctype.h b/enc/unicode/name2ctype.h -deleted file mode 100644 -index a45ea59..0000000 ---- a/enc/unicode/name2ctype.h -+++ /dev/null -@@ -1,23866 +0,0 @@ --/* C code produced by gperf version 3.0.3 */ --/* Command-line: gperf -7 -c -j1 -i1 -t -C -P -T -H uniname2ctype_hash -Q uniname2ctype_pool -N uniname2ctype_p */ --#ifndef USE_UNICODE_PROPERTIES --/* Computed positions: -k'1,3' */ --#else /* USE_UNICODE_PROPERTIES */ --/* Computed positions: -k'1-3,5-6,12,16,$' */ --#endif /* USE_UNICODE_PROPERTIES */ -- --#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ -- && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ -- && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ -- && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ -- && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ -- && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ -- && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ -- && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ -- && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ -- && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ -- && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ -- && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ -- && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ -- && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ -- && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ -- && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ -- && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ -- && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ -- && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ -- && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ -- && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ -- && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ -- && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) --/* The character set is not based on ISO-646. */ --error "gperf generated tables don't work with this execution character set. Please report a bug to ." --#endif -- -- --#define long size_t -- --#ifdef USE_UNICODE_PROPERTIES --#ifdef USE_UNICODE_PROPERTIES --/* 'Any': - */ --static const OnigCodePoint CR_Any[] = { -- 1, -- 0x0000, 0x10ffff, --}; /* CR_Any */ -- --/* 'Assigned': - */ --static const OnigCodePoint CR_Assigned[] = { -- 501, -- 0x0000, 0x0377, -- 0x037a, 0x037e, -- 0x0384, 0x038a, -- 0x038c, 0x038c, -- 0x038e, 0x03a1, -- 0x03a3, 0x0527, -- 0x0531, 0x0556, -- 0x0559, 0x055f, -- 0x0561, 0x0587, -- 0x0589, 0x058a, -- 0x0591, 0x05c7, -- 0x05d0, 0x05ea, -- 0x05f0, 0x05f4, -- 0x0600, 0x0603, -- 0x0606, 0x061b, -- 0x061e, 0x070d, -- 0x070f, 0x074a, -- 0x074d, 0x07b1, -- 0x07c0, 0x07fa, -- 0x0800, 0x082d, -- 0x0830, 0x083e, -- 0x0840, 0x085b, -- 0x085e, 0x085e, -- 0x0900, 0x0977, -- 0x0979, 0x097f, -- 0x0981, 0x0983, -- 0x0985, 0x098c, -- 0x098f, 0x0990, -- 0x0993, 0x09a8, -- 0x09aa, 0x09b0, -- 0x09b2, 0x09b2, -- 0x09b6, 0x09b9, -- 0x09bc, 0x09c4, -- 0x09c7, 0x09c8, -- 0x09cb, 0x09ce, -- 0x09d7, 0x09d7, -- 0x09dc, 0x09dd, -- 0x09df, 0x09e3, -- 0x09e6, 0x09fb, -- 0x0a01, 0x0a03, -- 0x0a05, 0x0a0a, -- 0x0a0f, 0x0a10, -- 0x0a13, 0x0a28, -- 0x0a2a, 0x0a30, -- 0x0a32, 0x0a33, -- 0x0a35, 0x0a36, -- 0x0a38, 0x0a39, -- 0x0a3c, 0x0a3c, -- 0x0a3e, 0x0a42, -- 0x0a47, 0x0a48, -- 0x0a4b, 0x0a4d, -- 0x0a51, 0x0a51, -- 0x0a59, 0x0a5c, -- 0x0a5e, 0x0a5e, -- 0x0a66, 0x0a75, -- 0x0a81, 0x0a83, -- 0x0a85, 0x0a8d, -- 0x0a8f, 0x0a91, -- 0x0a93, 0x0aa8, -- 0x0aaa, 0x0ab0, -- 0x0ab2, 0x0ab3, -- 0x0ab5, 0x0ab9, -- 0x0abc, 0x0ac5, -- 0x0ac7, 0x0ac9, -- 0x0acb, 0x0acd, -- 0x0ad0, 0x0ad0, -- 0x0ae0, 0x0ae3, -- 0x0ae6, 0x0aef, -- 0x0af1, 0x0af1, -- 0x0b01, 0x0b03, -- 0x0b05, 0x0b0c, -- 0x0b0f, 0x0b10, -- 0x0b13, 0x0b28, -- 0x0b2a, 0x0b30, -- 0x0b32, 0x0b33, -- 0x0b35, 0x0b39, -- 0x0b3c, 0x0b44, -- 0x0b47, 0x0b48, -- 0x0b4b, 0x0b4d, -- 0x0b56, 0x0b57, -- 0x0b5c, 0x0b5d, -- 0x0b5f, 0x0b63, -- 0x0b66, 0x0b77, -- 0x0b82, 0x0b83, -- 0x0b85, 0x0b8a, -- 0x0b8e, 0x0b90, -- 0x0b92, 0x0b95, -- 0x0b99, 0x0b9a, -- 0x0b9c, 0x0b9c, -- 0x0b9e, 0x0b9f, -- 0x0ba3, 0x0ba4, -- 0x0ba8, 0x0baa, -- 0x0bae, 0x0bb9, -- 0x0bbe, 0x0bc2, -- 0x0bc6, 0x0bc8, -- 0x0bca, 0x0bcd, -- 0x0bd0, 0x0bd0, -- 0x0bd7, 0x0bd7, -- 0x0be6, 0x0bfa, -- 0x0c01, 0x0c03, -- 0x0c05, 0x0c0c, -- 0x0c0e, 0x0c10, -- 0x0c12, 0x0c28, -- 0x0c2a, 0x0c33, -- 0x0c35, 0x0c39, -- 0x0c3d, 0x0c44, -- 0x0c46, 0x0c48, -- 0x0c4a, 0x0c4d, -- 0x0c55, 0x0c56, -- 0x0c58, 0x0c59, -- 0x0c60, 0x0c63, -- 0x0c66, 0x0c6f, -- 0x0c78, 0x0c7f, -- 0x0c82, 0x0c83, -- 0x0c85, 0x0c8c, -- 0x0c8e, 0x0c90, -- 0x0c92, 0x0ca8, -- 0x0caa, 0x0cb3, -- 0x0cb5, 0x0cb9, -- 0x0cbc, 0x0cc4, -- 0x0cc6, 0x0cc8, -- 0x0cca, 0x0ccd, -- 0x0cd5, 0x0cd6, -- 0x0cde, 0x0cde, -- 0x0ce0, 0x0ce3, -- 0x0ce6, 0x0cef, -- 0x0cf1, 0x0cf2, -- 0x0d02, 0x0d03, -- 0x0d05, 0x0d0c, -- 0x0d0e, 0x0d10, -- 0x0d12, 0x0d3a, -- 0x0d3d, 0x0d44, -- 0x0d46, 0x0d48, -- 0x0d4a, 0x0d4e, -- 0x0d57, 0x0d57, -- 0x0d60, 0x0d63, -- 0x0d66, 0x0d75, -- 0x0d79, 0x0d7f, -- 0x0d82, 0x0d83, -- 0x0d85, 0x0d96, -- 0x0d9a, 0x0db1, -- 0x0db3, 0x0dbb, -- 0x0dbd, 0x0dbd, -- 0x0dc0, 0x0dc6, -- 0x0dca, 0x0dca, -- 0x0dcf, 0x0dd4, -- 0x0dd6, 0x0dd6, -- 0x0dd8, 0x0ddf, -- 0x0df2, 0x0df4, -- 0x0e01, 0x0e3a, -- 0x0e3f, 0x0e5b, -- 0x0e81, 0x0e82, -- 0x0e84, 0x0e84, -- 0x0e87, 0x0e88, -- 0x0e8a, 0x0e8a, -- 0x0e8d, 0x0e8d, -- 0x0e94, 0x0e97, -- 0x0e99, 0x0e9f, -- 0x0ea1, 0x0ea3, -- 0x0ea5, 0x0ea5, -- 0x0ea7, 0x0ea7, -- 0x0eaa, 0x0eab, -- 0x0ead, 0x0eb9, -- 0x0ebb, 0x0ebd, -- 0x0ec0, 0x0ec4, -- 0x0ec6, 0x0ec6, -- 0x0ec8, 0x0ecd, -- 0x0ed0, 0x0ed9, -- 0x0edc, 0x0edd, -- 0x0f00, 0x0f47, -- 0x0f49, 0x0f6c, -- 0x0f71, 0x0f97, -- 0x0f99, 0x0fbc, -- 0x0fbe, 0x0fcc, -- 0x0fce, 0x0fda, -- 0x1000, 0x10c5, -- 0x10d0, 0x10fc, -- 0x1100, 0x1248, -- 0x124a, 0x124d, -- 0x1250, 0x1256, -- 0x1258, 0x1258, -- 0x125a, 0x125d, -- 0x1260, 0x1288, -- 0x128a, 0x128d, -- 0x1290, 0x12b0, -- 0x12b2, 0x12b5, -- 0x12b8, 0x12be, -- 0x12c0, 0x12c0, -- 0x12c2, 0x12c5, -- 0x12c8, 0x12d6, -- 0x12d8, 0x1310, -- 0x1312, 0x1315, -- 0x1318, 0x135a, -- 0x135d, 0x137c, -- 0x1380, 0x1399, -- 0x13a0, 0x13f4, -- 0x1400, 0x169c, -- 0x16a0, 0x16f0, -- 0x1700, 0x170c, -- 0x170e, 0x1714, -- 0x1720, 0x1736, -- 0x1740, 0x1753, -- 0x1760, 0x176c, -- 0x176e, 0x1770, -- 0x1772, 0x1773, -- 0x1780, 0x17dd, -- 0x17e0, 0x17e9, -- 0x17f0, 0x17f9, -- 0x1800, 0x180e, -- 0x1810, 0x1819, -- 0x1820, 0x1877, -- 0x1880, 0x18aa, -- 0x18b0, 0x18f5, -- 0x1900, 0x191c, -- 0x1920, 0x192b, -- 0x1930, 0x193b, -- 0x1940, 0x1940, -- 0x1944, 0x196d, -- 0x1970, 0x1974, -- 0x1980, 0x19ab, -- 0x19b0, 0x19c9, -- 0x19d0, 0x19da, -- 0x19de, 0x1a1b, -- 0x1a1e, 0x1a5e, -- 0x1a60, 0x1a7c, -- 0x1a7f, 0x1a89, -- 0x1a90, 0x1a99, -- 0x1aa0, 0x1aad, -- 0x1b00, 0x1b4b, -- 0x1b50, 0x1b7c, -- 0x1b80, 0x1baa, -- 0x1bae, 0x1bb9, -- 0x1bc0, 0x1bf3, -- 0x1bfc, 0x1c37, -- 0x1c3b, 0x1c49, -- 0x1c4d, 0x1c7f, -- 0x1cd0, 0x1cf2, -- 0x1d00, 0x1de6, -- 0x1dfc, 0x1f15, -- 0x1f18, 0x1f1d, -- 0x1f20, 0x1f45, -- 0x1f48, 0x1f4d, -- 0x1f50, 0x1f57, -- 0x1f59, 0x1f59, -- 0x1f5b, 0x1f5b, -- 0x1f5d, 0x1f5d, -- 0x1f5f, 0x1f7d, -- 0x1f80, 0x1fb4, -- 0x1fb6, 0x1fc4, -- 0x1fc6, 0x1fd3, -- 0x1fd6, 0x1fdb, -- 0x1fdd, 0x1fef, -- 0x1ff2, 0x1ff4, -- 0x1ff6, 0x1ffe, -- 0x2000, 0x2064, -- 0x206a, 0x2071, -- 0x2074, 0x208e, -- 0x2090, 0x209c, -- 0x20a0, 0x20b9, -- 0x20d0, 0x20f0, -- 0x2100, 0x2189, -- 0x2190, 0x23f3, -- 0x2400, 0x2426, -- 0x2440, 0x244a, -- 0x2460, 0x26ff, -- 0x2701, 0x27ca, -- 0x27cc, 0x27cc, -- 0x27ce, 0x2b4c, -- 0x2b50, 0x2b59, -- 0x2c00, 0x2c2e, -- 0x2c30, 0x2c5e, -- 0x2c60, 0x2cf1, -- 0x2cf9, 0x2d25, -- 0x2d30, 0x2d65, -- 0x2d6f, 0x2d70, -- 0x2d7f, 0x2d96, -- 0x2da0, 0x2da6, -- 0x2da8, 0x2dae, -- 0x2db0, 0x2db6, -- 0x2db8, 0x2dbe, -- 0x2dc0, 0x2dc6, -- 0x2dc8, 0x2dce, -- 0x2dd0, 0x2dd6, -- 0x2dd8, 0x2dde, -- 0x2de0, 0x2e31, -- 0x2e80, 0x2e99, -- 0x2e9b, 0x2ef3, -- 0x2f00, 0x2fd5, -- 0x2ff0, 0x2ffb, -- 0x3000, 0x303f, -- 0x3041, 0x3096, -- 0x3099, 0x30ff, -- 0x3105, 0x312d, -- 0x3131, 0x318e, -- 0x3190, 0x31ba, -- 0x31c0, 0x31e3, -- 0x31f0, 0x321e, -- 0x3220, 0x32fe, -- 0x3300, 0x4db5, -- 0x4dc0, 0x9fcb, -- 0xa000, 0xa48c, -- 0xa490, 0xa4c6, -- 0xa4d0, 0xa62b, -- 0xa640, 0xa673, -- 0xa67c, 0xa697, -- 0xa6a0, 0xa6f7, -- 0xa700, 0xa78e, -- 0xa790, 0xa791, -- 0xa7a0, 0xa7a9, -- 0xa7fa, 0xa82b, -- 0xa830, 0xa839, -- 0xa840, 0xa877, -- 0xa880, 0xa8c4, -- 0xa8ce, 0xa8d9, -- 0xa8e0, 0xa8fb, -- 0xa900, 0xa953, -- 0xa95f, 0xa97c, -- 0xa980, 0xa9cd, -- 0xa9cf, 0xa9d9, -- 0xa9de, 0xa9df, -- 0xaa00, 0xaa36, -- 0xaa40, 0xaa4d, -- 0xaa50, 0xaa59, -- 0xaa5c, 0xaa7b, -- 0xaa80, 0xaac2, -- 0xaadb, 0xaadf, -- 0xab01, 0xab06, -- 0xab09, 0xab0e, -- 0xab11, 0xab16, -- 0xab20, 0xab26, -- 0xab28, 0xab2e, -- 0xabc0, 0xabed, -- 0xabf0, 0xabf9, -- 0xac00, 0xd7a3, -- 0xd7b0, 0xd7c6, -- 0xd7cb, 0xd7fb, -- 0xd800, 0xfa2d, -- 0xfa30, 0xfa6d, -- 0xfa70, 0xfad9, -- 0xfb00, 0xfb06, -- 0xfb13, 0xfb17, -- 0xfb1d, 0xfb36, -- 0xfb38, 0xfb3c, -- 0xfb3e, 0xfb3e, -- 0xfb40, 0xfb41, -- 0xfb43, 0xfb44, -- 0xfb46, 0xfbc1, -- 0xfbd3, 0xfd3f, -- 0xfd50, 0xfd8f, -- 0xfd92, 0xfdc7, -- 0xfdf0, 0xfdfd, -- 0xfe00, 0xfe19, -- 0xfe20, 0xfe26, -- 0xfe30, 0xfe52, -- 0xfe54, 0xfe66, -- 0xfe68, 0xfe6b, -- 0xfe70, 0xfe74, -- 0xfe76, 0xfefc, -- 0xfeff, 0xfeff, -- 0xff01, 0xffbe, -- 0xffc2, 0xffc7, -- 0xffca, 0xffcf, -- 0xffd2, 0xffd7, -- 0xffda, 0xffdc, -- 0xffe0, 0xffe6, -- 0xffe8, 0xffee, -- 0xfff9, 0xfffd, -- 0x10000, 0x1000b, -- 0x1000d, 0x10026, -- 0x10028, 0x1003a, -- 0x1003c, 0x1003d, -- 0x1003f, 0x1004d, -- 0x10050, 0x1005d, -- 0x10080, 0x100fa, -- 0x10100, 0x10102, -- 0x10107, 0x10133, -- 0x10137, 0x1018a, -- 0x10190, 0x1019b, -- 0x101d0, 0x101fd, -- 0x10280, 0x1029c, -- 0x102a0, 0x102d0, -- 0x10300, 0x1031e, -- 0x10320, 0x10323, -- 0x10330, 0x1034a, -- 0x10380, 0x1039d, -- 0x1039f, 0x103c3, -- 0x103c8, 0x103d5, -- 0x10400, 0x1049d, -- 0x104a0, 0x104a9, -- 0x10800, 0x10805, -- 0x10808, 0x10808, -- 0x1080a, 0x10835, -- 0x10837, 0x10838, -- 0x1083c, 0x1083c, -- 0x1083f, 0x10855, -- 0x10857, 0x1085f, -- 0x10900, 0x1091b, -- 0x1091f, 0x10939, -- 0x1093f, 0x1093f, -- 0x10a00, 0x10a03, -- 0x10a05, 0x10a06, -- 0x10a0c, 0x10a13, -- 0x10a15, 0x10a17, -- 0x10a19, 0x10a33, -- 0x10a38, 0x10a3a, -- 0x10a3f, 0x10a47, -- 0x10a50, 0x10a58, -- 0x10a60, 0x10a7f, -- 0x10b00, 0x10b35, -- 0x10b39, 0x10b55, -- 0x10b58, 0x10b72, -- 0x10b78, 0x10b7f, -- 0x10c00, 0x10c48, -- 0x10e60, 0x10e7e, -- 0x11000, 0x1104d, -- 0x11052, 0x1106f, -- 0x11080, 0x110c1, -- 0x12000, 0x1236e, -- 0x12400, 0x12462, -- 0x12470, 0x12473, -- 0x13000, 0x1342e, -- 0x16800, 0x16a38, -- 0x1b000, 0x1b001, -- 0x1d000, 0x1d0f5, -- 0x1d100, 0x1d126, -- 0x1d129, 0x1d1dd, -- 0x1d200, 0x1d245, -- 0x1d300, 0x1d356, -- 0x1d360, 0x1d371, -- 0x1d400, 0x1d454, -- 0x1d456, 0x1d49c, -- 0x1d49e, 0x1d49f, -- 0x1d4a2, 0x1d4a2, -- 0x1d4a5, 0x1d4a6, -- 0x1d4a9, 0x1d4ac, -- 0x1d4ae, 0x1d4b9, -- 0x1d4bb, 0x1d4bb, -- 0x1d4bd, 0x1d4c3, -- 0x1d4c5, 0x1d505, -- 0x1d507, 0x1d50a, -- 0x1d50d, 0x1d514, -- 0x1d516, 0x1d51c, -- 0x1d51e, 0x1d539, -- 0x1d53b, 0x1d53e, -- 0x1d540, 0x1d544, -- 0x1d546, 0x1d546, -- 0x1d54a, 0x1d550, -- 0x1d552, 0x1d6a5, -- 0x1d6a8, 0x1d7cb, -- 0x1d7ce, 0x1d7ff, -- 0x1f000, 0x1f02b, -- 0x1f030, 0x1f093, -- 0x1f0a0, 0x1f0ae, -- 0x1f0b1, 0x1f0be, -- 0x1f0c1, 0x1f0cf, -- 0x1f0d1, 0x1f0df, -- 0x1f100, 0x1f10a, -- 0x1f110, 0x1f12e, -- 0x1f130, 0x1f169, -- 0x1f170, 0x1f19a, -- 0x1f1e6, 0x1f202, -- 0x1f210, 0x1f23a, -- 0x1f240, 0x1f248, -- 0x1f250, 0x1f251, -- 0x1f300, 0x1f320, -- 0x1f330, 0x1f335, -- 0x1f337, 0x1f37c, -- 0x1f380, 0x1f393, -- 0x1f3a0, 0x1f3c4, -- 0x1f3c6, 0x1f3ca, -- 0x1f3e0, 0x1f3f0, -- 0x1f400, 0x1f43e, -- 0x1f440, 0x1f440, -- 0x1f442, 0x1f4f7, -- 0x1f4f9, 0x1f4fc, -- 0x1f500, 0x1f53d, -- 0x1f550, 0x1f567, -- 0x1f5fb, 0x1f5ff, -- 0x1f601, 0x1f610, -- 0x1f612, 0x1f614, -- 0x1f616, 0x1f616, -- 0x1f618, 0x1f618, -- 0x1f61a, 0x1f61a, -- 0x1f61c, 0x1f61e, -- 0x1f620, 0x1f625, -- 0x1f628, 0x1f62b, -- 0x1f62d, 0x1f62d, -- 0x1f630, 0x1f633, -- 0x1f635, 0x1f640, -- 0x1f645, 0x1f64f, -- 0x1f680, 0x1f6c5, -- 0x1f700, 0x1f773, -- 0x20000, 0x2a6d6, -- 0x2a700, 0x2b734, -- 0x2b740, 0x2b81d, -- 0x2f800, 0x2fa1d, -- 0xe0001, 0xe0001, -- 0xe0020, 0xe007f, -- 0xe0100, 0xe01ef, -- 0xf0000, 0xffffd, -- 0x100000, 0x10fffd, --}; /* CR_Assigned */ -- --/* 'C': Major Category */ --static const OnigCodePoint CR_C[] = { -- 20, -- 0x0000, 0x001f, -- 0x007f, 0x009f, -- 0x00ad, 0x00ad, -- 0x0600, 0x0603, -- 0x06dd, 0x06dd, -- 0x070f, 0x070f, -- 0x17b4, 0x17b5, -- 0x200b, 0x200f, -- 0x202a, 0x202e, -- 0x2060, 0x2064, -- 0x206a, 0x206f, -- 0xd800, 0xf8ff, -- 0xfeff, 0xfeff, -- 0xfff9, 0xfffb, -- 0x110bd, 0x110bd, -- 0x1d173, 0x1d17a, -- 0xe0001, 0xe0001, -- 0xe0020, 0xe007f, -- 0xf0000, 0xffffd, -- 0x100000, 0x10ffff, --}; /* CR_C */ -- --/* 'Cc': General Category */ --static const OnigCodePoint CR_Cc[] = { -- 2, -- 0x0000, 0x001f, -- 0x007f, 0x009f, --}; /* CR_Cc */ -- --/* 'Cf': General Category */ --static const OnigCodePoint CR_Cf[] = { -- 15, -- 0x00ad, 0x00ad, -- 0x0600, 0x0603, -- 0x06dd, 0x06dd, -- 0x070f, 0x070f, -- 0x17b4, 0x17b5, -- 0x200b, 0x200f, -- 0x202a, 0x202e, -- 0x2060, 0x2064, -- 0x206a, 0x206f, -- 0xfeff, 0xfeff, -- 0xfff9, 0xfffb, -- 0x110bd, 0x110bd, -- 0x1d173, 0x1d17a, -- 0xe0001, 0xe0001, -- 0xe0020, 0xe007f, --}; /* CR_Cf */ -- --/* 'Cn': General Category */ --static const OnigCodePoint CR_Cn[] = { -- 501, -- 0x0378, 0x0379, -- 0x037f, 0x0383, -- 0x038b, 0x038b, -- 0x038d, 0x038d, -- 0x03a2, 0x03a2, -- 0x0528, 0x0530, -- 0x0557, 0x0558, -- 0x0560, 0x0560, -- 0x0588, 0x0588, -- 0x058b, 0x0590, -- 0x05c8, 0x05cf, -- 0x05eb, 0x05ef, -- 0x05f5, 0x05ff, -- 0x0604, 0x0605, -- 0x061c, 0x061d, -- 0x070e, 0x070e, -- 0x074b, 0x074c, -- 0x07b2, 0x07bf, -- 0x07fb, 0x07ff, -- 0x082e, 0x082f, -- 0x083f, 0x083f, -- 0x085c, 0x085d, -- 0x085f, 0x08ff, -- 0x0978, 0x0978, -- 0x0980, 0x0980, -- 0x0984, 0x0984, -- 0x098d, 0x098e, -- 0x0991, 0x0992, -- 0x09a9, 0x09a9, -- 0x09b1, 0x09b1, -- 0x09b3, 0x09b5, -- 0x09ba, 0x09bb, -- 0x09c5, 0x09c6, -- 0x09c9, 0x09ca, -- 0x09cf, 0x09d6, -- 0x09d8, 0x09db, -- 0x09de, 0x09de, -- 0x09e4, 0x09e5, -- 0x09fc, 0x0a00, -- 0x0a04, 0x0a04, -- 0x0a0b, 0x0a0e, -- 0x0a11, 0x0a12, -- 0x0a29, 0x0a29, -- 0x0a31, 0x0a31, -- 0x0a34, 0x0a34, -- 0x0a37, 0x0a37, -- 0x0a3a, 0x0a3b, -- 0x0a3d, 0x0a3d, -- 0x0a43, 0x0a46, -- 0x0a49, 0x0a4a, -- 0x0a4e, 0x0a50, -- 0x0a52, 0x0a58, -- 0x0a5d, 0x0a5d, -- 0x0a5f, 0x0a65, -- 0x0a76, 0x0a80, -- 0x0a84, 0x0a84, -- 0x0a8e, 0x0a8e, -- 0x0a92, 0x0a92, -- 0x0aa9, 0x0aa9, -- 0x0ab1, 0x0ab1, -- 0x0ab4, 0x0ab4, -- 0x0aba, 0x0abb, -- 0x0ac6, 0x0ac6, -- 0x0aca, 0x0aca, -- 0x0ace, 0x0acf, -- 0x0ad1, 0x0adf, -- 0x0ae4, 0x0ae5, -- 0x0af0, 0x0af0, -- 0x0af2, 0x0b00, -- 0x0b04, 0x0b04, -- 0x0b0d, 0x0b0e, -- 0x0b11, 0x0b12, -- 0x0b29, 0x0b29, -- 0x0b31, 0x0b31, -- 0x0b34, 0x0b34, -- 0x0b3a, 0x0b3b, -- 0x0b45, 0x0b46, -- 0x0b49, 0x0b4a, -- 0x0b4e, 0x0b55, -- 0x0b58, 0x0b5b, -- 0x0b5e, 0x0b5e, -- 0x0b64, 0x0b65, -- 0x0b78, 0x0b81, -- 0x0b84, 0x0b84, -- 0x0b8b, 0x0b8d, -- 0x0b91, 0x0b91, -- 0x0b96, 0x0b98, -- 0x0b9b, 0x0b9b, -- 0x0b9d, 0x0b9d, -- 0x0ba0, 0x0ba2, -- 0x0ba5, 0x0ba7, -- 0x0bab, 0x0bad, -- 0x0bba, 0x0bbd, -- 0x0bc3, 0x0bc5, -- 0x0bc9, 0x0bc9, -- 0x0bce, 0x0bcf, -- 0x0bd1, 0x0bd6, -- 0x0bd8, 0x0be5, -- 0x0bfb, 0x0c00, -- 0x0c04, 0x0c04, -- 0x0c0d, 0x0c0d, -- 0x0c11, 0x0c11, -- 0x0c29, 0x0c29, -- 0x0c34, 0x0c34, -- 0x0c3a, 0x0c3c, -- 0x0c45, 0x0c45, -- 0x0c49, 0x0c49, -- 0x0c4e, 0x0c54, -- 0x0c57, 0x0c57, -- 0x0c5a, 0x0c5f, -- 0x0c64, 0x0c65, -- 0x0c70, 0x0c77, -- 0x0c80, 0x0c81, -- 0x0c84, 0x0c84, -- 0x0c8d, 0x0c8d, -- 0x0c91, 0x0c91, -- 0x0ca9, 0x0ca9, -- 0x0cb4, 0x0cb4, -- 0x0cba, 0x0cbb, -- 0x0cc5, 0x0cc5, -- 0x0cc9, 0x0cc9, -- 0x0cce, 0x0cd4, -- 0x0cd7, 0x0cdd, -- 0x0cdf, 0x0cdf, -- 0x0ce4, 0x0ce5, -- 0x0cf0, 0x0cf0, -- 0x0cf3, 0x0d01, -- 0x0d04, 0x0d04, -- 0x0d0d, 0x0d0d, -- 0x0d11, 0x0d11, -- 0x0d3b, 0x0d3c, -- 0x0d45, 0x0d45, -- 0x0d49, 0x0d49, -- 0x0d4f, 0x0d56, -- 0x0d58, 0x0d5f, -- 0x0d64, 0x0d65, -- 0x0d76, 0x0d78, -- 0x0d80, 0x0d81, -- 0x0d84, 0x0d84, -- 0x0d97, 0x0d99, -- 0x0db2, 0x0db2, -- 0x0dbc, 0x0dbc, -- 0x0dbe, 0x0dbf, -- 0x0dc7, 0x0dc9, -- 0x0dcb, 0x0dce, -- 0x0dd5, 0x0dd5, -- 0x0dd7, 0x0dd7, -- 0x0de0, 0x0df1, -- 0x0df5, 0x0e00, -- 0x0e3b, 0x0e3e, -- 0x0e5c, 0x0e80, -- 0x0e83, 0x0e83, -- 0x0e85, 0x0e86, -- 0x0e89, 0x0e89, -- 0x0e8b, 0x0e8c, -- 0x0e8e, 0x0e93, -- 0x0e98, 0x0e98, -- 0x0ea0, 0x0ea0, -- 0x0ea4, 0x0ea4, -- 0x0ea6, 0x0ea6, -- 0x0ea8, 0x0ea9, -- 0x0eac, 0x0eac, -- 0x0eba, 0x0eba, -- 0x0ebe, 0x0ebf, -- 0x0ec5, 0x0ec5, -- 0x0ec7, 0x0ec7, -- 0x0ece, 0x0ecf, -- 0x0eda, 0x0edb, -- 0x0ede, 0x0eff, -- 0x0f48, 0x0f48, -- 0x0f6d, 0x0f70, -- 0x0f98, 0x0f98, -- 0x0fbd, 0x0fbd, -- 0x0fcd, 0x0fcd, -- 0x0fdb, 0x0fff, -- 0x10c6, 0x10cf, -- 0x10fd, 0x10ff, -- 0x1249, 0x1249, -- 0x124e, 0x124f, -- 0x1257, 0x1257, -- 0x1259, 0x1259, -- 0x125e, 0x125f, -- 0x1289, 0x1289, -- 0x128e, 0x128f, -- 0x12b1, 0x12b1, -- 0x12b6, 0x12b7, -- 0x12bf, 0x12bf, -- 0x12c1, 0x12c1, -- 0x12c6, 0x12c7, -- 0x12d7, 0x12d7, -- 0x1311, 0x1311, -- 0x1316, 0x1317, -- 0x135b, 0x135c, -- 0x137d, 0x137f, -- 0x139a, 0x139f, -- 0x13f5, 0x13ff, -- 0x169d, 0x169f, -- 0x16f1, 0x16ff, -- 0x170d, 0x170d, -- 0x1715, 0x171f, -- 0x1737, 0x173f, -- 0x1754, 0x175f, -- 0x176d, 0x176d, -- 0x1771, 0x1771, -- 0x1774, 0x177f, -- 0x17de, 0x17df, -- 0x17ea, 0x17ef, -- 0x17fa, 0x17ff, -- 0x180f, 0x180f, -- 0x181a, 0x181f, -- 0x1878, 0x187f, -- 0x18ab, 0x18af, -- 0x18f6, 0x18ff, -- 0x191d, 0x191f, -- 0x192c, 0x192f, -- 0x193c, 0x193f, -- 0x1941, 0x1943, -- 0x196e, 0x196f, -- 0x1975, 0x197f, -- 0x19ac, 0x19af, -- 0x19ca, 0x19cf, -- 0x19db, 0x19dd, -- 0x1a1c, 0x1a1d, -- 0x1a5f, 0x1a5f, -- 0x1a7d, 0x1a7e, -- 0x1a8a, 0x1a8f, -- 0x1a9a, 0x1a9f, -- 0x1aae, 0x1aff, -- 0x1b4c, 0x1b4f, -- 0x1b7d, 0x1b7f, -- 0x1bab, 0x1bad, -- 0x1bba, 0x1bbf, -- 0x1bf4, 0x1bfb, -- 0x1c38, 0x1c3a, -- 0x1c4a, 0x1c4c, -- 0x1c80, 0x1ccf, -- 0x1cf3, 0x1cff, -- 0x1de7, 0x1dfb, -- 0x1f16, 0x1f17, -- 0x1f1e, 0x1f1f, -- 0x1f46, 0x1f47, -- 0x1f4e, 0x1f4f, -- 0x1f58, 0x1f58, -- 0x1f5a, 0x1f5a, -- 0x1f5c, 0x1f5c, -- 0x1f5e, 0x1f5e, -- 0x1f7e, 0x1f7f, -- 0x1fb5, 0x1fb5, -- 0x1fc5, 0x1fc5, -- 0x1fd4, 0x1fd5, -- 0x1fdc, 0x1fdc, -- 0x1ff0, 0x1ff1, -- 0x1ff5, 0x1ff5, -- 0x1fff, 0x1fff, -- 0x2065, 0x2069, -- 0x2072, 0x2073, -- 0x208f, 0x208f, -- 0x209d, 0x209f, -- 0x20ba, 0x20cf, -- 0x20f1, 0x20ff, -- 0x218a, 0x218f, -- 0x23f4, 0x23ff, -- 0x2427, 0x243f, -- 0x244b, 0x245f, -- 0x2700, 0x2700, -- 0x27cb, 0x27cb, -- 0x27cd, 0x27cd, -- 0x2b4d, 0x2b4f, -- 0x2b5a, 0x2bff, -- 0x2c2f, 0x2c2f, -- 0x2c5f, 0x2c5f, -- 0x2cf2, 0x2cf8, -- 0x2d26, 0x2d2f, -- 0x2d66, 0x2d6e, -- 0x2d71, 0x2d7e, -- 0x2d97, 0x2d9f, -- 0x2da7, 0x2da7, -- 0x2daf, 0x2daf, -- 0x2db7, 0x2db7, -- 0x2dbf, 0x2dbf, -- 0x2dc7, 0x2dc7, -- 0x2dcf, 0x2dcf, -- 0x2dd7, 0x2dd7, -- 0x2ddf, 0x2ddf, -- 0x2e32, 0x2e7f, -- 0x2e9a, 0x2e9a, -- 0x2ef4, 0x2eff, -- 0x2fd6, 0x2fef, -- 0x2ffc, 0x2fff, -- 0x3040, 0x3040, -- 0x3097, 0x3098, -- 0x3100, 0x3104, -- 0x312e, 0x3130, -- 0x318f, 0x318f, -- 0x31bb, 0x31bf, -- 0x31e4, 0x31ef, -- 0x321f, 0x321f, -- 0x32ff, 0x32ff, -- 0x4db6, 0x4dbf, -- 0x9fcc, 0x9fff, -- 0xa48d, 0xa48f, -- 0xa4c7, 0xa4cf, -- 0xa62c, 0xa63f, -- 0xa674, 0xa67b, -- 0xa698, 0xa69f, -- 0xa6f8, 0xa6ff, -- 0xa78f, 0xa78f, -- 0xa792, 0xa79f, -- 0xa7aa, 0xa7f9, -- 0xa82c, 0xa82f, -- 0xa83a, 0xa83f, -- 0xa878, 0xa87f, -- 0xa8c5, 0xa8cd, -- 0xa8da, 0xa8df, -- 0xa8fc, 0xa8ff, -- 0xa954, 0xa95e, -- 0xa97d, 0xa97f, -- 0xa9ce, 0xa9ce, -- 0xa9da, 0xa9dd, -- 0xa9e0, 0xa9ff, -- 0xaa37, 0xaa3f, -- 0xaa4e, 0xaa4f, -- 0xaa5a, 0xaa5b, -- 0xaa7c, 0xaa7f, -- 0xaac3, 0xaada, -- 0xaae0, 0xab00, -- 0xab07, 0xab08, -- 0xab0f, 0xab10, -- 0xab17, 0xab1f, -- 0xab27, 0xab27, -- 0xab2f, 0xabbf, -- 0xabee, 0xabef, -- 0xabfa, 0xabff, -- 0xd7a4, 0xd7af, -- 0xd7c7, 0xd7ca, -- 0xd7fc, 0xd7ff, -- 0xfa2e, 0xfa2f, -- 0xfa6e, 0xfa6f, -- 0xfada, 0xfaff, -- 0xfb07, 0xfb12, -- 0xfb18, 0xfb1c, -- 0xfb37, 0xfb37, -- 0xfb3d, 0xfb3d, -- 0xfb3f, 0xfb3f, -- 0xfb42, 0xfb42, -- 0xfb45, 0xfb45, -- 0xfbc2, 0xfbd2, -- 0xfd40, 0xfd4f, -- 0xfd90, 0xfd91, -- 0xfdc8, 0xfdef, -- 0xfdfe, 0xfdff, -- 0xfe1a, 0xfe1f, -- 0xfe27, 0xfe2f, -- 0xfe53, 0xfe53, -- 0xfe67, 0xfe67, -- 0xfe6c, 0xfe6f, -- 0xfe75, 0xfe75, -- 0xfefd, 0xfefe, -- 0xff00, 0xff00, -- 0xffbf, 0xffc1, -- 0xffc8, 0xffc9, -- 0xffd0, 0xffd1, -- 0xffd8, 0xffd9, -- 0xffdd, 0xffdf, -- 0xffe7, 0xffe7, -- 0xffef, 0xfff8, -- 0xfffe, 0xffff, -- 0x1000c, 0x1000c, -- 0x10027, 0x10027, -- 0x1003b, 0x1003b, -- 0x1003e, 0x1003e, -- 0x1004e, 0x1004f, -- 0x1005e, 0x1007f, -- 0x100fb, 0x100ff, -- 0x10103, 0x10106, -- 0x10134, 0x10136, -- 0x1018b, 0x1018f, -- 0x1019c, 0x101cf, -- 0x101fe, 0x1027f, -- 0x1029d, 0x1029f, -- 0x102d1, 0x102ff, -- 0x1031f, 0x1031f, -- 0x10324, 0x1032f, -- 0x1034b, 0x1037f, -- 0x1039e, 0x1039e, -- 0x103c4, 0x103c7, -- 0x103d6, 0x103ff, -- 0x1049e, 0x1049f, -- 0x104aa, 0x107ff, -- 0x10806, 0x10807, -- 0x10809, 0x10809, -- 0x10836, 0x10836, -- 0x10839, 0x1083b, -- 0x1083d, 0x1083e, -- 0x10856, 0x10856, -- 0x10860, 0x108ff, -- 0x1091c, 0x1091e, -- 0x1093a, 0x1093e, -- 0x10940, 0x109ff, -- 0x10a04, 0x10a04, -- 0x10a07, 0x10a0b, -- 0x10a14, 0x10a14, -- 0x10a18, 0x10a18, -- 0x10a34, 0x10a37, -- 0x10a3b, 0x10a3e, -- 0x10a48, 0x10a4f, -- 0x10a59, 0x10a5f, -- 0x10a80, 0x10aff, -- 0x10b36, 0x10b38, -- 0x10b56, 0x10b57, -- 0x10b73, 0x10b77, -- 0x10b80, 0x10bff, -- 0x10c49, 0x10e5f, -- 0x10e7f, 0x10fff, -- 0x1104e, 0x11051, -- 0x11070, 0x1107f, -- 0x110c2, 0x11fff, -- 0x1236f, 0x123ff, -- 0x12463, 0x1246f, -- 0x12474, 0x12fff, -- 0x1342f, 0x167ff, -- 0x16a39, 0x1afff, -- 0x1b002, 0x1cfff, -- 0x1d0f6, 0x1d0ff, -- 0x1d127, 0x1d128, -- 0x1d1de, 0x1d1ff, -- 0x1d246, 0x1d2ff, -- 0x1d357, 0x1d35f, -- 0x1d372, 0x1d3ff, -- 0x1d455, 0x1d455, -- 0x1d49d, 0x1d49d, -- 0x1d4a0, 0x1d4a1, -- 0x1d4a3, 0x1d4a4, -- 0x1d4a7, 0x1d4a8, -- 0x1d4ad, 0x1d4ad, -- 0x1d4ba, 0x1d4ba, -- 0x1d4bc, 0x1d4bc, -- 0x1d4c4, 0x1d4c4, -- 0x1d506, 0x1d506, -- 0x1d50b, 0x1d50c, -- 0x1d515, 0x1d515, -- 0x1d51d, 0x1d51d, -- 0x1d53a, 0x1d53a, -- 0x1d53f, 0x1d53f, -- 0x1d545, 0x1d545, -- 0x1d547, 0x1d549, -- 0x1d551, 0x1d551, -- 0x1d6a6, 0x1d6a7, -- 0x1d7cc, 0x1d7cd, -- 0x1d800, 0x1efff, -- 0x1f02c, 0x1f02f, -- 0x1f094, 0x1f09f, -- 0x1f0af, 0x1f0b0, -- 0x1f0bf, 0x1f0c0, -- 0x1f0d0, 0x1f0d0, -- 0x1f0e0, 0x1f0ff, -- 0x1f10b, 0x1f10f, -- 0x1f12f, 0x1f12f, -- 0x1f16a, 0x1f16f, -- 0x1f19b, 0x1f1e5, -- 0x1f203, 0x1f20f, -- 0x1f23b, 0x1f23f, -- 0x1f249, 0x1f24f, -- 0x1f252, 0x1f2ff, -- 0x1f321, 0x1f32f, -- 0x1f336, 0x1f336, -- 0x1f37d, 0x1f37f, -- 0x1f394, 0x1f39f, -- 0x1f3c5, 0x1f3c5, -- 0x1f3cb, 0x1f3df, -- 0x1f3f1, 0x1f3ff, -- 0x1f43f, 0x1f43f, -- 0x1f441, 0x1f441, -- 0x1f4f8, 0x1f4f8, -- 0x1f4fd, 0x1f4ff, -- 0x1f53e, 0x1f54f, -- 0x1f568, 0x1f5fa, -- 0x1f600, 0x1f600, -- 0x1f611, 0x1f611, -- 0x1f615, 0x1f615, -- 0x1f617, 0x1f617, -- 0x1f619, 0x1f619, -- 0x1f61b, 0x1f61b, -- 0x1f61f, 0x1f61f, -- 0x1f626, 0x1f627, -- 0x1f62c, 0x1f62c, -- 0x1f62e, 0x1f62f, -- 0x1f634, 0x1f634, -- 0x1f641, 0x1f644, -- 0x1f650, 0x1f67f, -- 0x1f6c6, 0x1f6ff, -- 0x1f774, 0x1ffff, -- 0x2a6d7, 0x2a6ff, -- 0x2b735, 0x2b73f, -- 0x2b81e, 0x2f7ff, -- 0x2fa1e, 0xe0000, -- 0xe0002, 0xe001f, -- 0xe0080, 0xe00ff, -- 0xe01f0, 0xeffff, -- 0xffffe, 0xfffff, -- 0x10fffe, 0x10ffff, --}; /* CR_Cn */ -- --/* 'Co': General Category */ --static const OnigCodePoint CR_Co[] = { -- 3, -- 0xe000, 0xf8ff, -- 0xf0000, 0xffffd, -- 0x100000, 0x10fffd, --}; /* CR_Co */ -- --/* 'Cs': General Category */ --static const OnigCodePoint CR_Cs[] = { -- 1, -- 0xd800, 0xdfff, --}; /* CR_Cs */ -- --/* 'L': Major Category */ --static const OnigCodePoint CR_L[] = { -- 435, -- 0x0041, 0x005a, -- 0x0061, 0x007a, -- 0x00aa, 0x00aa, -- 0x00b5, 0x00b5, -- 0x00ba, 0x00ba, -- 0x00c0, 0x00d6, -- 0x00d8, 0x00f6, -- 0x00f8, 0x02c1, -- 0x02c6, 0x02d1, -- 0x02e0, 0x02e4, -- 0x02ec, 0x02ec, -- 0x02ee, 0x02ee, -- 0x0370, 0x0374, -- 0x0376, 0x0377, -- 0x037a, 0x037d, -- 0x0386, 0x0386, -- 0x0388, 0x038a, -- 0x038c, 0x038c, -- 0x038e, 0x03a1, -- 0x03a3, 0x03f5, -- 0x03f7, 0x0481, -- 0x048a, 0x0527, -- 0x0531, 0x0556, -- 0x0559, 0x0559, -- 0x0561, 0x0587, -- 0x05d0, 0x05ea, -- 0x05f0, 0x05f2, -- 0x0620, 0x064a, -- 0x066e, 0x066f, -- 0x0671, 0x06d3, -- 0x06d5, 0x06d5, -- 0x06e5, 0x06e6, -- 0x06ee, 0x06ef, -- 0x06fa, 0x06fc, -- 0x06ff, 0x06ff, -- 0x0710, 0x0710, -- 0x0712, 0x072f, -- 0x074d, 0x07a5, -- 0x07b1, 0x07b1, -- 0x07ca, 0x07ea, -- 0x07f4, 0x07f5, -- 0x07fa, 0x07fa, -- 0x0800, 0x0815, -- 0x081a, 0x081a, -- 0x0824, 0x0824, -- 0x0828, 0x0828, -- 0x0840, 0x0858, -- 0x0904, 0x0939, -- 0x093d, 0x093d, -- 0x0950, 0x0950, -- 0x0958, 0x0961, -- 0x0971, 0x0977, -- 0x0979, 0x097f, -- 0x0985, 0x098c, -- 0x098f, 0x0990, -- 0x0993, 0x09a8, -- 0x09aa, 0x09b0, -- 0x09b2, 0x09b2, -- 0x09b6, 0x09b9, -- 0x09bd, 0x09bd, -- 0x09ce, 0x09ce, -- 0x09dc, 0x09dd, -- 0x09df, 0x09e1, -- 0x09f0, 0x09f1, -- 0x0a05, 0x0a0a, -- 0x0a0f, 0x0a10, -- 0x0a13, 0x0a28, -- 0x0a2a, 0x0a30, -- 0x0a32, 0x0a33, -- 0x0a35, 0x0a36, -- 0x0a38, 0x0a39, -- 0x0a59, 0x0a5c, -- 0x0a5e, 0x0a5e, -- 0x0a72, 0x0a74, -- 0x0a85, 0x0a8d, -- 0x0a8f, 0x0a91, -- 0x0a93, 0x0aa8, -- 0x0aaa, 0x0ab0, -- 0x0ab2, 0x0ab3, -- 0x0ab5, 0x0ab9, -- 0x0abd, 0x0abd, -- 0x0ad0, 0x0ad0, -- 0x0ae0, 0x0ae1, -- 0x0b05, 0x0b0c, -- 0x0b0f, 0x0b10, -- 0x0b13, 0x0b28, -- 0x0b2a, 0x0b30, -- 0x0b32, 0x0b33, -- 0x0b35, 0x0b39, -- 0x0b3d, 0x0b3d, -- 0x0b5c, 0x0b5d, -- 0x0b5f, 0x0b61, -- 0x0b71, 0x0b71, -- 0x0b83, 0x0b83, -- 0x0b85, 0x0b8a, -- 0x0b8e, 0x0b90, -- 0x0b92, 0x0b95, -- 0x0b99, 0x0b9a, -- 0x0b9c, 0x0b9c, -- 0x0b9e, 0x0b9f, -- 0x0ba3, 0x0ba4, -- 0x0ba8, 0x0baa, -- 0x0bae, 0x0bb9, -- 0x0bd0, 0x0bd0, -- 0x0c05, 0x0c0c, -- 0x0c0e, 0x0c10, -- 0x0c12, 0x0c28, -- 0x0c2a, 0x0c33, -- 0x0c35, 0x0c39, -- 0x0c3d, 0x0c3d, -- 0x0c58, 0x0c59, -- 0x0c60, 0x0c61, -- 0x0c85, 0x0c8c, -- 0x0c8e, 0x0c90, -- 0x0c92, 0x0ca8, -- 0x0caa, 0x0cb3, -- 0x0cb5, 0x0cb9, -- 0x0cbd, 0x0cbd, -- 0x0cde, 0x0cde, -- 0x0ce0, 0x0ce1, -- 0x0cf1, 0x0cf2, -- 0x0d05, 0x0d0c, -- 0x0d0e, 0x0d10, -- 0x0d12, 0x0d3a, -- 0x0d3d, 0x0d3d, -- 0x0d4e, 0x0d4e, -- 0x0d60, 0x0d61, -- 0x0d7a, 0x0d7f, -- 0x0d85, 0x0d96, -- 0x0d9a, 0x0db1, -- 0x0db3, 0x0dbb, -- 0x0dbd, 0x0dbd, -- 0x0dc0, 0x0dc6, -- 0x0e01, 0x0e30, -- 0x0e32, 0x0e33, -- 0x0e40, 0x0e46, -- 0x0e81, 0x0e82, -- 0x0e84, 0x0e84, -- 0x0e87, 0x0e88, -- 0x0e8a, 0x0e8a, -- 0x0e8d, 0x0e8d, -- 0x0e94, 0x0e97, -- 0x0e99, 0x0e9f, -- 0x0ea1, 0x0ea3, -- 0x0ea5, 0x0ea5, -- 0x0ea7, 0x0ea7, -- 0x0eaa, 0x0eab, -- 0x0ead, 0x0eb0, -- 0x0eb2, 0x0eb3, -- 0x0ebd, 0x0ebd, -- 0x0ec0, 0x0ec4, -- 0x0ec6, 0x0ec6, -- 0x0edc, 0x0edd, -- 0x0f00, 0x0f00, -- 0x0f40, 0x0f47, -- 0x0f49, 0x0f6c, -- 0x0f88, 0x0f8c, -- 0x1000, 0x102a, -- 0x103f, 0x103f, -- 0x1050, 0x1055, -- 0x105a, 0x105d, -- 0x1061, 0x1061, -- 0x1065, 0x1066, -- 0x106e, 0x1070, -- 0x1075, 0x1081, -- 0x108e, 0x108e, -- 0x10a0, 0x10c5, -- 0x10d0, 0x10fa, -- 0x10fc, 0x10fc, -- 0x1100, 0x1248, -- 0x124a, 0x124d, -- 0x1250, 0x1256, -- 0x1258, 0x1258, -- 0x125a, 0x125d, -- 0x1260, 0x1288, -- 0x128a, 0x128d, -- 0x1290, 0x12b0, -- 0x12b2, 0x12b5, -- 0x12b8, 0x12be, -- 0x12c0, 0x12c0, -- 0x12c2, 0x12c5, -- 0x12c8, 0x12d6, -- 0x12d8, 0x1310, -- 0x1312, 0x1315, -- 0x1318, 0x135a, -- 0x1380, 0x138f, -- 0x13a0, 0x13f4, -- 0x1401, 0x166c, -- 0x166f, 0x167f, -- 0x1681, 0x169a, -- 0x16a0, 0x16ea, -- 0x1700, 0x170c, -- 0x170e, 0x1711, -- 0x1720, 0x1731, -- 0x1740, 0x1751, -- 0x1760, 0x176c, -- 0x176e, 0x1770, -- 0x1780, 0x17b3, -- 0x17d7, 0x17d7, -- 0x17dc, 0x17dc, -- 0x1820, 0x1877, -- 0x1880, 0x18a8, -- 0x18aa, 0x18aa, -- 0x18b0, 0x18f5, -- 0x1900, 0x191c, -- 0x1950, 0x196d, -- 0x1970, 0x1974, -- 0x1980, 0x19ab, -- 0x19c1, 0x19c7, -- 0x1a00, 0x1a16, -- 0x1a20, 0x1a54, -- 0x1aa7, 0x1aa7, -- 0x1b05, 0x1b33, -- 0x1b45, 0x1b4b, -- 0x1b83, 0x1ba0, -- 0x1bae, 0x1baf, -- 0x1bc0, 0x1be5, -- 0x1c00, 0x1c23, -- 0x1c4d, 0x1c4f, -- 0x1c5a, 0x1c7d, -- 0x1ce9, 0x1cec, -- 0x1cee, 0x1cf1, -- 0x1d00, 0x1dbf, -- 0x1e00, 0x1f15, -- 0x1f18, 0x1f1d, -- 0x1f20, 0x1f45, -- 0x1f48, 0x1f4d, -- 0x1f50, 0x1f57, -- 0x1f59, 0x1f59, -- 0x1f5b, 0x1f5b, -- 0x1f5d, 0x1f5d, -- 0x1f5f, 0x1f7d, -- 0x1f80, 0x1fb4, -- 0x1fb6, 0x1fbc, -- 0x1fbe, 0x1fbe, -- 0x1fc2, 0x1fc4, -- 0x1fc6, 0x1fcc, -- 0x1fd0, 0x1fd3, -- 0x1fd6, 0x1fdb, -- 0x1fe0, 0x1fec, -- 0x1ff2, 0x1ff4, -- 0x1ff6, 0x1ffc, -- 0x2071, 0x2071, -- 0x207f, 0x207f, -- 0x2090, 0x209c, -- 0x2102, 0x2102, -- 0x2107, 0x2107, -- 0x210a, 0x2113, -- 0x2115, 0x2115, -- 0x2119, 0x211d, -- 0x2124, 0x2124, -- 0x2126, 0x2126, -- 0x2128, 0x2128, -- 0x212a, 0x212d, -- 0x212f, 0x2139, -- 0x213c, 0x213f, -- 0x2145, 0x2149, -- 0x214e, 0x214e, -- 0x2183, 0x2184, -- 0x2c00, 0x2c2e, -- 0x2c30, 0x2c5e, -- 0x2c60, 0x2ce4, -- 0x2ceb, 0x2cee, -- 0x2d00, 0x2d25, -- 0x2d30, 0x2d65, -- 0x2d6f, 0x2d6f, -- 0x2d80, 0x2d96, -- 0x2da0, 0x2da6, -- 0x2da8, 0x2dae, -- 0x2db0, 0x2db6, -- 0x2db8, 0x2dbe, -- 0x2dc0, 0x2dc6, -- 0x2dc8, 0x2dce, -- 0x2dd0, 0x2dd6, -- 0x2dd8, 0x2dde, -- 0x2e2f, 0x2e2f, -- 0x3005, 0x3006, -- 0x3031, 0x3035, -- 0x303b, 0x303c, -- 0x3041, 0x3096, -- 0x309d, 0x309f, -- 0x30a1, 0x30fa, -- 0x30fc, 0x30ff, -- 0x3105, 0x312d, -- 0x3131, 0x318e, -- 0x31a0, 0x31ba, -- 0x31f0, 0x31ff, -- 0x3400, 0x4db5, -- 0x4e00, 0x9fcb, -- 0xa000, 0xa48c, -- 0xa4d0, 0xa4fd, -- 0xa500, 0xa60c, -- 0xa610, 0xa61f, -- 0xa62a, 0xa62b, -- 0xa640, 0xa66e, -- 0xa67f, 0xa697, -- 0xa6a0, 0xa6e5, -- 0xa717, 0xa71f, -- 0xa722, 0xa788, -- 0xa78b, 0xa78e, -- 0xa790, 0xa791, -- 0xa7a0, 0xa7a9, -- 0xa7fa, 0xa801, -- 0xa803, 0xa805, -- 0xa807, 0xa80a, -- 0xa80c, 0xa822, -- 0xa840, 0xa873, -- 0xa882, 0xa8b3, -- 0xa8f2, 0xa8f7, -- 0xa8fb, 0xa8fb, -- 0xa90a, 0xa925, -- 0xa930, 0xa946, -- 0xa960, 0xa97c, -- 0xa984, 0xa9b2, -- 0xa9cf, 0xa9cf, -- 0xaa00, 0xaa28, -- 0xaa40, 0xaa42, -- 0xaa44, 0xaa4b, -- 0xaa60, 0xaa76, -- 0xaa7a, 0xaa7a, -- 0xaa80, 0xaaaf, -- 0xaab1, 0xaab1, -- 0xaab5, 0xaab6, -- 0xaab9, 0xaabd, -- 0xaac0, 0xaac0, -- 0xaac2, 0xaac2, -- 0xaadb, 0xaadd, -- 0xab01, 0xab06, -- 0xab09, 0xab0e, -- 0xab11, 0xab16, -- 0xab20, 0xab26, -- 0xab28, 0xab2e, -- 0xabc0, 0xabe2, -- 0xac00, 0xd7a3, -- 0xd7b0, 0xd7c6, -- 0xd7cb, 0xd7fb, -- 0xf900, 0xfa2d, -- 0xfa30, 0xfa6d, -- 0xfa70, 0xfad9, -- 0xfb00, 0xfb06, -- 0xfb13, 0xfb17, -- 0xfb1d, 0xfb1d, -- 0xfb1f, 0xfb28, -- 0xfb2a, 0xfb36, -- 0xfb38, 0xfb3c, -- 0xfb3e, 0xfb3e, -- 0xfb40, 0xfb41, -- 0xfb43, 0xfb44, -- 0xfb46, 0xfbb1, -- 0xfbd3, 0xfd3d, -- 0xfd50, 0xfd8f, -- 0xfd92, 0xfdc7, -- 0xfdf0, 0xfdfb, -- 0xfe70, 0xfe74, -- 0xfe76, 0xfefc, -- 0xff21, 0xff3a, -- 0xff41, 0xff5a, -- 0xff66, 0xffbe, -- 0xffc2, 0xffc7, -- 0xffca, 0xffcf, -- 0xffd2, 0xffd7, -- 0xffda, 0xffdc, -- 0x10000, 0x1000b, -- 0x1000d, 0x10026, -- 0x10028, 0x1003a, -- 0x1003c, 0x1003d, -- 0x1003f, 0x1004d, -- 0x10050, 0x1005d, -- 0x10080, 0x100fa, -- 0x10280, 0x1029c, -- 0x102a0, 0x102d0, -- 0x10300, 0x1031e, -- 0x10330, 0x10340, -- 0x10342, 0x10349, -- 0x10380, 0x1039d, -- 0x103a0, 0x103c3, -- 0x103c8, 0x103cf, -- 0x10400, 0x1049d, -- 0x10800, 0x10805, -- 0x10808, 0x10808, -- 0x1080a, 0x10835, -- 0x10837, 0x10838, -- 0x1083c, 0x1083c, -- 0x1083f, 0x10855, -- 0x10900, 0x10915, -- 0x10920, 0x10939, -- 0x10a00, 0x10a00, -- 0x10a10, 0x10a13, -- 0x10a15, 0x10a17, -- 0x10a19, 0x10a33, -- 0x10a60, 0x10a7c, -- 0x10b00, 0x10b35, -- 0x10b40, 0x10b55, -- 0x10b60, 0x10b72, -- 0x10c00, 0x10c48, -- 0x11003, 0x11037, -- 0x11083, 0x110af, -- 0x12000, 0x1236e, -- 0x13000, 0x1342e, -- 0x16800, 0x16a38, -- 0x1b000, 0x1b001, -- 0x1d400, 0x1d454, -- 0x1d456, 0x1d49c, -- 0x1d49e, 0x1d49f, -- 0x1d4a2, 0x1d4a2, -- 0x1d4a5, 0x1d4a6, -- 0x1d4a9, 0x1d4ac, -- 0x1d4ae, 0x1d4b9, -- 0x1d4bb, 0x1d4bb, -- 0x1d4bd, 0x1d4c3, -- 0x1d4c5, 0x1d505, -- 0x1d507, 0x1d50a, -- 0x1d50d, 0x1d514, -- 0x1d516, 0x1d51c, -- 0x1d51e, 0x1d539, -- 0x1d53b, 0x1d53e, -- 0x1d540, 0x1d544, -- 0x1d546, 0x1d546, -- 0x1d54a, 0x1d550, -- 0x1d552, 0x1d6a5, -- 0x1d6a8, 0x1d6c0, -- 0x1d6c2, 0x1d6da, -- 0x1d6dc, 0x1d6fa, -- 0x1d6fc, 0x1d714, -- 0x1d716, 0x1d734, -- 0x1d736, 0x1d74e, -- 0x1d750, 0x1d76e, -- 0x1d770, 0x1d788, -- 0x1d78a, 0x1d7a8, -- 0x1d7aa, 0x1d7c2, -- 0x1d7c4, 0x1d7cb, -- 0x20000, 0x2a6d6, -- 0x2a700, 0x2b734, -- 0x2b740, 0x2b81d, -- 0x2f800, 0x2fa1d, --}; /* CR_L */ -- --/* 'Ll': General Category */ --static const OnigCodePoint CR_Ll[] = { -- 609, -- 0x0061, 0x007a, -- 0x00aa, 0x00aa, -- 0x00b5, 0x00b5, -- 0x00ba, 0x00ba, -- 0x00df, 0x00f6, -- 0x00f8, 0x00ff, -- 0x0101, 0x0101, -- 0x0103, 0x0103, -- 0x0105, 0x0105, -- 0x0107, 0x0107, -- 0x0109, 0x0109, -- 0x010b, 0x010b, -- 0x010d, 0x010d, -- 0x010f, 0x010f, -- 0x0111, 0x0111, -- 0x0113, 0x0113, -- 0x0115, 0x0115, -- 0x0117, 0x0117, -- 0x0119, 0x0119, -- 0x011b, 0x011b, -- 0x011d, 0x011d, -- 0x011f, 0x011f, -- 0x0121, 0x0121, -- 0x0123, 0x0123, -- 0x0125, 0x0125, -- 0x0127, 0x0127, -- 0x0129, 0x0129, -- 0x012b, 0x012b, -- 0x012d, 0x012d, -- 0x012f, 0x012f, -- 0x0131, 0x0131, -- 0x0133, 0x0133, -- 0x0135, 0x0135, -- 0x0137, 0x0138, -- 0x013a, 0x013a, -- 0x013c, 0x013c, -- 0x013e, 0x013e, -- 0x0140, 0x0140, -- 0x0142, 0x0142, -- 0x0144, 0x0144, -- 0x0146, 0x0146, -- 0x0148, 0x0149, -- 0x014b, 0x014b, -- 0x014d, 0x014d, -- 0x014f, 0x014f, -- 0x0151, 0x0151, -- 0x0153, 0x0153, -- 0x0155, 0x0155, -- 0x0157, 0x0157, -- 0x0159, 0x0159, -- 0x015b, 0x015b, -- 0x015d, 0x015d, -- 0x015f, 0x015f, -- 0x0161, 0x0161, -- 0x0163, 0x0163, -- 0x0165, 0x0165, -- 0x0167, 0x0167, -- 0x0169, 0x0169, -- 0x016b, 0x016b, -- 0x016d, 0x016d, -- 0x016f, 0x016f, -- 0x0171, 0x0171, -- 0x0173, 0x0173, -- 0x0175, 0x0175, -- 0x0177, 0x0177, -- 0x017a, 0x017a, -- 0x017c, 0x017c, -- 0x017e, 0x0180, -- 0x0183, 0x0183, -- 0x0185, 0x0185, -- 0x0188, 0x0188, -- 0x018c, 0x018d, -- 0x0192, 0x0192, -- 0x0195, 0x0195, -- 0x0199, 0x019b, -- 0x019e, 0x019e, -- 0x01a1, 0x01a1, -- 0x01a3, 0x01a3, -- 0x01a5, 0x01a5, -- 0x01a8, 0x01a8, -- 0x01aa, 0x01ab, -- 0x01ad, 0x01ad, -- 0x01b0, 0x01b0, -- 0x01b4, 0x01b4, -- 0x01b6, 0x01b6, -- 0x01b9, 0x01ba, -- 0x01bd, 0x01bf, -- 0x01c6, 0x01c6, -- 0x01c9, 0x01c9, -- 0x01cc, 0x01cc, -- 0x01ce, 0x01ce, -- 0x01d0, 0x01d0, -- 0x01d2, 0x01d2, -- 0x01d4, 0x01d4, -- 0x01d6, 0x01d6, -- 0x01d8, 0x01d8, -- 0x01da, 0x01da, -- 0x01dc, 0x01dd, -- 0x01df, 0x01df, -- 0x01e1, 0x01e1, -- 0x01e3, 0x01e3, -- 0x01e5, 0x01e5, -- 0x01e7, 0x01e7, -- 0x01e9, 0x01e9, -- 0x01eb, 0x01eb, -- 0x01ed, 0x01ed, -- 0x01ef, 0x01f0, -- 0x01f3, 0x01f3, -- 0x01f5, 0x01f5, -- 0x01f9, 0x01f9, -- 0x01fb, 0x01fb, -- 0x01fd, 0x01fd, -- 0x01ff, 0x01ff, -- 0x0201, 0x0201, -- 0x0203, 0x0203, -- 0x0205, 0x0205, -- 0x0207, 0x0207, -- 0x0209, 0x0209, -- 0x020b, 0x020b, -- 0x020d, 0x020d, -- 0x020f, 0x020f, -- 0x0211, 0x0211, -- 0x0213, 0x0213, -- 0x0215, 0x0215, -- 0x0217, 0x0217, -- 0x0219, 0x0219, -- 0x021b, 0x021b, -- 0x021d, 0x021d, -- 0x021f, 0x021f, -- 0x0221, 0x0221, -- 0x0223, 0x0223, -- 0x0225, 0x0225, -- 0x0227, 0x0227, -- 0x0229, 0x0229, -- 0x022b, 0x022b, -- 0x022d, 0x022d, -- 0x022f, 0x022f, -- 0x0231, 0x0231, -- 0x0233, 0x0239, -- 0x023c, 0x023c, -- 0x023f, 0x0240, -- 0x0242, 0x0242, -- 0x0247, 0x0247, -- 0x0249, 0x0249, -- 0x024b, 0x024b, -- 0x024d, 0x024d, -- 0x024f, 0x0293, -- 0x0295, 0x02af, -- 0x0371, 0x0371, -- 0x0373, 0x0373, -- 0x0377, 0x0377, -- 0x037b, 0x037d, -- 0x0390, 0x0390, -- 0x03ac, 0x03ce, -- 0x03d0, 0x03d1, -- 0x03d5, 0x03d7, -- 0x03d9, 0x03d9, -- 0x03db, 0x03db, -- 0x03dd, 0x03dd, -- 0x03df, 0x03df, -- 0x03e1, 0x03e1, -- 0x03e3, 0x03e3, -- 0x03e5, 0x03e5, -- 0x03e7, 0x03e7, -- 0x03e9, 0x03e9, -- 0x03eb, 0x03eb, -- 0x03ed, 0x03ed, -- 0x03ef, 0x03f3, -- 0x03f5, 0x03f5, -- 0x03f8, 0x03f8, -- 0x03fb, 0x03fc, -- 0x0430, 0x045f, -- 0x0461, 0x0461, -- 0x0463, 0x0463, -- 0x0465, 0x0465, -- 0x0467, 0x0467, -- 0x0469, 0x0469, -- 0x046b, 0x046b, -- 0x046d, 0x046d, -- 0x046f, 0x046f, -- 0x0471, 0x0471, -- 0x0473, 0x0473, -- 0x0475, 0x0475, -- 0x0477, 0x0477, -- 0x0479, 0x0479, -- 0x047b, 0x047b, -- 0x047d, 0x047d, -- 0x047f, 0x047f, -- 0x0481, 0x0481, -- 0x048b, 0x048b, -- 0x048d, 0x048d, -- 0x048f, 0x048f, -- 0x0491, 0x0491, -- 0x0493, 0x0493, -- 0x0495, 0x0495, -- 0x0497, 0x0497, -- 0x0499, 0x0499, -- 0x049b, 0x049b, -- 0x049d, 0x049d, -- 0x049f, 0x049f, -- 0x04a1, 0x04a1, -- 0x04a3, 0x04a3, -- 0x04a5, 0x04a5, -- 0x04a7, 0x04a7, -- 0x04a9, 0x04a9, -- 0x04ab, 0x04ab, -- 0x04ad, 0x04ad, -- 0x04af, 0x04af, -- 0x04b1, 0x04b1, -- 0x04b3, 0x04b3, -- 0x04b5, 0x04b5, -- 0x04b7, 0x04b7, -- 0x04b9, 0x04b9, -- 0x04bb, 0x04bb, -- 0x04bd, 0x04bd, -- 0x04bf, 0x04bf, -- 0x04c2, 0x04c2, -- 0x04c4, 0x04c4, -- 0x04c6, 0x04c6, -- 0x04c8, 0x04c8, -- 0x04ca, 0x04ca, -- 0x04cc, 0x04cc, -- 0x04ce, 0x04cf, -- 0x04d1, 0x04d1, -- 0x04d3, 0x04d3, -- 0x04d5, 0x04d5, -- 0x04d7, 0x04d7, -- 0x04d9, 0x04d9, -- 0x04db, 0x04db, -- 0x04dd, 0x04dd, -- 0x04df, 0x04df, -- 0x04e1, 0x04e1, -- 0x04e3, 0x04e3, -- 0x04e5, 0x04e5, -- 0x04e7, 0x04e7, -- 0x04e9, 0x04e9, -- 0x04eb, 0x04eb, -- 0x04ed, 0x04ed, -- 0x04ef, 0x04ef, -- 0x04f1, 0x04f1, -- 0x04f3, 0x04f3, -- 0x04f5, 0x04f5, -- 0x04f7, 0x04f7, -- 0x04f9, 0x04f9, -- 0x04fb, 0x04fb, -- 0x04fd, 0x04fd, -- 0x04ff, 0x04ff, -- 0x0501, 0x0501, -- 0x0503, 0x0503, -- 0x0505, 0x0505, -- 0x0507, 0x0507, -- 0x0509, 0x0509, -- 0x050b, 0x050b, -- 0x050d, 0x050d, -- 0x050f, 0x050f, -- 0x0511, 0x0511, -- 0x0513, 0x0513, -- 0x0515, 0x0515, -- 0x0517, 0x0517, -- 0x0519, 0x0519, -- 0x051b, 0x051b, -- 0x051d, 0x051d, -- 0x051f, 0x051f, -- 0x0521, 0x0521, -- 0x0523, 0x0523, -- 0x0525, 0x0525, -- 0x0527, 0x0527, -- 0x0561, 0x0587, -- 0x1d00, 0x1d2b, -- 0x1d62, 0x1d77, -- 0x1d79, 0x1d9a, -- 0x1e01, 0x1e01, -- 0x1e03, 0x1e03, -- 0x1e05, 0x1e05, -- 0x1e07, 0x1e07, -- 0x1e09, 0x1e09, -- 0x1e0b, 0x1e0b, -- 0x1e0d, 0x1e0d, -- 0x1e0f, 0x1e0f, -- 0x1e11, 0x1e11, -- 0x1e13, 0x1e13, -- 0x1e15, 0x1e15, -- 0x1e17, 0x1e17, -- 0x1e19, 0x1e19, -- 0x1e1b, 0x1e1b, -- 0x1e1d, 0x1e1d, -- 0x1e1f, 0x1e1f, -- 0x1e21, 0x1e21, -- 0x1e23, 0x1e23, -- 0x1e25, 0x1e25, -- 0x1e27, 0x1e27, -- 0x1e29, 0x1e29, -- 0x1e2b, 0x1e2b, -- 0x1e2d, 0x1e2d, -- 0x1e2f, 0x1e2f, -- 0x1e31, 0x1e31, -- 0x1e33, 0x1e33, -- 0x1e35, 0x1e35, -- 0x1e37, 0x1e37, -- 0x1e39, 0x1e39, -- 0x1e3b, 0x1e3b, -- 0x1e3d, 0x1e3d, -- 0x1e3f, 0x1e3f, -- 0x1e41, 0x1e41, -- 0x1e43, 0x1e43, -- 0x1e45, 0x1e45, -- 0x1e47, 0x1e47, -- 0x1e49, 0x1e49, -- 0x1e4b, 0x1e4b, -- 0x1e4d, 0x1e4d, -- 0x1e4f, 0x1e4f, -- 0x1e51, 0x1e51, -- 0x1e53, 0x1e53, -- 0x1e55, 0x1e55, -- 0x1e57, 0x1e57, -- 0x1e59, 0x1e59, -- 0x1e5b, 0x1e5b, -- 0x1e5d, 0x1e5d, -- 0x1e5f, 0x1e5f, -- 0x1e61, 0x1e61, -- 0x1e63, 0x1e63, -- 0x1e65, 0x1e65, -- 0x1e67, 0x1e67, -- 0x1e69, 0x1e69, -- 0x1e6b, 0x1e6b, -- 0x1e6d, 0x1e6d, -- 0x1e6f, 0x1e6f, -- 0x1e71, 0x1e71, -- 0x1e73, 0x1e73, -- 0x1e75, 0x1e75, -- 0x1e77, 0x1e77, -- 0x1e79, 0x1e79, -- 0x1e7b, 0x1e7b, -- 0x1e7d, 0x1e7d, -- 0x1e7f, 0x1e7f, -- 0x1e81, 0x1e81, -- 0x1e83, 0x1e83, -- 0x1e85, 0x1e85, -- 0x1e87, 0x1e87, -- 0x1e89, 0x1e89, -- 0x1e8b, 0x1e8b, -- 0x1e8d, 0x1e8d, -- 0x1e8f, 0x1e8f, -- 0x1e91, 0x1e91, -- 0x1e93, 0x1e93, -- 0x1e95, 0x1e9d, -- 0x1e9f, 0x1e9f, -- 0x1ea1, 0x1ea1, -- 0x1ea3, 0x1ea3, -- 0x1ea5, 0x1ea5, -- 0x1ea7, 0x1ea7, -- 0x1ea9, 0x1ea9, -- 0x1eab, 0x1eab, -- 0x1ead, 0x1ead, -- 0x1eaf, 0x1eaf, -- 0x1eb1, 0x1eb1, -- 0x1eb3, 0x1eb3, -- 0x1eb5, 0x1eb5, -- 0x1eb7, 0x1eb7, -- 0x1eb9, 0x1eb9, -- 0x1ebb, 0x1ebb, -- 0x1ebd, 0x1ebd, -- 0x1ebf, 0x1ebf, -- 0x1ec1, 0x1ec1, -- 0x1ec3, 0x1ec3, -- 0x1ec5, 0x1ec5, -- 0x1ec7, 0x1ec7, -- 0x1ec9, 0x1ec9, -- 0x1ecb, 0x1ecb, -- 0x1ecd, 0x1ecd, -- 0x1ecf, 0x1ecf, -- 0x1ed1, 0x1ed1, -- 0x1ed3, 0x1ed3, -- 0x1ed5, 0x1ed5, -- 0x1ed7, 0x1ed7, -- 0x1ed9, 0x1ed9, -- 0x1edb, 0x1edb, -- 0x1edd, 0x1edd, -- 0x1edf, 0x1edf, -- 0x1ee1, 0x1ee1, -- 0x1ee3, 0x1ee3, -- 0x1ee5, 0x1ee5, -- 0x1ee7, 0x1ee7, -- 0x1ee9, 0x1ee9, -- 0x1eeb, 0x1eeb, -- 0x1eed, 0x1eed, -- 0x1eef, 0x1eef, -- 0x1ef1, 0x1ef1, -- 0x1ef3, 0x1ef3, -- 0x1ef5, 0x1ef5, -- 0x1ef7, 0x1ef7, -- 0x1ef9, 0x1ef9, -- 0x1efb, 0x1efb, -- 0x1efd, 0x1efd, -- 0x1eff, 0x1f07, -- 0x1f10, 0x1f15, -- 0x1f20, 0x1f27, -- 0x1f30, 0x1f37, -- 0x1f40, 0x1f45, -- 0x1f50, 0x1f57, -- 0x1f60, 0x1f67, -- 0x1f70, 0x1f7d, -- 0x1f80, 0x1f87, -- 0x1f90, 0x1f97, -- 0x1fa0, 0x1fa7, -- 0x1fb0, 0x1fb4, -- 0x1fb6, 0x1fb7, -- 0x1fbe, 0x1fbe, -- 0x1fc2, 0x1fc4, -- 0x1fc6, 0x1fc7, -- 0x1fd0, 0x1fd3, -- 0x1fd6, 0x1fd7, -- 0x1fe0, 0x1fe7, -- 0x1ff2, 0x1ff4, -- 0x1ff6, 0x1ff7, -- 0x210a, 0x210a, -- 0x210e, 0x210f, -- 0x2113, 0x2113, -- 0x212f, 0x212f, -- 0x2134, 0x2134, -- 0x2139, 0x2139, -- 0x213c, 0x213d, -- 0x2146, 0x2149, -- 0x214e, 0x214e, -- 0x2184, 0x2184, -- 0x2c30, 0x2c5e, -- 0x2c61, 0x2c61, -- 0x2c65, 0x2c66, -- 0x2c68, 0x2c68, -- 0x2c6a, 0x2c6a, -- 0x2c6c, 0x2c6c, -- 0x2c71, 0x2c71, -- 0x2c73, 0x2c74, -- 0x2c76, 0x2c7c, -- 0x2c81, 0x2c81, -- 0x2c83, 0x2c83, -- 0x2c85, 0x2c85, -- 0x2c87, 0x2c87, -- 0x2c89, 0x2c89, -- 0x2c8b, 0x2c8b, -- 0x2c8d, 0x2c8d, -- 0x2c8f, 0x2c8f, -- 0x2c91, 0x2c91, -- 0x2c93, 0x2c93, -- 0x2c95, 0x2c95, -- 0x2c97, 0x2c97, -- 0x2c99, 0x2c99, -- 0x2c9b, 0x2c9b, -- 0x2c9d, 0x2c9d, -- 0x2c9f, 0x2c9f, -- 0x2ca1, 0x2ca1, -- 0x2ca3, 0x2ca3, -- 0x2ca5, 0x2ca5, -- 0x2ca7, 0x2ca7, -- 0x2ca9, 0x2ca9, -- 0x2cab, 0x2cab, -- 0x2cad, 0x2cad, -- 0x2caf, 0x2caf, -- 0x2cb1, 0x2cb1, -- 0x2cb3, 0x2cb3, -- 0x2cb5, 0x2cb5, -- 0x2cb7, 0x2cb7, -- 0x2cb9, 0x2cb9, -- 0x2cbb, 0x2cbb, -- 0x2cbd, 0x2cbd, -- 0x2cbf, 0x2cbf, -- 0x2cc1, 0x2cc1, -- 0x2cc3, 0x2cc3, -- 0x2cc5, 0x2cc5, -- 0x2cc7, 0x2cc7, -- 0x2cc9, 0x2cc9, -- 0x2ccb, 0x2ccb, -- 0x2ccd, 0x2ccd, -- 0x2ccf, 0x2ccf, -- 0x2cd1, 0x2cd1, -- 0x2cd3, 0x2cd3, -- 0x2cd5, 0x2cd5, -- 0x2cd7, 0x2cd7, -- 0x2cd9, 0x2cd9, -- 0x2cdb, 0x2cdb, -- 0x2cdd, 0x2cdd, -- 0x2cdf, 0x2cdf, -- 0x2ce1, 0x2ce1, -- 0x2ce3, 0x2ce4, -- 0x2cec, 0x2cec, -- 0x2cee, 0x2cee, -- 0x2d00, 0x2d25, -- 0xa641, 0xa641, -- 0xa643, 0xa643, -- 0xa645, 0xa645, -- 0xa647, 0xa647, -- 0xa649, 0xa649, -- 0xa64b, 0xa64b, -- 0xa64d, 0xa64d, -- 0xa64f, 0xa64f, -- 0xa651, 0xa651, -- 0xa653, 0xa653, -- 0xa655, 0xa655, -- 0xa657, 0xa657, -- 0xa659, 0xa659, -- 0xa65b, 0xa65b, -- 0xa65d, 0xa65d, -- 0xa65f, 0xa65f, -- 0xa661, 0xa661, -- 0xa663, 0xa663, -- 0xa665, 0xa665, -- 0xa667, 0xa667, -- 0xa669, 0xa669, -- 0xa66b, 0xa66b, -- 0xa66d, 0xa66d, -- 0xa681, 0xa681, -- 0xa683, 0xa683, -- 0xa685, 0xa685, -- 0xa687, 0xa687, -- 0xa689, 0xa689, -- 0xa68b, 0xa68b, -- 0xa68d, 0xa68d, -- 0xa68f, 0xa68f, -- 0xa691, 0xa691, -- 0xa693, 0xa693, -- 0xa695, 0xa695, -- 0xa697, 0xa697, -- 0xa723, 0xa723, -- 0xa725, 0xa725, -- 0xa727, 0xa727, -- 0xa729, 0xa729, -- 0xa72b, 0xa72b, -- 0xa72d, 0xa72d, -- 0xa72f, 0xa731, -- 0xa733, 0xa733, -- 0xa735, 0xa735, -- 0xa737, 0xa737, -- 0xa739, 0xa739, -- 0xa73b, 0xa73b, -- 0xa73d, 0xa73d, -- 0xa73f, 0xa73f, -- 0xa741, 0xa741, -- 0xa743, 0xa743, -- 0xa745, 0xa745, -- 0xa747, 0xa747, -- 0xa749, 0xa749, -- 0xa74b, 0xa74b, -- 0xa74d, 0xa74d, -- 0xa74f, 0xa74f, -- 0xa751, 0xa751, -- 0xa753, 0xa753, -- 0xa755, 0xa755, -- 0xa757, 0xa757, -- 0xa759, 0xa759, -- 0xa75b, 0xa75b, -- 0xa75d, 0xa75d, -- 0xa75f, 0xa75f, -- 0xa761, 0xa761, -- 0xa763, 0xa763, -- 0xa765, 0xa765, -- 0xa767, 0xa767, -- 0xa769, 0xa769, -- 0xa76b, 0xa76b, -- 0xa76d, 0xa76d, -- 0xa76f, 0xa76f, -- 0xa771, 0xa778, -- 0xa77a, 0xa77a, -- 0xa77c, 0xa77c, -- 0xa77f, 0xa77f, -- 0xa781, 0xa781, -- 0xa783, 0xa783, -- 0xa785, 0xa785, -- 0xa787, 0xa787, -- 0xa78c, 0xa78c, -- 0xa78e, 0xa78e, -- 0xa791, 0xa791, -- 0xa7a1, 0xa7a1, -- 0xa7a3, 0xa7a3, -- 0xa7a5, 0xa7a5, -- 0xa7a7, 0xa7a7, -- 0xa7a9, 0xa7a9, -- 0xa7fa, 0xa7fa, -- 0xfb00, 0xfb06, -- 0xfb13, 0xfb17, -- 0xff41, 0xff5a, -- 0x10428, 0x1044f, -- 0x1d41a, 0x1d433, -- 0x1d44e, 0x1d454, -- 0x1d456, 0x1d467, -- 0x1d482, 0x1d49b, -- 0x1d4b6, 0x1d4b9, -- 0x1d4bb, 0x1d4bb, -- 0x1d4bd, 0x1d4c3, -- 0x1d4c5, 0x1d4cf, -- 0x1d4ea, 0x1d503, -- 0x1d51e, 0x1d537, -- 0x1d552, 0x1d56b, -- 0x1d586, 0x1d59f, -- 0x1d5ba, 0x1d5d3, -- 0x1d5ee, 0x1d607, -- 0x1d622, 0x1d63b, -- 0x1d656, 0x1d66f, -- 0x1d68a, 0x1d6a5, -- 0x1d6c2, 0x1d6da, -- 0x1d6dc, 0x1d6e1, -- 0x1d6fc, 0x1d714, -- 0x1d716, 0x1d71b, -- 0x1d736, 0x1d74e, -- 0x1d750, 0x1d755, -- 0x1d770, 0x1d788, -- 0x1d78a, 0x1d78f, -- 0x1d7aa, 0x1d7c2, -- 0x1d7c4, 0x1d7c9, -- 0x1d7cb, 0x1d7cb, --}; /* CR_Ll */ -- --/* 'Lm': General Category */ --static const OnigCodePoint CR_Lm[] = { -- 49, -- 0x02b0, 0x02c1, -- 0x02c6, 0x02d1, -- 0x02e0, 0x02e4, -- 0x02ec, 0x02ec, -- 0x02ee, 0x02ee, -- 0x0374, 0x0374, -- 0x037a, 0x037a, -- 0x0559, 0x0559, -- 0x0640, 0x0640, -- 0x06e5, 0x06e6, -- 0x07f4, 0x07f5, -- 0x07fa, 0x07fa, -- 0x081a, 0x081a, -- 0x0824, 0x0824, -- 0x0828, 0x0828, -- 0x0971, 0x0971, -- 0x0e46, 0x0e46, -- 0x0ec6, 0x0ec6, -- 0x10fc, 0x10fc, -- 0x17d7, 0x17d7, -- 0x1843, 0x1843, -- 0x1aa7, 0x1aa7, -- 0x1c78, 0x1c7d, -- 0x1d2c, 0x1d61, -- 0x1d78, 0x1d78, -- 0x1d9b, 0x1dbf, -- 0x2071, 0x2071, -- 0x207f, 0x207f, -- 0x2090, 0x209c, -- 0x2c7d, 0x2c7d, -- 0x2d6f, 0x2d6f, -- 0x2e2f, 0x2e2f, -- 0x3005, 0x3005, -- 0x3031, 0x3035, -- 0x303b, 0x303b, -- 0x309d, 0x309e, -- 0x30fc, 0x30fe, -- 0xa015, 0xa015, -- 0xa4f8, 0xa4fd, -- 0xa60c, 0xa60c, -- 0xa67f, 0xa67f, -- 0xa717, 0xa71f, -- 0xa770, 0xa770, -- 0xa788, 0xa788, -- 0xa9cf, 0xa9cf, -- 0xaa70, 0xaa70, -- 0xaadd, 0xaadd, -- 0xff70, 0xff70, -- 0xff9e, 0xff9f, --}; /* CR_Lm */ -- --/* 'Lo': General Category */ --static const OnigCodePoint CR_Lo[] = { -- 323, -- 0x01bb, 0x01bb, -- 0x01c0, 0x01c3, -- 0x0294, 0x0294, -- 0x05d0, 0x05ea, -- 0x05f0, 0x05f2, -- 0x0620, 0x063f, -- 0x0641, 0x064a, -- 0x066e, 0x066f, -- 0x0671, 0x06d3, -- 0x06d5, 0x06d5, -- 0x06ee, 0x06ef, -- 0x06fa, 0x06fc, -- 0x06ff, 0x06ff, -- 0x0710, 0x0710, -- 0x0712, 0x072f, -- 0x074d, 0x07a5, -- 0x07b1, 0x07b1, -- 0x07ca, 0x07ea, -- 0x0800, 0x0815, -- 0x0840, 0x0858, -- 0x0904, 0x0939, -- 0x093d, 0x093d, -- 0x0950, 0x0950, -- 0x0958, 0x0961, -- 0x0972, 0x0977, -- 0x0979, 0x097f, -- 0x0985, 0x098c, -- 0x098f, 0x0990, -- 0x0993, 0x09a8, -- 0x09aa, 0x09b0, -- 0x09b2, 0x09b2, -- 0x09b6, 0x09b9, -- 0x09bd, 0x09bd, -- 0x09ce, 0x09ce, -- 0x09dc, 0x09dd, -- 0x09df, 0x09e1, -- 0x09f0, 0x09f1, -- 0x0a05, 0x0a0a, -- 0x0a0f, 0x0a10, -- 0x0a13, 0x0a28, -- 0x0a2a, 0x0a30, -- 0x0a32, 0x0a33, -- 0x0a35, 0x0a36, -- 0x0a38, 0x0a39, -- 0x0a59, 0x0a5c, -- 0x0a5e, 0x0a5e, -- 0x0a72, 0x0a74, -- 0x0a85, 0x0a8d, -- 0x0a8f, 0x0a91, -- 0x0a93, 0x0aa8, -- 0x0aaa, 0x0ab0, -- 0x0ab2, 0x0ab3, -- 0x0ab5, 0x0ab9, -- 0x0abd, 0x0abd, -- 0x0ad0, 0x0ad0, -- 0x0ae0, 0x0ae1, -- 0x0b05, 0x0b0c, -- 0x0b0f, 0x0b10, -- 0x0b13, 0x0b28, -- 0x0b2a, 0x0b30, -- 0x0b32, 0x0b33, -- 0x0b35, 0x0b39, -- 0x0b3d, 0x0b3d, -- 0x0b5c, 0x0b5d, -- 0x0b5f, 0x0b61, -- 0x0b71, 0x0b71, -- 0x0b83, 0x0b83, -- 0x0b85, 0x0b8a, -- 0x0b8e, 0x0b90, -- 0x0b92, 0x0b95, -- 0x0b99, 0x0b9a, -- 0x0b9c, 0x0b9c, -- 0x0b9e, 0x0b9f, -- 0x0ba3, 0x0ba4, -- 0x0ba8, 0x0baa, -- 0x0bae, 0x0bb9, -- 0x0bd0, 0x0bd0, -- 0x0c05, 0x0c0c, -- 0x0c0e, 0x0c10, -- 0x0c12, 0x0c28, -- 0x0c2a, 0x0c33, -- 0x0c35, 0x0c39, -- 0x0c3d, 0x0c3d, -- 0x0c58, 0x0c59, -- 0x0c60, 0x0c61, -- 0x0c85, 0x0c8c, -- 0x0c8e, 0x0c90, -- 0x0c92, 0x0ca8, -- 0x0caa, 0x0cb3, -- 0x0cb5, 0x0cb9, -- 0x0cbd, 0x0cbd, -- 0x0cde, 0x0cde, -- 0x0ce0, 0x0ce1, -- 0x0cf1, 0x0cf2, -- 0x0d05, 0x0d0c, -- 0x0d0e, 0x0d10, -- 0x0d12, 0x0d3a, -- 0x0d3d, 0x0d3d, -- 0x0d4e, 0x0d4e, -- 0x0d60, 0x0d61, -- 0x0d7a, 0x0d7f, -- 0x0d85, 0x0d96, -- 0x0d9a, 0x0db1, -- 0x0db3, 0x0dbb, -- 0x0dbd, 0x0dbd, -- 0x0dc0, 0x0dc6, -- 0x0e01, 0x0e30, -- 0x0e32, 0x0e33, -- 0x0e40, 0x0e45, -- 0x0e81, 0x0e82, -- 0x0e84, 0x0e84, -- 0x0e87, 0x0e88, -- 0x0e8a, 0x0e8a, -- 0x0e8d, 0x0e8d, -- 0x0e94, 0x0e97, -- 0x0e99, 0x0e9f, -- 0x0ea1, 0x0ea3, -- 0x0ea5, 0x0ea5, -- 0x0ea7, 0x0ea7, -- 0x0eaa, 0x0eab, -- 0x0ead, 0x0eb0, -- 0x0eb2, 0x0eb3, -- 0x0ebd, 0x0ebd, -- 0x0ec0, 0x0ec4, -- 0x0edc, 0x0edd, -- 0x0f00, 0x0f00, -- 0x0f40, 0x0f47, -- 0x0f49, 0x0f6c, -- 0x0f88, 0x0f8c, -- 0x1000, 0x102a, -- 0x103f, 0x103f, -- 0x1050, 0x1055, -- 0x105a, 0x105d, -- 0x1061, 0x1061, -- 0x1065, 0x1066, -- 0x106e, 0x1070, -- 0x1075, 0x1081, -- 0x108e, 0x108e, -- 0x10d0, 0x10fa, -- 0x1100, 0x1248, -- 0x124a, 0x124d, -- 0x1250, 0x1256, -- 0x1258, 0x1258, -- 0x125a, 0x125d, -- 0x1260, 0x1288, -- 0x128a, 0x128d, -- 0x1290, 0x12b0, -- 0x12b2, 0x12b5, -- 0x12b8, 0x12be, -- 0x12c0, 0x12c0, -- 0x12c2, 0x12c5, -- 0x12c8, 0x12d6, -- 0x12d8, 0x1310, -- 0x1312, 0x1315, -- 0x1318, 0x135a, -- 0x1380, 0x138f, -- 0x13a0, 0x13f4, -- 0x1401, 0x166c, -- 0x166f, 0x167f, -- 0x1681, 0x169a, -- 0x16a0, 0x16ea, -- 0x1700, 0x170c, -- 0x170e, 0x1711, -- 0x1720, 0x1731, -- 0x1740, 0x1751, -- 0x1760, 0x176c, -- 0x176e, 0x1770, -- 0x1780, 0x17b3, -- 0x17dc, 0x17dc, -- 0x1820, 0x1842, -- 0x1844, 0x1877, -- 0x1880, 0x18a8, -- 0x18aa, 0x18aa, -- 0x18b0, 0x18f5, -- 0x1900, 0x191c, -- 0x1950, 0x196d, -- 0x1970, 0x1974, -- 0x1980, 0x19ab, -- 0x19c1, 0x19c7, -- 0x1a00, 0x1a16, -- 0x1a20, 0x1a54, -- 0x1b05, 0x1b33, -- 0x1b45, 0x1b4b, -- 0x1b83, 0x1ba0, -- 0x1bae, 0x1baf, -- 0x1bc0, 0x1be5, -- 0x1c00, 0x1c23, -- 0x1c4d, 0x1c4f, -- 0x1c5a, 0x1c77, -- 0x1ce9, 0x1cec, -- 0x1cee, 0x1cf1, -- 0x2135, 0x2138, -- 0x2d30, 0x2d65, -- 0x2d80, 0x2d96, -- 0x2da0, 0x2da6, -- 0x2da8, 0x2dae, -- 0x2db0, 0x2db6, -- 0x2db8, 0x2dbe, -- 0x2dc0, 0x2dc6, -- 0x2dc8, 0x2dce, -- 0x2dd0, 0x2dd6, -- 0x2dd8, 0x2dde, -- 0x3006, 0x3006, -- 0x303c, 0x303c, -- 0x3041, 0x3096, -- 0x309f, 0x309f, -- 0x30a1, 0x30fa, -- 0x30ff, 0x30ff, -- 0x3105, 0x312d, -- 0x3131, 0x318e, -- 0x31a0, 0x31ba, -- 0x31f0, 0x31ff, -- 0x3400, 0x4db5, -- 0x4e00, 0x9fcb, -- 0xa000, 0xa014, -- 0xa016, 0xa48c, -- 0xa4d0, 0xa4f7, -- 0xa500, 0xa60b, -- 0xa610, 0xa61f, -- 0xa62a, 0xa62b, -- 0xa66e, 0xa66e, -- 0xa6a0, 0xa6e5, -- 0xa7fb, 0xa801, -- 0xa803, 0xa805, -- 0xa807, 0xa80a, -- 0xa80c, 0xa822, -- 0xa840, 0xa873, -- 0xa882, 0xa8b3, -- 0xa8f2, 0xa8f7, -- 0xa8fb, 0xa8fb, -- 0xa90a, 0xa925, -- 0xa930, 0xa946, -- 0xa960, 0xa97c, -- 0xa984, 0xa9b2, -- 0xaa00, 0xaa28, -- 0xaa40, 0xaa42, -- 0xaa44, 0xaa4b, -- 0xaa60, 0xaa6f, -- 0xaa71, 0xaa76, -- 0xaa7a, 0xaa7a, -- 0xaa80, 0xaaaf, -- 0xaab1, 0xaab1, -- 0xaab5, 0xaab6, -- 0xaab9, 0xaabd, -- 0xaac0, 0xaac0, -- 0xaac2, 0xaac2, -- 0xaadb, 0xaadc, -- 0xab01, 0xab06, -- 0xab09, 0xab0e, -- 0xab11, 0xab16, -- 0xab20, 0xab26, -- 0xab28, 0xab2e, -- 0xabc0, 0xabe2, -- 0xac00, 0xd7a3, -- 0xd7b0, 0xd7c6, -- 0xd7cb, 0xd7fb, -- 0xf900, 0xfa2d, -- 0xfa30, 0xfa6d, -- 0xfa70, 0xfad9, -- 0xfb1d, 0xfb1d, -- 0xfb1f, 0xfb28, -- 0xfb2a, 0xfb36, -- 0xfb38, 0xfb3c, -- 0xfb3e, 0xfb3e, -- 0xfb40, 0xfb41, -- 0xfb43, 0xfb44, -- 0xfb46, 0xfbb1, -- 0xfbd3, 0xfd3d, -- 0xfd50, 0xfd8f, -- 0xfd92, 0xfdc7, -- 0xfdf0, 0xfdfb, -- 0xfe70, 0xfe74, -- 0xfe76, 0xfefc, -- 0xff66, 0xff6f, -- 0xff71, 0xff9d, -- 0xffa0, 0xffbe, -- 0xffc2, 0xffc7, -- 0xffca, 0xffcf, -- 0xffd2, 0xffd7, -- 0xffda, 0xffdc, -- 0x10000, 0x1000b, -- 0x1000d, 0x10026, -- 0x10028, 0x1003a, -- 0x1003c, 0x1003d, -- 0x1003f, 0x1004d, -- 0x10050, 0x1005d, -- 0x10080, 0x100fa, -- 0x10280, 0x1029c, -- 0x102a0, 0x102d0, -- 0x10300, 0x1031e, -- 0x10330, 0x10340, -- 0x10342, 0x10349, -- 0x10380, 0x1039d, -- 0x103a0, 0x103c3, -- 0x103c8, 0x103cf, -- 0x10450, 0x1049d, -- 0x10800, 0x10805, -- 0x10808, 0x10808, -- 0x1080a, 0x10835, -- 0x10837, 0x10838, -- 0x1083c, 0x1083c, -- 0x1083f, 0x10855, -- 0x10900, 0x10915, -- 0x10920, 0x10939, -- 0x10a00, 0x10a00, -- 0x10a10, 0x10a13, -- 0x10a15, 0x10a17, -- 0x10a19, 0x10a33, -- 0x10a60, 0x10a7c, -- 0x10b00, 0x10b35, -- 0x10b40, 0x10b55, -- 0x10b60, 0x10b72, -- 0x10c00, 0x10c48, -- 0x11003, 0x11037, -- 0x11083, 0x110af, -- 0x12000, 0x1236e, -- 0x13000, 0x1342e, -- 0x16800, 0x16a38, -- 0x1b000, 0x1b001, -- 0x20000, 0x2a6d6, -- 0x2a700, 0x2b734, -- 0x2b740, 0x2b81d, -- 0x2f800, 0x2fa1d, --}; /* CR_Lo */ -- --/* 'Lt': General Category */ --static const OnigCodePoint CR_Lt[] = { -- 10, -- 0x01c5, 0x01c5, -- 0x01c8, 0x01c8, -- 0x01cb, 0x01cb, -- 0x01f2, 0x01f2, -- 0x1f88, 0x1f8f, -- 0x1f98, 0x1f9f, -- 0x1fa8, 0x1faf, -- 0x1fbc, 0x1fbc, -- 0x1fcc, 0x1fcc, -- 0x1ffc, 0x1ffc, --}; /* CR_Lt */ -- --/* 'Lu': General Category */ --static const OnigCodePoint CR_Lu[] = { -- 603, -- 0x0041, 0x005a, -- 0x00c0, 0x00d6, -- 0x00d8, 0x00de, -- 0x0100, 0x0100, -- 0x0102, 0x0102, -- 0x0104, 0x0104, -- 0x0106, 0x0106, -- 0x0108, 0x0108, -- 0x010a, 0x010a, -- 0x010c, 0x010c, -- 0x010e, 0x010e, -- 0x0110, 0x0110, -- 0x0112, 0x0112, -- 0x0114, 0x0114, -- 0x0116, 0x0116, -- 0x0118, 0x0118, -- 0x011a, 0x011a, -- 0x011c, 0x011c, -- 0x011e, 0x011e, -- 0x0120, 0x0120, -- 0x0122, 0x0122, -- 0x0124, 0x0124, -- 0x0126, 0x0126, -- 0x0128, 0x0128, -- 0x012a, 0x012a, -- 0x012c, 0x012c, -- 0x012e, 0x012e, -- 0x0130, 0x0130, -- 0x0132, 0x0132, -- 0x0134, 0x0134, -- 0x0136, 0x0136, -- 0x0139, 0x0139, -- 0x013b, 0x013b, -- 0x013d, 0x013d, -- 0x013f, 0x013f, -- 0x0141, 0x0141, -- 0x0143, 0x0143, -- 0x0145, 0x0145, -- 0x0147, 0x0147, -- 0x014a, 0x014a, -- 0x014c, 0x014c, -- 0x014e, 0x014e, -- 0x0150, 0x0150, -- 0x0152, 0x0152, -- 0x0154, 0x0154, -- 0x0156, 0x0156, -- 0x0158, 0x0158, -- 0x015a, 0x015a, -- 0x015c, 0x015c, -- 0x015e, 0x015e, -- 0x0160, 0x0160, -- 0x0162, 0x0162, -- 0x0164, 0x0164, -- 0x0166, 0x0166, -- 0x0168, 0x0168, -- 0x016a, 0x016a, -- 0x016c, 0x016c, -- 0x016e, 0x016e, -- 0x0170, 0x0170, -- 0x0172, 0x0172, -- 0x0174, 0x0174, -- 0x0176, 0x0176, -- 0x0178, 0x0179, -- 0x017b, 0x017b, -- 0x017d, 0x017d, -- 0x0181, 0x0182, -- 0x0184, 0x0184, -- 0x0186, 0x0187, -- 0x0189, 0x018b, -- 0x018e, 0x0191, -- 0x0193, 0x0194, -- 0x0196, 0x0198, -- 0x019c, 0x019d, -- 0x019f, 0x01a0, -- 0x01a2, 0x01a2, -- 0x01a4, 0x01a4, -- 0x01a6, 0x01a7, -- 0x01a9, 0x01a9, -- 0x01ac, 0x01ac, -- 0x01ae, 0x01af, -- 0x01b1, 0x01b3, -- 0x01b5, 0x01b5, -- 0x01b7, 0x01b8, -- 0x01bc, 0x01bc, -- 0x01c4, 0x01c4, -- 0x01c7, 0x01c7, -- 0x01ca, 0x01ca, -- 0x01cd, 0x01cd, -- 0x01cf, 0x01cf, -- 0x01d1, 0x01d1, -- 0x01d3, 0x01d3, -- 0x01d5, 0x01d5, -- 0x01d7, 0x01d7, -- 0x01d9, 0x01d9, -- 0x01db, 0x01db, -- 0x01de, 0x01de, -- 0x01e0, 0x01e0, -- 0x01e2, 0x01e2, -- 0x01e4, 0x01e4, -- 0x01e6, 0x01e6, -- 0x01e8, 0x01e8, -- 0x01ea, 0x01ea, -- 0x01ec, 0x01ec, -- 0x01ee, 0x01ee, -- 0x01f1, 0x01f1, -- 0x01f4, 0x01f4, -- 0x01f6, 0x01f8, -- 0x01fa, 0x01fa, -- 0x01fc, 0x01fc, -- 0x01fe, 0x01fe, -- 0x0200, 0x0200, -- 0x0202, 0x0202, -- 0x0204, 0x0204, -- 0x0206, 0x0206, -- 0x0208, 0x0208, -- 0x020a, 0x020a, -- 0x020c, 0x020c, -- 0x020e, 0x020e, -- 0x0210, 0x0210, -- 0x0212, 0x0212, -- 0x0214, 0x0214, -- 0x0216, 0x0216, -- 0x0218, 0x0218, -- 0x021a, 0x021a, -- 0x021c, 0x021c, -- 0x021e, 0x021e, -- 0x0220, 0x0220, -- 0x0222, 0x0222, -- 0x0224, 0x0224, -- 0x0226, 0x0226, -- 0x0228, 0x0228, -- 0x022a, 0x022a, -- 0x022c, 0x022c, -- 0x022e, 0x022e, -- 0x0230, 0x0230, -- 0x0232, 0x0232, -- 0x023a, 0x023b, -- 0x023d, 0x023e, -- 0x0241, 0x0241, -- 0x0243, 0x0246, -- 0x0248, 0x0248, -- 0x024a, 0x024a, -- 0x024c, 0x024c, -- 0x024e, 0x024e, -- 0x0370, 0x0370, -- 0x0372, 0x0372, -- 0x0376, 0x0376, -- 0x0386, 0x0386, -- 0x0388, 0x038a, -- 0x038c, 0x038c, -- 0x038e, 0x038f, -- 0x0391, 0x03a1, -- 0x03a3, 0x03ab, -- 0x03cf, 0x03cf, -- 0x03d2, 0x03d4, -- 0x03d8, 0x03d8, -- 0x03da, 0x03da, -- 0x03dc, 0x03dc, -- 0x03de, 0x03de, -- 0x03e0, 0x03e0, -- 0x03e2, 0x03e2, -- 0x03e4, 0x03e4, -- 0x03e6, 0x03e6, -- 0x03e8, 0x03e8, -- 0x03ea, 0x03ea, -- 0x03ec, 0x03ec, -- 0x03ee, 0x03ee, -- 0x03f4, 0x03f4, -- 0x03f7, 0x03f7, -- 0x03f9, 0x03fa, -- 0x03fd, 0x042f, -- 0x0460, 0x0460, -- 0x0462, 0x0462, -- 0x0464, 0x0464, -- 0x0466, 0x0466, -- 0x0468, 0x0468, -- 0x046a, 0x046a, -- 0x046c, 0x046c, -- 0x046e, 0x046e, -- 0x0470, 0x0470, -- 0x0472, 0x0472, -- 0x0474, 0x0474, -- 0x0476, 0x0476, -- 0x0478, 0x0478, -- 0x047a, 0x047a, -- 0x047c, 0x047c, -- 0x047e, 0x047e, -- 0x0480, 0x0480, -- 0x048a, 0x048a, -- 0x048c, 0x048c, -- 0x048e, 0x048e, -- 0x0490, 0x0490, -- 0x0492, 0x0492, -- 0x0494, 0x0494, -- 0x0496, 0x0496, -- 0x0498, 0x0498, -- 0x049a, 0x049a, -- 0x049c, 0x049c, -- 0x049e, 0x049e, -- 0x04a0, 0x04a0, -- 0x04a2, 0x04a2, -- 0x04a4, 0x04a4, -- 0x04a6, 0x04a6, -- 0x04a8, 0x04a8, -- 0x04aa, 0x04aa, -- 0x04ac, 0x04ac, -- 0x04ae, 0x04ae, -- 0x04b0, 0x04b0, -- 0x04b2, 0x04b2, -- 0x04b4, 0x04b4, -- 0x04b6, 0x04b6, -- 0x04b8, 0x04b8, -- 0x04ba, 0x04ba, -- 0x04bc, 0x04bc, -- 0x04be, 0x04be, -- 0x04c0, 0x04c1, -- 0x04c3, 0x04c3, -- 0x04c5, 0x04c5, -- 0x04c7, 0x04c7, -- 0x04c9, 0x04c9, -- 0x04cb, 0x04cb, -- 0x04cd, 0x04cd, -- 0x04d0, 0x04d0, -- 0x04d2, 0x04d2, -- 0x04d4, 0x04d4, -- 0x04d6, 0x04d6, -- 0x04d8, 0x04d8, -- 0x04da, 0x04da, -- 0x04dc, 0x04dc, -- 0x04de, 0x04de, -- 0x04e0, 0x04e0, -- 0x04e2, 0x04e2, -- 0x04e4, 0x04e4, -- 0x04e6, 0x04e6, -- 0x04e8, 0x04e8, -- 0x04ea, 0x04ea, -- 0x04ec, 0x04ec, -- 0x04ee, 0x04ee, -- 0x04f0, 0x04f0, -- 0x04f2, 0x04f2, -- 0x04f4, 0x04f4, -- 0x04f6, 0x04f6, -- 0x04f8, 0x04f8, -- 0x04fa, 0x04fa, -- 0x04fc, 0x04fc, -- 0x04fe, 0x04fe, -- 0x0500, 0x0500, -- 0x0502, 0x0502, -- 0x0504, 0x0504, -- 0x0506, 0x0506, -- 0x0508, 0x0508, -- 0x050a, 0x050a, -- 0x050c, 0x050c, -- 0x050e, 0x050e, -- 0x0510, 0x0510, -- 0x0512, 0x0512, -- 0x0514, 0x0514, -- 0x0516, 0x0516, -- 0x0518, 0x0518, -- 0x051a, 0x051a, -- 0x051c, 0x051c, -- 0x051e, 0x051e, -- 0x0520, 0x0520, -- 0x0522, 0x0522, -- 0x0524, 0x0524, -- 0x0526, 0x0526, -- 0x0531, 0x0556, -- 0x10a0, 0x10c5, -- 0x1e00, 0x1e00, -- 0x1e02, 0x1e02, -- 0x1e04, 0x1e04, -- 0x1e06, 0x1e06, -- 0x1e08, 0x1e08, -- 0x1e0a, 0x1e0a, -- 0x1e0c, 0x1e0c, -- 0x1e0e, 0x1e0e, -- 0x1e10, 0x1e10, -- 0x1e12, 0x1e12, -- 0x1e14, 0x1e14, -- 0x1e16, 0x1e16, -- 0x1e18, 0x1e18, -- 0x1e1a, 0x1e1a, -- 0x1e1c, 0x1e1c, -- 0x1e1e, 0x1e1e, -- 0x1e20, 0x1e20, -- 0x1e22, 0x1e22, -- 0x1e24, 0x1e24, -- 0x1e26, 0x1e26, -- 0x1e28, 0x1e28, -- 0x1e2a, 0x1e2a, -- 0x1e2c, 0x1e2c, -- 0x1e2e, 0x1e2e, -- 0x1e30, 0x1e30, -- 0x1e32, 0x1e32, -- 0x1e34, 0x1e34, -- 0x1e36, 0x1e36, -- 0x1e38, 0x1e38, -- 0x1e3a, 0x1e3a, -- 0x1e3c, 0x1e3c, -- 0x1e3e, 0x1e3e, -- 0x1e40, 0x1e40, -- 0x1e42, 0x1e42, -- 0x1e44, 0x1e44, -- 0x1e46, 0x1e46, -- 0x1e48, 0x1e48, -- 0x1e4a, 0x1e4a, -- 0x1e4c, 0x1e4c, -- 0x1e4e, 0x1e4e, -- 0x1e50, 0x1e50, -- 0x1e52, 0x1e52, -- 0x1e54, 0x1e54, -- 0x1e56, 0x1e56, -- 0x1e58, 0x1e58, -- 0x1e5a, 0x1e5a, -- 0x1e5c, 0x1e5c, -- 0x1e5e, 0x1e5e, -- 0x1e60, 0x1e60, -- 0x1e62, 0x1e62, -- 0x1e64, 0x1e64, -- 0x1e66, 0x1e66, -- 0x1e68, 0x1e68, -- 0x1e6a, 0x1e6a, -- 0x1e6c, 0x1e6c, -- 0x1e6e, 0x1e6e, -- 0x1e70, 0x1e70, -- 0x1e72, 0x1e72, -- 0x1e74, 0x1e74, -- 0x1e76, 0x1e76, -- 0x1e78, 0x1e78, -- 0x1e7a, 0x1e7a, -- 0x1e7c, 0x1e7c, -- 0x1e7e, 0x1e7e, -- 0x1e80, 0x1e80, -- 0x1e82, 0x1e82, -- 0x1e84, 0x1e84, -- 0x1e86, 0x1e86, -- 0x1e88, 0x1e88, -- 0x1e8a, 0x1e8a, -- 0x1e8c, 0x1e8c, -- 0x1e8e, 0x1e8e, -- 0x1e90, 0x1e90, -- 0x1e92, 0x1e92, -- 0x1e94, 0x1e94, -- 0x1e9e, 0x1e9e, -- 0x1ea0, 0x1ea0, -- 0x1ea2, 0x1ea2, -- 0x1ea4, 0x1ea4, -- 0x1ea6, 0x1ea6, -- 0x1ea8, 0x1ea8, -- 0x1eaa, 0x1eaa, -- 0x1eac, 0x1eac, -- 0x1eae, 0x1eae, -- 0x1eb0, 0x1eb0, -- 0x1eb2, 0x1eb2, -- 0x1eb4, 0x1eb4, -- 0x1eb6, 0x1eb6, -- 0x1eb8, 0x1eb8, -- 0x1eba, 0x1eba, -- 0x1ebc, 0x1ebc, -- 0x1ebe, 0x1ebe, -- 0x1ec0, 0x1ec0, -- 0x1ec2, 0x1ec2, -- 0x1ec4, 0x1ec4, -- 0x1ec6, 0x1ec6, -- 0x1ec8, 0x1ec8, -- 0x1eca, 0x1eca, -- 0x1ecc, 0x1ecc, -- 0x1ece, 0x1ece, -- 0x1ed0, 0x1ed0, -- 0x1ed2, 0x1ed2, -- 0x1ed4, 0x1ed4, -- 0x1ed6, 0x1ed6, -- 0x1ed8, 0x1ed8, -- 0x1eda, 0x1eda, -- 0x1edc, 0x1edc, -- 0x1ede, 0x1ede, -- 0x1ee0, 0x1ee0, -- 0x1ee2, 0x1ee2, -- 0x1ee4, 0x1ee4, -- 0x1ee6, 0x1ee6, -- 0x1ee8, 0x1ee8, -- 0x1eea, 0x1eea, -- 0x1eec, 0x1eec, -- 0x1eee, 0x1eee, -- 0x1ef0, 0x1ef0, -- 0x1ef2, 0x1ef2, -- 0x1ef4, 0x1ef4, -- 0x1ef6, 0x1ef6, -- 0x1ef8, 0x1ef8, -- 0x1efa, 0x1efa, -- 0x1efc, 0x1efc, -- 0x1efe, 0x1efe, -- 0x1f08, 0x1f0f, -- 0x1f18, 0x1f1d, -- 0x1f28, 0x1f2f, -- 0x1f38, 0x1f3f, -- 0x1f48, 0x1f4d, -- 0x1f59, 0x1f59, -- 0x1f5b, 0x1f5b, -- 0x1f5d, 0x1f5d, -- 0x1f5f, 0x1f5f, -- 0x1f68, 0x1f6f, -- 0x1fb8, 0x1fbb, -- 0x1fc8, 0x1fcb, -- 0x1fd8, 0x1fdb, -- 0x1fe8, 0x1fec, -- 0x1ff8, 0x1ffb, -- 0x2102, 0x2102, -- 0x2107, 0x2107, -- 0x210b, 0x210d, -- 0x2110, 0x2112, -- 0x2115, 0x2115, -- 0x2119, 0x211d, -- 0x2124, 0x2124, -- 0x2126, 0x2126, -- 0x2128, 0x2128, -- 0x212a, 0x212d, -- 0x2130, 0x2133, -- 0x213e, 0x213f, -- 0x2145, 0x2145, -- 0x2183, 0x2183, -- 0x2c00, 0x2c2e, -- 0x2c60, 0x2c60, -- 0x2c62, 0x2c64, -- 0x2c67, 0x2c67, -- 0x2c69, 0x2c69, -- 0x2c6b, 0x2c6b, -- 0x2c6d, 0x2c70, -- 0x2c72, 0x2c72, -- 0x2c75, 0x2c75, -- 0x2c7e, 0x2c80, -- 0x2c82, 0x2c82, -- 0x2c84, 0x2c84, -- 0x2c86, 0x2c86, -- 0x2c88, 0x2c88, -- 0x2c8a, 0x2c8a, -- 0x2c8c, 0x2c8c, -- 0x2c8e, 0x2c8e, -- 0x2c90, 0x2c90, -- 0x2c92, 0x2c92, -- 0x2c94, 0x2c94, -- 0x2c96, 0x2c96, -- 0x2c98, 0x2c98, -- 0x2c9a, 0x2c9a, -- 0x2c9c, 0x2c9c, -- 0x2c9e, 0x2c9e, -- 0x2ca0, 0x2ca0, -- 0x2ca2, 0x2ca2, -- 0x2ca4, 0x2ca4, -- 0x2ca6, 0x2ca6, -- 0x2ca8, 0x2ca8, -- 0x2caa, 0x2caa, -- 0x2cac, 0x2cac, -- 0x2cae, 0x2cae, -- 0x2cb0, 0x2cb0, -- 0x2cb2, 0x2cb2, -- 0x2cb4, 0x2cb4, -- 0x2cb6, 0x2cb6, -- 0x2cb8, 0x2cb8, -- 0x2cba, 0x2cba, -- 0x2cbc, 0x2cbc, -- 0x2cbe, 0x2cbe, -- 0x2cc0, 0x2cc0, -- 0x2cc2, 0x2cc2, -- 0x2cc4, 0x2cc4, -- 0x2cc6, 0x2cc6, -- 0x2cc8, 0x2cc8, -- 0x2cca, 0x2cca, -- 0x2ccc, 0x2ccc, -- 0x2cce, 0x2cce, -- 0x2cd0, 0x2cd0, -- 0x2cd2, 0x2cd2, -- 0x2cd4, 0x2cd4, -- 0x2cd6, 0x2cd6, -- 0x2cd8, 0x2cd8, -- 0x2cda, 0x2cda, -- 0x2cdc, 0x2cdc, -- 0x2cde, 0x2cde, -- 0x2ce0, 0x2ce0, -- 0x2ce2, 0x2ce2, -- 0x2ceb, 0x2ceb, -- 0x2ced, 0x2ced, -- 0xa640, 0xa640, -- 0xa642, 0xa642, -- 0xa644, 0xa644, -- 0xa646, 0xa646, -- 0xa648, 0xa648, -- 0xa64a, 0xa64a, -- 0xa64c, 0xa64c, -- 0xa64e, 0xa64e, -- 0xa650, 0xa650, -- 0xa652, 0xa652, -- 0xa654, 0xa654, -- 0xa656, 0xa656, -- 0xa658, 0xa658, -- 0xa65a, 0xa65a, -- 0xa65c, 0xa65c, -- 0xa65e, 0xa65e, -- 0xa660, 0xa660, -- 0xa662, 0xa662, -- 0xa664, 0xa664, -- 0xa666, 0xa666, -- 0xa668, 0xa668, -- 0xa66a, 0xa66a, -- 0xa66c, 0xa66c, -- 0xa680, 0xa680, -- 0xa682, 0xa682, -- 0xa684, 0xa684, -- 0xa686, 0xa686, -- 0xa688, 0xa688, -- 0xa68a, 0xa68a, -- 0xa68c, 0xa68c, -- 0xa68e, 0xa68e, -- 0xa690, 0xa690, -- 0xa692, 0xa692, -- 0xa694, 0xa694, -- 0xa696, 0xa696, -- 0xa722, 0xa722, -- 0xa724, 0xa724, -- 0xa726, 0xa726, -- 0xa728, 0xa728, -- 0xa72a, 0xa72a, -- 0xa72c, 0xa72c, -- 0xa72e, 0xa72e, -- 0xa732, 0xa732, -- 0xa734, 0xa734, -- 0xa736, 0xa736, -- 0xa738, 0xa738, -- 0xa73a, 0xa73a, -- 0xa73c, 0xa73c, -- 0xa73e, 0xa73e, -- 0xa740, 0xa740, -- 0xa742, 0xa742, -- 0xa744, 0xa744, -- 0xa746, 0xa746, -- 0xa748, 0xa748, -- 0xa74a, 0xa74a, -- 0xa74c, 0xa74c, -- 0xa74e, 0xa74e, -- 0xa750, 0xa750, -- 0xa752, 0xa752, -- 0xa754, 0xa754, -- 0xa756, 0xa756, -- 0xa758, 0xa758, -- 0xa75a, 0xa75a, -- 0xa75c, 0xa75c, -- 0xa75e, 0xa75e, -- 0xa760, 0xa760, -- 0xa762, 0xa762, -- 0xa764, 0xa764, -- 0xa766, 0xa766, -- 0xa768, 0xa768, -- 0xa76a, 0xa76a, -- 0xa76c, 0xa76c, -- 0xa76e, 0xa76e, -- 0xa779, 0xa779, -- 0xa77b, 0xa77b, -- 0xa77d, 0xa77e, -- 0xa780, 0xa780, -- 0xa782, 0xa782, -- 0xa784, 0xa784, -- 0xa786, 0xa786, -- 0xa78b, 0xa78b, -- 0xa78d, 0xa78d, -- 0xa790, 0xa790, -- 0xa7a0, 0xa7a0, -- 0xa7a2, 0xa7a2, -- 0xa7a4, 0xa7a4, -- 0xa7a6, 0xa7a6, -- 0xa7a8, 0xa7a8, -- 0xff21, 0xff3a, -- 0x10400, 0x10427, -- 0x1d400, 0x1d419, -- 0x1d434, 0x1d44d, -- 0x1d468, 0x1d481, -- 0x1d49c, 0x1d49c, -- 0x1d49e, 0x1d49f, -- 0x1d4a2, 0x1d4a2, -- 0x1d4a5, 0x1d4a6, -- 0x1d4a9, 0x1d4ac, -- 0x1d4ae, 0x1d4b5, -- 0x1d4d0, 0x1d4e9, -- 0x1d504, 0x1d505, -- 0x1d507, 0x1d50a, -- 0x1d50d, 0x1d514, -- 0x1d516, 0x1d51c, -- 0x1d538, 0x1d539, -- 0x1d53b, 0x1d53e, -- 0x1d540, 0x1d544, -- 0x1d546, 0x1d546, -- 0x1d54a, 0x1d550, -- 0x1d56c, 0x1d585, -- 0x1d5a0, 0x1d5b9, -- 0x1d5d4, 0x1d5ed, -- 0x1d608, 0x1d621, -- 0x1d63c, 0x1d655, -- 0x1d670, 0x1d689, -- 0x1d6a8, 0x1d6c0, -- 0x1d6e2, 0x1d6fa, -- 0x1d71c, 0x1d734, -- 0x1d756, 0x1d76e, -- 0x1d790, 0x1d7a8, -- 0x1d7ca, 0x1d7ca, --}; /* CR_Lu */ -- --/* 'M': Major Category */ --static const OnigCodePoint CR_M[] = { -- 193, -- 0x0300, 0x036f, -- 0x0483, 0x0489, -- 0x0591, 0x05bd, -- 0x05bf, 0x05bf, -- 0x05c1, 0x05c2, -- 0x05c4, 0x05c5, -- 0x05c7, 0x05c7, -- 0x0610, 0x061a, -- 0x064b, 0x065f, -- 0x0670, 0x0670, -- 0x06d6, 0x06dc, -- 0x06df, 0x06e4, -- 0x06e7, 0x06e8, -- 0x06ea, 0x06ed, -- 0x0711, 0x0711, -- 0x0730, 0x074a, -- 0x07a6, 0x07b0, -- 0x07eb, 0x07f3, -- 0x0816, 0x0819, -- 0x081b, 0x0823, -- 0x0825, 0x0827, -- 0x0829, 0x082d, -- 0x0859, 0x085b, -- 0x0900, 0x0903, -- 0x093a, 0x093c, -- 0x093e, 0x094f, -- 0x0951, 0x0957, -- 0x0962, 0x0963, -- 0x0981, 0x0983, -- 0x09bc, 0x09bc, -- 0x09be, 0x09c4, -- 0x09c7, 0x09c8, -- 0x09cb, 0x09cd, -- 0x09d7, 0x09d7, -- 0x09e2, 0x09e3, -- 0x0a01, 0x0a03, -- 0x0a3c, 0x0a3c, -- 0x0a3e, 0x0a42, -- 0x0a47, 0x0a48, -- 0x0a4b, 0x0a4d, -- 0x0a51, 0x0a51, -- 0x0a70, 0x0a71, -- 0x0a75, 0x0a75, -- 0x0a81, 0x0a83, -- 0x0abc, 0x0abc, -- 0x0abe, 0x0ac5, -- 0x0ac7, 0x0ac9, -- 0x0acb, 0x0acd, -- 0x0ae2, 0x0ae3, -- 0x0b01, 0x0b03, -- 0x0b3c, 0x0b3c, -- 0x0b3e, 0x0b44, -- 0x0b47, 0x0b48, -- 0x0b4b, 0x0b4d, -- 0x0b56, 0x0b57, -- 0x0b62, 0x0b63, -- 0x0b82, 0x0b82, -- 0x0bbe, 0x0bc2, -- 0x0bc6, 0x0bc8, -- 0x0bca, 0x0bcd, -- 0x0bd7, 0x0bd7, -- 0x0c01, 0x0c03, -- 0x0c3e, 0x0c44, -- 0x0c46, 0x0c48, -- 0x0c4a, 0x0c4d, -- 0x0c55, 0x0c56, -- 0x0c62, 0x0c63, -- 0x0c82, 0x0c83, -- 0x0cbc, 0x0cbc, -- 0x0cbe, 0x0cc4, -- 0x0cc6, 0x0cc8, -- 0x0cca, 0x0ccd, -- 0x0cd5, 0x0cd6, -- 0x0ce2, 0x0ce3, -- 0x0d02, 0x0d03, -- 0x0d3e, 0x0d44, -- 0x0d46, 0x0d48, -- 0x0d4a, 0x0d4d, -- 0x0d57, 0x0d57, -- 0x0d62, 0x0d63, -- 0x0d82, 0x0d83, -- 0x0dca, 0x0dca, -- 0x0dcf, 0x0dd4, -- 0x0dd6, 0x0dd6, -- 0x0dd8, 0x0ddf, -- 0x0df2, 0x0df3, -- 0x0e31, 0x0e31, -- 0x0e34, 0x0e3a, -- 0x0e47, 0x0e4e, -- 0x0eb1, 0x0eb1, -- 0x0eb4, 0x0eb9, -- 0x0ebb, 0x0ebc, -- 0x0ec8, 0x0ecd, -- 0x0f18, 0x0f19, -- 0x0f35, 0x0f35, -- 0x0f37, 0x0f37, -- 0x0f39, 0x0f39, -- 0x0f3e, 0x0f3f, -- 0x0f71, 0x0f84, -- 0x0f86, 0x0f87, -- 0x0f8d, 0x0f97, -- 0x0f99, 0x0fbc, -- 0x0fc6, 0x0fc6, -- 0x102b, 0x103e, -- 0x1056, 0x1059, -- 0x105e, 0x1060, -- 0x1062, 0x1064, -- 0x1067, 0x106d, -- 0x1071, 0x1074, -- 0x1082, 0x108d, -- 0x108f, 0x108f, -- 0x109a, 0x109d, -- 0x135d, 0x135f, -- 0x1712, 0x1714, -- 0x1732, 0x1734, -- 0x1752, 0x1753, -- 0x1772, 0x1773, -- 0x17b6, 0x17d3, -- 0x17dd, 0x17dd, -- 0x180b, 0x180d, -- 0x18a9, 0x18a9, -- 0x1920, 0x192b, -- 0x1930, 0x193b, -- 0x19b0, 0x19c0, -- 0x19c8, 0x19c9, -- 0x1a17, 0x1a1b, -- 0x1a55, 0x1a5e, -- 0x1a60, 0x1a7c, -- 0x1a7f, 0x1a7f, -- 0x1b00, 0x1b04, -- 0x1b34, 0x1b44, -- 0x1b6b, 0x1b73, -- 0x1b80, 0x1b82, -- 0x1ba1, 0x1baa, -- 0x1be6, 0x1bf3, -- 0x1c24, 0x1c37, -- 0x1cd0, 0x1cd2, -- 0x1cd4, 0x1ce8, -- 0x1ced, 0x1ced, -- 0x1cf2, 0x1cf2, -- 0x1dc0, 0x1de6, -- 0x1dfc, 0x1dff, -- 0x20d0, 0x20f0, -- 0x2cef, 0x2cf1, -- 0x2d7f, 0x2d7f, -- 0x2de0, 0x2dff, -- 0x302a, 0x302f, -- 0x3099, 0x309a, -- 0xa66f, 0xa672, -- 0xa67c, 0xa67d, -- 0xa6f0, 0xa6f1, -- 0xa802, 0xa802, -- 0xa806, 0xa806, -- 0xa80b, 0xa80b, -- 0xa823, 0xa827, -- 0xa880, 0xa881, -- 0xa8b4, 0xa8c4, -- 0xa8e0, 0xa8f1, -- 0xa926, 0xa92d, -- 0xa947, 0xa953, -- 0xa980, 0xa983, -- 0xa9b3, 0xa9c0, -- 0xaa29, 0xaa36, -- 0xaa43, 0xaa43, -- 0xaa4c, 0xaa4d, -- 0xaa7b, 0xaa7b, -- 0xaab0, 0xaab0, -- 0xaab2, 0xaab4, -- 0xaab7, 0xaab8, -- 0xaabe, 0xaabf, -- 0xaac1, 0xaac1, -- 0xabe3, 0xabea, -- 0xabec, 0xabed, -- 0xfb1e, 0xfb1e, -- 0xfe00, 0xfe0f, -- 0xfe20, 0xfe26, -- 0x101fd, 0x101fd, -- 0x10a01, 0x10a03, -- 0x10a05, 0x10a06, -- 0x10a0c, 0x10a0f, -- 0x10a38, 0x10a3a, -- 0x10a3f, 0x10a3f, -- 0x11000, 0x11002, -- 0x11038, 0x11046, -- 0x11080, 0x11082, -- 0x110b0, 0x110ba, -- 0x1d165, 0x1d169, -- 0x1d16d, 0x1d172, -- 0x1d17b, 0x1d182, -- 0x1d185, 0x1d18b, -- 0x1d1aa, 0x1d1ad, -- 0x1d242, 0x1d244, -- 0xe0100, 0xe01ef, --}; /* CR_M */ -- --/* 'Mc': General Category */ --static const OnigCodePoint CR_Mc[] = { -- 113, -- 0x0903, 0x0903, -- 0x093b, 0x093b, -- 0x093e, 0x0940, -- 0x0949, 0x094c, -- 0x094e, 0x094f, -- 0x0982, 0x0983, -- 0x09be, 0x09c0, -- 0x09c7, 0x09c8, -- 0x09cb, 0x09cc, -- 0x09d7, 0x09d7, -- 0x0a03, 0x0a03, -- 0x0a3e, 0x0a40, -- 0x0a83, 0x0a83, -- 0x0abe, 0x0ac0, -- 0x0ac9, 0x0ac9, -- 0x0acb, 0x0acc, -- 0x0b02, 0x0b03, -- 0x0b3e, 0x0b3e, -- 0x0b40, 0x0b40, -- 0x0b47, 0x0b48, -- 0x0b4b, 0x0b4c, -- 0x0b57, 0x0b57, -- 0x0bbe, 0x0bbf, -- 0x0bc1, 0x0bc2, -- 0x0bc6, 0x0bc8, -- 0x0bca, 0x0bcc, -- 0x0bd7, 0x0bd7, -- 0x0c01, 0x0c03, -- 0x0c41, 0x0c44, -- 0x0c82, 0x0c83, -- 0x0cbe, 0x0cbe, -- 0x0cc0, 0x0cc4, -- 0x0cc7, 0x0cc8, -- 0x0cca, 0x0ccb, -- 0x0cd5, 0x0cd6, -- 0x0d02, 0x0d03, -- 0x0d3e, 0x0d40, -- 0x0d46, 0x0d48, -- 0x0d4a, 0x0d4c, -- 0x0d57, 0x0d57, -- 0x0d82, 0x0d83, -- 0x0dcf, 0x0dd1, -- 0x0dd8, 0x0ddf, -- 0x0df2, 0x0df3, -- 0x0f3e, 0x0f3f, -- 0x0f7f, 0x0f7f, -- 0x102b, 0x102c, -- 0x1031, 0x1031, -- 0x1038, 0x1038, -- 0x103b, 0x103c, -- 0x1056, 0x1057, -- 0x1062, 0x1064, -- 0x1067, 0x106d, -- 0x1083, 0x1084, -- 0x1087, 0x108c, -- 0x108f, 0x108f, -- 0x109a, 0x109c, -- 0x17b6, 0x17b6, -- 0x17be, 0x17c5, -- 0x17c7, 0x17c8, -- 0x1923, 0x1926, -- 0x1929, 0x192b, -- 0x1930, 0x1931, -- 0x1933, 0x1938, -- 0x19b0, 0x19c0, -- 0x19c8, 0x19c9, -- 0x1a19, 0x1a1b, -- 0x1a55, 0x1a55, -- 0x1a57, 0x1a57, -- 0x1a61, 0x1a61, -- 0x1a63, 0x1a64, -- 0x1a6d, 0x1a72, -- 0x1b04, 0x1b04, -- 0x1b35, 0x1b35, -- 0x1b3b, 0x1b3b, -- 0x1b3d, 0x1b41, -- 0x1b43, 0x1b44, -- 0x1b82, 0x1b82, -- 0x1ba1, 0x1ba1, -- 0x1ba6, 0x1ba7, -- 0x1baa, 0x1baa, -- 0x1be7, 0x1be7, -- 0x1bea, 0x1bec, -- 0x1bee, 0x1bee, -- 0x1bf2, 0x1bf3, -- 0x1c24, 0x1c2b, -- 0x1c34, 0x1c35, -- 0x1ce1, 0x1ce1, -- 0x1cf2, 0x1cf2, -- 0xa823, 0xa824, -- 0xa827, 0xa827, -- 0xa880, 0xa881, -- 0xa8b4, 0xa8c3, -- 0xa952, 0xa953, -- 0xa983, 0xa983, -- 0xa9b4, 0xa9b5, -- 0xa9ba, 0xa9bb, -- 0xa9bd, 0xa9c0, -- 0xaa2f, 0xaa30, -- 0xaa33, 0xaa34, -- 0xaa4d, 0xaa4d, -- 0xaa7b, 0xaa7b, -- 0xabe3, 0xabe4, -- 0xabe6, 0xabe7, -- 0xabe9, 0xabea, -- 0xabec, 0xabec, -- 0x11000, 0x11000, -- 0x11002, 0x11002, -- 0x11082, 0x11082, -- 0x110b0, 0x110b2, -- 0x110b7, 0x110b8, -- 0x1d165, 0x1d166, -- 0x1d16d, 0x1d172, --}; /* CR_Mc */ -- --/* 'Me': General Category */ --static const OnigCodePoint CR_Me[] = { -- 4, -- 0x0488, 0x0489, -- 0x20dd, 0x20e0, -- 0x20e2, 0x20e4, -- 0xa670, 0xa672, --}; /* CR_Me */ -- --/* 'Mn': General Category */ --static const OnigCodePoint CR_Mn[] = { -- 203, -- 0x0300, 0x036f, -- 0x0483, 0x0487, -- 0x0591, 0x05bd, -- 0x05bf, 0x05bf, -- 0x05c1, 0x05c2, -- 0x05c4, 0x05c5, -- 0x05c7, 0x05c7, -- 0x0610, 0x061a, -- 0x064b, 0x065f, -- 0x0670, 0x0670, -- 0x06d6, 0x06dc, -- 0x06df, 0x06e4, -- 0x06e7, 0x06e8, -- 0x06ea, 0x06ed, -- 0x0711, 0x0711, -- 0x0730, 0x074a, -- 0x07a6, 0x07b0, -- 0x07eb, 0x07f3, -- 0x0816, 0x0819, -- 0x081b, 0x0823, -- 0x0825, 0x0827, -- 0x0829, 0x082d, -- 0x0859, 0x085b, -- 0x0900, 0x0902, -- 0x093a, 0x093a, -- 0x093c, 0x093c, -- 0x0941, 0x0948, -- 0x094d, 0x094d, -- 0x0951, 0x0957, -- 0x0962, 0x0963, -- 0x0981, 0x0981, -- 0x09bc, 0x09bc, -- 0x09c1, 0x09c4, -- 0x09cd, 0x09cd, -- 0x09e2, 0x09e3, -- 0x0a01, 0x0a02, -- 0x0a3c, 0x0a3c, -- 0x0a41, 0x0a42, -- 0x0a47, 0x0a48, -- 0x0a4b, 0x0a4d, -- 0x0a51, 0x0a51, -- 0x0a70, 0x0a71, -- 0x0a75, 0x0a75, -- 0x0a81, 0x0a82, -- 0x0abc, 0x0abc, -- 0x0ac1, 0x0ac5, -- 0x0ac7, 0x0ac8, -- 0x0acd, 0x0acd, -- 0x0ae2, 0x0ae3, -- 0x0b01, 0x0b01, -- 0x0b3c, 0x0b3c, -- 0x0b3f, 0x0b3f, -- 0x0b41, 0x0b44, -- 0x0b4d, 0x0b4d, -- 0x0b56, 0x0b56, -- 0x0b62, 0x0b63, -- 0x0b82, 0x0b82, -- 0x0bc0, 0x0bc0, -- 0x0bcd, 0x0bcd, -- 0x0c3e, 0x0c40, -- 0x0c46, 0x0c48, -- 0x0c4a, 0x0c4d, -- 0x0c55, 0x0c56, -- 0x0c62, 0x0c63, -- 0x0cbc, 0x0cbc, -- 0x0cbf, 0x0cbf, -- 0x0cc6, 0x0cc6, -- 0x0ccc, 0x0ccd, -- 0x0ce2, 0x0ce3, -- 0x0d41, 0x0d44, -- 0x0d4d, 0x0d4d, -- 0x0d62, 0x0d63, -- 0x0dca, 0x0dca, -- 0x0dd2, 0x0dd4, -- 0x0dd6, 0x0dd6, -- 0x0e31, 0x0e31, -- 0x0e34, 0x0e3a, -- 0x0e47, 0x0e4e, -- 0x0eb1, 0x0eb1, -- 0x0eb4, 0x0eb9, -- 0x0ebb, 0x0ebc, -- 0x0ec8, 0x0ecd, -- 0x0f18, 0x0f19, -- 0x0f35, 0x0f35, -- 0x0f37, 0x0f37, -- 0x0f39, 0x0f39, -- 0x0f71, 0x0f7e, -- 0x0f80, 0x0f84, -- 0x0f86, 0x0f87, -- 0x0f8d, 0x0f97, -- 0x0f99, 0x0fbc, -- 0x0fc6, 0x0fc6, -- 0x102d, 0x1030, -- 0x1032, 0x1037, -- 0x1039, 0x103a, -- 0x103d, 0x103e, -- 0x1058, 0x1059, -- 0x105e, 0x1060, -- 0x1071, 0x1074, -- 0x1082, 0x1082, -- 0x1085, 0x1086, -- 0x108d, 0x108d, -- 0x109d, 0x109d, -- 0x135d, 0x135f, -- 0x1712, 0x1714, -- 0x1732, 0x1734, -- 0x1752, 0x1753, -- 0x1772, 0x1773, -- 0x17b7, 0x17bd, -- 0x17c6, 0x17c6, -- 0x17c9, 0x17d3, -- 0x17dd, 0x17dd, -- 0x180b, 0x180d, -- 0x18a9, 0x18a9, -- 0x1920, 0x1922, -- 0x1927, 0x1928, -- 0x1932, 0x1932, -- 0x1939, 0x193b, -- 0x1a17, 0x1a18, -- 0x1a56, 0x1a56, -- 0x1a58, 0x1a5e, -- 0x1a60, 0x1a60, -- 0x1a62, 0x1a62, -- 0x1a65, 0x1a6c, -- 0x1a73, 0x1a7c, -- 0x1a7f, 0x1a7f, -- 0x1b00, 0x1b03, -- 0x1b34, 0x1b34, -- 0x1b36, 0x1b3a, -- 0x1b3c, 0x1b3c, -- 0x1b42, 0x1b42, -- 0x1b6b, 0x1b73, -- 0x1b80, 0x1b81, -- 0x1ba2, 0x1ba5, -- 0x1ba8, 0x1ba9, -- 0x1be6, 0x1be6, -- 0x1be8, 0x1be9, -- 0x1bed, 0x1bed, -- 0x1bef, 0x1bf1, -- 0x1c2c, 0x1c33, -- 0x1c36, 0x1c37, -- 0x1cd0, 0x1cd2, -- 0x1cd4, 0x1ce0, -- 0x1ce2, 0x1ce8, -- 0x1ced, 0x1ced, -- 0x1dc0, 0x1de6, -- 0x1dfc, 0x1dff, -- 0x20d0, 0x20dc, -- 0x20e1, 0x20e1, -- 0x20e5, 0x20f0, -- 0x2cef, 0x2cf1, -- 0x2d7f, 0x2d7f, -- 0x2de0, 0x2dff, -- 0x302a, 0x302f, -- 0x3099, 0x309a, -- 0xa66f, 0xa66f, -- 0xa67c, 0xa67d, -- 0xa6f0, 0xa6f1, -- 0xa802, 0xa802, -- 0xa806, 0xa806, -- 0xa80b, 0xa80b, -- 0xa825, 0xa826, -- 0xa8c4, 0xa8c4, -- 0xa8e0, 0xa8f1, -- 0xa926, 0xa92d, -- 0xa947, 0xa951, -- 0xa980, 0xa982, -- 0xa9b3, 0xa9b3, -- 0xa9b6, 0xa9b9, -- 0xa9bc, 0xa9bc, -- 0xaa29, 0xaa2e, -- 0xaa31, 0xaa32, -- 0xaa35, 0xaa36, -- 0xaa43, 0xaa43, -- 0xaa4c, 0xaa4c, -- 0xaab0, 0xaab0, -- 0xaab2, 0xaab4, -- 0xaab7, 0xaab8, -- 0xaabe, 0xaabf, -- 0xaac1, 0xaac1, -- 0xabe5, 0xabe5, -- 0xabe8, 0xabe8, -- 0xabed, 0xabed, -- 0xfb1e, 0xfb1e, -- 0xfe00, 0xfe0f, -- 0xfe20, 0xfe26, -- 0x101fd, 0x101fd, -- 0x10a01, 0x10a03, -- 0x10a05, 0x10a06, -- 0x10a0c, 0x10a0f, -- 0x10a38, 0x10a3a, -- 0x10a3f, 0x10a3f, -- 0x11001, 0x11001, -- 0x11038, 0x11046, -- 0x11080, 0x11081, -- 0x110b3, 0x110b6, -- 0x110b9, 0x110ba, -- 0x1d167, 0x1d169, -- 0x1d17b, 0x1d182, -- 0x1d185, 0x1d18b, -- 0x1d1aa, 0x1d1ad, -- 0x1d242, 0x1d244, -- 0xe0100, 0xe01ef, --}; /* CR_Mn */ -- --/* 'N': Major Category */ --static const OnigCodePoint CR_N[] = { -- 83, -- 0x0030, 0x0039, -- 0x00b2, 0x00b3, -- 0x00b9, 0x00b9, -- 0x00bc, 0x00be, -- 0x0660, 0x0669, -- 0x06f0, 0x06f9, -- 0x07c0, 0x07c9, -- 0x0966, 0x096f, -- 0x09e6, 0x09ef, -- 0x09f4, 0x09f9, -- 0x0a66, 0x0a6f, -- 0x0ae6, 0x0aef, -- 0x0b66, 0x0b6f, -- 0x0b72, 0x0b77, -- 0x0be6, 0x0bf2, -- 0x0c66, 0x0c6f, -- 0x0c78, 0x0c7e, -- 0x0ce6, 0x0cef, -- 0x0d66, 0x0d75, -- 0x0e50, 0x0e59, -- 0x0ed0, 0x0ed9, -- 0x0f20, 0x0f33, -- 0x1040, 0x1049, -- 0x1090, 0x1099, -- 0x1369, 0x137c, -- 0x16ee, 0x16f0, -- 0x17e0, 0x17e9, -- 0x17f0, 0x17f9, -- 0x1810, 0x1819, -- 0x1946, 0x194f, -- 0x19d0, 0x19da, -- 0x1a80, 0x1a89, -- 0x1a90, 0x1a99, -- 0x1b50, 0x1b59, -- 0x1bb0, 0x1bb9, -- 0x1c40, 0x1c49, -- 0x1c50, 0x1c59, -- 0x2070, 0x2070, -- 0x2074, 0x2079, -- 0x2080, 0x2089, -- 0x2150, 0x2182, -- 0x2185, 0x2189, -- 0x2460, 0x249b, -- 0x24ea, 0x24ff, -- 0x2776, 0x2793, -- 0x2cfd, 0x2cfd, -- 0x3007, 0x3007, -- 0x3021, 0x3029, -- 0x3038, 0x303a, -- 0x3192, 0x3195, -- 0x3220, 0x3229, -- 0x3251, 0x325f, -- 0x3280, 0x3289, -- 0x32b1, 0x32bf, -- 0xa620, 0xa629, -- 0xa6e6, 0xa6ef, -- 0xa830, 0xa835, -- 0xa8d0, 0xa8d9, -- 0xa900, 0xa909, -- 0xa9d0, 0xa9d9, -- 0xaa50, 0xaa59, -- 0xabf0, 0xabf9, -- 0xff10, 0xff19, -- 0x10107, 0x10133, -- 0x10140, 0x10178, -- 0x1018a, 0x1018a, -- 0x10320, 0x10323, -- 0x10341, 0x10341, -- 0x1034a, 0x1034a, -- 0x103d1, 0x103d5, -- 0x104a0, 0x104a9, -- 0x10858, 0x1085f, -- 0x10916, 0x1091b, -- 0x10a40, 0x10a47, -- 0x10a7d, 0x10a7e, -- 0x10b58, 0x10b5f, -- 0x10b78, 0x10b7f, -- 0x10e60, 0x10e7e, -- 0x11052, 0x1106f, -- 0x12400, 0x12462, -- 0x1d360, 0x1d371, -- 0x1d7ce, 0x1d7ff, -- 0x1f100, 0x1f10a, --}; /* CR_N */ -- --/* 'Nd': General Category */ --static const OnigCodePoint CR_Nd[] = { -- 38, -- 0x0030, 0x0039, -- 0x0660, 0x0669, -- 0x06f0, 0x06f9, -- 0x07c0, 0x07c9, -- 0x0966, 0x096f, -- 0x09e6, 0x09ef, -- 0x0a66, 0x0a6f, -- 0x0ae6, 0x0aef, -- 0x0b66, 0x0b6f, -- 0x0be6, 0x0bef, -- 0x0c66, 0x0c6f, -- 0x0ce6, 0x0cef, -- 0x0d66, 0x0d6f, -- 0x0e50, 0x0e59, -- 0x0ed0, 0x0ed9, -- 0x0f20, 0x0f29, -- 0x1040, 0x1049, -- 0x1090, 0x1099, -- 0x17e0, 0x17e9, -- 0x1810, 0x1819, -- 0x1946, 0x194f, -- 0x19d0, 0x19d9, -- 0x1a80, 0x1a89, -- 0x1a90, 0x1a99, -- 0x1b50, 0x1b59, -- 0x1bb0, 0x1bb9, -- 0x1c40, 0x1c49, -- 0x1c50, 0x1c59, -- 0xa620, 0xa629, -- 0xa8d0, 0xa8d9, -- 0xa900, 0xa909, -- 0xa9d0, 0xa9d9, -- 0xaa50, 0xaa59, -- 0xabf0, 0xabf9, -- 0xff10, 0xff19, -- 0x104a0, 0x104a9, -- 0x11066, 0x1106f, -- 0x1d7ce, 0x1d7ff, --}; /* CR_Nd */ -- --/* 'Nl': General Category */ --static const OnigCodePoint CR_Nl[] = { -- 12, -- 0x16ee, 0x16f0, -- 0x2160, 0x2182, -- 0x2185, 0x2188, -- 0x3007, 0x3007, -- 0x3021, 0x3029, -- 0x3038, 0x303a, -- 0xa6e6, 0xa6ef, -- 0x10140, 0x10174, -- 0x10341, 0x10341, -- 0x1034a, 0x1034a, -- 0x103d1, 0x103d5, -- 0x12400, 0x12462, --}; /* CR_Nl */ -- --/* 'No': General Category */ --static const OnigCodePoint CR_No[] = { -- 41, -- 0x00b2, 0x00b3, -- 0x00b9, 0x00b9, -- 0x00bc, 0x00be, -- 0x09f4, 0x09f9, -- 0x0b72, 0x0b77, -- 0x0bf0, 0x0bf2, -- 0x0c78, 0x0c7e, -- 0x0d70, 0x0d75, -- 0x0f2a, 0x0f33, -- 0x1369, 0x137c, -- 0x17f0, 0x17f9, -- 0x19da, 0x19da, -- 0x2070, 0x2070, -- 0x2074, 0x2079, -- 0x2080, 0x2089, -- 0x2150, 0x215f, -- 0x2189, 0x2189, -- 0x2460, 0x249b, -- 0x24ea, 0x24ff, -- 0x2776, 0x2793, -- 0x2cfd, 0x2cfd, -- 0x3192, 0x3195, -- 0x3220, 0x3229, -- 0x3251, 0x325f, -- 0x3280, 0x3289, -- 0x32b1, 0x32bf, -- 0xa830, 0xa835, -- 0x10107, 0x10133, -- 0x10175, 0x10178, -- 0x1018a, 0x1018a, -- 0x10320, 0x10323, -- 0x10858, 0x1085f, -- 0x10916, 0x1091b, -- 0x10a40, 0x10a47, -- 0x10a7d, 0x10a7e, -- 0x10b58, 0x10b5f, -- 0x10b78, 0x10b7f, -- 0x10e60, 0x10e7e, -- 0x11052, 0x11065, -- 0x1d360, 0x1d371, -- 0x1f100, 0x1f10a, --}; /* CR_No */ -- --/* 'P': Major Category */ --static const OnigCodePoint CR_P[] = { -- 133, -- 0x0021, 0x0023, -- 0x0025, 0x002a, -- 0x002c, 0x002f, -- 0x003a, 0x003b, -- 0x003f, 0x0040, -- 0x005b, 0x005d, -- 0x005f, 0x005f, -- 0x007b, 0x007b, -- 0x007d, 0x007d, -- 0x00a1, 0x00a1, -- 0x00ab, 0x00ab, -- 0x00b7, 0x00b7, -- 0x00bb, 0x00bb, -- 0x00bf, 0x00bf, -- 0x037e, 0x037e, -- 0x0387, 0x0387, -- 0x055a, 0x055f, -- 0x0589, 0x058a, -- 0x05be, 0x05be, -- 0x05c0, 0x05c0, -- 0x05c3, 0x05c3, -- 0x05c6, 0x05c6, -- 0x05f3, 0x05f4, -- 0x0609, 0x060a, -- 0x060c, 0x060d, -- 0x061b, 0x061b, -- 0x061e, 0x061f, -- 0x066a, 0x066d, -- 0x06d4, 0x06d4, -- 0x0700, 0x070d, -- 0x07f7, 0x07f9, -- 0x0830, 0x083e, -- 0x085e, 0x085e, -- 0x0964, 0x0965, -- 0x0970, 0x0970, -- 0x0df4, 0x0df4, -- 0x0e4f, 0x0e4f, -- 0x0e5a, 0x0e5b, -- 0x0f04, 0x0f12, -- 0x0f3a, 0x0f3d, -- 0x0f85, 0x0f85, -- 0x0fd0, 0x0fd4, -- 0x0fd9, 0x0fda, -- 0x104a, 0x104f, -- 0x10fb, 0x10fb, -- 0x1361, 0x1368, -- 0x1400, 0x1400, -- 0x166d, 0x166e, -- 0x169b, 0x169c, -- 0x16eb, 0x16ed, -- 0x1735, 0x1736, -- 0x17d4, 0x17d6, -- 0x17d8, 0x17da, -- 0x1800, 0x180a, -- 0x1944, 0x1945, -- 0x1a1e, 0x1a1f, -- 0x1aa0, 0x1aa6, -- 0x1aa8, 0x1aad, -- 0x1b5a, 0x1b60, -- 0x1bfc, 0x1bff, -- 0x1c3b, 0x1c3f, -- 0x1c7e, 0x1c7f, -- 0x1cd3, 0x1cd3, -- 0x2010, 0x2027, -- 0x2030, 0x2043, -- 0x2045, 0x2051, -- 0x2053, 0x205e, -- 0x207d, 0x207e, -- 0x208d, 0x208e, -- 0x2329, 0x232a, -- 0x2768, 0x2775, -- 0x27c5, 0x27c6, -- 0x27e6, 0x27ef, -- 0x2983, 0x2998, -- 0x29d8, 0x29db, -- 0x29fc, 0x29fd, -- 0x2cf9, 0x2cfc, -- 0x2cfe, 0x2cff, -- 0x2d70, 0x2d70, -- 0x2e00, 0x2e2e, -- 0x2e30, 0x2e31, -- 0x3001, 0x3003, -- 0x3008, 0x3011, -- 0x3014, 0x301f, -- 0x3030, 0x3030, -- 0x303d, 0x303d, -- 0x30a0, 0x30a0, -- 0x30fb, 0x30fb, -- 0xa4fe, 0xa4ff, -- 0xa60d, 0xa60f, -- 0xa673, 0xa673, -- 0xa67e, 0xa67e, -- 0xa6f2, 0xa6f7, -- 0xa874, 0xa877, -- 0xa8ce, 0xa8cf, -- 0xa8f8, 0xa8fa, -- 0xa92e, 0xa92f, -- 0xa95f, 0xa95f, -- 0xa9c1, 0xa9cd, -- 0xa9de, 0xa9df, -- 0xaa5c, 0xaa5f, -- 0xaade, 0xaadf, -- 0xabeb, 0xabeb, -- 0xfd3e, 0xfd3f, -- 0xfe10, 0xfe19, -- 0xfe30, 0xfe52, -- 0xfe54, 0xfe61, -- 0xfe63, 0xfe63, -- 0xfe68, 0xfe68, -- 0xfe6a, 0xfe6b, -- 0xff01, 0xff03, -- 0xff05, 0xff0a, -- 0xff0c, 0xff0f, -- 0xff1a, 0xff1b, -- 0xff1f, 0xff20, -- 0xff3b, 0xff3d, -- 0xff3f, 0xff3f, -- 0xff5b, 0xff5b, -- 0xff5d, 0xff5d, -- 0xff5f, 0xff65, -- 0x10100, 0x10101, -- 0x1039f, 0x1039f, -- 0x103d0, 0x103d0, -- 0x10857, 0x10857, -- 0x1091f, 0x1091f, -- 0x1093f, 0x1093f, -- 0x10a50, 0x10a58, -- 0x10a7f, 0x10a7f, -- 0x10b39, 0x10b3f, -- 0x11047, 0x1104d, -- 0x110bb, 0x110bc, -- 0x110be, 0x110c1, -- 0x12470, 0x12473, --}; /* CR_P */ -- --/* 'Pc': General Category */ --static const OnigCodePoint CR_Pc[] = { -- 6, -- 0x005f, 0x005f, -- 0x203f, 0x2040, -- 0x2054, 0x2054, -- 0xfe33, 0xfe34, -- 0xfe4d, 0xfe4f, -- 0xff3f, 0xff3f, --}; /* CR_Pc */ -- --/* 'Pd': General Category */ --static const OnigCodePoint CR_Pd[] = { -- 15, -- 0x002d, 0x002d, -- 0x058a, 0x058a, -- 0x05be, 0x05be, -- 0x1400, 0x1400, -- 0x1806, 0x1806, -- 0x2010, 0x2015, -- 0x2e17, 0x2e17, -- 0x2e1a, 0x2e1a, -- 0x301c, 0x301c, -- 0x3030, 0x3030, -- 0x30a0, 0x30a0, -- 0xfe31, 0xfe32, -- 0xfe58, 0xfe58, -- 0xfe63, 0xfe63, -- 0xff0d, 0xff0d, --}; /* CR_Pd */ -- --/* 'Pe': General Category */ --static const OnigCodePoint CR_Pe[] = { -- 70, -- 0x0029, 0x0029, -- 0x005d, 0x005d, -- 0x007d, 0x007d, -- 0x0f3b, 0x0f3b, -- 0x0f3d, 0x0f3d, -- 0x169c, 0x169c, -- 0x2046, 0x2046, -- 0x207e, 0x207e, -- 0x208e, 0x208e, -- 0x232a, 0x232a, -- 0x2769, 0x2769, -- 0x276b, 0x276b, -- 0x276d, 0x276d, -- 0x276f, 0x276f, -- 0x2771, 0x2771, -- 0x2773, 0x2773, -- 0x2775, 0x2775, -- 0x27c6, 0x27c6, -- 0x27e7, 0x27e7, -- 0x27e9, 0x27e9, -- 0x27eb, 0x27eb, -- 0x27ed, 0x27ed, -- 0x27ef, 0x27ef, -- 0x2984, 0x2984, -- 0x2986, 0x2986, -- 0x2988, 0x2988, -- 0x298a, 0x298a, -- 0x298c, 0x298c, -- 0x298e, 0x298e, -- 0x2990, 0x2990, -- 0x2992, 0x2992, -- 0x2994, 0x2994, -- 0x2996, 0x2996, -- 0x2998, 0x2998, -- 0x29d9, 0x29d9, -- 0x29db, 0x29db, -- 0x29fd, 0x29fd, -- 0x2e23, 0x2e23, -- 0x2e25, 0x2e25, -- 0x2e27, 0x2e27, -- 0x2e29, 0x2e29, -- 0x3009, 0x3009, -- 0x300b, 0x300b, -- 0x300d, 0x300d, -- 0x300f, 0x300f, -- 0x3011, 0x3011, -- 0x3015, 0x3015, -- 0x3017, 0x3017, -- 0x3019, 0x3019, -- 0x301b, 0x301b, -- 0x301e, 0x301f, -- 0xfd3f, 0xfd3f, -- 0xfe18, 0xfe18, -- 0xfe36, 0xfe36, -- 0xfe38, 0xfe38, -- 0xfe3a, 0xfe3a, -- 0xfe3c, 0xfe3c, -- 0xfe3e, 0xfe3e, -- 0xfe40, 0xfe40, -- 0xfe42, 0xfe42, -- 0xfe44, 0xfe44, -- 0xfe48, 0xfe48, -- 0xfe5a, 0xfe5a, -- 0xfe5c, 0xfe5c, -- 0xfe5e, 0xfe5e, -- 0xff09, 0xff09, -- 0xff3d, 0xff3d, -- 0xff5d, 0xff5d, -- 0xff60, 0xff60, -- 0xff63, 0xff63, --}; /* CR_Pe */ -- --/* 'Pf': General Category */ --static const OnigCodePoint CR_Pf[] = { -- 10, -- 0x00bb, 0x00bb, -- 0x2019, 0x2019, -- 0x201d, 0x201d, -- 0x203a, 0x203a, -- 0x2e03, 0x2e03, -- 0x2e05, 0x2e05, -- 0x2e0a, 0x2e0a, -- 0x2e0d, 0x2e0d, -- 0x2e1d, 0x2e1d, -- 0x2e21, 0x2e21, --}; /* CR_Pf */ -- --/* 'Pi': General Category */ --static const OnigCodePoint CR_Pi[] = { -- 11, -- 0x00ab, 0x00ab, -- 0x2018, 0x2018, -- 0x201b, 0x201c, -- 0x201f, 0x201f, -- 0x2039, 0x2039, -- 0x2e02, 0x2e02, -- 0x2e04, 0x2e04, -- 0x2e09, 0x2e09, -- 0x2e0c, 0x2e0c, -- 0x2e1c, 0x2e1c, -- 0x2e20, 0x2e20, --}; /* CR_Pi */ -- --/* 'Po': General Category */ --static const OnigCodePoint CR_Po[] = { -- 128, -- 0x0021, 0x0023, -- 0x0025, 0x0027, -- 0x002a, 0x002a, -- 0x002c, 0x002c, -- 0x002e, 0x002f, -- 0x003a, 0x003b, -- 0x003f, 0x0040, -- 0x005c, 0x005c, -- 0x00a1, 0x00a1, -- 0x00b7, 0x00b7, -- 0x00bf, 0x00bf, -- 0x037e, 0x037e, -- 0x0387, 0x0387, -- 0x055a, 0x055f, -- 0x0589, 0x0589, -- 0x05c0, 0x05c0, -- 0x05c3, 0x05c3, -- 0x05c6, 0x05c6, -- 0x05f3, 0x05f4, -- 0x0609, 0x060a, -- 0x060c, 0x060d, -- 0x061b, 0x061b, -- 0x061e, 0x061f, -- 0x066a, 0x066d, -- 0x06d4, 0x06d4, -- 0x0700, 0x070d, -- 0x07f7, 0x07f9, -- 0x0830, 0x083e, -- 0x085e, 0x085e, -- 0x0964, 0x0965, -- 0x0970, 0x0970, -- 0x0df4, 0x0df4, -- 0x0e4f, 0x0e4f, -- 0x0e5a, 0x0e5b, -- 0x0f04, 0x0f12, -- 0x0f85, 0x0f85, -- 0x0fd0, 0x0fd4, -- 0x0fd9, 0x0fda, -- 0x104a, 0x104f, -- 0x10fb, 0x10fb, -- 0x1361, 0x1368, -- 0x166d, 0x166e, -- 0x16eb, 0x16ed, -- 0x1735, 0x1736, -- 0x17d4, 0x17d6, -- 0x17d8, 0x17da, -- 0x1800, 0x1805, -- 0x1807, 0x180a, -- 0x1944, 0x1945, -- 0x1a1e, 0x1a1f, -- 0x1aa0, 0x1aa6, -- 0x1aa8, 0x1aad, -- 0x1b5a, 0x1b60, -- 0x1bfc, 0x1bff, -- 0x1c3b, 0x1c3f, -- 0x1c7e, 0x1c7f, -- 0x1cd3, 0x1cd3, -- 0x2016, 0x2017, -- 0x2020, 0x2027, -- 0x2030, 0x2038, -- 0x203b, 0x203e, -- 0x2041, 0x2043, -- 0x2047, 0x2051, -- 0x2053, 0x2053, -- 0x2055, 0x205e, -- 0x2cf9, 0x2cfc, -- 0x2cfe, 0x2cff, -- 0x2d70, 0x2d70, -- 0x2e00, 0x2e01, -- 0x2e06, 0x2e08, -- 0x2e0b, 0x2e0b, -- 0x2e0e, 0x2e16, -- 0x2e18, 0x2e19, -- 0x2e1b, 0x2e1b, -- 0x2e1e, 0x2e1f, -- 0x2e2a, 0x2e2e, -- 0x2e30, 0x2e31, -- 0x3001, 0x3003, -- 0x303d, 0x303d, -- 0x30fb, 0x30fb, -- 0xa4fe, 0xa4ff, -- 0xa60d, 0xa60f, -- 0xa673, 0xa673, -- 0xa67e, 0xa67e, -- 0xa6f2, 0xa6f7, -- 0xa874, 0xa877, -- 0xa8ce, 0xa8cf, -- 0xa8f8, 0xa8fa, -- 0xa92e, 0xa92f, -- 0xa95f, 0xa95f, -- 0xa9c1, 0xa9cd, -- 0xa9de, 0xa9df, -- 0xaa5c, 0xaa5f, -- 0xaade, 0xaadf, -- 0xabeb, 0xabeb, -- 0xfe10, 0xfe16, -- 0xfe19, 0xfe19, -- 0xfe30, 0xfe30, -- 0xfe45, 0xfe46, -- 0xfe49, 0xfe4c, -- 0xfe50, 0xfe52, -- 0xfe54, 0xfe57, -- 0xfe5f, 0xfe61, -- 0xfe68, 0xfe68, -- 0xfe6a, 0xfe6b, -- 0xff01, 0xff03, -- 0xff05, 0xff07, -- 0xff0a, 0xff0a, -- 0xff0c, 0xff0c, -- 0xff0e, 0xff0f, -- 0xff1a, 0xff1b, -- 0xff1f, 0xff20, -- 0xff3c, 0xff3c, -- 0xff61, 0xff61, -- 0xff64, 0xff65, -- 0x10100, 0x10101, -- 0x1039f, 0x1039f, -- 0x103d0, 0x103d0, -- 0x10857, 0x10857, -- 0x1091f, 0x1091f, -- 0x1093f, 0x1093f, -- 0x10a50, 0x10a58, -- 0x10a7f, 0x10a7f, -- 0x10b39, 0x10b3f, -- 0x11047, 0x1104d, -- 0x110bb, 0x110bc, -- 0x110be, 0x110c1, -- 0x12470, 0x12473, --}; /* CR_Po */ -- --/* 'Ps': General Category */ --static const OnigCodePoint CR_Ps[] = { -- 72, -- 0x0028, 0x0028, -- 0x005b, 0x005b, -- 0x007b, 0x007b, -- 0x0f3a, 0x0f3a, -- 0x0f3c, 0x0f3c, -- 0x169b, 0x169b, -- 0x201a, 0x201a, -- 0x201e, 0x201e, -- 0x2045, 0x2045, -- 0x207d, 0x207d, -- 0x208d, 0x208d, -- 0x2329, 0x2329, -- 0x2768, 0x2768, -- 0x276a, 0x276a, -- 0x276c, 0x276c, -- 0x276e, 0x276e, -- 0x2770, 0x2770, -- 0x2772, 0x2772, -- 0x2774, 0x2774, -- 0x27c5, 0x27c5, -- 0x27e6, 0x27e6, -- 0x27e8, 0x27e8, -- 0x27ea, 0x27ea, -- 0x27ec, 0x27ec, -- 0x27ee, 0x27ee, -- 0x2983, 0x2983, -- 0x2985, 0x2985, -- 0x2987, 0x2987, -- 0x2989, 0x2989, -- 0x298b, 0x298b, -- 0x298d, 0x298d, -- 0x298f, 0x298f, -- 0x2991, 0x2991, -- 0x2993, 0x2993, -- 0x2995, 0x2995, -- 0x2997, 0x2997, -- 0x29d8, 0x29d8, -- 0x29da, 0x29da, -- 0x29fc, 0x29fc, -- 0x2e22, 0x2e22, -- 0x2e24, 0x2e24, -- 0x2e26, 0x2e26, -- 0x2e28, 0x2e28, -- 0x3008, 0x3008, -- 0x300a, 0x300a, -- 0x300c, 0x300c, -- 0x300e, 0x300e, -- 0x3010, 0x3010, -- 0x3014, 0x3014, -- 0x3016, 0x3016, -- 0x3018, 0x3018, -- 0x301a, 0x301a, -- 0x301d, 0x301d, -- 0xfd3e, 0xfd3e, -- 0xfe17, 0xfe17, -- 0xfe35, 0xfe35, -- 0xfe37, 0xfe37, -- 0xfe39, 0xfe39, -- 0xfe3b, 0xfe3b, -- 0xfe3d, 0xfe3d, -- 0xfe3f, 0xfe3f, -- 0xfe41, 0xfe41, -- 0xfe43, 0xfe43, -- 0xfe47, 0xfe47, -- 0xfe59, 0xfe59, -- 0xfe5b, 0xfe5b, -- 0xfe5d, 0xfe5d, -- 0xff08, 0xff08, -- 0xff3b, 0xff3b, -- 0xff5b, 0xff5b, -- 0xff5f, 0xff5f, -- 0xff62, 0xff62, --}; /* CR_Ps */ -- --/* 'S': Major Category */ --static const OnigCodePoint CR_S[] = { -- 208, -- 0x0024, 0x0024, -- 0x002b, 0x002b, -- 0x003c, 0x003e, -- 0x005e, 0x005e, -- 0x0060, 0x0060, -- 0x007c, 0x007c, -- 0x007e, 0x007e, -- 0x00a2, 0x00a9, -- 0x00ac, 0x00ac, -- 0x00ae, 0x00b1, -- 0x00b4, 0x00b4, -- 0x00b6, 0x00b6, -- 0x00b8, 0x00b8, -- 0x00d7, 0x00d7, -- 0x00f7, 0x00f7, -- 0x02c2, 0x02c5, -- 0x02d2, 0x02df, -- 0x02e5, 0x02eb, -- 0x02ed, 0x02ed, -- 0x02ef, 0x02ff, -- 0x0375, 0x0375, -- 0x0384, 0x0385, -- 0x03f6, 0x03f6, -- 0x0482, 0x0482, -- 0x0606, 0x0608, -- 0x060b, 0x060b, -- 0x060e, 0x060f, -- 0x06de, 0x06de, -- 0x06e9, 0x06e9, -- 0x06fd, 0x06fe, -- 0x07f6, 0x07f6, -- 0x09f2, 0x09f3, -- 0x09fa, 0x09fb, -- 0x0af1, 0x0af1, -- 0x0b70, 0x0b70, -- 0x0bf3, 0x0bfa, -- 0x0c7f, 0x0c7f, -- 0x0d79, 0x0d79, -- 0x0e3f, 0x0e3f, -- 0x0f01, 0x0f03, -- 0x0f13, 0x0f17, -- 0x0f1a, 0x0f1f, -- 0x0f34, 0x0f34, -- 0x0f36, 0x0f36, -- 0x0f38, 0x0f38, -- 0x0fbe, 0x0fc5, -- 0x0fc7, 0x0fcc, -- 0x0fce, 0x0fcf, -- 0x0fd5, 0x0fd8, -- 0x109e, 0x109f, -- 0x1360, 0x1360, -- 0x1390, 0x1399, -- 0x17db, 0x17db, -- 0x1940, 0x1940, -- 0x19de, 0x19ff, -- 0x1b61, 0x1b6a, -- 0x1b74, 0x1b7c, -- 0x1fbd, 0x1fbd, -- 0x1fbf, 0x1fc1, -- 0x1fcd, 0x1fcf, -- 0x1fdd, 0x1fdf, -- 0x1fed, 0x1fef, -- 0x1ffd, 0x1ffe, -- 0x2044, 0x2044, -- 0x2052, 0x2052, -- 0x207a, 0x207c, -- 0x208a, 0x208c, -- 0x20a0, 0x20b9, -- 0x2100, 0x2101, -- 0x2103, 0x2106, -- 0x2108, 0x2109, -- 0x2114, 0x2114, -- 0x2116, 0x2118, -- 0x211e, 0x2123, -- 0x2125, 0x2125, -- 0x2127, 0x2127, -- 0x2129, 0x2129, -- 0x212e, 0x212e, -- 0x213a, 0x213b, -- 0x2140, 0x2144, -- 0x214a, 0x214d, -- 0x214f, 0x214f, -- 0x2190, 0x2328, -- 0x232b, 0x23f3, -- 0x2400, 0x2426, -- 0x2440, 0x244a, -- 0x249c, 0x24e9, -- 0x2500, 0x26ff, -- 0x2701, 0x2767, -- 0x2794, 0x27c4, -- 0x27c7, 0x27ca, -- 0x27cc, 0x27cc, -- 0x27ce, 0x27e5, -- 0x27f0, 0x2982, -- 0x2999, 0x29d7, -- 0x29dc, 0x29fb, -- 0x29fe, 0x2b4c, -- 0x2b50, 0x2b59, -- 0x2ce5, 0x2cea, -- 0x2e80, 0x2e99, -- 0x2e9b, 0x2ef3, -- 0x2f00, 0x2fd5, -- 0x2ff0, 0x2ffb, -- 0x3004, 0x3004, -- 0x3012, 0x3013, -- 0x3020, 0x3020, -- 0x3036, 0x3037, -- 0x303e, 0x303f, -- 0x309b, 0x309c, -- 0x3190, 0x3191, -- 0x3196, 0x319f, -- 0x31c0, 0x31e3, -- 0x3200, 0x321e, -- 0x322a, 0x3250, -- 0x3260, 0x327f, -- 0x328a, 0x32b0, -- 0x32c0, 0x32fe, -- 0x3300, 0x33ff, -- 0x4dc0, 0x4dff, -- 0xa490, 0xa4c6, -- 0xa700, 0xa716, -- 0xa720, 0xa721, -- 0xa789, 0xa78a, -- 0xa828, 0xa82b, -- 0xa836, 0xa839, -- 0xaa77, 0xaa79, -- 0xfb29, 0xfb29, -- 0xfbb2, 0xfbc1, -- 0xfdfc, 0xfdfd, -- 0xfe62, 0xfe62, -- 0xfe64, 0xfe66, -- 0xfe69, 0xfe69, -- 0xff04, 0xff04, -- 0xff0b, 0xff0b, -- 0xff1c, 0xff1e, -- 0xff3e, 0xff3e, -- 0xff40, 0xff40, -- 0xff5c, 0xff5c, -- 0xff5e, 0xff5e, -- 0xffe0, 0xffe6, -- 0xffe8, 0xffee, -- 0xfffc, 0xfffd, -- 0x10102, 0x10102, -- 0x10137, 0x1013f, -- 0x10179, 0x10189, -- 0x10190, 0x1019b, -- 0x101d0, 0x101fc, -- 0x1d000, 0x1d0f5, -- 0x1d100, 0x1d126, -- 0x1d129, 0x1d164, -- 0x1d16a, 0x1d16c, -- 0x1d183, 0x1d184, -- 0x1d18c, 0x1d1a9, -- 0x1d1ae, 0x1d1dd, -- 0x1d200, 0x1d241, -- 0x1d245, 0x1d245, -- 0x1d300, 0x1d356, -- 0x1d6c1, 0x1d6c1, -- 0x1d6db, 0x1d6db, -- 0x1d6fb, 0x1d6fb, -- 0x1d715, 0x1d715, -- 0x1d735, 0x1d735, -- 0x1d74f, 0x1d74f, -- 0x1d76f, 0x1d76f, -- 0x1d789, 0x1d789, -- 0x1d7a9, 0x1d7a9, -- 0x1d7c3, 0x1d7c3, -- 0x1f000, 0x1f02b, -- 0x1f030, 0x1f093, -- 0x1f0a0, 0x1f0ae, -- 0x1f0b1, 0x1f0be, -- 0x1f0c1, 0x1f0cf, -- 0x1f0d1, 0x1f0df, -- 0x1f110, 0x1f12e, -- 0x1f130, 0x1f169, -- 0x1f170, 0x1f19a, -- 0x1f1e6, 0x1f202, -- 0x1f210, 0x1f23a, -- 0x1f240, 0x1f248, -- 0x1f250, 0x1f251, -- 0x1f300, 0x1f320, -- 0x1f330, 0x1f335, -- 0x1f337, 0x1f37c, -- 0x1f380, 0x1f393, -- 0x1f3a0, 0x1f3c4, -- 0x1f3c6, 0x1f3ca, -- 0x1f3e0, 0x1f3f0, -- 0x1f400, 0x1f43e, -- 0x1f440, 0x1f440, -- 0x1f442, 0x1f4f7, -- 0x1f4f9, 0x1f4fc, -- 0x1f500, 0x1f53d, -- 0x1f550, 0x1f567, -- 0x1f5fb, 0x1f5ff, -- 0x1f601, 0x1f610, -- 0x1f612, 0x1f614, -- 0x1f616, 0x1f616, -- 0x1f618, 0x1f618, -- 0x1f61a, 0x1f61a, -- 0x1f61c, 0x1f61e, -- 0x1f620, 0x1f625, -- 0x1f628, 0x1f62b, -- 0x1f62d, 0x1f62d, -- 0x1f630, 0x1f633, -- 0x1f635, 0x1f640, -- 0x1f645, 0x1f64f, -- 0x1f680, 0x1f6c5, -- 0x1f700, 0x1f773, --}; /* CR_S */ -- --/* 'Sc': General Category */ --static const OnigCodePoint CR_Sc[] = { -- 16, -- 0x0024, 0x0024, -- 0x00a2, 0x00a5, -- 0x060b, 0x060b, -- 0x09f2, 0x09f3, -- 0x09fb, 0x09fb, -- 0x0af1, 0x0af1, -- 0x0bf9, 0x0bf9, -- 0x0e3f, 0x0e3f, -- 0x17db, 0x17db, -- 0x20a0, 0x20b9, -- 0xa838, 0xa838, -- 0xfdfc, 0xfdfc, -- 0xfe69, 0xfe69, -- 0xff04, 0xff04, -- 0xffe0, 0xffe1, -- 0xffe5, 0xffe6, --}; /* CR_Sc */ -- --/* 'Sk': General Category */ --static const OnigCodePoint CR_Sk[] = { -- 27, -- 0x005e, 0x005e, -- 0x0060, 0x0060, -- 0x00a8, 0x00a8, -- 0x00af, 0x00af, -- 0x00b4, 0x00b4, -- 0x00b8, 0x00b8, -- 0x02c2, 0x02c5, -- 0x02d2, 0x02df, -- 0x02e5, 0x02eb, -- 0x02ed, 0x02ed, -- 0x02ef, 0x02ff, -- 0x0375, 0x0375, -- 0x0384, 0x0385, -- 0x1fbd, 0x1fbd, -- 0x1fbf, 0x1fc1, -- 0x1fcd, 0x1fcf, -- 0x1fdd, 0x1fdf, -- 0x1fed, 0x1fef, -- 0x1ffd, 0x1ffe, -- 0x309b, 0x309c, -- 0xa700, 0xa716, -- 0xa720, 0xa721, -- 0xa789, 0xa78a, -- 0xfbb2, 0xfbc1, -- 0xff3e, 0xff3e, -- 0xff40, 0xff40, -- 0xffe3, 0xffe3, --}; /* CR_Sk */ -- --/* 'Sm': General Category */ --static const OnigCodePoint CR_Sm[] = { -- 66, -- 0x002b, 0x002b, -- 0x003c, 0x003e, -- 0x007c, 0x007c, -- 0x007e, 0x007e, -- 0x00ac, 0x00ac, -- 0x00b1, 0x00b1, -- 0x00d7, 0x00d7, -- 0x00f7, 0x00f7, -- 0x03f6, 0x03f6, -- 0x0606, 0x0608, -- 0x2044, 0x2044, -- 0x2052, 0x2052, -- 0x207a, 0x207c, -- 0x208a, 0x208c, -- 0x2118, 0x2118, -- 0x2140, 0x2144, -- 0x214b, 0x214b, -- 0x2190, 0x2194, -- 0x219a, 0x219b, -- 0x21a0, 0x21a0, -- 0x21a3, 0x21a3, -- 0x21a6, 0x21a6, -- 0x21ae, 0x21ae, -- 0x21ce, 0x21cf, -- 0x21d2, 0x21d2, -- 0x21d4, 0x21d4, -- 0x21f4, 0x22ff, -- 0x2308, 0x230b, -- 0x2320, 0x2321, -- 0x237c, 0x237c, -- 0x239b, 0x23b3, -- 0x23dc, 0x23e1, -- 0x25b7, 0x25b7, -- 0x25c1, 0x25c1, -- 0x25f8, 0x25ff, -- 0x266f, 0x266f, -- 0x27c0, 0x27c4, -- 0x27c7, 0x27ca, -- 0x27cc, 0x27cc, -- 0x27ce, 0x27e5, -- 0x27f0, 0x27ff, -- 0x2900, 0x2982, -- 0x2999, 0x29d7, -- 0x29dc, 0x29fb, -- 0x29fe, 0x2aff, -- 0x2b30, 0x2b44, -- 0x2b47, 0x2b4c, -- 0xfb29, 0xfb29, -- 0xfe62, 0xfe62, -- 0xfe64, 0xfe66, -- 0xff0b, 0xff0b, -- 0xff1c, 0xff1e, -- 0xff5c, 0xff5c, -- 0xff5e, 0xff5e, -- 0xffe2, 0xffe2, -- 0xffe9, 0xffec, -- 0x1d6c1, 0x1d6c1, -- 0x1d6db, 0x1d6db, -- 0x1d6fb, 0x1d6fb, -- 0x1d715, 0x1d715, -- 0x1d735, 0x1d735, -- 0x1d74f, 0x1d74f, -- 0x1d76f, 0x1d76f, -- 0x1d789, 0x1d789, -- 0x1d7a9, 0x1d7a9, -- 0x1d7c3, 0x1d7c3, --}; /* CR_Sm */ -- --/* 'So': General Category */ --static const OnigCodePoint CR_So[] = { -- 164, -- 0x00a6, 0x00a7, -- 0x00a9, 0x00a9, -- 0x00ae, 0x00ae, -- 0x00b0, 0x00b0, -- 0x00b6, 0x00b6, -- 0x0482, 0x0482, -- 0x060e, 0x060f, -- 0x06de, 0x06de, -- 0x06e9, 0x06e9, -- 0x06fd, 0x06fe, -- 0x07f6, 0x07f6, -- 0x09fa, 0x09fa, -- 0x0b70, 0x0b70, -- 0x0bf3, 0x0bf8, -- 0x0bfa, 0x0bfa, -- 0x0c7f, 0x0c7f, -- 0x0d79, 0x0d79, -- 0x0f01, 0x0f03, -- 0x0f13, 0x0f17, -- 0x0f1a, 0x0f1f, -- 0x0f34, 0x0f34, -- 0x0f36, 0x0f36, -- 0x0f38, 0x0f38, -- 0x0fbe, 0x0fc5, -- 0x0fc7, 0x0fcc, -- 0x0fce, 0x0fcf, -- 0x0fd5, 0x0fd8, -- 0x109e, 0x109f, -- 0x1360, 0x1360, -- 0x1390, 0x1399, -- 0x1940, 0x1940, -- 0x19de, 0x19ff, -- 0x1b61, 0x1b6a, -- 0x1b74, 0x1b7c, -- 0x2100, 0x2101, -- 0x2103, 0x2106, -- 0x2108, 0x2109, -- 0x2114, 0x2114, -- 0x2116, 0x2117, -- 0x211e, 0x2123, -- 0x2125, 0x2125, -- 0x2127, 0x2127, -- 0x2129, 0x2129, -- 0x212e, 0x212e, -- 0x213a, 0x213b, -- 0x214a, 0x214a, -- 0x214c, 0x214d, -- 0x214f, 0x214f, -- 0x2195, 0x2199, -- 0x219c, 0x219f, -- 0x21a1, 0x21a2, -- 0x21a4, 0x21a5, -- 0x21a7, 0x21ad, -- 0x21af, 0x21cd, -- 0x21d0, 0x21d1, -- 0x21d3, 0x21d3, -- 0x21d5, 0x21f3, -- 0x2300, 0x2307, -- 0x230c, 0x231f, -- 0x2322, 0x2328, -- 0x232b, 0x237b, -- 0x237d, 0x239a, -- 0x23b4, 0x23db, -- 0x23e2, 0x23f3, -- 0x2400, 0x2426, -- 0x2440, 0x244a, -- 0x249c, 0x24e9, -- 0x2500, 0x25b6, -- 0x25b8, 0x25c0, -- 0x25c2, 0x25f7, -- 0x2600, 0x266e, -- 0x2670, 0x26ff, -- 0x2701, 0x2767, -- 0x2794, 0x27bf, -- 0x2800, 0x28ff, -- 0x2b00, 0x2b2f, -- 0x2b45, 0x2b46, -- 0x2b50, 0x2b59, -- 0x2ce5, 0x2cea, -- 0x2e80, 0x2e99, -- 0x2e9b, 0x2ef3, -- 0x2f00, 0x2fd5, -- 0x2ff0, 0x2ffb, -- 0x3004, 0x3004, -- 0x3012, 0x3013, -- 0x3020, 0x3020, -- 0x3036, 0x3037, -- 0x303e, 0x303f, -- 0x3190, 0x3191, -- 0x3196, 0x319f, -- 0x31c0, 0x31e3, -- 0x3200, 0x321e, -- 0x322a, 0x3250, -- 0x3260, 0x327f, -- 0x328a, 0x32b0, -- 0x32c0, 0x32fe, -- 0x3300, 0x33ff, -- 0x4dc0, 0x4dff, -- 0xa490, 0xa4c6, -- 0xa828, 0xa82b, -- 0xa836, 0xa837, -- 0xa839, 0xa839, -- 0xaa77, 0xaa79, -- 0xfdfd, 0xfdfd, -- 0xffe4, 0xffe4, -- 0xffe8, 0xffe8, -- 0xffed, 0xffee, -- 0xfffc, 0xfffd, -- 0x10102, 0x10102, -- 0x10137, 0x1013f, -- 0x10179, 0x10189, -- 0x10190, 0x1019b, -- 0x101d0, 0x101fc, -- 0x1d000, 0x1d0f5, -- 0x1d100, 0x1d126, -- 0x1d129, 0x1d164, -- 0x1d16a, 0x1d16c, -- 0x1d183, 0x1d184, -- 0x1d18c, 0x1d1a9, -- 0x1d1ae, 0x1d1dd, -- 0x1d200, 0x1d241, -- 0x1d245, 0x1d245, -- 0x1d300, 0x1d356, -- 0x1f000, 0x1f02b, -- 0x1f030, 0x1f093, -- 0x1f0a0, 0x1f0ae, -- 0x1f0b1, 0x1f0be, -- 0x1f0c1, 0x1f0cf, -- 0x1f0d1, 0x1f0df, -- 0x1f110, 0x1f12e, -- 0x1f130, 0x1f169, -- 0x1f170, 0x1f19a, -- 0x1f1e6, 0x1f202, -- 0x1f210, 0x1f23a, -- 0x1f240, 0x1f248, -- 0x1f250, 0x1f251, -- 0x1f300, 0x1f320, -- 0x1f330, 0x1f335, -- 0x1f337, 0x1f37c, -- 0x1f380, 0x1f393, -- 0x1f3a0, 0x1f3c4, -- 0x1f3c6, 0x1f3ca, -- 0x1f3e0, 0x1f3f0, -- 0x1f400, 0x1f43e, -- 0x1f440, 0x1f440, -- 0x1f442, 0x1f4f7, -- 0x1f4f9, 0x1f4fc, -- 0x1f500, 0x1f53d, -- 0x1f550, 0x1f567, -- 0x1f5fb, 0x1f5ff, -- 0x1f601, 0x1f610, -- 0x1f612, 0x1f614, -- 0x1f616, 0x1f616, -- 0x1f618, 0x1f618, -- 0x1f61a, 0x1f61a, -- 0x1f61c, 0x1f61e, -- 0x1f620, 0x1f625, -- 0x1f628, 0x1f62b, -- 0x1f62d, 0x1f62d, -- 0x1f630, 0x1f633, -- 0x1f635, 0x1f640, -- 0x1f645, 0x1f64f, -- 0x1f680, 0x1f6c5, -- 0x1f700, 0x1f773, --}; /* CR_So */ -- --/* 'Z': Major Category */ --static const OnigCodePoint CR_Z[] = { -- 9, -- 0x0020, 0x0020, -- 0x00a0, 0x00a0, -- 0x1680, 0x1680, -- 0x180e, 0x180e, -- 0x2000, 0x200a, -- 0x2028, 0x2029, -- 0x202f, 0x202f, -- 0x205f, 0x205f, -- 0x3000, 0x3000, --}; /* CR_Z */ -- --/* 'Zl': General Category */ --static const OnigCodePoint CR_Zl[] = { -- 1, -- 0x2028, 0x2028, --}; /* CR_Zl */ -- --/* 'Zp': General Category */ --static const OnigCodePoint CR_Zp[] = { -- 1, -- 0x2029, 0x2029, --}; /* CR_Zp */ -- --/* 'Zs': General Category */ --static const OnigCodePoint CR_Zs[] = { -- 8, -- 0x0020, 0x0020, -- 0x00a0, 0x00a0, -- 0x1680, 0x1680, -- 0x180e, 0x180e, -- 0x2000, 0x200a, -- 0x202f, 0x202f, -- 0x205f, 0x205f, -- 0x3000, 0x3000, --}; /* CR_Zs */ -- --/* 'Math': Derived Property */ --static const OnigCodePoint CR_Math[] = { -- 106, -- 0x002b, 0x002b, -- 0x003c, 0x003e, -- 0x005e, 0x005e, -- 0x007c, 0x007c, -- 0x007e, 0x007e, -- 0x00ac, 0x00ac, -- 0x00b1, 0x00b1, -- 0x00d7, 0x00d7, -- 0x00f7, 0x00f7, -- 0x03d0, 0x03d2, -- 0x03d5, 0x03d5, -- 0x03f0, 0x03f1, -- 0x03f4, 0x03f6, -- 0x0606, 0x0608, -- 0x2016, 0x2016, -- 0x2032, 0x2034, -- 0x2040, 0x2040, -- 0x2044, 0x2044, -- 0x2052, 0x2052, -- 0x2061, 0x2064, -- 0x207a, 0x207e, -- 0x208a, 0x208e, -- 0x20d0, 0x20dc, -- 0x20e1, 0x20e1, -- 0x20e5, 0x20e6, -- 0x20eb, 0x20ef, -- 0x2102, 0x2102, -- 0x2107, 0x2107, -- 0x210a, 0x2113, -- 0x2115, 0x2115, -- 0x2118, 0x211d, -- 0x2124, 0x2124, -- 0x2128, 0x2129, -- 0x212c, 0x212d, -- 0x212f, 0x2131, -- 0x2133, 0x2138, -- 0x213c, 0x2149, -- 0x214b, 0x214b, -- 0x2190, 0x21a7, -- 0x21a9, 0x21ae, -- 0x21b0, 0x21b1, -- 0x21b6, 0x21b7, -- 0x21bc, 0x21db, -- 0x21dd, 0x21dd, -- 0x21e4, 0x21e5, -- 0x21f4, 0x22ff, -- 0x2308, 0x230b, -- 0x2320, 0x2321, -- 0x237c, 0x237c, -- 0x239b, 0x23b5, -- 0x23b7, 0x23b7, -- 0x23d0, 0x23d0, -- 0x23dc, 0x23e2, -- 0x25a0, 0x25a1, -- 0x25ae, 0x25b7, -- 0x25bc, 0x25c1, -- 0x25c6, 0x25c7, -- 0x25ca, 0x25cb, -- 0x25cf, 0x25d3, -- 0x25e2, 0x25e2, -- 0x25e4, 0x25e4, -- 0x25e7, 0x25ec, -- 0x25f8, 0x25ff, -- 0x2605, 0x2606, -- 0x2640, 0x2640, -- 0x2642, 0x2642, -- 0x2660, 0x2663, -- 0x266d, 0x266f, -- 0x27c0, 0x27ca, -- 0x27cc, 0x27cc, -- 0x27ce, 0x27ff, -- 0x2900, 0x2aff, -- 0x2b30, 0x2b44, -- 0x2b47, 0x2b4c, -- 0xfb29, 0xfb29, -- 0xfe61, 0xfe66, -- 0xfe68, 0xfe68, -- 0xff0b, 0xff0b, -- 0xff1c, 0xff1e, -- 0xff3c, 0xff3c, -- 0xff3e, 0xff3e, -- 0xff5c, 0xff5c, -- 0xff5e, 0xff5e, -- 0xffe2, 0xffe2, -- 0xffe9, 0xffec, -- 0x1d400, 0x1d454, -- 0x1d456, 0x1d49c, -- 0x1d49e, 0x1d49f, -- 0x1d4a2, 0x1d4a2, -- 0x1d4a5, 0x1d4a6, -- 0x1d4a9, 0x1d4ac, -- 0x1d4ae, 0x1d4b9, -- 0x1d4bb, 0x1d4bb, -- 0x1d4bd, 0x1d4c3, -- 0x1d4c5, 0x1d505, -- 0x1d507, 0x1d50a, -- 0x1d50d, 0x1d514, -- 0x1d516, 0x1d51c, -- 0x1d51e, 0x1d539, -- 0x1d53b, 0x1d53e, -- 0x1d540, 0x1d544, -- 0x1d546, 0x1d546, -- 0x1d54a, 0x1d550, -- 0x1d552, 0x1d6a5, -- 0x1d6a8, 0x1d7cb, -- 0x1d7ce, 0x1d7ff, --}; /* CR_Math */ -- --/* 'Alphabetic': Derived Property */ --static const OnigCodePoint CR_Alphabetic[] = { -- 486, -- 0x0041, 0x005a, -- 0x0061, 0x007a, -- 0x00aa, 0x00aa, -- 0x00b5, 0x00b5, -- 0x00ba, 0x00ba, -- 0x00c0, 0x00d6, -- 0x00d8, 0x00f6, -- 0x00f8, 0x02c1, -- 0x02c6, 0x02d1, -- 0x02e0, 0x02e4, -- 0x02ec, 0x02ec, -- 0x02ee, 0x02ee, -- 0x0345, 0x0345, -- 0x0370, 0x0374, -- 0x0376, 0x0377, -- 0x037a, 0x037d, -- 0x0386, 0x0386, -- 0x0388, 0x038a, -- 0x038c, 0x038c, -- 0x038e, 0x03a1, -- 0x03a3, 0x03f5, -- 0x03f7, 0x0481, -- 0x048a, 0x0527, -- 0x0531, 0x0556, -- 0x0559, 0x0559, -- 0x0561, 0x0587, -- 0x05b0, 0x05bd, -- 0x05bf, 0x05bf, -- 0x05c1, 0x05c2, -- 0x05c4, 0x05c5, -- 0x05c7, 0x05c7, -- 0x05d0, 0x05ea, -- 0x05f0, 0x05f2, -- 0x0610, 0x061a, -- 0x0620, 0x0657, -- 0x0659, 0x065f, -- 0x066e, 0x06d3, -- 0x06d5, 0x06dc, -- 0x06e1, 0x06e8, -- 0x06ed, 0x06ef, -- 0x06fa, 0x06fc, -- 0x06ff, 0x06ff, -- 0x0710, 0x073f, -- 0x074d, 0x07b1, -- 0x07ca, 0x07ea, -- 0x07f4, 0x07f5, -- 0x07fa, 0x07fa, -- 0x0800, 0x0817, -- 0x081a, 0x082c, -- 0x0840, 0x0858, -- 0x0900, 0x093b, -- 0x093d, 0x094c, -- 0x094e, 0x0950, -- 0x0955, 0x0963, -- 0x0971, 0x0977, -- 0x0979, 0x097f, -- 0x0981, 0x0983, -- 0x0985, 0x098c, -- 0x098f, 0x0990, -- 0x0993, 0x09a8, -- 0x09aa, 0x09b0, -- 0x09b2, 0x09b2, -- 0x09b6, 0x09b9, -- 0x09bd, 0x09c4, -- 0x09c7, 0x09c8, -- 0x09cb, 0x09cc, -- 0x09ce, 0x09ce, -- 0x09d7, 0x09d7, -- 0x09dc, 0x09dd, -- 0x09df, 0x09e3, -- 0x09f0, 0x09f1, -- 0x0a01, 0x0a03, -- 0x0a05, 0x0a0a, -- 0x0a0f, 0x0a10, -- 0x0a13, 0x0a28, -- 0x0a2a, 0x0a30, -- 0x0a32, 0x0a33, -- 0x0a35, 0x0a36, -- 0x0a38, 0x0a39, -- 0x0a3e, 0x0a42, -- 0x0a47, 0x0a48, -- 0x0a4b, 0x0a4c, -- 0x0a51, 0x0a51, -- 0x0a59, 0x0a5c, -- 0x0a5e, 0x0a5e, -- 0x0a70, 0x0a75, -- 0x0a81, 0x0a83, -- 0x0a85, 0x0a8d, -- 0x0a8f, 0x0a91, -- 0x0a93, 0x0aa8, -- 0x0aaa, 0x0ab0, -- 0x0ab2, 0x0ab3, -- 0x0ab5, 0x0ab9, -- 0x0abd, 0x0ac5, -- 0x0ac7, 0x0ac9, -- 0x0acb, 0x0acc, -- 0x0ad0, 0x0ad0, -- 0x0ae0, 0x0ae3, -- 0x0b01, 0x0b03, -- 0x0b05, 0x0b0c, -- 0x0b0f, 0x0b10, -- 0x0b13, 0x0b28, -- 0x0b2a, 0x0b30, -- 0x0b32, 0x0b33, -- 0x0b35, 0x0b39, -- 0x0b3d, 0x0b44, -- 0x0b47, 0x0b48, -- 0x0b4b, 0x0b4c, -- 0x0b56, 0x0b57, -- 0x0b5c, 0x0b5d, -- 0x0b5f, 0x0b63, -- 0x0b71, 0x0b71, -- 0x0b82, 0x0b83, -- 0x0b85, 0x0b8a, -- 0x0b8e, 0x0b90, -- 0x0b92, 0x0b95, -- 0x0b99, 0x0b9a, -- 0x0b9c, 0x0b9c, -- 0x0b9e, 0x0b9f, -- 0x0ba3, 0x0ba4, -- 0x0ba8, 0x0baa, -- 0x0bae, 0x0bb9, -- 0x0bbe, 0x0bc2, -- 0x0bc6, 0x0bc8, -- 0x0bca, 0x0bcc, -- 0x0bd0, 0x0bd0, -- 0x0bd7, 0x0bd7, -- 0x0c01, 0x0c03, -- 0x0c05, 0x0c0c, -- 0x0c0e, 0x0c10, -- 0x0c12, 0x0c28, -- 0x0c2a, 0x0c33, -- 0x0c35, 0x0c39, -- 0x0c3d, 0x0c44, -- 0x0c46, 0x0c48, -- 0x0c4a, 0x0c4c, -- 0x0c55, 0x0c56, -- 0x0c58, 0x0c59, -- 0x0c60, 0x0c63, -- 0x0c82, 0x0c83, -- 0x0c85, 0x0c8c, -- 0x0c8e, 0x0c90, -- 0x0c92, 0x0ca8, -- 0x0caa, 0x0cb3, -- 0x0cb5, 0x0cb9, -- 0x0cbd, 0x0cc4, -- 0x0cc6, 0x0cc8, -- 0x0cca, 0x0ccc, -- 0x0cd5, 0x0cd6, -- 0x0cde, 0x0cde, -- 0x0ce0, 0x0ce3, -- 0x0cf1, 0x0cf2, -- 0x0d02, 0x0d03, -- 0x0d05, 0x0d0c, -- 0x0d0e, 0x0d10, -- 0x0d12, 0x0d3a, -- 0x0d3d, 0x0d44, -- 0x0d46, 0x0d48, -- 0x0d4a, 0x0d4c, -- 0x0d4e, 0x0d4e, -- 0x0d57, 0x0d57, -- 0x0d60, 0x0d63, -- 0x0d7a, 0x0d7f, -- 0x0d82, 0x0d83, -- 0x0d85, 0x0d96, -- 0x0d9a, 0x0db1, -- 0x0db3, 0x0dbb, -- 0x0dbd, 0x0dbd, -- 0x0dc0, 0x0dc6, -- 0x0dcf, 0x0dd4, -- 0x0dd6, 0x0dd6, -- 0x0dd8, 0x0ddf, -- 0x0df2, 0x0df3, -- 0x0e01, 0x0e3a, -- 0x0e40, 0x0e46, -- 0x0e4d, 0x0e4d, -- 0x0e81, 0x0e82, -- 0x0e84, 0x0e84, -- 0x0e87, 0x0e88, -- 0x0e8a, 0x0e8a, -- 0x0e8d, 0x0e8d, -- 0x0e94, 0x0e97, -- 0x0e99, 0x0e9f, -- 0x0ea1, 0x0ea3, -- 0x0ea5, 0x0ea5, -- 0x0ea7, 0x0ea7, -- 0x0eaa, 0x0eab, -- 0x0ead, 0x0eb9, -- 0x0ebb, 0x0ebd, -- 0x0ec0, 0x0ec4, -- 0x0ec6, 0x0ec6, -- 0x0ecd, 0x0ecd, -- 0x0edc, 0x0edd, -- 0x0f00, 0x0f00, -- 0x0f40, 0x0f47, -- 0x0f49, 0x0f6c, -- 0x0f71, 0x0f81, -- 0x0f88, 0x0f97, -- 0x0f99, 0x0fbc, -- 0x1000, 0x1036, -- 0x1038, 0x1038, -- 0x103b, 0x103f, -- 0x1050, 0x1062, -- 0x1065, 0x1068, -- 0x106e, 0x1086, -- 0x108e, 0x108e, -- 0x109c, 0x109d, -- 0x10a0, 0x10c5, -- 0x10d0, 0x10fa, -- 0x10fc, 0x10fc, -- 0x1100, 0x1248, -- 0x124a, 0x124d, -- 0x1250, 0x1256, -- 0x1258, 0x1258, -- 0x125a, 0x125d, -- 0x1260, 0x1288, -- 0x128a, 0x128d, -- 0x1290, 0x12b0, -- 0x12b2, 0x12b5, -- 0x12b8, 0x12be, -- 0x12c0, 0x12c0, -- 0x12c2, 0x12c5, -- 0x12c8, 0x12d6, -- 0x12d8, 0x1310, -- 0x1312, 0x1315, -- 0x1318, 0x135a, -- 0x135f, 0x135f, -- 0x1380, 0x138f, -- 0x13a0, 0x13f4, -- 0x1401, 0x166c, -- 0x166f, 0x167f, -- 0x1681, 0x169a, -- 0x16a0, 0x16ea, -- 0x16ee, 0x16f0, -- 0x1700, 0x170c, -- 0x170e, 0x1713, -- 0x1720, 0x1733, -- 0x1740, 0x1753, -- 0x1760, 0x176c, -- 0x176e, 0x1770, -- 0x1772, 0x1773, -- 0x1780, 0x17b3, -- 0x17b6, 0x17c8, -- 0x17d7, 0x17d7, -- 0x17dc, 0x17dc, -- 0x1820, 0x1877, -- 0x1880, 0x18aa, -- 0x18b0, 0x18f5, -- 0x1900, 0x191c, -- 0x1920, 0x192b, -- 0x1930, 0x1938, -- 0x1950, 0x196d, -- 0x1970, 0x1974, -- 0x1980, 0x19ab, -- 0x19b0, 0x19c9, -- 0x1a00, 0x1a1b, -- 0x1a20, 0x1a5e, -- 0x1a61, 0x1a74, -- 0x1aa7, 0x1aa7, -- 0x1b00, 0x1b33, -- 0x1b35, 0x1b43, -- 0x1b45, 0x1b4b, -- 0x1b80, 0x1ba9, -- 0x1bae, 0x1baf, -- 0x1bc0, 0x1be5, -- 0x1be7, 0x1bf1, -- 0x1c00, 0x1c35, -- 0x1c4d, 0x1c4f, -- 0x1c5a, 0x1c7d, -- 0x1ce9, 0x1cec, -- 0x1cee, 0x1cf2, -- 0x1d00, 0x1dbf, -- 0x1e00, 0x1f15, -- 0x1f18, 0x1f1d, -- 0x1f20, 0x1f45, -- 0x1f48, 0x1f4d, -- 0x1f50, 0x1f57, -- 0x1f59, 0x1f59, -- 0x1f5b, 0x1f5b, -- 0x1f5d, 0x1f5d, -- 0x1f5f, 0x1f7d, -- 0x1f80, 0x1fb4, -- 0x1fb6, 0x1fbc, -- 0x1fbe, 0x1fbe, -- 0x1fc2, 0x1fc4, -- 0x1fc6, 0x1fcc, -- 0x1fd0, 0x1fd3, -- 0x1fd6, 0x1fdb, -- 0x1fe0, 0x1fec, -- 0x1ff2, 0x1ff4, -- 0x1ff6, 0x1ffc, -- 0x2071, 0x2071, -- 0x207f, 0x207f, -- 0x2090, 0x209c, -- 0x2102, 0x2102, -- 0x2107, 0x2107, -- 0x210a, 0x2113, -- 0x2115, 0x2115, -- 0x2119, 0x211d, -- 0x2124, 0x2124, -- 0x2126, 0x2126, -- 0x2128, 0x2128, -- 0x212a, 0x212d, -- 0x212f, 0x2139, -- 0x213c, 0x213f, -- 0x2145, 0x2149, -- 0x214e, 0x214e, -- 0x2160, 0x2188, -- 0x24b6, 0x24e9, -- 0x2c00, 0x2c2e, -- 0x2c30, 0x2c5e, -- 0x2c60, 0x2ce4, -- 0x2ceb, 0x2cee, -- 0x2d00, 0x2d25, -- 0x2d30, 0x2d65, -- 0x2d6f, 0x2d6f, -- 0x2d80, 0x2d96, -- 0x2da0, 0x2da6, -- 0x2da8, 0x2dae, -- 0x2db0, 0x2db6, -- 0x2db8, 0x2dbe, -- 0x2dc0, 0x2dc6, -- 0x2dc8, 0x2dce, -- 0x2dd0, 0x2dd6, -- 0x2dd8, 0x2dde, -- 0x2de0, 0x2dff, -- 0x2e2f, 0x2e2f, -- 0x3005, 0x3007, -- 0x3021, 0x3029, -- 0x3031, 0x3035, -- 0x3038, 0x303c, -- 0x3041, 0x3096, -- 0x309d, 0x309f, -- 0x30a1, 0x30fa, -- 0x30fc, 0x30ff, -- 0x3105, 0x312d, -- 0x3131, 0x318e, -- 0x31a0, 0x31ba, -- 0x31f0, 0x31ff, -- 0x3400, 0x4db5, -- 0x4e00, 0x9fcb, -- 0xa000, 0xa48c, -- 0xa4d0, 0xa4fd, -- 0xa500, 0xa60c, -- 0xa610, 0xa61f, -- 0xa62a, 0xa62b, -- 0xa640, 0xa66e, -- 0xa67f, 0xa697, -- 0xa6a0, 0xa6ef, -- 0xa717, 0xa71f, -- 0xa722, 0xa788, -- 0xa78b, 0xa78e, -- 0xa790, 0xa791, -- 0xa7a0, 0xa7a9, -- 0xa7fa, 0xa801, -- 0xa803, 0xa805, -- 0xa807, 0xa80a, -- 0xa80c, 0xa827, -- 0xa840, 0xa873, -- 0xa880, 0xa8c3, -- 0xa8f2, 0xa8f7, -- 0xa8fb, 0xa8fb, -- 0xa90a, 0xa92a, -- 0xa930, 0xa952, -- 0xa960, 0xa97c, -- 0xa980, 0xa9b2, -- 0xa9b4, 0xa9bf, -- 0xa9cf, 0xa9cf, -- 0xaa00, 0xaa36, -- 0xaa40, 0xaa4d, -- 0xaa60, 0xaa76, -- 0xaa7a, 0xaa7a, -- 0xaa80, 0xaabe, -- 0xaac0, 0xaac0, -- 0xaac2, 0xaac2, -- 0xaadb, 0xaadd, -- 0xab01, 0xab06, -- 0xab09, 0xab0e, -- 0xab11, 0xab16, -- 0xab20, 0xab26, -- 0xab28, 0xab2e, -- 0xabc0, 0xabea, -- 0xac00, 0xd7a3, -- 0xd7b0, 0xd7c6, -- 0xd7cb, 0xd7fb, -- 0xf900, 0xfa2d, -- 0xfa30, 0xfa6d, -- 0xfa70, 0xfad9, -- 0xfb00, 0xfb06, -- 0xfb13, 0xfb17, -- 0xfb1d, 0xfb28, -- 0xfb2a, 0xfb36, -- 0xfb38, 0xfb3c, -- 0xfb3e, 0xfb3e, -- 0xfb40, 0xfb41, -- 0xfb43, 0xfb44, -- 0xfb46, 0xfbb1, -- 0xfbd3, 0xfd3d, -- 0xfd50, 0xfd8f, -- 0xfd92, 0xfdc7, -- 0xfdf0, 0xfdfb, -- 0xfe70, 0xfe74, -- 0xfe76, 0xfefc, -- 0xff21, 0xff3a, -- 0xff41, 0xff5a, -- 0xff66, 0xffbe, -- 0xffc2, 0xffc7, -- 0xffca, 0xffcf, -- 0xffd2, 0xffd7, -- 0xffda, 0xffdc, -- 0x10000, 0x1000b, -- 0x1000d, 0x10026, -- 0x10028, 0x1003a, -- 0x1003c, 0x1003d, -- 0x1003f, 0x1004d, -- 0x10050, 0x1005d, -- 0x10080, 0x100fa, -- 0x10140, 0x10174, -- 0x10280, 0x1029c, -- 0x102a0, 0x102d0, -- 0x10300, 0x1031e, -- 0x10330, 0x1034a, -- 0x10380, 0x1039d, -- 0x103a0, 0x103c3, -- 0x103c8, 0x103cf, -- 0x103d1, 0x103d5, -- 0x10400, 0x1049d, -- 0x10800, 0x10805, -- 0x10808, 0x10808, -- 0x1080a, 0x10835, -- 0x10837, 0x10838, -- 0x1083c, 0x1083c, -- 0x1083f, 0x10855, -- 0x10900, 0x10915, -- 0x10920, 0x10939, -- 0x10a00, 0x10a03, -- 0x10a05, 0x10a06, -- 0x10a0c, 0x10a13, -- 0x10a15, 0x10a17, -- 0x10a19, 0x10a33, -- 0x10a60, 0x10a7c, -- 0x10b00, 0x10b35, -- 0x10b40, 0x10b55, -- 0x10b60, 0x10b72, -- 0x10c00, 0x10c48, -- 0x11000, 0x11045, -- 0x11082, 0x110b8, -- 0x12000, 0x1236e, -- 0x12400, 0x12462, -- 0x13000, 0x1342e, -- 0x16800, 0x16a38, -- 0x1b000, 0x1b001, -- 0x1d400, 0x1d454, -- 0x1d456, 0x1d49c, -- 0x1d49e, 0x1d49f, -- 0x1d4a2, 0x1d4a2, -- 0x1d4a5, 0x1d4a6, -- 0x1d4a9, 0x1d4ac, -- 0x1d4ae, 0x1d4b9, -- 0x1d4bb, 0x1d4bb, -- 0x1d4bd, 0x1d4c3, -- 0x1d4c5, 0x1d505, -- 0x1d507, 0x1d50a, -- 0x1d50d, 0x1d514, -- 0x1d516, 0x1d51c, -- 0x1d51e, 0x1d539, -- 0x1d53b, 0x1d53e, -- 0x1d540, 0x1d544, -- 0x1d546, 0x1d546, -- 0x1d54a, 0x1d550, -- 0x1d552, 0x1d6a5, -- 0x1d6a8, 0x1d6c0, -- 0x1d6c2, 0x1d6da, -- 0x1d6dc, 0x1d6fa, -- 0x1d6fc, 0x1d714, -- 0x1d716, 0x1d734, -- 0x1d736, 0x1d74e, -- 0x1d750, 0x1d76e, -- 0x1d770, 0x1d788, -- 0x1d78a, 0x1d7a8, -- 0x1d7aa, 0x1d7c2, -- 0x1d7c4, 0x1d7cb, -- 0x20000, 0x2a6d6, -- 0x2a700, 0x2b734, -- 0x2b740, 0x2b81d, -- 0x2f800, 0x2fa1d, --}; /* CR_Alphabetic */ -- --/* 'Lowercase': Derived Property */ --static const OnigCodePoint CR_Lowercase[] = { -- 612, -- 0x0061, 0x007a, -- 0x00aa, 0x00aa, -- 0x00b5, 0x00b5, -- 0x00ba, 0x00ba, -- 0x00df, 0x00f6, -- 0x00f8, 0x00ff, -- 0x0101, 0x0101, -- 0x0103, 0x0103, -- 0x0105, 0x0105, -- 0x0107, 0x0107, -- 0x0109, 0x0109, -- 0x010b, 0x010b, -- 0x010d, 0x010d, -- 0x010f, 0x010f, -- 0x0111, 0x0111, -- 0x0113, 0x0113, -- 0x0115, 0x0115, -- 0x0117, 0x0117, -- 0x0119, 0x0119, -- 0x011b, 0x011b, -- 0x011d, 0x011d, -- 0x011f, 0x011f, -- 0x0121, 0x0121, -- 0x0123, 0x0123, -- 0x0125, 0x0125, -- 0x0127, 0x0127, -- 0x0129, 0x0129, -- 0x012b, 0x012b, -- 0x012d, 0x012d, -- 0x012f, 0x012f, -- 0x0131, 0x0131, -- 0x0133, 0x0133, -- 0x0135, 0x0135, -- 0x0137, 0x0138, -- 0x013a, 0x013a, -- 0x013c, 0x013c, -- 0x013e, 0x013e, -- 0x0140, 0x0140, -- 0x0142, 0x0142, -- 0x0144, 0x0144, -- 0x0146, 0x0146, -- 0x0148, 0x0149, -- 0x014b, 0x014b, -- 0x014d, 0x014d, -- 0x014f, 0x014f, -- 0x0151, 0x0151, -- 0x0153, 0x0153, -- 0x0155, 0x0155, -- 0x0157, 0x0157, -- 0x0159, 0x0159, -- 0x015b, 0x015b, -- 0x015d, 0x015d, -- 0x015f, 0x015f, -- 0x0161, 0x0161, -- 0x0163, 0x0163, -- 0x0165, 0x0165, -- 0x0167, 0x0167, -- 0x0169, 0x0169, -- 0x016b, 0x016b, -- 0x016d, 0x016d, -- 0x016f, 0x016f, -- 0x0171, 0x0171, -- 0x0173, 0x0173, -- 0x0175, 0x0175, -- 0x0177, 0x0177, -- 0x017a, 0x017a, -- 0x017c, 0x017c, -- 0x017e, 0x0180, -- 0x0183, 0x0183, -- 0x0185, 0x0185, -- 0x0188, 0x0188, -- 0x018c, 0x018d, -- 0x0192, 0x0192, -- 0x0195, 0x0195, -- 0x0199, 0x019b, -- 0x019e, 0x019e, -- 0x01a1, 0x01a1, -- 0x01a3, 0x01a3, -- 0x01a5, 0x01a5, -- 0x01a8, 0x01a8, -- 0x01aa, 0x01ab, -- 0x01ad, 0x01ad, -- 0x01b0, 0x01b0, -- 0x01b4, 0x01b4, -- 0x01b6, 0x01b6, -- 0x01b9, 0x01ba, -- 0x01bd, 0x01bf, -- 0x01c6, 0x01c6, -- 0x01c9, 0x01c9, -- 0x01cc, 0x01cc, -- 0x01ce, 0x01ce, -- 0x01d0, 0x01d0, -- 0x01d2, 0x01d2, -- 0x01d4, 0x01d4, -- 0x01d6, 0x01d6, -- 0x01d8, 0x01d8, -- 0x01da, 0x01da, -- 0x01dc, 0x01dd, -- 0x01df, 0x01df, -- 0x01e1, 0x01e1, -- 0x01e3, 0x01e3, -- 0x01e5, 0x01e5, -- 0x01e7, 0x01e7, -- 0x01e9, 0x01e9, -- 0x01eb, 0x01eb, -- 0x01ed, 0x01ed, -- 0x01ef, 0x01f0, -- 0x01f3, 0x01f3, -- 0x01f5, 0x01f5, -- 0x01f9, 0x01f9, -- 0x01fb, 0x01fb, -- 0x01fd, 0x01fd, -- 0x01ff, 0x01ff, -- 0x0201, 0x0201, -- 0x0203, 0x0203, -- 0x0205, 0x0205, -- 0x0207, 0x0207, -- 0x0209, 0x0209, -- 0x020b, 0x020b, -- 0x020d, 0x020d, -- 0x020f, 0x020f, -- 0x0211, 0x0211, -- 0x0213, 0x0213, -- 0x0215, 0x0215, -- 0x0217, 0x0217, -- 0x0219, 0x0219, -- 0x021b, 0x021b, -- 0x021d, 0x021d, -- 0x021f, 0x021f, -- 0x0221, 0x0221, -- 0x0223, 0x0223, -- 0x0225, 0x0225, -- 0x0227, 0x0227, -- 0x0229, 0x0229, -- 0x022b, 0x022b, -- 0x022d, 0x022d, -- 0x022f, 0x022f, -- 0x0231, 0x0231, -- 0x0233, 0x0239, -- 0x023c, 0x023c, -- 0x023f, 0x0240, -- 0x0242, 0x0242, -- 0x0247, 0x0247, -- 0x0249, 0x0249, -- 0x024b, 0x024b, -- 0x024d, 0x024d, -- 0x024f, 0x0293, -- 0x0295, 0x02b8, -- 0x02c0, 0x02c1, -- 0x02e0, 0x02e4, -- 0x0345, 0x0345, -- 0x0371, 0x0371, -- 0x0373, 0x0373, -- 0x0377, 0x0377, -- 0x037a, 0x037d, -- 0x0390, 0x0390, -- 0x03ac, 0x03ce, -- 0x03d0, 0x03d1, -- 0x03d5, 0x03d7, -- 0x03d9, 0x03d9, -- 0x03db, 0x03db, -- 0x03dd, 0x03dd, -- 0x03df, 0x03df, -- 0x03e1, 0x03e1, -- 0x03e3, 0x03e3, -- 0x03e5, 0x03e5, -- 0x03e7, 0x03e7, -- 0x03e9, 0x03e9, -- 0x03eb, 0x03eb, -- 0x03ed, 0x03ed, -- 0x03ef, 0x03f3, -- 0x03f5, 0x03f5, -- 0x03f8, 0x03f8, -- 0x03fb, 0x03fc, -- 0x0430, 0x045f, -- 0x0461, 0x0461, -- 0x0463, 0x0463, -- 0x0465, 0x0465, -- 0x0467, 0x0467, -- 0x0469, 0x0469, -- 0x046b, 0x046b, -- 0x046d, 0x046d, -- 0x046f, 0x046f, -- 0x0471, 0x0471, -- 0x0473, 0x0473, -- 0x0475, 0x0475, -- 0x0477, 0x0477, -- 0x0479, 0x0479, -- 0x047b, 0x047b, -- 0x047d, 0x047d, -- 0x047f, 0x047f, -- 0x0481, 0x0481, -- 0x048b, 0x048b, -- 0x048d, 0x048d, -- 0x048f, 0x048f, -- 0x0491, 0x0491, -- 0x0493, 0x0493, -- 0x0495, 0x0495, -- 0x0497, 0x0497, -- 0x0499, 0x0499, -- 0x049b, 0x049b, -- 0x049d, 0x049d, -- 0x049f, 0x049f, -- 0x04a1, 0x04a1, -- 0x04a3, 0x04a3, -- 0x04a5, 0x04a5, -- 0x04a7, 0x04a7, -- 0x04a9, 0x04a9, -- 0x04ab, 0x04ab, -- 0x04ad, 0x04ad, -- 0x04af, 0x04af, -- 0x04b1, 0x04b1, -- 0x04b3, 0x04b3, -- 0x04b5, 0x04b5, -- 0x04b7, 0x04b7, -- 0x04b9, 0x04b9, -- 0x04bb, 0x04bb, -- 0x04bd, 0x04bd, -- 0x04bf, 0x04bf, -- 0x04c2, 0x04c2, -- 0x04c4, 0x04c4, -- 0x04c6, 0x04c6, -- 0x04c8, 0x04c8, -- 0x04ca, 0x04ca, -- 0x04cc, 0x04cc, -- 0x04ce, 0x04cf, -- 0x04d1, 0x04d1, -- 0x04d3, 0x04d3, -- 0x04d5, 0x04d5, -- 0x04d7, 0x04d7, -- 0x04d9, 0x04d9, -- 0x04db, 0x04db, -- 0x04dd, 0x04dd, -- 0x04df, 0x04df, -- 0x04e1, 0x04e1, -- 0x04e3, 0x04e3, -- 0x04e5, 0x04e5, -- 0x04e7, 0x04e7, -- 0x04e9, 0x04e9, -- 0x04eb, 0x04eb, -- 0x04ed, 0x04ed, -- 0x04ef, 0x04ef, -- 0x04f1, 0x04f1, -- 0x04f3, 0x04f3, -- 0x04f5, 0x04f5, -- 0x04f7, 0x04f7, -- 0x04f9, 0x04f9, -- 0x04fb, 0x04fb, -- 0x04fd, 0x04fd, -- 0x04ff, 0x04ff, -- 0x0501, 0x0501, -- 0x0503, 0x0503, -- 0x0505, 0x0505, -- 0x0507, 0x0507, -- 0x0509, 0x0509, -- 0x050b, 0x050b, -- 0x050d, 0x050d, -- 0x050f, 0x050f, -- 0x0511, 0x0511, -- 0x0513, 0x0513, -- 0x0515, 0x0515, -- 0x0517, 0x0517, -- 0x0519, 0x0519, -- 0x051b, 0x051b, -- 0x051d, 0x051d, -- 0x051f, 0x051f, -- 0x0521, 0x0521, -- 0x0523, 0x0523, -- 0x0525, 0x0525, -- 0x0527, 0x0527, -- 0x0561, 0x0587, -- 0x1d00, 0x1dbf, -- 0x1e01, 0x1e01, -- 0x1e03, 0x1e03, -- 0x1e05, 0x1e05, -- 0x1e07, 0x1e07, -- 0x1e09, 0x1e09, -- 0x1e0b, 0x1e0b, -- 0x1e0d, 0x1e0d, -- 0x1e0f, 0x1e0f, -- 0x1e11, 0x1e11, -- 0x1e13, 0x1e13, -- 0x1e15, 0x1e15, -- 0x1e17, 0x1e17, -- 0x1e19, 0x1e19, -- 0x1e1b, 0x1e1b, -- 0x1e1d, 0x1e1d, -- 0x1e1f, 0x1e1f, -- 0x1e21, 0x1e21, -- 0x1e23, 0x1e23, -- 0x1e25, 0x1e25, -- 0x1e27, 0x1e27, -- 0x1e29, 0x1e29, -- 0x1e2b, 0x1e2b, -- 0x1e2d, 0x1e2d, -- 0x1e2f, 0x1e2f, -- 0x1e31, 0x1e31, -- 0x1e33, 0x1e33, -- 0x1e35, 0x1e35, -- 0x1e37, 0x1e37, -- 0x1e39, 0x1e39, -- 0x1e3b, 0x1e3b, -- 0x1e3d, 0x1e3d, -- 0x1e3f, 0x1e3f, -- 0x1e41, 0x1e41, -- 0x1e43, 0x1e43, -- 0x1e45, 0x1e45, -- 0x1e47, 0x1e47, -- 0x1e49, 0x1e49, -- 0x1e4b, 0x1e4b, -- 0x1e4d, 0x1e4d, -- 0x1e4f, 0x1e4f, -- 0x1e51, 0x1e51, -- 0x1e53, 0x1e53, -- 0x1e55, 0x1e55, -- 0x1e57, 0x1e57, -- 0x1e59, 0x1e59, -- 0x1e5b, 0x1e5b, -- 0x1e5d, 0x1e5d, -- 0x1e5f, 0x1e5f, -- 0x1e61, 0x1e61, -- 0x1e63, 0x1e63, -- 0x1e65, 0x1e65, -- 0x1e67, 0x1e67, -- 0x1e69, 0x1e69, -- 0x1e6b, 0x1e6b, -- 0x1e6d, 0x1e6d, -- 0x1e6f, 0x1e6f, -- 0x1e71, 0x1e71, -- 0x1e73, 0x1e73, -- 0x1e75, 0x1e75, -- 0x1e77, 0x1e77, -- 0x1e79, 0x1e79, -- 0x1e7b, 0x1e7b, -- 0x1e7d, 0x1e7d, -- 0x1e7f, 0x1e7f, -- 0x1e81, 0x1e81, -- 0x1e83, 0x1e83, -- 0x1e85, 0x1e85, -- 0x1e87, 0x1e87, -- 0x1e89, 0x1e89, -- 0x1e8b, 0x1e8b, -- 0x1e8d, 0x1e8d, -- 0x1e8f, 0x1e8f, -- 0x1e91, 0x1e91, -- 0x1e93, 0x1e93, -- 0x1e95, 0x1e9d, -- 0x1e9f, 0x1e9f, -- 0x1ea1, 0x1ea1, -- 0x1ea3, 0x1ea3, -- 0x1ea5, 0x1ea5, -- 0x1ea7, 0x1ea7, -- 0x1ea9, 0x1ea9, -- 0x1eab, 0x1eab, -- 0x1ead, 0x1ead, -- 0x1eaf, 0x1eaf, -- 0x1eb1, 0x1eb1, -- 0x1eb3, 0x1eb3, -- 0x1eb5, 0x1eb5, -- 0x1eb7, 0x1eb7, -- 0x1eb9, 0x1eb9, -- 0x1ebb, 0x1ebb, -- 0x1ebd, 0x1ebd, -- 0x1ebf, 0x1ebf, -- 0x1ec1, 0x1ec1, -- 0x1ec3, 0x1ec3, -- 0x1ec5, 0x1ec5, -- 0x1ec7, 0x1ec7, -- 0x1ec9, 0x1ec9, -- 0x1ecb, 0x1ecb, -- 0x1ecd, 0x1ecd, -- 0x1ecf, 0x1ecf, -- 0x1ed1, 0x1ed1, -- 0x1ed3, 0x1ed3, -- 0x1ed5, 0x1ed5, -- 0x1ed7, 0x1ed7, -- 0x1ed9, 0x1ed9, -- 0x1edb, 0x1edb, -- 0x1edd, 0x1edd, -- 0x1edf, 0x1edf, -- 0x1ee1, 0x1ee1, -- 0x1ee3, 0x1ee3, -- 0x1ee5, 0x1ee5, -- 0x1ee7, 0x1ee7, -- 0x1ee9, 0x1ee9, -- 0x1eeb, 0x1eeb, -- 0x1eed, 0x1eed, -- 0x1eef, 0x1eef, -- 0x1ef1, 0x1ef1, -- 0x1ef3, 0x1ef3, -- 0x1ef5, 0x1ef5, -- 0x1ef7, 0x1ef7, -- 0x1ef9, 0x1ef9, -- 0x1efb, 0x1efb, -- 0x1efd, 0x1efd, -- 0x1eff, 0x1f07, -- 0x1f10, 0x1f15, -- 0x1f20, 0x1f27, -- 0x1f30, 0x1f37, -- 0x1f40, 0x1f45, -- 0x1f50, 0x1f57, -- 0x1f60, 0x1f67, -- 0x1f70, 0x1f7d, -- 0x1f80, 0x1f87, -- 0x1f90, 0x1f97, -- 0x1fa0, 0x1fa7, -- 0x1fb0, 0x1fb4, -- 0x1fb6, 0x1fb7, -- 0x1fbe, 0x1fbe, -- 0x1fc2, 0x1fc4, -- 0x1fc6, 0x1fc7, -- 0x1fd0, 0x1fd3, -- 0x1fd6, 0x1fd7, -- 0x1fe0, 0x1fe7, -- 0x1ff2, 0x1ff4, -- 0x1ff6, 0x1ff7, -- 0x2090, 0x2094, -- 0x210a, 0x210a, -- 0x210e, 0x210f, -- 0x2113, 0x2113, -- 0x212f, 0x212f, -- 0x2134, 0x2134, -- 0x2139, 0x2139, -- 0x213c, 0x213d, -- 0x2146, 0x2149, -- 0x214e, 0x214e, -- 0x2170, 0x217f, -- 0x2184, 0x2184, -- 0x24d0, 0x24e9, -- 0x2c30, 0x2c5e, -- 0x2c61, 0x2c61, -- 0x2c65, 0x2c66, -- 0x2c68, 0x2c68, -- 0x2c6a, 0x2c6a, -- 0x2c6c, 0x2c6c, -- 0x2c71, 0x2c71, -- 0x2c73, 0x2c74, -- 0x2c76, 0x2c7d, -- 0x2c81, 0x2c81, -- 0x2c83, 0x2c83, -- 0x2c85, 0x2c85, -- 0x2c87, 0x2c87, -- 0x2c89, 0x2c89, -- 0x2c8b, 0x2c8b, -- 0x2c8d, 0x2c8d, -- 0x2c8f, 0x2c8f, -- 0x2c91, 0x2c91, -- 0x2c93, 0x2c93, -- 0x2c95, 0x2c95, -- 0x2c97, 0x2c97, -- 0x2c99, 0x2c99, -- 0x2c9b, 0x2c9b, -- 0x2c9d, 0x2c9d, -- 0x2c9f, 0x2c9f, -- 0x2ca1, 0x2ca1, -- 0x2ca3, 0x2ca3, -- 0x2ca5, 0x2ca5, -- 0x2ca7, 0x2ca7, -- 0x2ca9, 0x2ca9, -- 0x2cab, 0x2cab, -- 0x2cad, 0x2cad, -- 0x2caf, 0x2caf, -- 0x2cb1, 0x2cb1, -- 0x2cb3, 0x2cb3, -- 0x2cb5, 0x2cb5, -- 0x2cb7, 0x2cb7, -- 0x2cb9, 0x2cb9, -- 0x2cbb, 0x2cbb, -- 0x2cbd, 0x2cbd, -- 0x2cbf, 0x2cbf, -- 0x2cc1, 0x2cc1, -- 0x2cc3, 0x2cc3, -- 0x2cc5, 0x2cc5, -- 0x2cc7, 0x2cc7, -- 0x2cc9, 0x2cc9, -- 0x2ccb, 0x2ccb, -- 0x2ccd, 0x2ccd, -- 0x2ccf, 0x2ccf, -- 0x2cd1, 0x2cd1, -- 0x2cd3, 0x2cd3, -- 0x2cd5, 0x2cd5, -- 0x2cd7, 0x2cd7, -- 0x2cd9, 0x2cd9, -- 0x2cdb, 0x2cdb, -- 0x2cdd, 0x2cdd, -- 0x2cdf, 0x2cdf, -- 0x2ce1, 0x2ce1, -- 0x2ce3, 0x2ce4, -- 0x2cec, 0x2cec, -- 0x2cee, 0x2cee, -- 0x2d00, 0x2d25, -- 0xa641, 0xa641, -- 0xa643, 0xa643, -- 0xa645, 0xa645, -- 0xa647, 0xa647, -- 0xa649, 0xa649, -- 0xa64b, 0xa64b, -- 0xa64d, 0xa64d, -- 0xa64f, 0xa64f, -- 0xa651, 0xa651, -- 0xa653, 0xa653, -- 0xa655, 0xa655, -- 0xa657, 0xa657, -- 0xa659, 0xa659, -- 0xa65b, 0xa65b, -- 0xa65d, 0xa65d, -- 0xa65f, 0xa65f, -- 0xa661, 0xa661, -- 0xa663, 0xa663, -- 0xa665, 0xa665, -- 0xa667, 0xa667, -- 0xa669, 0xa669, -- 0xa66b, 0xa66b, -- 0xa66d, 0xa66d, -- 0xa681, 0xa681, -- 0xa683, 0xa683, -- 0xa685, 0xa685, -- 0xa687, 0xa687, -- 0xa689, 0xa689, -- 0xa68b, 0xa68b, -- 0xa68d, 0xa68d, -- 0xa68f, 0xa68f, -- 0xa691, 0xa691, -- 0xa693, 0xa693, -- 0xa695, 0xa695, -- 0xa697, 0xa697, -- 0xa723, 0xa723, -- 0xa725, 0xa725, -- 0xa727, 0xa727, -- 0xa729, 0xa729, -- 0xa72b, 0xa72b, -- 0xa72d, 0xa72d, -- 0xa72f, 0xa731, -- 0xa733, 0xa733, -- 0xa735, 0xa735, -- 0xa737, 0xa737, -- 0xa739, 0xa739, -- 0xa73b, 0xa73b, -- 0xa73d, 0xa73d, -- 0xa73f, 0xa73f, -- 0xa741, 0xa741, -- 0xa743, 0xa743, -- 0xa745, 0xa745, -- 0xa747, 0xa747, -- 0xa749, 0xa749, -- 0xa74b, 0xa74b, -- 0xa74d, 0xa74d, -- 0xa74f, 0xa74f, -- 0xa751, 0xa751, -- 0xa753, 0xa753, -- 0xa755, 0xa755, -- 0xa757, 0xa757, -- 0xa759, 0xa759, -- 0xa75b, 0xa75b, -- 0xa75d, 0xa75d, -- 0xa75f, 0xa75f, -- 0xa761, 0xa761, -- 0xa763, 0xa763, -- 0xa765, 0xa765, -- 0xa767, 0xa767, -- 0xa769, 0xa769, -- 0xa76b, 0xa76b, -- 0xa76d, 0xa76d, -- 0xa76f, 0xa778, -- 0xa77a, 0xa77a, -- 0xa77c, 0xa77c, -- 0xa77f, 0xa77f, -- 0xa781, 0xa781, -- 0xa783, 0xa783, -- 0xa785, 0xa785, -- 0xa787, 0xa787, -- 0xa78c, 0xa78c, -- 0xa78e, 0xa78e, -- 0xa791, 0xa791, -- 0xa7a1, 0xa7a1, -- 0xa7a3, 0xa7a3, -- 0xa7a5, 0xa7a5, -- 0xa7a7, 0xa7a7, -- 0xa7a9, 0xa7a9, -- 0xa7fa, 0xa7fa, -- 0xfb00, 0xfb06, -- 0xfb13, 0xfb17, -- 0xff41, 0xff5a, -- 0x10428, 0x1044f, -- 0x1d41a, 0x1d433, -- 0x1d44e, 0x1d454, -- 0x1d456, 0x1d467, -- 0x1d482, 0x1d49b, -- 0x1d4b6, 0x1d4b9, -- 0x1d4bb, 0x1d4bb, -- 0x1d4bd, 0x1d4c3, -- 0x1d4c5, 0x1d4cf, -- 0x1d4ea, 0x1d503, -- 0x1d51e, 0x1d537, -- 0x1d552, 0x1d56b, -- 0x1d586, 0x1d59f, -- 0x1d5ba, 0x1d5d3, -- 0x1d5ee, 0x1d607, -- 0x1d622, 0x1d63b, -- 0x1d656, 0x1d66f, -- 0x1d68a, 0x1d6a5, -- 0x1d6c2, 0x1d6da, -- 0x1d6dc, 0x1d6e1, -- 0x1d6fc, 0x1d714, -- 0x1d716, 0x1d71b, -- 0x1d736, 0x1d74e, -- 0x1d750, 0x1d755, -- 0x1d770, 0x1d788, -- 0x1d78a, 0x1d78f, -- 0x1d7aa, 0x1d7c2, -- 0x1d7c4, 0x1d7c9, -- 0x1d7cb, 0x1d7cb, --}; /* CR_Lowercase */ -- --/* 'Uppercase': Derived Property */ --static const OnigCodePoint CR_Uppercase[] = { -- 605, -- 0x0041, 0x005a, -- 0x00c0, 0x00d6, -- 0x00d8, 0x00de, -- 0x0100, 0x0100, -- 0x0102, 0x0102, -- 0x0104, 0x0104, -- 0x0106, 0x0106, -- 0x0108, 0x0108, -- 0x010a, 0x010a, -- 0x010c, 0x010c, -- 0x010e, 0x010e, -- 0x0110, 0x0110, -- 0x0112, 0x0112, -- 0x0114, 0x0114, -- 0x0116, 0x0116, -- 0x0118, 0x0118, -- 0x011a, 0x011a, -- 0x011c, 0x011c, -- 0x011e, 0x011e, -- 0x0120, 0x0120, -- 0x0122, 0x0122, -- 0x0124, 0x0124, -- 0x0126, 0x0126, -- 0x0128, 0x0128, -- 0x012a, 0x012a, -- 0x012c, 0x012c, -- 0x012e, 0x012e, -- 0x0130, 0x0130, -- 0x0132, 0x0132, -- 0x0134, 0x0134, -- 0x0136, 0x0136, -- 0x0139, 0x0139, -- 0x013b, 0x013b, -- 0x013d, 0x013d, -- 0x013f, 0x013f, -- 0x0141, 0x0141, -- 0x0143, 0x0143, -- 0x0145, 0x0145, -- 0x0147, 0x0147, -- 0x014a, 0x014a, -- 0x014c, 0x014c, -- 0x014e, 0x014e, -- 0x0150, 0x0150, -- 0x0152, 0x0152, -- 0x0154, 0x0154, -- 0x0156, 0x0156, -- 0x0158, 0x0158, -- 0x015a, 0x015a, -- 0x015c, 0x015c, -- 0x015e, 0x015e, -- 0x0160, 0x0160, -- 0x0162, 0x0162, -- 0x0164, 0x0164, -- 0x0166, 0x0166, -- 0x0168, 0x0168, -- 0x016a, 0x016a, -- 0x016c, 0x016c, -- 0x016e, 0x016e, -- 0x0170, 0x0170, -- 0x0172, 0x0172, -- 0x0174, 0x0174, -- 0x0176, 0x0176, -- 0x0178, 0x0179, -- 0x017b, 0x017b, -- 0x017d, 0x017d, -- 0x0181, 0x0182, -- 0x0184, 0x0184, -- 0x0186, 0x0187, -- 0x0189, 0x018b, -- 0x018e, 0x0191, -- 0x0193, 0x0194, -- 0x0196, 0x0198, -- 0x019c, 0x019d, -- 0x019f, 0x01a0, -- 0x01a2, 0x01a2, -- 0x01a4, 0x01a4, -- 0x01a6, 0x01a7, -- 0x01a9, 0x01a9, -- 0x01ac, 0x01ac, -- 0x01ae, 0x01af, -- 0x01b1, 0x01b3, -- 0x01b5, 0x01b5, -- 0x01b7, 0x01b8, -- 0x01bc, 0x01bc, -- 0x01c4, 0x01c4, -- 0x01c7, 0x01c7, -- 0x01ca, 0x01ca, -- 0x01cd, 0x01cd, -- 0x01cf, 0x01cf, -- 0x01d1, 0x01d1, -- 0x01d3, 0x01d3, -- 0x01d5, 0x01d5, -- 0x01d7, 0x01d7, -- 0x01d9, 0x01d9, -- 0x01db, 0x01db, -- 0x01de, 0x01de, -- 0x01e0, 0x01e0, -- 0x01e2, 0x01e2, -- 0x01e4, 0x01e4, -- 0x01e6, 0x01e6, -- 0x01e8, 0x01e8, -- 0x01ea, 0x01ea, -- 0x01ec, 0x01ec, -- 0x01ee, 0x01ee, -- 0x01f1, 0x01f1, -- 0x01f4, 0x01f4, -- 0x01f6, 0x01f8, -- 0x01fa, 0x01fa, -- 0x01fc, 0x01fc, -- 0x01fe, 0x01fe, -- 0x0200, 0x0200, -- 0x0202, 0x0202, -- 0x0204, 0x0204, -- 0x0206, 0x0206, -- 0x0208, 0x0208, -- 0x020a, 0x020a, -- 0x020c, 0x020c, -- 0x020e, 0x020e, -- 0x0210, 0x0210, -- 0x0212, 0x0212, -- 0x0214, 0x0214, -- 0x0216, 0x0216, -- 0x0218, 0x0218, -- 0x021a, 0x021a, -- 0x021c, 0x021c, -- 0x021e, 0x021e, -- 0x0220, 0x0220, -- 0x0222, 0x0222, -- 0x0224, 0x0224, -- 0x0226, 0x0226, -- 0x0228, 0x0228, -- 0x022a, 0x022a, -- 0x022c, 0x022c, -- 0x022e, 0x022e, -- 0x0230, 0x0230, -- 0x0232, 0x0232, -- 0x023a, 0x023b, -- 0x023d, 0x023e, -- 0x0241, 0x0241, -- 0x0243, 0x0246, -- 0x0248, 0x0248, -- 0x024a, 0x024a, -- 0x024c, 0x024c, -- 0x024e, 0x024e, -- 0x0370, 0x0370, -- 0x0372, 0x0372, -- 0x0376, 0x0376, -- 0x0386, 0x0386, -- 0x0388, 0x038a, -- 0x038c, 0x038c, -- 0x038e, 0x038f, -- 0x0391, 0x03a1, -- 0x03a3, 0x03ab, -- 0x03cf, 0x03cf, -- 0x03d2, 0x03d4, -- 0x03d8, 0x03d8, -- 0x03da, 0x03da, -- 0x03dc, 0x03dc, -- 0x03de, 0x03de, -- 0x03e0, 0x03e0, -- 0x03e2, 0x03e2, -- 0x03e4, 0x03e4, -- 0x03e6, 0x03e6, -- 0x03e8, 0x03e8, -- 0x03ea, 0x03ea, -- 0x03ec, 0x03ec, -- 0x03ee, 0x03ee, -- 0x03f4, 0x03f4, -- 0x03f7, 0x03f7, -- 0x03f9, 0x03fa, -- 0x03fd, 0x042f, -- 0x0460, 0x0460, -- 0x0462, 0x0462, -- 0x0464, 0x0464, -- 0x0466, 0x0466, -- 0x0468, 0x0468, -- 0x046a, 0x046a, -- 0x046c, 0x046c, -- 0x046e, 0x046e, -- 0x0470, 0x0470, -- 0x0472, 0x0472, -- 0x0474, 0x0474, -- 0x0476, 0x0476, -- 0x0478, 0x0478, -- 0x047a, 0x047a, -- 0x047c, 0x047c, -- 0x047e, 0x047e, -- 0x0480, 0x0480, -- 0x048a, 0x048a, -- 0x048c, 0x048c, -- 0x048e, 0x048e, -- 0x0490, 0x0490, -- 0x0492, 0x0492, -- 0x0494, 0x0494, -- 0x0496, 0x0496, -- 0x0498, 0x0498, -- 0x049a, 0x049a, -- 0x049c, 0x049c, -- 0x049e, 0x049e, -- 0x04a0, 0x04a0, -- 0x04a2, 0x04a2, -- 0x04a4, 0x04a4, -- 0x04a6, 0x04a6, -- 0x04a8, 0x04a8, -- 0x04aa, 0x04aa, -- 0x04ac, 0x04ac, -- 0x04ae, 0x04ae, -- 0x04b0, 0x04b0, -- 0x04b2, 0x04b2, -- 0x04b4, 0x04b4, -- 0x04b6, 0x04b6, -- 0x04b8, 0x04b8, -- 0x04ba, 0x04ba, -- 0x04bc, 0x04bc, -- 0x04be, 0x04be, -- 0x04c0, 0x04c1, -- 0x04c3, 0x04c3, -- 0x04c5, 0x04c5, -- 0x04c7, 0x04c7, -- 0x04c9, 0x04c9, -- 0x04cb, 0x04cb, -- 0x04cd, 0x04cd, -- 0x04d0, 0x04d0, -- 0x04d2, 0x04d2, -- 0x04d4, 0x04d4, -- 0x04d6, 0x04d6, -- 0x04d8, 0x04d8, -- 0x04da, 0x04da, -- 0x04dc, 0x04dc, -- 0x04de, 0x04de, -- 0x04e0, 0x04e0, -- 0x04e2, 0x04e2, -- 0x04e4, 0x04e4, -- 0x04e6, 0x04e6, -- 0x04e8, 0x04e8, -- 0x04ea, 0x04ea, -- 0x04ec, 0x04ec, -- 0x04ee, 0x04ee, -- 0x04f0, 0x04f0, -- 0x04f2, 0x04f2, -- 0x04f4, 0x04f4, -- 0x04f6, 0x04f6, -- 0x04f8, 0x04f8, -- 0x04fa, 0x04fa, -- 0x04fc, 0x04fc, -- 0x04fe, 0x04fe, -- 0x0500, 0x0500, -- 0x0502, 0x0502, -- 0x0504, 0x0504, -- 0x0506, 0x0506, -- 0x0508, 0x0508, -- 0x050a, 0x050a, -- 0x050c, 0x050c, -- 0x050e, 0x050e, -- 0x0510, 0x0510, -- 0x0512, 0x0512, -- 0x0514, 0x0514, -- 0x0516, 0x0516, -- 0x0518, 0x0518, -- 0x051a, 0x051a, -- 0x051c, 0x051c, -- 0x051e, 0x051e, -- 0x0520, 0x0520, -- 0x0522, 0x0522, -- 0x0524, 0x0524, -- 0x0526, 0x0526, -- 0x0531, 0x0556, -- 0x10a0, 0x10c5, -- 0x1e00, 0x1e00, -- 0x1e02, 0x1e02, -- 0x1e04, 0x1e04, -- 0x1e06, 0x1e06, -- 0x1e08, 0x1e08, -- 0x1e0a, 0x1e0a, -- 0x1e0c, 0x1e0c, -- 0x1e0e, 0x1e0e, -- 0x1e10, 0x1e10, -- 0x1e12, 0x1e12, -- 0x1e14, 0x1e14, -- 0x1e16, 0x1e16, -- 0x1e18, 0x1e18, -- 0x1e1a, 0x1e1a, -- 0x1e1c, 0x1e1c, -- 0x1e1e, 0x1e1e, -- 0x1e20, 0x1e20, -- 0x1e22, 0x1e22, -- 0x1e24, 0x1e24, -- 0x1e26, 0x1e26, -- 0x1e28, 0x1e28, -- 0x1e2a, 0x1e2a, -- 0x1e2c, 0x1e2c, -- 0x1e2e, 0x1e2e, -- 0x1e30, 0x1e30, -- 0x1e32, 0x1e32, -- 0x1e34, 0x1e34, -- 0x1e36, 0x1e36, -- 0x1e38, 0x1e38, -- 0x1e3a, 0x1e3a, -- 0x1e3c, 0x1e3c, -- 0x1e3e, 0x1e3e, -- 0x1e40, 0x1e40, -- 0x1e42, 0x1e42, -- 0x1e44, 0x1e44, -- 0x1e46, 0x1e46, -- 0x1e48, 0x1e48, -- 0x1e4a, 0x1e4a, -- 0x1e4c, 0x1e4c, -- 0x1e4e, 0x1e4e, -- 0x1e50, 0x1e50, -- 0x1e52, 0x1e52, -- 0x1e54, 0x1e54, -- 0x1e56, 0x1e56, -- 0x1e58, 0x1e58, -- 0x1e5a, 0x1e5a, -- 0x1e5c, 0x1e5c, -- 0x1e5e, 0x1e5e, -- 0x1e60, 0x1e60, -- 0x1e62, 0x1e62, -- 0x1e64, 0x1e64, -- 0x1e66, 0x1e66, -- 0x1e68, 0x1e68, -- 0x1e6a, 0x1e6a, -- 0x1e6c, 0x1e6c, -- 0x1e6e, 0x1e6e, -- 0x1e70, 0x1e70, -- 0x1e72, 0x1e72, -- 0x1e74, 0x1e74, -- 0x1e76, 0x1e76, -- 0x1e78, 0x1e78, -- 0x1e7a, 0x1e7a, -- 0x1e7c, 0x1e7c, -- 0x1e7e, 0x1e7e, -- 0x1e80, 0x1e80, -- 0x1e82, 0x1e82, -- 0x1e84, 0x1e84, -- 0x1e86, 0x1e86, -- 0x1e88, 0x1e88, -- 0x1e8a, 0x1e8a, -- 0x1e8c, 0x1e8c, -- 0x1e8e, 0x1e8e, -- 0x1e90, 0x1e90, -- 0x1e92, 0x1e92, -- 0x1e94, 0x1e94, -- 0x1e9e, 0x1e9e, -- 0x1ea0, 0x1ea0, -- 0x1ea2, 0x1ea2, -- 0x1ea4, 0x1ea4, -- 0x1ea6, 0x1ea6, -- 0x1ea8, 0x1ea8, -- 0x1eaa, 0x1eaa, -- 0x1eac, 0x1eac, -- 0x1eae, 0x1eae, -- 0x1eb0, 0x1eb0, -- 0x1eb2, 0x1eb2, -- 0x1eb4, 0x1eb4, -- 0x1eb6, 0x1eb6, -- 0x1eb8, 0x1eb8, -- 0x1eba, 0x1eba, -- 0x1ebc, 0x1ebc, -- 0x1ebe, 0x1ebe, -- 0x1ec0, 0x1ec0, -- 0x1ec2, 0x1ec2, -- 0x1ec4, 0x1ec4, -- 0x1ec6, 0x1ec6, -- 0x1ec8, 0x1ec8, -- 0x1eca, 0x1eca, -- 0x1ecc, 0x1ecc, -- 0x1ece, 0x1ece, -- 0x1ed0, 0x1ed0, -- 0x1ed2, 0x1ed2, -- 0x1ed4, 0x1ed4, -- 0x1ed6, 0x1ed6, -- 0x1ed8, 0x1ed8, -- 0x1eda, 0x1eda, -- 0x1edc, 0x1edc, -- 0x1ede, 0x1ede, -- 0x1ee0, 0x1ee0, -- 0x1ee2, 0x1ee2, -- 0x1ee4, 0x1ee4, -- 0x1ee6, 0x1ee6, -- 0x1ee8, 0x1ee8, -- 0x1eea, 0x1eea, -- 0x1eec, 0x1eec, -- 0x1eee, 0x1eee, -- 0x1ef0, 0x1ef0, -- 0x1ef2, 0x1ef2, -- 0x1ef4, 0x1ef4, -- 0x1ef6, 0x1ef6, -- 0x1ef8, 0x1ef8, -- 0x1efa, 0x1efa, -- 0x1efc, 0x1efc, -- 0x1efe, 0x1efe, -- 0x1f08, 0x1f0f, -- 0x1f18, 0x1f1d, -- 0x1f28, 0x1f2f, -- 0x1f38, 0x1f3f, -- 0x1f48, 0x1f4d, -- 0x1f59, 0x1f59, -- 0x1f5b, 0x1f5b, -- 0x1f5d, 0x1f5d, -- 0x1f5f, 0x1f5f, -- 0x1f68, 0x1f6f, -- 0x1fb8, 0x1fbb, -- 0x1fc8, 0x1fcb, -- 0x1fd8, 0x1fdb, -- 0x1fe8, 0x1fec, -- 0x1ff8, 0x1ffb, -- 0x2102, 0x2102, -- 0x2107, 0x2107, -- 0x210b, 0x210d, -- 0x2110, 0x2112, -- 0x2115, 0x2115, -- 0x2119, 0x211d, -- 0x2124, 0x2124, -- 0x2126, 0x2126, -- 0x2128, 0x2128, -- 0x212a, 0x212d, -- 0x2130, 0x2133, -- 0x213e, 0x213f, -- 0x2145, 0x2145, -- 0x2160, 0x216f, -- 0x2183, 0x2183, -- 0x24b6, 0x24cf, -- 0x2c00, 0x2c2e, -- 0x2c60, 0x2c60, -- 0x2c62, 0x2c64, -- 0x2c67, 0x2c67, -- 0x2c69, 0x2c69, -- 0x2c6b, 0x2c6b, -- 0x2c6d, 0x2c70, -- 0x2c72, 0x2c72, -- 0x2c75, 0x2c75, -- 0x2c7e, 0x2c80, -- 0x2c82, 0x2c82, -- 0x2c84, 0x2c84, -- 0x2c86, 0x2c86, -- 0x2c88, 0x2c88, -- 0x2c8a, 0x2c8a, -- 0x2c8c, 0x2c8c, -- 0x2c8e, 0x2c8e, -- 0x2c90, 0x2c90, -- 0x2c92, 0x2c92, -- 0x2c94, 0x2c94, -- 0x2c96, 0x2c96, -- 0x2c98, 0x2c98, -- 0x2c9a, 0x2c9a, -- 0x2c9c, 0x2c9c, -- 0x2c9e, 0x2c9e, -- 0x2ca0, 0x2ca0, -- 0x2ca2, 0x2ca2, -- 0x2ca4, 0x2ca4, -- 0x2ca6, 0x2ca6, -- 0x2ca8, 0x2ca8, -- 0x2caa, 0x2caa, -- 0x2cac, 0x2cac, -- 0x2cae, 0x2cae, -- 0x2cb0, 0x2cb0, -- 0x2cb2, 0x2cb2, -- 0x2cb4, 0x2cb4, -- 0x2cb6, 0x2cb6, -- 0x2cb8, 0x2cb8, -- 0x2cba, 0x2cba, -- 0x2cbc, 0x2cbc, -- 0x2cbe, 0x2cbe, -- 0x2cc0, 0x2cc0, -- 0x2cc2, 0x2cc2, -- 0x2cc4, 0x2cc4, -- 0x2cc6, 0x2cc6, -- 0x2cc8, 0x2cc8, -- 0x2cca, 0x2cca, -- 0x2ccc, 0x2ccc, -- 0x2cce, 0x2cce, -- 0x2cd0, 0x2cd0, -- 0x2cd2, 0x2cd2, -- 0x2cd4, 0x2cd4, -- 0x2cd6, 0x2cd6, -- 0x2cd8, 0x2cd8, -- 0x2cda, 0x2cda, -- 0x2cdc, 0x2cdc, -- 0x2cde, 0x2cde, -- 0x2ce0, 0x2ce0, -- 0x2ce2, 0x2ce2, -- 0x2ceb, 0x2ceb, -- 0x2ced, 0x2ced, -- 0xa640, 0xa640, -- 0xa642, 0xa642, -- 0xa644, 0xa644, -- 0xa646, 0xa646, -- 0xa648, 0xa648, -- 0xa64a, 0xa64a, -- 0xa64c, 0xa64c, -- 0xa64e, 0xa64e, -- 0xa650, 0xa650, -- 0xa652, 0xa652, -- 0xa654, 0xa654, -- 0xa656, 0xa656, -- 0xa658, 0xa658, -- 0xa65a, 0xa65a, -- 0xa65c, 0xa65c, -- 0xa65e, 0xa65e, -- 0xa660, 0xa660, -- 0xa662, 0xa662, -- 0xa664, 0xa664, -- 0xa666, 0xa666, -- 0xa668, 0xa668, -- 0xa66a, 0xa66a, -- 0xa66c, 0xa66c, -- 0xa680, 0xa680, -- 0xa682, 0xa682, -- 0xa684, 0xa684, -- 0xa686, 0xa686, -- 0xa688, 0xa688, -- 0xa68a, 0xa68a, -- 0xa68c, 0xa68c, -- 0xa68e, 0xa68e, -- 0xa690, 0xa690, -- 0xa692, 0xa692, -- 0xa694, 0xa694, -- 0xa696, 0xa696, -- 0xa722, 0xa722, -- 0xa724, 0xa724, -- 0xa726, 0xa726, -- 0xa728, 0xa728, -- 0xa72a, 0xa72a, -- 0xa72c, 0xa72c, -- 0xa72e, 0xa72e, -- 0xa732, 0xa732, -- 0xa734, 0xa734, -- 0xa736, 0xa736, -- 0xa738, 0xa738, -- 0xa73a, 0xa73a, -- 0xa73c, 0xa73c, -- 0xa73e, 0xa73e, -- 0xa740, 0xa740, -- 0xa742, 0xa742, -- 0xa744, 0xa744, -- 0xa746, 0xa746, -- 0xa748, 0xa748, -- 0xa74a, 0xa74a, -- 0xa74c, 0xa74c, -- 0xa74e, 0xa74e, -- 0xa750, 0xa750, -- 0xa752, 0xa752, -- 0xa754, 0xa754, -- 0xa756, 0xa756, -- 0xa758, 0xa758, -- 0xa75a, 0xa75a, -- 0xa75c, 0xa75c, -- 0xa75e, 0xa75e, -- 0xa760, 0xa760, -- 0xa762, 0xa762, -- 0xa764, 0xa764, -- 0xa766, 0xa766, -- 0xa768, 0xa768, -- 0xa76a, 0xa76a, -- 0xa76c, 0xa76c, -- 0xa76e, 0xa76e, -- 0xa779, 0xa779, -- 0xa77b, 0xa77b, -- 0xa77d, 0xa77e, -- 0xa780, 0xa780, -- 0xa782, 0xa782, -- 0xa784, 0xa784, -- 0xa786, 0xa786, -- 0xa78b, 0xa78b, -- 0xa78d, 0xa78d, -- 0xa790, 0xa790, -- 0xa7a0, 0xa7a0, -- 0xa7a2, 0xa7a2, -- 0xa7a4, 0xa7a4, -- 0xa7a6, 0xa7a6, -- 0xa7a8, 0xa7a8, -- 0xff21, 0xff3a, -- 0x10400, 0x10427, -- 0x1d400, 0x1d419, -- 0x1d434, 0x1d44d, -- 0x1d468, 0x1d481, -- 0x1d49c, 0x1d49c, -- 0x1d49e, 0x1d49f, -- 0x1d4a2, 0x1d4a2, -- 0x1d4a5, 0x1d4a6, -- 0x1d4a9, 0x1d4ac, -- 0x1d4ae, 0x1d4b5, -- 0x1d4d0, 0x1d4e9, -- 0x1d504, 0x1d505, -- 0x1d507, 0x1d50a, -- 0x1d50d, 0x1d514, -- 0x1d516, 0x1d51c, -- 0x1d538, 0x1d539, -- 0x1d53b, 0x1d53e, -- 0x1d540, 0x1d544, -- 0x1d546, 0x1d546, -- 0x1d54a, 0x1d550, -- 0x1d56c, 0x1d585, -- 0x1d5a0, 0x1d5b9, -- 0x1d5d4, 0x1d5ed, -- 0x1d608, 0x1d621, -- 0x1d63c, 0x1d655, -- 0x1d670, 0x1d689, -- 0x1d6a8, 0x1d6c0, -- 0x1d6e2, 0x1d6fa, -- 0x1d71c, 0x1d734, -- 0x1d756, 0x1d76e, -- 0x1d790, 0x1d7a8, -- 0x1d7ca, 0x1d7ca, --}; /* CR_Uppercase */ -- --/* 'Cased': Derived Property */ --static const OnigCodePoint CR_Cased[] = { -- 112, -- 0x0041, 0x005a, -- 0x0061, 0x007a, -- 0x00aa, 0x00aa, -- 0x00b5, 0x00b5, -- 0x00ba, 0x00ba, -- 0x00c0, 0x00d6, -- 0x00d8, 0x00f6, -- 0x00f8, 0x01ba, -- 0x01bc, 0x01bf, -- 0x01c4, 0x0293, -- 0x0295, 0x02b8, -- 0x02c0, 0x02c1, -- 0x02e0, 0x02e4, -- 0x0345, 0x0345, -- 0x0370, 0x0373, -- 0x0376, 0x0377, -- 0x037a, 0x037d, -- 0x0386, 0x0386, -- 0x0388, 0x038a, -- 0x038c, 0x038c, -- 0x038e, 0x03a1, -- 0x03a3, 0x03f5, -- 0x03f7, 0x0481, -- 0x048a, 0x0527, -- 0x0531, 0x0556, -- 0x0561, 0x0587, -- 0x10a0, 0x10c5, -- 0x1d00, 0x1dbf, -- 0x1e00, 0x1f15, -- 0x1f18, 0x1f1d, -- 0x1f20, 0x1f45, -- 0x1f48, 0x1f4d, -- 0x1f50, 0x1f57, -- 0x1f59, 0x1f59, -- 0x1f5b, 0x1f5b, -- 0x1f5d, 0x1f5d, -- 0x1f5f, 0x1f7d, -- 0x1f80, 0x1fb4, -- 0x1fb6, 0x1fbc, -- 0x1fbe, 0x1fbe, -- 0x1fc2, 0x1fc4, -- 0x1fc6, 0x1fcc, -- 0x1fd0, 0x1fd3, -- 0x1fd6, 0x1fdb, -- 0x1fe0, 0x1fec, -- 0x1ff2, 0x1ff4, -- 0x1ff6, 0x1ffc, -- 0x2090, 0x2094, -- 0x2102, 0x2102, -- 0x2107, 0x2107, -- 0x210a, 0x2113, -- 0x2115, 0x2115, -- 0x2119, 0x211d, -- 0x2124, 0x2124, -- 0x2126, 0x2126, -- 0x2128, 0x2128, -- 0x212a, 0x212d, -- 0x212f, 0x2134, -- 0x2139, 0x2139, -- 0x213c, 0x213f, -- 0x2145, 0x2149, -- 0x214e, 0x214e, -- 0x2160, 0x217f, -- 0x2183, 0x2184, -- 0x24b6, 0x24e9, -- 0x2c00, 0x2c2e, -- 0x2c30, 0x2c5e, -- 0x2c60, 0x2ce4, -- 0x2ceb, 0x2cee, -- 0x2d00, 0x2d25, -- 0xa640, 0xa66d, -- 0xa680, 0xa697, -- 0xa722, 0xa787, -- 0xa78b, 0xa78e, -- 0xa790, 0xa791, -- 0xa7a0, 0xa7a9, -- 0xa7fa, 0xa7fa, -- 0xfb00, 0xfb06, -- 0xfb13, 0xfb17, -- 0xff21, 0xff3a, -- 0xff41, 0xff5a, -- 0x10400, 0x1044f, -- 0x1d400, 0x1d454, -- 0x1d456, 0x1d49c, -- 0x1d49e, 0x1d49f, -- 0x1d4a2, 0x1d4a2, -- 0x1d4a5, 0x1d4a6, -- 0x1d4a9, 0x1d4ac, -- 0x1d4ae, 0x1d4b9, -- 0x1d4bb, 0x1d4bb, -- 0x1d4bd, 0x1d4c3, -- 0x1d4c5, 0x1d505, -- 0x1d507, 0x1d50a, -- 0x1d50d, 0x1d514, -- 0x1d516, 0x1d51c, -- 0x1d51e, 0x1d539, -- 0x1d53b, 0x1d53e, -- 0x1d540, 0x1d544, -- 0x1d546, 0x1d546, -- 0x1d54a, 0x1d550, -- 0x1d552, 0x1d6a5, -- 0x1d6a8, 0x1d6c0, -- 0x1d6c2, 0x1d6da, -- 0x1d6dc, 0x1d6fa, -- 0x1d6fc, 0x1d714, -- 0x1d716, 0x1d734, -- 0x1d736, 0x1d74e, -- 0x1d750, 0x1d76e, -- 0x1d770, 0x1d788, -- 0x1d78a, 0x1d7a8, -- 0x1d7aa, 0x1d7c2, -- 0x1d7c4, 0x1d7cb, --}; /* CR_Cased */ -- --/* 'Case_Ignorable': Derived Property */ --static const OnigCodePoint CR_Case_Ignorable[] = { -- 277, -- 0x0027, 0x0027, -- 0x002e, 0x002e, -- 0x003a, 0x003a, -- 0x005e, 0x005e, -- 0x0060, 0x0060, -- 0x00a8, 0x00a8, -- 0x00ad, 0x00ad, -- 0x00af, 0x00af, -- 0x00b4, 0x00b4, -- 0x00b7, 0x00b8, -- 0x02b0, 0x036f, -- 0x0374, 0x0375, -- 0x037a, 0x037a, -- 0x0384, 0x0385, -- 0x0387, 0x0387, -- 0x0483, 0x0489, -- 0x0559, 0x0559, -- 0x0591, 0x05bd, -- 0x05bf, 0x05bf, -- 0x05c1, 0x05c2, -- 0x05c4, 0x05c5, -- 0x05c7, 0x05c7, -- 0x05f4, 0x05f4, -- 0x0600, 0x0603, -- 0x0610, 0x061a, -- 0x0640, 0x0640, -- 0x064b, 0x065f, -- 0x0670, 0x0670, -- 0x06d6, 0x06dd, -- 0x06df, 0x06e8, -- 0x06ea, 0x06ed, -- 0x070f, 0x070f, -- 0x0711, 0x0711, -- 0x0730, 0x074a, -- 0x07a6, 0x07b0, -- 0x07eb, 0x07f5, -- 0x07fa, 0x07fa, -- 0x0816, 0x082d, -- 0x0859, 0x085b, -- 0x0900, 0x0902, -- 0x093a, 0x093a, -- 0x093c, 0x093c, -- 0x0941, 0x0948, -- 0x094d, 0x094d, -- 0x0951, 0x0957, -- 0x0962, 0x0963, -- 0x0971, 0x0971, -- 0x0981, 0x0981, -- 0x09bc, 0x09bc, -- 0x09c1, 0x09c4, -- 0x09cd, 0x09cd, -- 0x09e2, 0x09e3, -- 0x0a01, 0x0a02, -- 0x0a3c, 0x0a3c, -- 0x0a41, 0x0a42, -- 0x0a47, 0x0a48, -- 0x0a4b, 0x0a4d, -- 0x0a51, 0x0a51, -- 0x0a70, 0x0a71, -- 0x0a75, 0x0a75, -- 0x0a81, 0x0a82, -- 0x0abc, 0x0abc, -- 0x0ac1, 0x0ac5, -- 0x0ac7, 0x0ac8, -- 0x0acd, 0x0acd, -- 0x0ae2, 0x0ae3, -- 0x0b01, 0x0b01, -- 0x0b3c, 0x0b3c, -- 0x0b3f, 0x0b3f, -- 0x0b41, 0x0b44, -- 0x0b4d, 0x0b4d, -- 0x0b56, 0x0b56, -- 0x0b62, 0x0b63, -- 0x0b82, 0x0b82, -- 0x0bc0, 0x0bc0, -- 0x0bcd, 0x0bcd, -- 0x0c3e, 0x0c40, -- 0x0c46, 0x0c48, -- 0x0c4a, 0x0c4d, -- 0x0c55, 0x0c56, -- 0x0c62, 0x0c63, -- 0x0cbc, 0x0cbc, -- 0x0cbf, 0x0cbf, -- 0x0cc6, 0x0cc6, -- 0x0ccc, 0x0ccd, -- 0x0ce2, 0x0ce3, -- 0x0d41, 0x0d44, -- 0x0d4d, 0x0d4d, -- 0x0d62, 0x0d63, -- 0x0dca, 0x0dca, -- 0x0dd2, 0x0dd4, -- 0x0dd6, 0x0dd6, -- 0x0e31, 0x0e31, -- 0x0e34, 0x0e3a, -- 0x0e46, 0x0e4e, -- 0x0eb1, 0x0eb1, -- 0x0eb4, 0x0eb9, -- 0x0ebb, 0x0ebc, -- 0x0ec6, 0x0ec6, -- 0x0ec8, 0x0ecd, -- 0x0f18, 0x0f19, -- 0x0f35, 0x0f35, -- 0x0f37, 0x0f37, -- 0x0f39, 0x0f39, -- 0x0f71, 0x0f7e, -- 0x0f80, 0x0f84, -- 0x0f86, 0x0f87, -- 0x0f8d, 0x0f97, -- 0x0f99, 0x0fbc, -- 0x0fc6, 0x0fc6, -- 0x102d, 0x1030, -- 0x1032, 0x1037, -- 0x1039, 0x103a, -- 0x103d, 0x103e, -- 0x1058, 0x1059, -- 0x105e, 0x1060, -- 0x1071, 0x1074, -- 0x1082, 0x1082, -- 0x1085, 0x1086, -- 0x108d, 0x108d, -- 0x109d, 0x109d, -- 0x10fc, 0x10fc, -- 0x135d, 0x135f, -- 0x1712, 0x1714, -- 0x1732, 0x1734, -- 0x1752, 0x1753, -- 0x1772, 0x1773, -- 0x17b4, 0x17b5, -- 0x17b7, 0x17bd, -- 0x17c6, 0x17c6, -- 0x17c9, 0x17d3, -- 0x17d7, 0x17d7, -- 0x17dd, 0x17dd, -- 0x180b, 0x180d, -- 0x1843, 0x1843, -- 0x18a9, 0x18a9, -- 0x1920, 0x1922, -- 0x1927, 0x1928, -- 0x1932, 0x1932, -- 0x1939, 0x193b, -- 0x1a17, 0x1a18, -- 0x1a56, 0x1a56, -- 0x1a58, 0x1a5e, -- 0x1a60, 0x1a60, -- 0x1a62, 0x1a62, -- 0x1a65, 0x1a6c, -- 0x1a73, 0x1a7c, -- 0x1a7f, 0x1a7f, -- 0x1aa7, 0x1aa7, -- 0x1b00, 0x1b03, -- 0x1b34, 0x1b34, -- 0x1b36, 0x1b3a, -- 0x1b3c, 0x1b3c, -- 0x1b42, 0x1b42, -- 0x1b6b, 0x1b73, -- 0x1b80, 0x1b81, -- 0x1ba2, 0x1ba5, -- 0x1ba8, 0x1ba9, -- 0x1be6, 0x1be6, -- 0x1be8, 0x1be9, -- 0x1bed, 0x1bed, -- 0x1bef, 0x1bf1, -- 0x1c2c, 0x1c33, -- 0x1c36, 0x1c37, -- 0x1c78, 0x1c7d, -- 0x1cd0, 0x1cd2, -- 0x1cd4, 0x1ce0, -- 0x1ce2, 0x1ce8, -- 0x1ced, 0x1ced, -- 0x1d2c, 0x1d61, -- 0x1d78, 0x1d78, -- 0x1d9b, 0x1de6, -- 0x1dfc, 0x1dff, -- 0x1fbd, 0x1fbd, -- 0x1fbf, 0x1fc1, -- 0x1fcd, 0x1fcf, -- 0x1fdd, 0x1fdf, -- 0x1fed, 0x1fef, -- 0x1ffd, 0x1ffe, -- 0x200b, 0x200f, -- 0x2018, 0x2019, -- 0x2024, 0x2024, -- 0x2027, 0x2027, -- 0x202a, 0x202e, -- 0x2060, 0x2064, -- 0x206a, 0x206f, -- 0x2071, 0x2071, -- 0x207f, 0x207f, -- 0x2090, 0x209c, -- 0x20d0, 0x20f0, -- 0x2c7d, 0x2c7d, -- 0x2cef, 0x2cf1, -- 0x2d6f, 0x2d6f, -- 0x2d7f, 0x2d7f, -- 0x2de0, 0x2dff, -- 0x2e2f, 0x2e2f, -- 0x3005, 0x3005, -- 0x302a, 0x302f, -- 0x3031, 0x3035, -- 0x303b, 0x303b, -- 0x3099, 0x309e, -- 0x30fc, 0x30fe, -- 0xa015, 0xa015, -- 0xa4f8, 0xa4fd, -- 0xa60c, 0xa60c, -- 0xa66f, 0xa672, -- 0xa67c, 0xa67d, -- 0xa67f, 0xa67f, -- 0xa6f0, 0xa6f1, -- 0xa700, 0xa721, -- 0xa770, 0xa770, -- 0xa788, 0xa78a, -- 0xa802, 0xa802, -- 0xa806, 0xa806, -- 0xa80b, 0xa80b, -- 0xa825, 0xa826, -- 0xa8c4, 0xa8c4, -- 0xa8e0, 0xa8f1, -- 0xa926, 0xa92d, -- 0xa947, 0xa951, -- 0xa980, 0xa982, -- 0xa9b3, 0xa9b3, -- 0xa9b6, 0xa9b9, -- 0xa9bc, 0xa9bc, -- 0xa9cf, 0xa9cf, -- 0xaa29, 0xaa2e, -- 0xaa31, 0xaa32, -- 0xaa35, 0xaa36, -- 0xaa43, 0xaa43, -- 0xaa4c, 0xaa4c, -- 0xaa70, 0xaa70, -- 0xaab0, 0xaab0, -- 0xaab2, 0xaab4, -- 0xaab7, 0xaab8, -- 0xaabe, 0xaabf, -- 0xaac1, 0xaac1, -- 0xaadd, 0xaadd, -- 0xabe5, 0xabe5, -- 0xabe8, 0xabe8, -- 0xabed, 0xabed, -- 0xfb1e, 0xfb1e, -- 0xfbb2, 0xfbc1, -- 0xfe00, 0xfe0f, -- 0xfe13, 0xfe13, -- 0xfe20, 0xfe26, -- 0xfe52, 0xfe52, -- 0xfe55, 0xfe55, -- 0xfeff, 0xfeff, -- 0xff07, 0xff07, -- 0xff0e, 0xff0e, -- 0xff1a, 0xff1a, -- 0xff3e, 0xff3e, -- 0xff40, 0xff40, -- 0xff70, 0xff70, -- 0xff9e, 0xff9f, -- 0xffe3, 0xffe3, -- 0xfff9, 0xfffb, -- 0x101fd, 0x101fd, -- 0x10a01, 0x10a03, -- 0x10a05, 0x10a06, -- 0x10a0c, 0x10a0f, -- 0x10a38, 0x10a3a, -- 0x10a3f, 0x10a3f, -- 0x11001, 0x11001, -- 0x11038, 0x11046, -- 0x11080, 0x11081, -- 0x110b3, 0x110b6, -- 0x110b9, 0x110ba, -- 0x110bd, 0x110bd, -- 0x1d167, 0x1d169, -- 0x1d173, 0x1d182, -- 0x1d185, 0x1d18b, -- 0x1d1aa, 0x1d1ad, -- 0x1d242, 0x1d244, -- 0xe0001, 0xe0001, -- 0xe0020, 0xe007f, -- 0xe0100, 0xe01ef, --}; /* CR_Case_Ignorable */ -- --/* 'Changes_When_Lowercased': Derived Property */ --static const OnigCodePoint CR_Changes_When_Lowercased[] = { -- 566, -- 0x0041, 0x005a, -- 0x00c0, 0x00d6, -- 0x00d8, 0x00de, -- 0x0100, 0x0100, -- 0x0102, 0x0102, -- 0x0104, 0x0104, -- 0x0106, 0x0106, -- 0x0108, 0x0108, -- 0x010a, 0x010a, -- 0x010c, 0x010c, -- 0x010e, 0x010e, -- 0x0110, 0x0110, -- 0x0112, 0x0112, -- 0x0114, 0x0114, -- 0x0116, 0x0116, -- 0x0118, 0x0118, -- 0x011a, 0x011a, -- 0x011c, 0x011c, -- 0x011e, 0x011e, -- 0x0120, 0x0120, -- 0x0122, 0x0122, -- 0x0124, 0x0124, -- 0x0126, 0x0126, -- 0x0128, 0x0128, -- 0x012a, 0x012a, -- 0x012c, 0x012c, -- 0x012e, 0x012e, -- 0x0130, 0x0130, -- 0x0132, 0x0132, -- 0x0134, 0x0134, -- 0x0136, 0x0136, -- 0x0139, 0x0139, -- 0x013b, 0x013b, -- 0x013d, 0x013d, -- 0x013f, 0x013f, -- 0x0141, 0x0141, -- 0x0143, 0x0143, -- 0x0145, 0x0145, -- 0x0147, 0x0147, -- 0x014a, 0x014a, -- 0x014c, 0x014c, -- 0x014e, 0x014e, -- 0x0150, 0x0150, -- 0x0152, 0x0152, -- 0x0154, 0x0154, -- 0x0156, 0x0156, -- 0x0158, 0x0158, -- 0x015a, 0x015a, -- 0x015c, 0x015c, -- 0x015e, 0x015e, -- 0x0160, 0x0160, -- 0x0162, 0x0162, -- 0x0164, 0x0164, -- 0x0166, 0x0166, -- 0x0168, 0x0168, -- 0x016a, 0x016a, -- 0x016c, 0x016c, -- 0x016e, 0x016e, -- 0x0170, 0x0170, -- 0x0172, 0x0172, -- 0x0174, 0x0174, -- 0x0176, 0x0176, -- 0x0178, 0x0179, -- 0x017b, 0x017b, -- 0x017d, 0x017d, -- 0x0181, 0x0182, -- 0x0184, 0x0184, -- 0x0186, 0x0187, -- 0x0189, 0x018b, -- 0x018e, 0x0191, -- 0x0193, 0x0194, -- 0x0196, 0x0198, -- 0x019c, 0x019d, -- 0x019f, 0x01a0, -- 0x01a2, 0x01a2, -- 0x01a4, 0x01a4, -- 0x01a6, 0x01a7, -- 0x01a9, 0x01a9, -- 0x01ac, 0x01ac, -- 0x01ae, 0x01af, -- 0x01b1, 0x01b3, -- 0x01b5, 0x01b5, -- 0x01b7, 0x01b8, -- 0x01bc, 0x01bc, -- 0x01c4, 0x01c5, -- 0x01c7, 0x01c8, -- 0x01ca, 0x01cb, -- 0x01cd, 0x01cd, -- 0x01cf, 0x01cf, -- 0x01d1, 0x01d1, -- 0x01d3, 0x01d3, -- 0x01d5, 0x01d5, -- 0x01d7, 0x01d7, -- 0x01d9, 0x01d9, -- 0x01db, 0x01db, -- 0x01de, 0x01de, -- 0x01e0, 0x01e0, -- 0x01e2, 0x01e2, -- 0x01e4, 0x01e4, -- 0x01e6, 0x01e6, -- 0x01e8, 0x01e8, -- 0x01ea, 0x01ea, -- 0x01ec, 0x01ec, -- 0x01ee, 0x01ee, -- 0x01f1, 0x01f2, -- 0x01f4, 0x01f4, -- 0x01f6, 0x01f8, -- 0x01fa, 0x01fa, -- 0x01fc, 0x01fc, -- 0x01fe, 0x01fe, -- 0x0200, 0x0200, -- 0x0202, 0x0202, -- 0x0204, 0x0204, -- 0x0206, 0x0206, -- 0x0208, 0x0208, -- 0x020a, 0x020a, -- 0x020c, 0x020c, -- 0x020e, 0x020e, -- 0x0210, 0x0210, -- 0x0212, 0x0212, -- 0x0214, 0x0214, -- 0x0216, 0x0216, -- 0x0218, 0x0218, -- 0x021a, 0x021a, -- 0x021c, 0x021c, -- 0x021e, 0x021e, -- 0x0220, 0x0220, -- 0x0222, 0x0222, -- 0x0224, 0x0224, -- 0x0226, 0x0226, -- 0x0228, 0x0228, -- 0x022a, 0x022a, -- 0x022c, 0x022c, -- 0x022e, 0x022e, -- 0x0230, 0x0230, -- 0x0232, 0x0232, -- 0x023a, 0x023b, -- 0x023d, 0x023e, -- 0x0241, 0x0241, -- 0x0243, 0x0246, -- 0x0248, 0x0248, -- 0x024a, 0x024a, -- 0x024c, 0x024c, -- 0x024e, 0x024e, -- 0x0370, 0x0370, -- 0x0372, 0x0372, -- 0x0376, 0x0376, -- 0x0386, 0x0386, -- 0x0388, 0x038a, -- 0x038c, 0x038c, -- 0x038e, 0x038f, -- 0x0391, 0x03a1, -- 0x03a3, 0x03ab, -- 0x03cf, 0x03cf, -- 0x03d8, 0x03d8, -- 0x03da, 0x03da, -- 0x03dc, 0x03dc, -- 0x03de, 0x03de, -- 0x03e0, 0x03e0, -- 0x03e2, 0x03e2, -- 0x03e4, 0x03e4, -- 0x03e6, 0x03e6, -- 0x03e8, 0x03e8, -- 0x03ea, 0x03ea, -- 0x03ec, 0x03ec, -- 0x03ee, 0x03ee, -- 0x03f4, 0x03f4, -- 0x03f7, 0x03f7, -- 0x03f9, 0x03fa, -- 0x03fd, 0x042f, -- 0x0460, 0x0460, -- 0x0462, 0x0462, -- 0x0464, 0x0464, -- 0x0466, 0x0466, -- 0x0468, 0x0468, -- 0x046a, 0x046a, -- 0x046c, 0x046c, -- 0x046e, 0x046e, -- 0x0470, 0x0470, -- 0x0472, 0x0472, -- 0x0474, 0x0474, -- 0x0476, 0x0476, -- 0x0478, 0x0478, -- 0x047a, 0x047a, -- 0x047c, 0x047c, -- 0x047e, 0x047e, -- 0x0480, 0x0480, -- 0x048a, 0x048a, -- 0x048c, 0x048c, -- 0x048e, 0x048e, -- 0x0490, 0x0490, -- 0x0492, 0x0492, -- 0x0494, 0x0494, -- 0x0496, 0x0496, -- 0x0498, 0x0498, -- 0x049a, 0x049a, -- 0x049c, 0x049c, -- 0x049e, 0x049e, -- 0x04a0, 0x04a0, -- 0x04a2, 0x04a2, -- 0x04a4, 0x04a4, -- 0x04a6, 0x04a6, -- 0x04a8, 0x04a8, -- 0x04aa, 0x04aa, -- 0x04ac, 0x04ac, -- 0x04ae, 0x04ae, -- 0x04b0, 0x04b0, -- 0x04b2, 0x04b2, -- 0x04b4, 0x04b4, -- 0x04b6, 0x04b6, -- 0x04b8, 0x04b8, -- 0x04ba, 0x04ba, -- 0x04bc, 0x04bc, -- 0x04be, 0x04be, -- 0x04c0, 0x04c1, -- 0x04c3, 0x04c3, -- 0x04c5, 0x04c5, -- 0x04c7, 0x04c7, -- 0x04c9, 0x04c9, -- 0x04cb, 0x04cb, -- 0x04cd, 0x04cd, -- 0x04d0, 0x04d0, -- 0x04d2, 0x04d2, -- 0x04d4, 0x04d4, -- 0x04d6, 0x04d6, -- 0x04d8, 0x04d8, -- 0x04da, 0x04da, -- 0x04dc, 0x04dc, -- 0x04de, 0x04de, -- 0x04e0, 0x04e0, -- 0x04e2, 0x04e2, -- 0x04e4, 0x04e4, -- 0x04e6, 0x04e6, -- 0x04e8, 0x04e8, -- 0x04ea, 0x04ea, -- 0x04ec, 0x04ec, -- 0x04ee, 0x04ee, -- 0x04f0, 0x04f0, -- 0x04f2, 0x04f2, -- 0x04f4, 0x04f4, -- 0x04f6, 0x04f6, -- 0x04f8, 0x04f8, -- 0x04fa, 0x04fa, -- 0x04fc, 0x04fc, -- 0x04fe, 0x04fe, -- 0x0500, 0x0500, -- 0x0502, 0x0502, -- 0x0504, 0x0504, -- 0x0506, 0x0506, -- 0x0508, 0x0508, -- 0x050a, 0x050a, -- 0x050c, 0x050c, -- 0x050e, 0x050e, -- 0x0510, 0x0510, -- 0x0512, 0x0512, -- 0x0514, 0x0514, -- 0x0516, 0x0516, -- 0x0518, 0x0518, -- 0x051a, 0x051a, -- 0x051c, 0x051c, -- 0x051e, 0x051e, -- 0x0520, 0x0520, -- 0x0522, 0x0522, -- 0x0524, 0x0524, -- 0x0526, 0x0526, -- 0x0531, 0x0556, -- 0x10a0, 0x10c5, -- 0x1e00, 0x1e00, -- 0x1e02, 0x1e02, -- 0x1e04, 0x1e04, -- 0x1e06, 0x1e06, -- 0x1e08, 0x1e08, -- 0x1e0a, 0x1e0a, -- 0x1e0c, 0x1e0c, -- 0x1e0e, 0x1e0e, -- 0x1e10, 0x1e10, -- 0x1e12, 0x1e12, -- 0x1e14, 0x1e14, -- 0x1e16, 0x1e16, -- 0x1e18, 0x1e18, -- 0x1e1a, 0x1e1a, -- 0x1e1c, 0x1e1c, -- 0x1e1e, 0x1e1e, -- 0x1e20, 0x1e20, -- 0x1e22, 0x1e22, -- 0x1e24, 0x1e24, -- 0x1e26, 0x1e26, -- 0x1e28, 0x1e28, -- 0x1e2a, 0x1e2a, -- 0x1e2c, 0x1e2c, -- 0x1e2e, 0x1e2e, -- 0x1e30, 0x1e30, -- 0x1e32, 0x1e32, -- 0x1e34, 0x1e34, -- 0x1e36, 0x1e36, -- 0x1e38, 0x1e38, -- 0x1e3a, 0x1e3a, -- 0x1e3c, 0x1e3c, -- 0x1e3e, 0x1e3e, -- 0x1e40, 0x1e40, -- 0x1e42, 0x1e42, -- 0x1e44, 0x1e44, -- 0x1e46, 0x1e46, -- 0x1e48, 0x1e48, -- 0x1e4a, 0x1e4a, -- 0x1e4c, 0x1e4c, -- 0x1e4e, 0x1e4e, -- 0x1e50, 0x1e50, -- 0x1e52, 0x1e52, -- 0x1e54, 0x1e54, -- 0x1e56, 0x1e56, -- 0x1e58, 0x1e58, -- 0x1e5a, 0x1e5a, -- 0x1e5c, 0x1e5c, -- 0x1e5e, 0x1e5e, -- 0x1e60, 0x1e60, -- 0x1e62, 0x1e62, -- 0x1e64, 0x1e64, -- 0x1e66, 0x1e66, -- 0x1e68, 0x1e68, -- 0x1e6a, 0x1e6a, -- 0x1e6c, 0x1e6c, -- 0x1e6e, 0x1e6e, -- 0x1e70, 0x1e70, -- 0x1e72, 0x1e72, -- 0x1e74, 0x1e74, -- 0x1e76, 0x1e76, -- 0x1e78, 0x1e78, -- 0x1e7a, 0x1e7a, -- 0x1e7c, 0x1e7c, -- 0x1e7e, 0x1e7e, -- 0x1e80, 0x1e80, -- 0x1e82, 0x1e82, -- 0x1e84, 0x1e84, -- 0x1e86, 0x1e86, -- 0x1e88, 0x1e88, -- 0x1e8a, 0x1e8a, -- 0x1e8c, 0x1e8c, -- 0x1e8e, 0x1e8e, -- 0x1e90, 0x1e90, -- 0x1e92, 0x1e92, -- 0x1e94, 0x1e94, -- 0x1e9e, 0x1e9e, -- 0x1ea0, 0x1ea0, -- 0x1ea2, 0x1ea2, -- 0x1ea4, 0x1ea4, -- 0x1ea6, 0x1ea6, -- 0x1ea8, 0x1ea8, -- 0x1eaa, 0x1eaa, -- 0x1eac, 0x1eac, -- 0x1eae, 0x1eae, -- 0x1eb0, 0x1eb0, -- 0x1eb2, 0x1eb2, -- 0x1eb4, 0x1eb4, -- 0x1eb6, 0x1eb6, -- 0x1eb8, 0x1eb8, -- 0x1eba, 0x1eba, -- 0x1ebc, 0x1ebc, -- 0x1ebe, 0x1ebe, -- 0x1ec0, 0x1ec0, -- 0x1ec2, 0x1ec2, -- 0x1ec4, 0x1ec4, -- 0x1ec6, 0x1ec6, -- 0x1ec8, 0x1ec8, -- 0x1eca, 0x1eca, -- 0x1ecc, 0x1ecc, -- 0x1ece, 0x1ece, -- 0x1ed0, 0x1ed0, -- 0x1ed2, 0x1ed2, -- 0x1ed4, 0x1ed4, -- 0x1ed6, 0x1ed6, -- 0x1ed8, 0x1ed8, -- 0x1eda, 0x1eda, -- 0x1edc, 0x1edc, -- 0x1ede, 0x1ede, -- 0x1ee0, 0x1ee0, -- 0x1ee2, 0x1ee2, -- 0x1ee4, 0x1ee4, -- 0x1ee6, 0x1ee6, -- 0x1ee8, 0x1ee8, -- 0x1eea, 0x1eea, -- 0x1eec, 0x1eec, -- 0x1eee, 0x1eee, -- 0x1ef0, 0x1ef0, -- 0x1ef2, 0x1ef2, -- 0x1ef4, 0x1ef4, -- 0x1ef6, 0x1ef6, -- 0x1ef8, 0x1ef8, -- 0x1efa, 0x1efa, -- 0x1efc, 0x1efc, -- 0x1efe, 0x1efe, -- 0x1f08, 0x1f0f, -- 0x1f18, 0x1f1d, -- 0x1f28, 0x1f2f, -- 0x1f38, 0x1f3f, -- 0x1f48, 0x1f4d, -- 0x1f59, 0x1f59, -- 0x1f5b, 0x1f5b, -- 0x1f5d, 0x1f5d, -- 0x1f5f, 0x1f5f, -- 0x1f68, 0x1f6f, -- 0x1f88, 0x1f8f, -- 0x1f98, 0x1f9f, -- 0x1fa8, 0x1faf, -- 0x1fb8, 0x1fbc, -- 0x1fc8, 0x1fcc, -- 0x1fd8, 0x1fdb, -- 0x1fe8, 0x1fec, -- 0x1ff8, 0x1ffc, -- 0x2126, 0x2126, -- 0x212a, 0x212b, -- 0x2132, 0x2132, -- 0x2160, 0x216f, -- 0x2183, 0x2183, -- 0x24b6, 0x24cf, -- 0x2c00, 0x2c2e, -- 0x2c60, 0x2c60, -- 0x2c62, 0x2c64, -- 0x2c67, 0x2c67, -- 0x2c69, 0x2c69, -- 0x2c6b, 0x2c6b, -- 0x2c6d, 0x2c70, -- 0x2c72, 0x2c72, -- 0x2c75, 0x2c75, -- 0x2c7e, 0x2c80, -- 0x2c82, 0x2c82, -- 0x2c84, 0x2c84, -- 0x2c86, 0x2c86, -- 0x2c88, 0x2c88, -- 0x2c8a, 0x2c8a, -- 0x2c8c, 0x2c8c, -- 0x2c8e, 0x2c8e, -- 0x2c90, 0x2c90, -- 0x2c92, 0x2c92, -- 0x2c94, 0x2c94, -- 0x2c96, 0x2c96, -- 0x2c98, 0x2c98, -- 0x2c9a, 0x2c9a, -- 0x2c9c, 0x2c9c, -- 0x2c9e, 0x2c9e, -- 0x2ca0, 0x2ca0, -- 0x2ca2, 0x2ca2, -- 0x2ca4, 0x2ca4, -- 0x2ca6, 0x2ca6, -- 0x2ca8, 0x2ca8, -- 0x2caa, 0x2caa, -- 0x2cac, 0x2cac, -- 0x2cae, 0x2cae, -- 0x2cb0, 0x2cb0, -- 0x2cb2, 0x2cb2, -- 0x2cb4, 0x2cb4, -- 0x2cb6, 0x2cb6, -- 0x2cb8, 0x2cb8, -- 0x2cba, 0x2cba, -- 0x2cbc, 0x2cbc, -- 0x2cbe, 0x2cbe, -- 0x2cc0, 0x2cc0, -- 0x2cc2, 0x2cc2, -- 0x2cc4, 0x2cc4, -- 0x2cc6, 0x2cc6, -- 0x2cc8, 0x2cc8, -- 0x2cca, 0x2cca, -- 0x2ccc, 0x2ccc, -- 0x2cce, 0x2cce, -- 0x2cd0, 0x2cd0, -- 0x2cd2, 0x2cd2, -- 0x2cd4, 0x2cd4, -- 0x2cd6, 0x2cd6, -- 0x2cd8, 0x2cd8, -- 0x2cda, 0x2cda, -- 0x2cdc, 0x2cdc, -- 0x2cde, 0x2cde, -- 0x2ce0, 0x2ce0, -- 0x2ce2, 0x2ce2, -- 0x2ceb, 0x2ceb, -- 0x2ced, 0x2ced, -- 0xa640, 0xa640, -- 0xa642, 0xa642, -- 0xa644, 0xa644, -- 0xa646, 0xa646, -- 0xa648, 0xa648, -- 0xa64a, 0xa64a, -- 0xa64c, 0xa64c, -- 0xa64e, 0xa64e, -- 0xa650, 0xa650, -- 0xa652, 0xa652, -- 0xa654, 0xa654, -- 0xa656, 0xa656, -- 0xa658, 0xa658, -- 0xa65a, 0xa65a, -- 0xa65c, 0xa65c, -- 0xa65e, 0xa65e, -- 0xa660, 0xa660, -- 0xa662, 0xa662, -- 0xa664, 0xa664, -- 0xa666, 0xa666, -- 0xa668, 0xa668, -- 0xa66a, 0xa66a, -- 0xa66c, 0xa66c, -- 0xa680, 0xa680, -- 0xa682, 0xa682, -- 0xa684, 0xa684, -- 0xa686, 0xa686, -- 0xa688, 0xa688, -- 0xa68a, 0xa68a, -- 0xa68c, 0xa68c, -- 0xa68e, 0xa68e, -- 0xa690, 0xa690, -- 0xa692, 0xa692, -- 0xa694, 0xa694, -- 0xa696, 0xa696, -- 0xa722, 0xa722, -- 0xa724, 0xa724, -- 0xa726, 0xa726, -- 0xa728, 0xa728, -- 0xa72a, 0xa72a, -- 0xa72c, 0xa72c, -- 0xa72e, 0xa72e, -- 0xa732, 0xa732, -- 0xa734, 0xa734, -- 0xa736, 0xa736, -- 0xa738, 0xa738, -- 0xa73a, 0xa73a, -- 0xa73c, 0xa73c, -- 0xa73e, 0xa73e, -- 0xa740, 0xa740, -- 0xa742, 0xa742, -- 0xa744, 0xa744, -- 0xa746, 0xa746, -- 0xa748, 0xa748, -- 0xa74a, 0xa74a, -- 0xa74c, 0xa74c, -- 0xa74e, 0xa74e, -- 0xa750, 0xa750, -- 0xa752, 0xa752, -- 0xa754, 0xa754, -- 0xa756, 0xa756, -- 0xa758, 0xa758, -- 0xa75a, 0xa75a, -- 0xa75c, 0xa75c, -- 0xa75e, 0xa75e, -- 0xa760, 0xa760, -- 0xa762, 0xa762, -- 0xa764, 0xa764, -- 0xa766, 0xa766, -- 0xa768, 0xa768, -- 0xa76a, 0xa76a, -- 0xa76c, 0xa76c, -- 0xa76e, 0xa76e, -- 0xa779, 0xa779, -- 0xa77b, 0xa77b, -- 0xa77d, 0xa77e, -- 0xa780, 0xa780, -- 0xa782, 0xa782, -- 0xa784, 0xa784, -- 0xa786, 0xa786, -- 0xa78b, 0xa78b, -- 0xa78d, 0xa78d, -- 0xa790, 0xa790, -- 0xa7a0, 0xa7a0, -- 0xa7a2, 0xa7a2, -- 0xa7a4, 0xa7a4, -- 0xa7a6, 0xa7a6, -- 0xa7a8, 0xa7a8, -- 0xff21, 0xff3a, -- 0x10400, 0x10427, --}; /* CR_Changes_When_Lowercased */ -- --/* 'Changes_When_Uppercased': Derived Property */ --static const OnigCodePoint CR_Changes_When_Uppercased[] = { -- 582, -- 0x0061, 0x007a, -- 0x00b5, 0x00b5, -- 0x00df, 0x00f6, -- 0x00f8, 0x00ff, -- 0x0101, 0x0101, -- 0x0103, 0x0103, -- 0x0105, 0x0105, -- 0x0107, 0x0107, -- 0x0109, 0x0109, -- 0x010b, 0x010b, -- 0x010d, 0x010d, -- 0x010f, 0x010f, -- 0x0111, 0x0111, -- 0x0113, 0x0113, -- 0x0115, 0x0115, -- 0x0117, 0x0117, -- 0x0119, 0x0119, -- 0x011b, 0x011b, -- 0x011d, 0x011d, -- 0x011f, 0x011f, -- 0x0121, 0x0121, -- 0x0123, 0x0123, -- 0x0125, 0x0125, -- 0x0127, 0x0127, -- 0x0129, 0x0129, -- 0x012b, 0x012b, -- 0x012d, 0x012d, -- 0x012f, 0x012f, -- 0x0131, 0x0131, -- 0x0133, 0x0133, -- 0x0135, 0x0135, -- 0x0137, 0x0137, -- 0x013a, 0x013a, -- 0x013c, 0x013c, -- 0x013e, 0x013e, -- 0x0140, 0x0140, -- 0x0142, 0x0142, -- 0x0144, 0x0144, -- 0x0146, 0x0146, -- 0x0148, 0x0149, -- 0x014b, 0x014b, -- 0x014d, 0x014d, -- 0x014f, 0x014f, -- 0x0151, 0x0151, -- 0x0153, 0x0153, -- 0x0155, 0x0155, -- 0x0157, 0x0157, -- 0x0159, 0x0159, -- 0x015b, 0x015b, -- 0x015d, 0x015d, -- 0x015f, 0x015f, -- 0x0161, 0x0161, -- 0x0163, 0x0163, -- 0x0165, 0x0165, -- 0x0167, 0x0167, -- 0x0169, 0x0169, -- 0x016b, 0x016b, -- 0x016d, 0x016d, -- 0x016f, 0x016f, -- 0x0171, 0x0171, -- 0x0173, 0x0173, -- 0x0175, 0x0175, -- 0x0177, 0x0177, -- 0x017a, 0x017a, -- 0x017c, 0x017c, -- 0x017e, 0x0180, -- 0x0183, 0x0183, -- 0x0185, 0x0185, -- 0x0188, 0x0188, -- 0x018c, 0x018c, -- 0x0192, 0x0192, -- 0x0195, 0x0195, -- 0x0199, 0x019a, -- 0x019e, 0x019e, -- 0x01a1, 0x01a1, -- 0x01a3, 0x01a3, -- 0x01a5, 0x01a5, -- 0x01a8, 0x01a8, -- 0x01ad, 0x01ad, -- 0x01b0, 0x01b0, -- 0x01b4, 0x01b4, -- 0x01b6, 0x01b6, -- 0x01b9, 0x01b9, -- 0x01bd, 0x01bd, -- 0x01bf, 0x01bf, -- 0x01c5, 0x01c6, -- 0x01c8, 0x01c9, -- 0x01cb, 0x01cc, -- 0x01ce, 0x01ce, -- 0x01d0, 0x01d0, -- 0x01d2, 0x01d2, -- 0x01d4, 0x01d4, -- 0x01d6, 0x01d6, -- 0x01d8, 0x01d8, -- 0x01da, 0x01da, -- 0x01dc, 0x01dd, -- 0x01df, 0x01df, -- 0x01e1, 0x01e1, -- 0x01e3, 0x01e3, -- 0x01e5, 0x01e5, -- 0x01e7, 0x01e7, -- 0x01e9, 0x01e9, -- 0x01eb, 0x01eb, -- 0x01ed, 0x01ed, -- 0x01ef, 0x01f0, -- 0x01f2, 0x01f3, -- 0x01f5, 0x01f5, -- 0x01f9, 0x01f9, -- 0x01fb, 0x01fb, -- 0x01fd, 0x01fd, -- 0x01ff, 0x01ff, -- 0x0201, 0x0201, -- 0x0203, 0x0203, -- 0x0205, 0x0205, -- 0x0207, 0x0207, -- 0x0209, 0x0209, -- 0x020b, 0x020b, -- 0x020d, 0x020d, -- 0x020f, 0x020f, -- 0x0211, 0x0211, -- 0x0213, 0x0213, -- 0x0215, 0x0215, -- 0x0217, 0x0217, -- 0x0219, 0x0219, -- 0x021b, 0x021b, -- 0x021d, 0x021d, -- 0x021f, 0x021f, -- 0x0223, 0x0223, -- 0x0225, 0x0225, -- 0x0227, 0x0227, -- 0x0229, 0x0229, -- 0x022b, 0x022b, -- 0x022d, 0x022d, -- 0x022f, 0x022f, -- 0x0231, 0x0231, -- 0x0233, 0x0233, -- 0x023c, 0x023c, -- 0x023f, 0x0240, -- 0x0242, 0x0242, -- 0x0247, 0x0247, -- 0x0249, 0x0249, -- 0x024b, 0x024b, -- 0x024d, 0x024d, -- 0x024f, 0x0254, -- 0x0256, 0x0257, -- 0x0259, 0x0259, -- 0x025b, 0x025b, -- 0x0260, 0x0260, -- 0x0263, 0x0263, -- 0x0265, 0x0265, -- 0x0268, 0x0269, -- 0x026b, 0x026b, -- 0x026f, 0x026f, -- 0x0271, 0x0272, -- 0x0275, 0x0275, -- 0x027d, 0x027d, -- 0x0280, 0x0280, -- 0x0283, 0x0283, -- 0x0288, 0x028c, -- 0x0292, 0x0292, -- 0x0345, 0x0345, -- 0x0371, 0x0371, -- 0x0373, 0x0373, -- 0x0377, 0x0377, -- 0x037b, 0x037d, -- 0x0390, 0x0390, -- 0x03ac, 0x03ce, -- 0x03d0, 0x03d1, -- 0x03d5, 0x03d7, -- 0x03d9, 0x03d9, -- 0x03db, 0x03db, -- 0x03dd, 0x03dd, -- 0x03df, 0x03df, -- 0x03e1, 0x03e1, -- 0x03e3, 0x03e3, -- 0x03e5, 0x03e5, -- 0x03e7, 0x03e7, -- 0x03e9, 0x03e9, -- 0x03eb, 0x03eb, -- 0x03ed, 0x03ed, -- 0x03ef, 0x03f2, -- 0x03f5, 0x03f5, -- 0x03f8, 0x03f8, -- 0x03fb, 0x03fb, -- 0x0430, 0x045f, -- 0x0461, 0x0461, -- 0x0463, 0x0463, -- 0x0465, 0x0465, -- 0x0467, 0x0467, -- 0x0469, 0x0469, -- 0x046b, 0x046b, -- 0x046d, 0x046d, -- 0x046f, 0x046f, -- 0x0471, 0x0471, -- 0x0473, 0x0473, -- 0x0475, 0x0475, -- 0x0477, 0x0477, -- 0x0479, 0x0479, -- 0x047b, 0x047b, -- 0x047d, 0x047d, -- 0x047f, 0x047f, -- 0x0481, 0x0481, -- 0x048b, 0x048b, -- 0x048d, 0x048d, -- 0x048f, 0x048f, -- 0x0491, 0x0491, -- 0x0493, 0x0493, -- 0x0495, 0x0495, -- 0x0497, 0x0497, -- 0x0499, 0x0499, -- 0x049b, 0x049b, -- 0x049d, 0x049d, -- 0x049f, 0x049f, -- 0x04a1, 0x04a1, -- 0x04a3, 0x04a3, -- 0x04a5, 0x04a5, -- 0x04a7, 0x04a7, -- 0x04a9, 0x04a9, -- 0x04ab, 0x04ab, -- 0x04ad, 0x04ad, -- 0x04af, 0x04af, -- 0x04b1, 0x04b1, -- 0x04b3, 0x04b3, -- 0x04b5, 0x04b5, -- 0x04b7, 0x04b7, -- 0x04b9, 0x04b9, -- 0x04bb, 0x04bb, -- 0x04bd, 0x04bd, -- 0x04bf, 0x04bf, -- 0x04c2, 0x04c2, -- 0x04c4, 0x04c4, -- 0x04c6, 0x04c6, -- 0x04c8, 0x04c8, -- 0x04ca, 0x04ca, -- 0x04cc, 0x04cc, -- 0x04ce, 0x04cf, -- 0x04d1, 0x04d1, -- 0x04d3, 0x04d3, -- 0x04d5, 0x04d5, -- 0x04d7, 0x04d7, -- 0x04d9, 0x04d9, -- 0x04db, 0x04db, -- 0x04dd, 0x04dd, -- 0x04df, 0x04df, -- 0x04e1, 0x04e1, -- 0x04e3, 0x04e3, -- 0x04e5, 0x04e5, -- 0x04e7, 0x04e7, -- 0x04e9, 0x04e9, -- 0x04eb, 0x04eb, -- 0x04ed, 0x04ed, -- 0x04ef, 0x04ef, -- 0x04f1, 0x04f1, -- 0x04f3, 0x04f3, -- 0x04f5, 0x04f5, -- 0x04f7, 0x04f7, -- 0x04f9, 0x04f9, -- 0x04fb, 0x04fb, -- 0x04fd, 0x04fd, -- 0x04ff, 0x04ff, -- 0x0501, 0x0501, -- 0x0503, 0x0503, -- 0x0505, 0x0505, -- 0x0507, 0x0507, -- 0x0509, 0x0509, -- 0x050b, 0x050b, -- 0x050d, 0x050d, -- 0x050f, 0x050f, -- 0x0511, 0x0511, -- 0x0513, 0x0513, -- 0x0515, 0x0515, -- 0x0517, 0x0517, -- 0x0519, 0x0519, -- 0x051b, 0x051b, -- 0x051d, 0x051d, -- 0x051f, 0x051f, -- 0x0521, 0x0521, -- 0x0523, 0x0523, -- 0x0525, 0x0525, -- 0x0527, 0x0527, -- 0x0561, 0x0587, -- 0x1d79, 0x1d79, -- 0x1d7d, 0x1d7d, -- 0x1e01, 0x1e01, -- 0x1e03, 0x1e03, -- 0x1e05, 0x1e05, -- 0x1e07, 0x1e07, -- 0x1e09, 0x1e09, -- 0x1e0b, 0x1e0b, -- 0x1e0d, 0x1e0d, -- 0x1e0f, 0x1e0f, -- 0x1e11, 0x1e11, -- 0x1e13, 0x1e13, -- 0x1e15, 0x1e15, -- 0x1e17, 0x1e17, -- 0x1e19, 0x1e19, -- 0x1e1b, 0x1e1b, -- 0x1e1d, 0x1e1d, -- 0x1e1f, 0x1e1f, -- 0x1e21, 0x1e21, -- 0x1e23, 0x1e23, -- 0x1e25, 0x1e25, -- 0x1e27, 0x1e27, -- 0x1e29, 0x1e29, -- 0x1e2b, 0x1e2b, -- 0x1e2d, 0x1e2d, -- 0x1e2f, 0x1e2f, -- 0x1e31, 0x1e31, -- 0x1e33, 0x1e33, -- 0x1e35, 0x1e35, -- 0x1e37, 0x1e37, -- 0x1e39, 0x1e39, -- 0x1e3b, 0x1e3b, -- 0x1e3d, 0x1e3d, -- 0x1e3f, 0x1e3f, -- 0x1e41, 0x1e41, -- 0x1e43, 0x1e43, -- 0x1e45, 0x1e45, -- 0x1e47, 0x1e47, -- 0x1e49, 0x1e49, -- 0x1e4b, 0x1e4b, -- 0x1e4d, 0x1e4d, -- 0x1e4f, 0x1e4f, -- 0x1e51, 0x1e51, -- 0x1e53, 0x1e53, -- 0x1e55, 0x1e55, -- 0x1e57, 0x1e57, -- 0x1e59, 0x1e59, -- 0x1e5b, 0x1e5b, -- 0x1e5d, 0x1e5d, -- 0x1e5f, 0x1e5f, -- 0x1e61, 0x1e61, -- 0x1e63, 0x1e63, -- 0x1e65, 0x1e65, -- 0x1e67, 0x1e67, -- 0x1e69, 0x1e69, -- 0x1e6b, 0x1e6b, -- 0x1e6d, 0x1e6d, -- 0x1e6f, 0x1e6f, -- 0x1e71, 0x1e71, -- 0x1e73, 0x1e73, -- 0x1e75, 0x1e75, -- 0x1e77, 0x1e77, -- 0x1e79, 0x1e79, -- 0x1e7b, 0x1e7b, -- 0x1e7d, 0x1e7d, -- 0x1e7f, 0x1e7f, -- 0x1e81, 0x1e81, -- 0x1e83, 0x1e83, -- 0x1e85, 0x1e85, -- 0x1e87, 0x1e87, -- 0x1e89, 0x1e89, -- 0x1e8b, 0x1e8b, -- 0x1e8d, 0x1e8d, -- 0x1e8f, 0x1e8f, -- 0x1e91, 0x1e91, -- 0x1e93, 0x1e93, -- 0x1e95, 0x1e9b, -- 0x1ea1, 0x1ea1, -- 0x1ea3, 0x1ea3, -- 0x1ea5, 0x1ea5, -- 0x1ea7, 0x1ea7, -- 0x1ea9, 0x1ea9, -- 0x1eab, 0x1eab, -- 0x1ead, 0x1ead, -- 0x1eaf, 0x1eaf, -- 0x1eb1, 0x1eb1, -- 0x1eb3, 0x1eb3, -- 0x1eb5, 0x1eb5, -- 0x1eb7, 0x1eb7, -- 0x1eb9, 0x1eb9, -- 0x1ebb, 0x1ebb, -- 0x1ebd, 0x1ebd, -- 0x1ebf, 0x1ebf, -- 0x1ec1, 0x1ec1, -- 0x1ec3, 0x1ec3, -- 0x1ec5, 0x1ec5, -- 0x1ec7, 0x1ec7, -- 0x1ec9, 0x1ec9, -- 0x1ecb, 0x1ecb, -- 0x1ecd, 0x1ecd, -- 0x1ecf, 0x1ecf, -- 0x1ed1, 0x1ed1, -- 0x1ed3, 0x1ed3, -- 0x1ed5, 0x1ed5, -- 0x1ed7, 0x1ed7, -- 0x1ed9, 0x1ed9, -- 0x1edb, 0x1edb, -- 0x1edd, 0x1edd, -- 0x1edf, 0x1edf, -- 0x1ee1, 0x1ee1, -- 0x1ee3, 0x1ee3, -- 0x1ee5, 0x1ee5, -- 0x1ee7, 0x1ee7, -- 0x1ee9, 0x1ee9, -- 0x1eeb, 0x1eeb, -- 0x1eed, 0x1eed, -- 0x1eef, 0x1eef, -- 0x1ef1, 0x1ef1, -- 0x1ef3, 0x1ef3, -- 0x1ef5, 0x1ef5, -- 0x1ef7, 0x1ef7, -- 0x1ef9, 0x1ef9, -- 0x1efb, 0x1efb, -- 0x1efd, 0x1efd, -- 0x1eff, 0x1f07, -- 0x1f10, 0x1f15, -- 0x1f20, 0x1f27, -- 0x1f30, 0x1f37, -- 0x1f40, 0x1f45, -- 0x1f50, 0x1f57, -- 0x1f60, 0x1f67, -- 0x1f70, 0x1f7d, -- 0x1f80, 0x1fb4, -- 0x1fb6, 0x1fb7, -- 0x1fbc, 0x1fbc, -- 0x1fbe, 0x1fbe, -- 0x1fc2, 0x1fc4, -- 0x1fc6, 0x1fc7, -- 0x1fcc, 0x1fcc, -- 0x1fd0, 0x1fd3, -- 0x1fd6, 0x1fd7, -- 0x1fe0, 0x1fe7, -- 0x1ff2, 0x1ff4, -- 0x1ff6, 0x1ff7, -- 0x1ffc, 0x1ffc, -- 0x214e, 0x214e, -- 0x2170, 0x217f, -- 0x2184, 0x2184, -- 0x24d0, 0x24e9, -- 0x2c30, 0x2c5e, -- 0x2c61, 0x2c61, -- 0x2c65, 0x2c66, -- 0x2c68, 0x2c68, -- 0x2c6a, 0x2c6a, -- 0x2c6c, 0x2c6c, -- 0x2c73, 0x2c73, -- 0x2c76, 0x2c76, -- 0x2c81, 0x2c81, -- 0x2c83, 0x2c83, -- 0x2c85, 0x2c85, -- 0x2c87, 0x2c87, -- 0x2c89, 0x2c89, -- 0x2c8b, 0x2c8b, -- 0x2c8d, 0x2c8d, -- 0x2c8f, 0x2c8f, -- 0x2c91, 0x2c91, -- 0x2c93, 0x2c93, -- 0x2c95, 0x2c95, -- 0x2c97, 0x2c97, -- 0x2c99, 0x2c99, -- 0x2c9b, 0x2c9b, -- 0x2c9d, 0x2c9d, -- 0x2c9f, 0x2c9f, -- 0x2ca1, 0x2ca1, -- 0x2ca3, 0x2ca3, -- 0x2ca5, 0x2ca5, -- 0x2ca7, 0x2ca7, -- 0x2ca9, 0x2ca9, -- 0x2cab, 0x2cab, -- 0x2cad, 0x2cad, -- 0x2caf, 0x2caf, -- 0x2cb1, 0x2cb1, -- 0x2cb3, 0x2cb3, -- 0x2cb5, 0x2cb5, -- 0x2cb7, 0x2cb7, -- 0x2cb9, 0x2cb9, -- 0x2cbb, 0x2cbb, -- 0x2cbd, 0x2cbd, -- 0x2cbf, 0x2cbf, -- 0x2cc1, 0x2cc1, -- 0x2cc3, 0x2cc3, -- 0x2cc5, 0x2cc5, -- 0x2cc7, 0x2cc7, -- 0x2cc9, 0x2cc9, -- 0x2ccb, 0x2ccb, -- 0x2ccd, 0x2ccd, -- 0x2ccf, 0x2ccf, -- 0x2cd1, 0x2cd1, -- 0x2cd3, 0x2cd3, -- 0x2cd5, 0x2cd5, -- 0x2cd7, 0x2cd7, -- 0x2cd9, 0x2cd9, -- 0x2cdb, 0x2cdb, -- 0x2cdd, 0x2cdd, -- 0x2cdf, 0x2cdf, -- 0x2ce1, 0x2ce1, -- 0x2ce3, 0x2ce3, -- 0x2cec, 0x2cec, -- 0x2cee, 0x2cee, -- 0x2d00, 0x2d25, -- 0xa641, 0xa641, -- 0xa643, 0xa643, -- 0xa645, 0xa645, -- 0xa647, 0xa647, -- 0xa649, 0xa649, -- 0xa64b, 0xa64b, -- 0xa64d, 0xa64d, -- 0xa64f, 0xa64f, -- 0xa651, 0xa651, -- 0xa653, 0xa653, -- 0xa655, 0xa655, -- 0xa657, 0xa657, -- 0xa659, 0xa659, -- 0xa65b, 0xa65b, -- 0xa65d, 0xa65d, -- 0xa65f, 0xa65f, -- 0xa661, 0xa661, -- 0xa663, 0xa663, -- 0xa665, 0xa665, -- 0xa667, 0xa667, -- 0xa669, 0xa669, -- 0xa66b, 0xa66b, -- 0xa66d, 0xa66d, -- 0xa681, 0xa681, -- 0xa683, 0xa683, -- 0xa685, 0xa685, -- 0xa687, 0xa687, -- 0xa689, 0xa689, -- 0xa68b, 0xa68b, -- 0xa68d, 0xa68d, -- 0xa68f, 0xa68f, -- 0xa691, 0xa691, -- 0xa693, 0xa693, -- 0xa695, 0xa695, -- 0xa697, 0xa697, -- 0xa723, 0xa723, -- 0xa725, 0xa725, -- 0xa727, 0xa727, -- 0xa729, 0xa729, -- 0xa72b, 0xa72b, -- 0xa72d, 0xa72d, -- 0xa72f, 0xa72f, -- 0xa733, 0xa733, -- 0xa735, 0xa735, -- 0xa737, 0xa737, -- 0xa739, 0xa739, -- 0xa73b, 0xa73b, -- 0xa73d, 0xa73d, -- 0xa73f, 0xa73f, -- 0xa741, 0xa741, -- 0xa743, 0xa743, -- 0xa745, 0xa745, -- 0xa747, 0xa747, -- 0xa749, 0xa749, -- 0xa74b, 0xa74b, -- 0xa74d, 0xa74d, -- 0xa74f, 0xa74f, -- 0xa751, 0xa751, -- 0xa753, 0xa753, -- 0xa755, 0xa755, -- 0xa757, 0xa757, -- 0xa759, 0xa759, -- 0xa75b, 0xa75b, -- 0xa75d, 0xa75d, -- 0xa75f, 0xa75f, -- 0xa761, 0xa761, -- 0xa763, 0xa763, -- 0xa765, 0xa765, -- 0xa767, 0xa767, -- 0xa769, 0xa769, -- 0xa76b, 0xa76b, -- 0xa76d, 0xa76d, -- 0xa76f, 0xa76f, -- 0xa77a, 0xa77a, -- 0xa77c, 0xa77c, -- 0xa77f, 0xa77f, -- 0xa781, 0xa781, -- 0xa783, 0xa783, -- 0xa785, 0xa785, -- 0xa787, 0xa787, -- 0xa78c, 0xa78c, -- 0xa791, 0xa791, -- 0xa7a1, 0xa7a1, -- 0xa7a3, 0xa7a3, -- 0xa7a5, 0xa7a5, -- 0xa7a7, 0xa7a7, -- 0xa7a9, 0xa7a9, -- 0xfb00, 0xfb06, -- 0xfb13, 0xfb17, -- 0xff41, 0xff5a, -- 0x10428, 0x1044f, --}; /* CR_Changes_When_Uppercased */ -- --/* 'Changes_When_Titlecased': Derived Property */ --static const OnigCodePoint CR_Changes_When_Titlecased[] = { -- 583, -- 0x0061, 0x007a, -- 0x00b5, 0x00b5, -- 0x00df, 0x00f6, -- 0x00f8, 0x00ff, -- 0x0101, 0x0101, -- 0x0103, 0x0103, -- 0x0105, 0x0105, -- 0x0107, 0x0107, -- 0x0109, 0x0109, -- 0x010b, 0x010b, -- 0x010d, 0x010d, -- 0x010f, 0x010f, -- 0x0111, 0x0111, -- 0x0113, 0x0113, -- 0x0115, 0x0115, -- 0x0117, 0x0117, -- 0x0119, 0x0119, -- 0x011b, 0x011b, -- 0x011d, 0x011d, -- 0x011f, 0x011f, -- 0x0121, 0x0121, -- 0x0123, 0x0123, -- 0x0125, 0x0125, -- 0x0127, 0x0127, -- 0x0129, 0x0129, -- 0x012b, 0x012b, -- 0x012d, 0x012d, -- 0x012f, 0x012f, -- 0x0131, 0x0131, -- 0x0133, 0x0133, -- 0x0135, 0x0135, -- 0x0137, 0x0137, -- 0x013a, 0x013a, -- 0x013c, 0x013c, -- 0x013e, 0x013e, -- 0x0140, 0x0140, -- 0x0142, 0x0142, -- 0x0144, 0x0144, -- 0x0146, 0x0146, -- 0x0148, 0x0149, -- 0x014b, 0x014b, -- 0x014d, 0x014d, -- 0x014f, 0x014f, -- 0x0151, 0x0151, -- 0x0153, 0x0153, -- 0x0155, 0x0155, -- 0x0157, 0x0157, -- 0x0159, 0x0159, -- 0x015b, 0x015b, -- 0x015d, 0x015d, -- 0x015f, 0x015f, -- 0x0161, 0x0161, -- 0x0163, 0x0163, -- 0x0165, 0x0165, -- 0x0167, 0x0167, -- 0x0169, 0x0169, -- 0x016b, 0x016b, -- 0x016d, 0x016d, -- 0x016f, 0x016f, -- 0x0171, 0x0171, -- 0x0173, 0x0173, -- 0x0175, 0x0175, -- 0x0177, 0x0177, -- 0x017a, 0x017a, -- 0x017c, 0x017c, -- 0x017e, 0x0180, -- 0x0183, 0x0183, -- 0x0185, 0x0185, -- 0x0188, 0x0188, -- 0x018c, 0x018c, -- 0x0192, 0x0192, -- 0x0195, 0x0195, -- 0x0199, 0x019a, -- 0x019e, 0x019e, -- 0x01a1, 0x01a1, -- 0x01a3, 0x01a3, -- 0x01a5, 0x01a5, -- 0x01a8, 0x01a8, -- 0x01ad, 0x01ad, -- 0x01b0, 0x01b0, -- 0x01b4, 0x01b4, -- 0x01b6, 0x01b6, -- 0x01b9, 0x01b9, -- 0x01bd, 0x01bd, -- 0x01bf, 0x01bf, -- 0x01c4, 0x01c4, -- 0x01c6, 0x01c7, -- 0x01c9, 0x01ca, -- 0x01cc, 0x01cc, -- 0x01ce, 0x01ce, -- 0x01d0, 0x01d0, -- 0x01d2, 0x01d2, -- 0x01d4, 0x01d4, -- 0x01d6, 0x01d6, -- 0x01d8, 0x01d8, -- 0x01da, 0x01da, -- 0x01dc, 0x01dd, -- 0x01df, 0x01df, -- 0x01e1, 0x01e1, -- 0x01e3, 0x01e3, -- 0x01e5, 0x01e5, -- 0x01e7, 0x01e7, -- 0x01e9, 0x01e9, -- 0x01eb, 0x01eb, -- 0x01ed, 0x01ed, -- 0x01ef, 0x01f1, -- 0x01f3, 0x01f3, -- 0x01f5, 0x01f5, -- 0x01f9, 0x01f9, -- 0x01fb, 0x01fb, -- 0x01fd, 0x01fd, -- 0x01ff, 0x01ff, -- 0x0201, 0x0201, -- 0x0203, 0x0203, -- 0x0205, 0x0205, -- 0x0207, 0x0207, -- 0x0209, 0x0209, -- 0x020b, 0x020b, -- 0x020d, 0x020d, -- 0x020f, 0x020f, -- 0x0211, 0x0211, -- 0x0213, 0x0213, -- 0x0215, 0x0215, -- 0x0217, 0x0217, -- 0x0219, 0x0219, -- 0x021b, 0x021b, -- 0x021d, 0x021d, -- 0x021f, 0x021f, -- 0x0223, 0x0223, -- 0x0225, 0x0225, -- 0x0227, 0x0227, -- 0x0229, 0x0229, -- 0x022b, 0x022b, -- 0x022d, 0x022d, -- 0x022f, 0x022f, -- 0x0231, 0x0231, -- 0x0233, 0x0233, -- 0x023c, 0x023c, -- 0x023f, 0x0240, -- 0x0242, 0x0242, -- 0x0247, 0x0247, -- 0x0249, 0x0249, -- 0x024b, 0x024b, -- 0x024d, 0x024d, -- 0x024f, 0x0254, -- 0x0256, 0x0257, -- 0x0259, 0x0259, -- 0x025b, 0x025b, -- 0x0260, 0x0260, -- 0x0263, 0x0263, -- 0x0265, 0x0265, -- 0x0268, 0x0269, -- 0x026b, 0x026b, -- 0x026f, 0x026f, -- 0x0271, 0x0272, -- 0x0275, 0x0275, -- 0x027d, 0x027d, -- 0x0280, 0x0280, -- 0x0283, 0x0283, -- 0x0288, 0x028c, -- 0x0292, 0x0292, -- 0x0345, 0x0345, -- 0x0371, 0x0371, -- 0x0373, 0x0373, -- 0x0377, 0x0377, -- 0x037b, 0x037d, -- 0x0390, 0x0390, -- 0x03ac, 0x03ce, -- 0x03d0, 0x03d1, -- 0x03d5, 0x03d7, -- 0x03d9, 0x03d9, -- 0x03db, 0x03db, -- 0x03dd, 0x03dd, -- 0x03df, 0x03df, -- 0x03e1, 0x03e1, -- 0x03e3, 0x03e3, -- 0x03e5, 0x03e5, -- 0x03e7, 0x03e7, -- 0x03e9, 0x03e9, -- 0x03eb, 0x03eb, -- 0x03ed, 0x03ed, -- 0x03ef, 0x03f2, -- 0x03f5, 0x03f5, -- 0x03f8, 0x03f8, -- 0x03fb, 0x03fb, -- 0x0430, 0x045f, -- 0x0461, 0x0461, -- 0x0463, 0x0463, -- 0x0465, 0x0465, -- 0x0467, 0x0467, -- 0x0469, 0x0469, -- 0x046b, 0x046b, -- 0x046d, 0x046d, -- 0x046f, 0x046f, -- 0x0471, 0x0471, -- 0x0473, 0x0473, -- 0x0475, 0x0475, -- 0x0477, 0x0477, -- 0x0479, 0x0479, -- 0x047b, 0x047b, -- 0x047d, 0x047d, -- 0x047f, 0x047f, -- 0x0481, 0x0481, -- 0x048b, 0x048b, -- 0x048d, 0x048d, -- 0x048f, 0x048f, -- 0x0491, 0x0491, -- 0x0493, 0x0493, -- 0x0495, 0x0495, -- 0x0497, 0x0497, -- 0x0499, 0x0499, -- 0x049b, 0x049b, -- 0x049d, 0x049d, -- 0x049f, 0x049f, -- 0x04a1, 0x04a1, -- 0x04a3, 0x04a3, -- 0x04a5, 0x04a5, -- 0x04a7, 0x04a7, -- 0x04a9, 0x04a9, -- 0x04ab, 0x04ab, -- 0x04ad, 0x04ad, -- 0x04af, 0x04af, -- 0x04b1, 0x04b1, -- 0x04b3, 0x04b3, -- 0x04b5, 0x04b5, -- 0x04b7, 0x04b7, -- 0x04b9, 0x04b9, -- 0x04bb, 0x04bb, -- 0x04bd, 0x04bd, -- 0x04bf, 0x04bf, -- 0x04c2, 0x04c2, -- 0x04c4, 0x04c4, -- 0x04c6, 0x04c6, -- 0x04c8, 0x04c8, -- 0x04ca, 0x04ca, -- 0x04cc, 0x04cc, -- 0x04ce, 0x04cf, -- 0x04d1, 0x04d1, -- 0x04d3, 0x04d3, -- 0x04d5, 0x04d5, -- 0x04d7, 0x04d7, -- 0x04d9, 0x04d9, -- 0x04db, 0x04db, -- 0x04dd, 0x04dd, -- 0x04df, 0x04df, -- 0x04e1, 0x04e1, -- 0x04e3, 0x04e3, -- 0x04e5, 0x04e5, -- 0x04e7, 0x04e7, -- 0x04e9, 0x04e9, -- 0x04eb, 0x04eb, -- 0x04ed, 0x04ed, -- 0x04ef, 0x04ef, -- 0x04f1, 0x04f1, -- 0x04f3, 0x04f3, -- 0x04f5, 0x04f5, -- 0x04f7, 0x04f7, -- 0x04f9, 0x04f9, -- 0x04fb, 0x04fb, -- 0x04fd, 0x04fd, -- 0x04ff, 0x04ff, -- 0x0501, 0x0501, -- 0x0503, 0x0503, -- 0x0505, 0x0505, -- 0x0507, 0x0507, -- 0x0509, 0x0509, -- 0x050b, 0x050b, -- 0x050d, 0x050d, -- 0x050f, 0x050f, -- 0x0511, 0x0511, -- 0x0513, 0x0513, -- 0x0515, 0x0515, -- 0x0517, 0x0517, -- 0x0519, 0x0519, -- 0x051b, 0x051b, -- 0x051d, 0x051d, -- 0x051f, 0x051f, -- 0x0521, 0x0521, -- 0x0523, 0x0523, -- 0x0525, 0x0525, -- 0x0527, 0x0527, -- 0x0561, 0x0587, -- 0x1d79, 0x1d79, -- 0x1d7d, 0x1d7d, -- 0x1e01, 0x1e01, -- 0x1e03, 0x1e03, -- 0x1e05, 0x1e05, -- 0x1e07, 0x1e07, -- 0x1e09, 0x1e09, -- 0x1e0b, 0x1e0b, -- 0x1e0d, 0x1e0d, -- 0x1e0f, 0x1e0f, -- 0x1e11, 0x1e11, -- 0x1e13, 0x1e13, -- 0x1e15, 0x1e15, -- 0x1e17, 0x1e17, -- 0x1e19, 0x1e19, -- 0x1e1b, 0x1e1b, -- 0x1e1d, 0x1e1d, -- 0x1e1f, 0x1e1f, -- 0x1e21, 0x1e21, -- 0x1e23, 0x1e23, -- 0x1e25, 0x1e25, -- 0x1e27, 0x1e27, -- 0x1e29, 0x1e29, -- 0x1e2b, 0x1e2b, -- 0x1e2d, 0x1e2d, -- 0x1e2f, 0x1e2f, -- 0x1e31, 0x1e31, -- 0x1e33, 0x1e33, -- 0x1e35, 0x1e35, -- 0x1e37, 0x1e37, -- 0x1e39, 0x1e39, -- 0x1e3b, 0x1e3b, -- 0x1e3d, 0x1e3d, -- 0x1e3f, 0x1e3f, -- 0x1e41, 0x1e41, -- 0x1e43, 0x1e43, -- 0x1e45, 0x1e45, -- 0x1e47, 0x1e47, -- 0x1e49, 0x1e49, -- 0x1e4b, 0x1e4b, -- 0x1e4d, 0x1e4d, -- 0x1e4f, 0x1e4f, -- 0x1e51, 0x1e51, -- 0x1e53, 0x1e53, -- 0x1e55, 0x1e55, -- 0x1e57, 0x1e57, -- 0x1e59, 0x1e59, -- 0x1e5b, 0x1e5b, -- 0x1e5d, 0x1e5d, -- 0x1e5f, 0x1e5f, -- 0x1e61, 0x1e61, -- 0x1e63, 0x1e63, -- 0x1e65, 0x1e65, -- 0x1e67, 0x1e67, -- 0x1e69, 0x1e69, -- 0x1e6b, 0x1e6b, -- 0x1e6d, 0x1e6d, -- 0x1e6f, 0x1e6f, -- 0x1e71, 0x1e71, -- 0x1e73, 0x1e73, -- 0x1e75, 0x1e75, -- 0x1e77, 0x1e77, -- 0x1e79, 0x1e79, -- 0x1e7b, 0x1e7b, -- 0x1e7d, 0x1e7d, -- 0x1e7f, 0x1e7f, -- 0x1e81, 0x1e81, -- 0x1e83, 0x1e83, -- 0x1e85, 0x1e85, -- 0x1e87, 0x1e87, -- 0x1e89, 0x1e89, -- 0x1e8b, 0x1e8b, -- 0x1e8d, 0x1e8d, -- 0x1e8f, 0x1e8f, -- 0x1e91, 0x1e91, -- 0x1e93, 0x1e93, -- 0x1e95, 0x1e9b, -- 0x1ea1, 0x1ea1, -- 0x1ea3, 0x1ea3, -- 0x1ea5, 0x1ea5, -- 0x1ea7, 0x1ea7, -- 0x1ea9, 0x1ea9, -- 0x1eab, 0x1eab, -- 0x1ead, 0x1ead, -- 0x1eaf, 0x1eaf, -- 0x1eb1, 0x1eb1, -- 0x1eb3, 0x1eb3, -- 0x1eb5, 0x1eb5, -- 0x1eb7, 0x1eb7, -- 0x1eb9, 0x1eb9, -- 0x1ebb, 0x1ebb, -- 0x1ebd, 0x1ebd, -- 0x1ebf, 0x1ebf, -- 0x1ec1, 0x1ec1, -- 0x1ec3, 0x1ec3, -- 0x1ec5, 0x1ec5, -- 0x1ec7, 0x1ec7, -- 0x1ec9, 0x1ec9, -- 0x1ecb, 0x1ecb, -- 0x1ecd, 0x1ecd, -- 0x1ecf, 0x1ecf, -- 0x1ed1, 0x1ed1, -- 0x1ed3, 0x1ed3, -- 0x1ed5, 0x1ed5, -- 0x1ed7, 0x1ed7, -- 0x1ed9, 0x1ed9, -- 0x1edb, 0x1edb, -- 0x1edd, 0x1edd, -- 0x1edf, 0x1edf, -- 0x1ee1, 0x1ee1, -- 0x1ee3, 0x1ee3, -- 0x1ee5, 0x1ee5, -- 0x1ee7, 0x1ee7, -- 0x1ee9, 0x1ee9, -- 0x1eeb, 0x1eeb, -- 0x1eed, 0x1eed, -- 0x1eef, 0x1eef, -- 0x1ef1, 0x1ef1, -- 0x1ef3, 0x1ef3, -- 0x1ef5, 0x1ef5, -- 0x1ef7, 0x1ef7, -- 0x1ef9, 0x1ef9, -- 0x1efb, 0x1efb, -- 0x1efd, 0x1efd, -- 0x1eff, 0x1f07, -- 0x1f10, 0x1f15, -- 0x1f20, 0x1f27, -- 0x1f30, 0x1f37, -- 0x1f40, 0x1f45, -- 0x1f50, 0x1f57, -- 0x1f60, 0x1f67, -- 0x1f70, 0x1f7d, -- 0x1f80, 0x1f87, -- 0x1f90, 0x1f97, -- 0x1fa0, 0x1fa7, -- 0x1fb0, 0x1fb4, -- 0x1fb6, 0x1fb7, -- 0x1fbe, 0x1fbe, -- 0x1fc2, 0x1fc4, -- 0x1fc6, 0x1fc7, -- 0x1fd0, 0x1fd3, -- 0x1fd6, 0x1fd7, -- 0x1fe0, 0x1fe7, -- 0x1ff2, 0x1ff4, -- 0x1ff6, 0x1ff7, -- 0x214e, 0x214e, -- 0x2170, 0x217f, -- 0x2184, 0x2184, -- 0x24d0, 0x24e9, -- 0x2c30, 0x2c5e, -- 0x2c61, 0x2c61, -- 0x2c65, 0x2c66, -- 0x2c68, 0x2c68, -- 0x2c6a, 0x2c6a, -- 0x2c6c, 0x2c6c, -- 0x2c73, 0x2c73, -- 0x2c76, 0x2c76, -- 0x2c81, 0x2c81, -- 0x2c83, 0x2c83, -- 0x2c85, 0x2c85, -- 0x2c87, 0x2c87, -- 0x2c89, 0x2c89, -- 0x2c8b, 0x2c8b, -- 0x2c8d, 0x2c8d, -- 0x2c8f, 0x2c8f, -- 0x2c91, 0x2c91, -- 0x2c93, 0x2c93, -- 0x2c95, 0x2c95, -- 0x2c97, 0x2c97, -- 0x2c99, 0x2c99, -- 0x2c9b, 0x2c9b, -- 0x2c9d, 0x2c9d, -- 0x2c9f, 0x2c9f, -- 0x2ca1, 0x2ca1, -- 0x2ca3, 0x2ca3, -- 0x2ca5, 0x2ca5, -- 0x2ca7, 0x2ca7, -- 0x2ca9, 0x2ca9, -- 0x2cab, 0x2cab, -- 0x2cad, 0x2cad, -- 0x2caf, 0x2caf, -- 0x2cb1, 0x2cb1, -- 0x2cb3, 0x2cb3, -- 0x2cb5, 0x2cb5, -- 0x2cb7, 0x2cb7, -- 0x2cb9, 0x2cb9, -- 0x2cbb, 0x2cbb, -- 0x2cbd, 0x2cbd, -- 0x2cbf, 0x2cbf, -- 0x2cc1, 0x2cc1, -- 0x2cc3, 0x2cc3, -- 0x2cc5, 0x2cc5, -- 0x2cc7, 0x2cc7, -- 0x2cc9, 0x2cc9, -- 0x2ccb, 0x2ccb, -- 0x2ccd, 0x2ccd, -- 0x2ccf, 0x2ccf, -- 0x2cd1, 0x2cd1, -- 0x2cd3, 0x2cd3, -- 0x2cd5, 0x2cd5, -- 0x2cd7, 0x2cd7, -- 0x2cd9, 0x2cd9, -- 0x2cdb, 0x2cdb, -- 0x2cdd, 0x2cdd, -- 0x2cdf, 0x2cdf, -- 0x2ce1, 0x2ce1, -- 0x2ce3, 0x2ce3, -- 0x2cec, 0x2cec, -- 0x2cee, 0x2cee, -- 0x2d00, 0x2d25, -- 0xa641, 0xa641, -- 0xa643, 0xa643, -- 0xa645, 0xa645, -- 0xa647, 0xa647, -- 0xa649, 0xa649, -- 0xa64b, 0xa64b, -- 0xa64d, 0xa64d, -- 0xa64f, 0xa64f, -- 0xa651, 0xa651, -- 0xa653, 0xa653, -- 0xa655, 0xa655, -- 0xa657, 0xa657, -- 0xa659, 0xa659, -- 0xa65b, 0xa65b, -- 0xa65d, 0xa65d, -- 0xa65f, 0xa65f, -- 0xa661, 0xa661, -- 0xa663, 0xa663, -- 0xa665, 0xa665, -- 0xa667, 0xa667, -- 0xa669, 0xa669, -- 0xa66b, 0xa66b, -- 0xa66d, 0xa66d, -- 0xa681, 0xa681, -- 0xa683, 0xa683, -- 0xa685, 0xa685, -- 0xa687, 0xa687, -- 0xa689, 0xa689, -- 0xa68b, 0xa68b, -- 0xa68d, 0xa68d, -- 0xa68f, 0xa68f, -- 0xa691, 0xa691, -- 0xa693, 0xa693, -- 0xa695, 0xa695, -- 0xa697, 0xa697, -- 0xa723, 0xa723, -- 0xa725, 0xa725, -- 0xa727, 0xa727, -- 0xa729, 0xa729, -- 0xa72b, 0xa72b, -- 0xa72d, 0xa72d, -- 0xa72f, 0xa72f, -- 0xa733, 0xa733, -- 0xa735, 0xa735, -- 0xa737, 0xa737, -- 0xa739, 0xa739, -- 0xa73b, 0xa73b, -- 0xa73d, 0xa73d, -- 0xa73f, 0xa73f, -- 0xa741, 0xa741, -- 0xa743, 0xa743, -- 0xa745, 0xa745, -- 0xa747, 0xa747, -- 0xa749, 0xa749, -- 0xa74b, 0xa74b, -- 0xa74d, 0xa74d, -- 0xa74f, 0xa74f, -- 0xa751, 0xa751, -- 0xa753, 0xa753, -- 0xa755, 0xa755, -- 0xa757, 0xa757, -- 0xa759, 0xa759, -- 0xa75b, 0xa75b, -- 0xa75d, 0xa75d, -- 0xa75f, 0xa75f, -- 0xa761, 0xa761, -- 0xa763, 0xa763, -- 0xa765, 0xa765, -- 0xa767, 0xa767, -- 0xa769, 0xa769, -- 0xa76b, 0xa76b, -- 0xa76d, 0xa76d, -- 0xa76f, 0xa76f, -- 0xa77a, 0xa77a, -- 0xa77c, 0xa77c, -- 0xa77f, 0xa77f, -- 0xa781, 0xa781, -- 0xa783, 0xa783, -- 0xa785, 0xa785, -- 0xa787, 0xa787, -- 0xa78c, 0xa78c, -- 0xa791, 0xa791, -- 0xa7a1, 0xa7a1, -- 0xa7a3, 0xa7a3, -- 0xa7a5, 0xa7a5, -- 0xa7a7, 0xa7a7, -- 0xa7a9, 0xa7a9, -- 0xfb00, 0xfb06, -- 0xfb13, 0xfb17, -- 0xff41, 0xff5a, -- 0x10428, 0x1044f, --}; /* CR_Changes_When_Titlecased */ -- --/* 'Changes_When_Casefolded': Derived Property */ --static const OnigCodePoint CR_Changes_When_Casefolded[] = { -- 577, -- 0x0041, 0x005a, -- 0x00b5, 0x00b5, -- 0x00c0, 0x00d6, -- 0x00d8, 0x00df, -- 0x0100, 0x0100, -- 0x0102, 0x0102, -- 0x0104, 0x0104, -- 0x0106, 0x0106, -- 0x0108, 0x0108, -- 0x010a, 0x010a, -- 0x010c, 0x010c, -- 0x010e, 0x010e, -- 0x0110, 0x0110, -- 0x0112, 0x0112, -- 0x0114, 0x0114, -- 0x0116, 0x0116, -- 0x0118, 0x0118, -- 0x011a, 0x011a, -- 0x011c, 0x011c, -- 0x011e, 0x011e, -- 0x0120, 0x0120, -- 0x0122, 0x0122, -- 0x0124, 0x0124, -- 0x0126, 0x0126, -- 0x0128, 0x0128, -- 0x012a, 0x012a, -- 0x012c, 0x012c, -- 0x012e, 0x012e, -- 0x0130, 0x0130, -- 0x0132, 0x0132, -- 0x0134, 0x0134, -- 0x0136, 0x0136, -- 0x0139, 0x0139, -- 0x013b, 0x013b, -- 0x013d, 0x013d, -- 0x013f, 0x013f, -- 0x0141, 0x0141, -- 0x0143, 0x0143, -- 0x0145, 0x0145, -- 0x0147, 0x0147, -- 0x0149, 0x014a, -- 0x014c, 0x014c, -- 0x014e, 0x014e, -- 0x0150, 0x0150, -- 0x0152, 0x0152, -- 0x0154, 0x0154, -- 0x0156, 0x0156, -- 0x0158, 0x0158, -- 0x015a, 0x015a, -- 0x015c, 0x015c, -- 0x015e, 0x015e, -- 0x0160, 0x0160, -- 0x0162, 0x0162, -- 0x0164, 0x0164, -- 0x0166, 0x0166, -- 0x0168, 0x0168, -- 0x016a, 0x016a, -- 0x016c, 0x016c, -- 0x016e, 0x016e, -- 0x0170, 0x0170, -- 0x0172, 0x0172, -- 0x0174, 0x0174, -- 0x0176, 0x0176, -- 0x0178, 0x0179, -- 0x017b, 0x017b, -- 0x017d, 0x017d, -- 0x017f, 0x017f, -- 0x0181, 0x0182, -- 0x0184, 0x0184, -- 0x0186, 0x0187, -- 0x0189, 0x018b, -- 0x018e, 0x0191, -- 0x0193, 0x0194, -- 0x0196, 0x0198, -- 0x019c, 0x019d, -- 0x019f, 0x01a0, -- 0x01a2, 0x01a2, -- 0x01a4, 0x01a4, -- 0x01a6, 0x01a7, -- 0x01a9, 0x01a9, -- 0x01ac, 0x01ac, -- 0x01ae, 0x01af, -- 0x01b1, 0x01b3, -- 0x01b5, 0x01b5, -- 0x01b7, 0x01b8, -- 0x01bc, 0x01bc, -- 0x01c4, 0x01c5, -- 0x01c7, 0x01c8, -- 0x01ca, 0x01cb, -- 0x01cd, 0x01cd, -- 0x01cf, 0x01cf, -- 0x01d1, 0x01d1, -- 0x01d3, 0x01d3, -- 0x01d5, 0x01d5, -- 0x01d7, 0x01d7, -- 0x01d9, 0x01d9, -- 0x01db, 0x01db, -- 0x01de, 0x01de, -- 0x01e0, 0x01e0, -- 0x01e2, 0x01e2, -- 0x01e4, 0x01e4, -- 0x01e6, 0x01e6, -- 0x01e8, 0x01e8, -- 0x01ea, 0x01ea, -- 0x01ec, 0x01ec, -- 0x01ee, 0x01ee, -- 0x01f1, 0x01f2, -- 0x01f4, 0x01f4, -- 0x01f6, 0x01f8, -- 0x01fa, 0x01fa, -- 0x01fc, 0x01fc, -- 0x01fe, 0x01fe, -- 0x0200, 0x0200, -- 0x0202, 0x0202, -- 0x0204, 0x0204, -- 0x0206, 0x0206, -- 0x0208, 0x0208, -- 0x020a, 0x020a, -- 0x020c, 0x020c, -- 0x020e, 0x020e, -- 0x0210, 0x0210, -- 0x0212, 0x0212, -- 0x0214, 0x0214, -- 0x0216, 0x0216, -- 0x0218, 0x0218, -- 0x021a, 0x021a, -- 0x021c, 0x021c, -- 0x021e, 0x021e, -- 0x0220, 0x0220, -- 0x0222, 0x0222, -- 0x0224, 0x0224, -- 0x0226, 0x0226, -- 0x0228, 0x0228, -- 0x022a, 0x022a, -- 0x022c, 0x022c, -- 0x022e, 0x022e, -- 0x0230, 0x0230, -- 0x0232, 0x0232, -- 0x023a, 0x023b, -- 0x023d, 0x023e, -- 0x0241, 0x0241, -- 0x0243, 0x0246, -- 0x0248, 0x0248, -- 0x024a, 0x024a, -- 0x024c, 0x024c, -- 0x024e, 0x024e, -- 0x0345, 0x0345, -- 0x0370, 0x0370, -- 0x0372, 0x0372, -- 0x0376, 0x0376, -- 0x0386, 0x0386, -- 0x0388, 0x038a, -- 0x038c, 0x038c, -- 0x038e, 0x038f, -- 0x0391, 0x03a1, -- 0x03a3, 0x03ab, -- 0x03c2, 0x03c2, -- 0x03cf, 0x03d1, -- 0x03d5, 0x03d6, -- 0x03d8, 0x03d8, -- 0x03da, 0x03da, -- 0x03dc, 0x03dc, -- 0x03de, 0x03de, -- 0x03e0, 0x03e0, -- 0x03e2, 0x03e2, -- 0x03e4, 0x03e4, -- 0x03e6, 0x03e6, -- 0x03e8, 0x03e8, -- 0x03ea, 0x03ea, -- 0x03ec, 0x03ec, -- 0x03ee, 0x03ee, -- 0x03f0, 0x03f1, -- 0x03f4, 0x03f5, -- 0x03f7, 0x03f7, -- 0x03f9, 0x03fa, -- 0x03fd, 0x042f, -- 0x0460, 0x0460, -- 0x0462, 0x0462, -- 0x0464, 0x0464, -- 0x0466, 0x0466, -- 0x0468, 0x0468, -- 0x046a, 0x046a, -- 0x046c, 0x046c, -- 0x046e, 0x046e, -- 0x0470, 0x0470, -- 0x0472, 0x0472, -- 0x0474, 0x0474, -- 0x0476, 0x0476, -- 0x0478, 0x0478, -- 0x047a, 0x047a, -- 0x047c, 0x047c, -- 0x047e, 0x047e, -- 0x0480, 0x0480, -- 0x048a, 0x048a, -- 0x048c, 0x048c, -- 0x048e, 0x048e, -- 0x0490, 0x0490, -- 0x0492, 0x0492, -- 0x0494, 0x0494, -- 0x0496, 0x0496, -- 0x0498, 0x0498, -- 0x049a, 0x049a, -- 0x049c, 0x049c, -- 0x049e, 0x049e, -- 0x04a0, 0x04a0, -- 0x04a2, 0x04a2, -- 0x04a4, 0x04a4, -- 0x04a6, 0x04a6, -- 0x04a8, 0x04a8, -- 0x04aa, 0x04aa, -- 0x04ac, 0x04ac, -- 0x04ae, 0x04ae, -- 0x04b0, 0x04b0, -- 0x04b2, 0x04b2, -- 0x04b4, 0x04b4, -- 0x04b6, 0x04b6, -- 0x04b8, 0x04b8, -- 0x04ba, 0x04ba, -- 0x04bc, 0x04bc, -- 0x04be, 0x04be, -- 0x04c0, 0x04c1, -- 0x04c3, 0x04c3, -- 0x04c5, 0x04c5, -- 0x04c7, 0x04c7, -- 0x04c9, 0x04c9, -- 0x04cb, 0x04cb, -- 0x04cd, 0x04cd, -- 0x04d0, 0x04d0, -- 0x04d2, 0x04d2, -- 0x04d4, 0x04d4, -- 0x04d6, 0x04d6, -- 0x04d8, 0x04d8, -- 0x04da, 0x04da, -- 0x04dc, 0x04dc, -- 0x04de, 0x04de, -- 0x04e0, 0x04e0, -- 0x04e2, 0x04e2, -- 0x04e4, 0x04e4, -- 0x04e6, 0x04e6, -- 0x04e8, 0x04e8, -- 0x04ea, 0x04ea, -- 0x04ec, 0x04ec, -- 0x04ee, 0x04ee, -- 0x04f0, 0x04f0, -- 0x04f2, 0x04f2, -- 0x04f4, 0x04f4, -- 0x04f6, 0x04f6, -- 0x04f8, 0x04f8, -- 0x04fa, 0x04fa, -- 0x04fc, 0x04fc, -- 0x04fe, 0x04fe, -- 0x0500, 0x0500, -- 0x0502, 0x0502, -- 0x0504, 0x0504, -- 0x0506, 0x0506, -- 0x0508, 0x0508, -- 0x050a, 0x050a, -- 0x050c, 0x050c, -- 0x050e, 0x050e, -- 0x0510, 0x0510, -- 0x0512, 0x0512, -- 0x0514, 0x0514, -- 0x0516, 0x0516, -- 0x0518, 0x0518, -- 0x051a, 0x051a, -- 0x051c, 0x051c, -- 0x051e, 0x051e, -- 0x0520, 0x0520, -- 0x0522, 0x0522, -- 0x0524, 0x0524, -- 0x0526, 0x0526, -- 0x0531, 0x0556, -- 0x0587, 0x0587, -- 0x10a0, 0x10c5, -- 0x1e00, 0x1e00, -- 0x1e02, 0x1e02, -- 0x1e04, 0x1e04, -- 0x1e06, 0x1e06, -- 0x1e08, 0x1e08, -- 0x1e0a, 0x1e0a, -- 0x1e0c, 0x1e0c, -- 0x1e0e, 0x1e0e, -- 0x1e10, 0x1e10, -- 0x1e12, 0x1e12, -- 0x1e14, 0x1e14, -- 0x1e16, 0x1e16, -- 0x1e18, 0x1e18, -- 0x1e1a, 0x1e1a, -- 0x1e1c, 0x1e1c, -- 0x1e1e, 0x1e1e, -- 0x1e20, 0x1e20, -- 0x1e22, 0x1e22, -- 0x1e24, 0x1e24, -- 0x1e26, 0x1e26, -- 0x1e28, 0x1e28, -- 0x1e2a, 0x1e2a, -- 0x1e2c, 0x1e2c, -- 0x1e2e, 0x1e2e, -- 0x1e30, 0x1e30, -- 0x1e32, 0x1e32, -- 0x1e34, 0x1e34, -- 0x1e36, 0x1e36, -- 0x1e38, 0x1e38, -- 0x1e3a, 0x1e3a, -- 0x1e3c, 0x1e3c, -- 0x1e3e, 0x1e3e, -- 0x1e40, 0x1e40, -- 0x1e42, 0x1e42, -- 0x1e44, 0x1e44, -- 0x1e46, 0x1e46, -- 0x1e48, 0x1e48, -- 0x1e4a, 0x1e4a, -- 0x1e4c, 0x1e4c, -- 0x1e4e, 0x1e4e, -- 0x1e50, 0x1e50, -- 0x1e52, 0x1e52, -- 0x1e54, 0x1e54, -- 0x1e56, 0x1e56, -- 0x1e58, 0x1e58, -- 0x1e5a, 0x1e5a, -- 0x1e5c, 0x1e5c, -- 0x1e5e, 0x1e5e, -- 0x1e60, 0x1e60, -- 0x1e62, 0x1e62, -- 0x1e64, 0x1e64, -- 0x1e66, 0x1e66, -- 0x1e68, 0x1e68, -- 0x1e6a, 0x1e6a, -- 0x1e6c, 0x1e6c, -- 0x1e6e, 0x1e6e, -- 0x1e70, 0x1e70, -- 0x1e72, 0x1e72, -- 0x1e74, 0x1e74, -- 0x1e76, 0x1e76, -- 0x1e78, 0x1e78, -- 0x1e7a, 0x1e7a, -- 0x1e7c, 0x1e7c, -- 0x1e7e, 0x1e7e, -- 0x1e80, 0x1e80, -- 0x1e82, 0x1e82, -- 0x1e84, 0x1e84, -- 0x1e86, 0x1e86, -- 0x1e88, 0x1e88, -- 0x1e8a, 0x1e8a, -- 0x1e8c, 0x1e8c, -- 0x1e8e, 0x1e8e, -- 0x1e90, 0x1e90, -- 0x1e92, 0x1e92, -- 0x1e94, 0x1e94, -- 0x1e9a, 0x1e9b, -- 0x1e9e, 0x1e9e, -- 0x1ea0, 0x1ea0, -- 0x1ea2, 0x1ea2, -- 0x1ea4, 0x1ea4, -- 0x1ea6, 0x1ea6, -- 0x1ea8, 0x1ea8, -- 0x1eaa, 0x1eaa, -- 0x1eac, 0x1eac, -- 0x1eae, 0x1eae, -- 0x1eb0, 0x1eb0, -- 0x1eb2, 0x1eb2, -- 0x1eb4, 0x1eb4, -- 0x1eb6, 0x1eb6, -- 0x1eb8, 0x1eb8, -- 0x1eba, 0x1eba, -- 0x1ebc, 0x1ebc, -- 0x1ebe, 0x1ebe, -- 0x1ec0, 0x1ec0, -- 0x1ec2, 0x1ec2, -- 0x1ec4, 0x1ec4, -- 0x1ec6, 0x1ec6, -- 0x1ec8, 0x1ec8, -- 0x1eca, 0x1eca, -- 0x1ecc, 0x1ecc, -- 0x1ece, 0x1ece, -- 0x1ed0, 0x1ed0, -- 0x1ed2, 0x1ed2, -- 0x1ed4, 0x1ed4, -- 0x1ed6, 0x1ed6, -- 0x1ed8, 0x1ed8, -- 0x1eda, 0x1eda, -- 0x1edc, 0x1edc, -- 0x1ede, 0x1ede, -- 0x1ee0, 0x1ee0, -- 0x1ee2, 0x1ee2, -- 0x1ee4, 0x1ee4, -- 0x1ee6, 0x1ee6, -- 0x1ee8, 0x1ee8, -- 0x1eea, 0x1eea, -- 0x1eec, 0x1eec, -- 0x1eee, 0x1eee, -- 0x1ef0, 0x1ef0, -- 0x1ef2, 0x1ef2, -- 0x1ef4, 0x1ef4, -- 0x1ef6, 0x1ef6, -- 0x1ef8, 0x1ef8, -- 0x1efa, 0x1efa, -- 0x1efc, 0x1efc, -- 0x1efe, 0x1efe, -- 0x1f08, 0x1f0f, -- 0x1f18, 0x1f1d, -- 0x1f28, 0x1f2f, -- 0x1f38, 0x1f3f, -- 0x1f48, 0x1f4d, -- 0x1f59, 0x1f59, -- 0x1f5b, 0x1f5b, -- 0x1f5d, 0x1f5d, -- 0x1f5f, 0x1f5f, -- 0x1f68, 0x1f6f, -- 0x1f80, 0x1faf, -- 0x1fb2, 0x1fb4, -- 0x1fb7, 0x1fbc, -- 0x1fc2, 0x1fc4, -- 0x1fc7, 0x1fcc, -- 0x1fd8, 0x1fdb, -- 0x1fe8, 0x1fec, -- 0x1ff2, 0x1ff4, -- 0x1ff7, 0x1ffc, -- 0x2126, 0x2126, -- 0x212a, 0x212b, -- 0x2132, 0x2132, -- 0x2160, 0x216f, -- 0x2183, 0x2183, -- 0x24b6, 0x24cf, -- 0x2c00, 0x2c2e, -- 0x2c60, 0x2c60, -- 0x2c62, 0x2c64, -- 0x2c67, 0x2c67, -- 0x2c69, 0x2c69, -- 0x2c6b, 0x2c6b, -- 0x2c6d, 0x2c70, -- 0x2c72, 0x2c72, -- 0x2c75, 0x2c75, -- 0x2c7e, 0x2c80, -- 0x2c82, 0x2c82, -- 0x2c84, 0x2c84, -- 0x2c86, 0x2c86, -- 0x2c88, 0x2c88, -- 0x2c8a, 0x2c8a, -- 0x2c8c, 0x2c8c, -- 0x2c8e, 0x2c8e, -- 0x2c90, 0x2c90, -- 0x2c92, 0x2c92, -- 0x2c94, 0x2c94, -- 0x2c96, 0x2c96, -- 0x2c98, 0x2c98, -- 0x2c9a, 0x2c9a, -- 0x2c9c, 0x2c9c, -- 0x2c9e, 0x2c9e, -- 0x2ca0, 0x2ca0, -- 0x2ca2, 0x2ca2, -- 0x2ca4, 0x2ca4, -- 0x2ca6, 0x2ca6, -- 0x2ca8, 0x2ca8, -- 0x2caa, 0x2caa, -- 0x2cac, 0x2cac, -- 0x2cae, 0x2cae, -- 0x2cb0, 0x2cb0, -- 0x2cb2, 0x2cb2, -- 0x2cb4, 0x2cb4, -- 0x2cb6, 0x2cb6, -- 0x2cb8, 0x2cb8, -- 0x2cba, 0x2cba, -- 0x2cbc, 0x2cbc, -- 0x2cbe, 0x2cbe, -- 0x2cc0, 0x2cc0, -- 0x2cc2, 0x2cc2, -- 0x2cc4, 0x2cc4, -- 0x2cc6, 0x2cc6, -- 0x2cc8, 0x2cc8, -- 0x2cca, 0x2cca, -- 0x2ccc, 0x2ccc, -- 0x2cce, 0x2cce, -- 0x2cd0, 0x2cd0, -- 0x2cd2, 0x2cd2, -- 0x2cd4, 0x2cd4, -- 0x2cd6, 0x2cd6, -- 0x2cd8, 0x2cd8, -- 0x2cda, 0x2cda, -- 0x2cdc, 0x2cdc, -- 0x2cde, 0x2cde, -- 0x2ce0, 0x2ce0, -- 0x2ce2, 0x2ce2, -- 0x2ceb, 0x2ceb, -- 0x2ced, 0x2ced, -- 0xa640, 0xa640, -- 0xa642, 0xa642, -- 0xa644, 0xa644, -- 0xa646, 0xa646, -- 0xa648, 0xa648, -- 0xa64a, 0xa64a, -- 0xa64c, 0xa64c, -- 0xa64e, 0xa64e, -- 0xa650, 0xa650, -- 0xa652, 0xa652, -- 0xa654, 0xa654, -- 0xa656, 0xa656, -- 0xa658, 0xa658, -- 0xa65a, 0xa65a, -- 0xa65c, 0xa65c, -- 0xa65e, 0xa65e, -- 0xa660, 0xa660, -- 0xa662, 0xa662, -- 0xa664, 0xa664, -- 0xa666, 0xa666, -- 0xa668, 0xa668, -- 0xa66a, 0xa66a, -- 0xa66c, 0xa66c, -- 0xa680, 0xa680, -- 0xa682, 0xa682, -- 0xa684, 0xa684, -- 0xa686, 0xa686, -- 0xa688, 0xa688, -- 0xa68a, 0xa68a, -- 0xa68c, 0xa68c, -- 0xa68e, 0xa68e, -- 0xa690, 0xa690, -- 0xa692, 0xa692, -- 0xa694, 0xa694, -- 0xa696, 0xa696, -- 0xa722, 0xa722, -- 0xa724, 0xa724, -- 0xa726, 0xa726, -- 0xa728, 0xa728, -- 0xa72a, 0xa72a, -- 0xa72c, 0xa72c, -- 0xa72e, 0xa72e, -- 0xa732, 0xa732, -- 0xa734, 0xa734, -- 0xa736, 0xa736, -- 0xa738, 0xa738, -- 0xa73a, 0xa73a, -- 0xa73c, 0xa73c, -- 0xa73e, 0xa73e, -- 0xa740, 0xa740, -- 0xa742, 0xa742, -- 0xa744, 0xa744, -- 0xa746, 0xa746, -- 0xa748, 0xa748, -- 0xa74a, 0xa74a, -- 0xa74c, 0xa74c, -- 0xa74e, 0xa74e, -- 0xa750, 0xa750, -- 0xa752, 0xa752, -- 0xa754, 0xa754, -- 0xa756, 0xa756, -- 0xa758, 0xa758, -- 0xa75a, 0xa75a, -- 0xa75c, 0xa75c, -- 0xa75e, 0xa75e, -- 0xa760, 0xa760, -- 0xa762, 0xa762, -- 0xa764, 0xa764, -- 0xa766, 0xa766, -- 0xa768, 0xa768, -- 0xa76a, 0xa76a, -- 0xa76c, 0xa76c, -- 0xa76e, 0xa76e, -- 0xa779, 0xa779, -- 0xa77b, 0xa77b, -- 0xa77d, 0xa77e, -- 0xa780, 0xa780, -- 0xa782, 0xa782, -- 0xa784, 0xa784, -- 0xa786, 0xa786, -- 0xa78b, 0xa78b, -- 0xa78d, 0xa78d, -- 0xa790, 0xa790, -- 0xa7a0, 0xa7a0, -- 0xa7a2, 0xa7a2, -- 0xa7a4, 0xa7a4, -- 0xa7a6, 0xa7a6, -- 0xa7a8, 0xa7a8, -- 0xfb00, 0xfb06, -- 0xfb13, 0xfb17, -- 0xff21, 0xff3a, -- 0x10400, 0x10427, --}; /* CR_Changes_When_Casefolded */ -- --/* 'Changes_When_Casemapped': Derived Property */ --static const OnigCodePoint CR_Changes_When_Casemapped[] = { -- 99, -- 0x0041, 0x005a, -- 0x0061, 0x007a, -- 0x00b5, 0x00b5, -- 0x00c0, 0x00d6, -- 0x00d8, 0x00f6, -- 0x00f8, 0x0137, -- 0x0139, 0x018c, -- 0x018e, 0x019a, -- 0x019c, 0x01a9, -- 0x01ac, 0x01b9, -- 0x01bc, 0x01bd, -- 0x01bf, 0x01bf, -- 0x01c4, 0x0220, -- 0x0222, 0x0233, -- 0x023a, 0x0254, -- 0x0256, 0x0257, -- 0x0259, 0x0259, -- 0x025b, 0x025b, -- 0x0260, 0x0260, -- 0x0263, 0x0263, -- 0x0265, 0x0265, -- 0x0268, 0x0269, -- 0x026b, 0x026b, -- 0x026f, 0x026f, -- 0x0271, 0x0272, -- 0x0275, 0x0275, -- 0x027d, 0x027d, -- 0x0280, 0x0280, -- 0x0283, 0x0283, -- 0x0288, 0x028c, -- 0x0292, 0x0292, -- 0x0345, 0x0345, -- 0x0370, 0x0373, -- 0x0376, 0x0377, -- 0x037b, 0x037d, -- 0x0386, 0x0386, -- 0x0388, 0x038a, -- 0x038c, 0x038c, -- 0x038e, 0x03a1, -- 0x03a3, 0x03d1, -- 0x03d5, 0x03f2, -- 0x03f4, 0x03f5, -- 0x03f7, 0x03fb, -- 0x03fd, 0x0481, -- 0x048a, 0x0527, -- 0x0531, 0x0556, -- 0x0561, 0x0587, -- 0x10a0, 0x10c5, -- 0x1d79, 0x1d79, -- 0x1d7d, 0x1d7d, -- 0x1e00, 0x1e9b, -- 0x1e9e, 0x1e9e, -- 0x1ea0, 0x1f15, -- 0x1f18, 0x1f1d, -- 0x1f20, 0x1f45, -- 0x1f48, 0x1f4d, -- 0x1f50, 0x1f57, -- 0x1f59, 0x1f59, -- 0x1f5b, 0x1f5b, -- 0x1f5d, 0x1f5d, -- 0x1f5f, 0x1f7d, -- 0x1f80, 0x1fb4, -- 0x1fb6, 0x1fbc, -- 0x1fbe, 0x1fbe, -- 0x1fc2, 0x1fc4, -- 0x1fc6, 0x1fcc, -- 0x1fd0, 0x1fd3, -- 0x1fd6, 0x1fdb, -- 0x1fe0, 0x1fec, -- 0x1ff2, 0x1ff4, -- 0x1ff6, 0x1ffc, -- 0x2126, 0x2126, -- 0x212a, 0x212b, -- 0x2132, 0x2132, -- 0x214e, 0x214e, -- 0x2160, 0x217f, -- 0x2183, 0x2184, -- 0x24b6, 0x24e9, -- 0x2c00, 0x2c2e, -- 0x2c30, 0x2c5e, -- 0x2c60, 0x2c70, -- 0x2c72, 0x2c73, -- 0x2c75, 0x2c76, -- 0x2c7e, 0x2ce3, -- 0x2ceb, 0x2cee, -- 0x2d00, 0x2d25, -- 0xa640, 0xa66d, -- 0xa680, 0xa697, -- 0xa722, 0xa72f, -- 0xa732, 0xa76f, -- 0xa779, 0xa787, -- 0xa78b, 0xa78d, -- 0xa790, 0xa791, -- 0xa7a0, 0xa7a9, -- 0xfb00, 0xfb06, -- 0xfb13, 0xfb17, -- 0xff21, 0xff3a, -- 0xff41, 0xff5a, -- 0x10400, 0x1044f, --}; /* CR_Changes_When_Casemapped */ -- --/* 'ID_Start': Derived Property */ --static const OnigCodePoint CR_ID_Start[] = { -- 437, -- 0x0041, 0x005a, -- 0x0061, 0x007a, -- 0x00aa, 0x00aa, -- 0x00b5, 0x00b5, -- 0x00ba, 0x00ba, -- 0x00c0, 0x00d6, -- 0x00d8, 0x00f6, -- 0x00f8, 0x02c1, -- 0x02c6, 0x02d1, -- 0x02e0, 0x02e4, -- 0x02ec, 0x02ec, -- 0x02ee, 0x02ee, -- 0x0370, 0x0374, -- 0x0376, 0x0377, -- 0x037a, 0x037d, -- 0x0386, 0x0386, -- 0x0388, 0x038a, -- 0x038c, 0x038c, -- 0x038e, 0x03a1, -- 0x03a3, 0x03f5, -- 0x03f7, 0x0481, -- 0x048a, 0x0527, -- 0x0531, 0x0556, -- 0x0559, 0x0559, -- 0x0561, 0x0587, -- 0x05d0, 0x05ea, -- 0x05f0, 0x05f2, -- 0x0620, 0x064a, -- 0x066e, 0x066f, -- 0x0671, 0x06d3, -- 0x06d5, 0x06d5, -- 0x06e5, 0x06e6, -- 0x06ee, 0x06ef, -- 0x06fa, 0x06fc, -- 0x06ff, 0x06ff, -- 0x0710, 0x0710, -- 0x0712, 0x072f, -- 0x074d, 0x07a5, -- 0x07b1, 0x07b1, -- 0x07ca, 0x07ea, -- 0x07f4, 0x07f5, -- 0x07fa, 0x07fa, -- 0x0800, 0x0815, -- 0x081a, 0x081a, -- 0x0824, 0x0824, -- 0x0828, 0x0828, -- 0x0840, 0x0858, -- 0x0904, 0x0939, -- 0x093d, 0x093d, -- 0x0950, 0x0950, -- 0x0958, 0x0961, -- 0x0971, 0x0977, -- 0x0979, 0x097f, -- 0x0985, 0x098c, -- 0x098f, 0x0990, -- 0x0993, 0x09a8, -- 0x09aa, 0x09b0, -- 0x09b2, 0x09b2, -- 0x09b6, 0x09b9, -- 0x09bd, 0x09bd, -- 0x09ce, 0x09ce, -- 0x09dc, 0x09dd, -- 0x09df, 0x09e1, -- 0x09f0, 0x09f1, -- 0x0a05, 0x0a0a, -- 0x0a0f, 0x0a10, -- 0x0a13, 0x0a28, -- 0x0a2a, 0x0a30, -- 0x0a32, 0x0a33, -- 0x0a35, 0x0a36, -- 0x0a38, 0x0a39, -- 0x0a59, 0x0a5c, -- 0x0a5e, 0x0a5e, -- 0x0a72, 0x0a74, -- 0x0a85, 0x0a8d, -- 0x0a8f, 0x0a91, -- 0x0a93, 0x0aa8, -- 0x0aaa, 0x0ab0, -- 0x0ab2, 0x0ab3, -- 0x0ab5, 0x0ab9, -- 0x0abd, 0x0abd, -- 0x0ad0, 0x0ad0, -- 0x0ae0, 0x0ae1, -- 0x0b05, 0x0b0c, -- 0x0b0f, 0x0b10, -- 0x0b13, 0x0b28, -- 0x0b2a, 0x0b30, -- 0x0b32, 0x0b33, -- 0x0b35, 0x0b39, -- 0x0b3d, 0x0b3d, -- 0x0b5c, 0x0b5d, -- 0x0b5f, 0x0b61, -- 0x0b71, 0x0b71, -- 0x0b83, 0x0b83, -- 0x0b85, 0x0b8a, -- 0x0b8e, 0x0b90, -- 0x0b92, 0x0b95, -- 0x0b99, 0x0b9a, -- 0x0b9c, 0x0b9c, -- 0x0b9e, 0x0b9f, -- 0x0ba3, 0x0ba4, -- 0x0ba8, 0x0baa, -- 0x0bae, 0x0bb9, -- 0x0bd0, 0x0bd0, -- 0x0c05, 0x0c0c, -- 0x0c0e, 0x0c10, -- 0x0c12, 0x0c28, -- 0x0c2a, 0x0c33, -- 0x0c35, 0x0c39, -- 0x0c3d, 0x0c3d, -- 0x0c58, 0x0c59, -- 0x0c60, 0x0c61, -- 0x0c85, 0x0c8c, -- 0x0c8e, 0x0c90, -- 0x0c92, 0x0ca8, -- 0x0caa, 0x0cb3, -- 0x0cb5, 0x0cb9, -- 0x0cbd, 0x0cbd, -- 0x0cde, 0x0cde, -- 0x0ce0, 0x0ce1, -- 0x0cf1, 0x0cf2, -- 0x0d05, 0x0d0c, -- 0x0d0e, 0x0d10, -- 0x0d12, 0x0d3a, -- 0x0d3d, 0x0d3d, -- 0x0d4e, 0x0d4e, -- 0x0d60, 0x0d61, -- 0x0d7a, 0x0d7f, -- 0x0d85, 0x0d96, -- 0x0d9a, 0x0db1, -- 0x0db3, 0x0dbb, -- 0x0dbd, 0x0dbd, -- 0x0dc0, 0x0dc6, -- 0x0e01, 0x0e30, -- 0x0e32, 0x0e33, -- 0x0e40, 0x0e46, -- 0x0e81, 0x0e82, -- 0x0e84, 0x0e84, -- 0x0e87, 0x0e88, -- 0x0e8a, 0x0e8a, -- 0x0e8d, 0x0e8d, -- 0x0e94, 0x0e97, -- 0x0e99, 0x0e9f, -- 0x0ea1, 0x0ea3, -- 0x0ea5, 0x0ea5, -- 0x0ea7, 0x0ea7, -- 0x0eaa, 0x0eab, -- 0x0ead, 0x0eb0, -- 0x0eb2, 0x0eb3, -- 0x0ebd, 0x0ebd, -- 0x0ec0, 0x0ec4, -- 0x0ec6, 0x0ec6, -- 0x0edc, 0x0edd, -- 0x0f00, 0x0f00, -- 0x0f40, 0x0f47, -- 0x0f49, 0x0f6c, -- 0x0f88, 0x0f8c, -- 0x1000, 0x102a, -- 0x103f, 0x103f, -- 0x1050, 0x1055, -- 0x105a, 0x105d, -- 0x1061, 0x1061, -- 0x1065, 0x1066, -- 0x106e, 0x1070, -- 0x1075, 0x1081, -- 0x108e, 0x108e, -- 0x10a0, 0x10c5, -- 0x10d0, 0x10fa, -- 0x10fc, 0x10fc, -- 0x1100, 0x1248, -- 0x124a, 0x124d, -- 0x1250, 0x1256, -- 0x1258, 0x1258, -- 0x125a, 0x125d, -- 0x1260, 0x1288, -- 0x128a, 0x128d, -- 0x1290, 0x12b0, -- 0x12b2, 0x12b5, -- 0x12b8, 0x12be, -- 0x12c0, 0x12c0, -- 0x12c2, 0x12c5, -- 0x12c8, 0x12d6, -- 0x12d8, 0x1310, -- 0x1312, 0x1315, -- 0x1318, 0x135a, -- 0x1380, 0x138f, -- 0x13a0, 0x13f4, -- 0x1401, 0x166c, -- 0x166f, 0x167f, -- 0x1681, 0x169a, -- 0x16a0, 0x16ea, -- 0x16ee, 0x16f0, -- 0x1700, 0x170c, -- 0x170e, 0x1711, -- 0x1720, 0x1731, -- 0x1740, 0x1751, -- 0x1760, 0x176c, -- 0x176e, 0x1770, -- 0x1780, 0x17b3, -- 0x17d7, 0x17d7, -- 0x17dc, 0x17dc, -- 0x1820, 0x1877, -- 0x1880, 0x18a8, -- 0x18aa, 0x18aa, -- 0x18b0, 0x18f5, -- 0x1900, 0x191c, -- 0x1950, 0x196d, -- 0x1970, 0x1974, -- 0x1980, 0x19ab, -- 0x19c1, 0x19c7, -- 0x1a00, 0x1a16, -- 0x1a20, 0x1a54, -- 0x1aa7, 0x1aa7, -- 0x1b05, 0x1b33, -- 0x1b45, 0x1b4b, -- 0x1b83, 0x1ba0, -- 0x1bae, 0x1baf, -- 0x1bc0, 0x1be5, -- 0x1c00, 0x1c23, -- 0x1c4d, 0x1c4f, -- 0x1c5a, 0x1c7d, -- 0x1ce9, 0x1cec, -- 0x1cee, 0x1cf1, -- 0x1d00, 0x1dbf, -- 0x1e00, 0x1f15, -- 0x1f18, 0x1f1d, -- 0x1f20, 0x1f45, -- 0x1f48, 0x1f4d, -- 0x1f50, 0x1f57, -- 0x1f59, 0x1f59, -- 0x1f5b, 0x1f5b, -- 0x1f5d, 0x1f5d, -- 0x1f5f, 0x1f7d, -- 0x1f80, 0x1fb4, -- 0x1fb6, 0x1fbc, -- 0x1fbe, 0x1fbe, -- 0x1fc2, 0x1fc4, -- 0x1fc6, 0x1fcc, -- 0x1fd0, 0x1fd3, -- 0x1fd6, 0x1fdb, -- 0x1fe0, 0x1fec, -- 0x1ff2, 0x1ff4, -- 0x1ff6, 0x1ffc, -- 0x2071, 0x2071, -- 0x207f, 0x207f, -- 0x2090, 0x209c, -- 0x2102, 0x2102, -- 0x2107, 0x2107, -- 0x210a, 0x2113, -- 0x2115, 0x2115, -- 0x2118, 0x211d, -- 0x2124, 0x2124, -- 0x2126, 0x2126, -- 0x2128, 0x2128, -- 0x212a, 0x2139, -- 0x213c, 0x213f, -- 0x2145, 0x2149, -- 0x214e, 0x214e, -- 0x2160, 0x2188, -- 0x2c00, 0x2c2e, -- 0x2c30, 0x2c5e, -- 0x2c60, 0x2ce4, -- 0x2ceb, 0x2cee, -- 0x2d00, 0x2d25, -- 0x2d30, 0x2d65, -- 0x2d6f, 0x2d6f, -- 0x2d80, 0x2d96, -- 0x2da0, 0x2da6, -- 0x2da8, 0x2dae, -- 0x2db0, 0x2db6, -- 0x2db8, 0x2dbe, -- 0x2dc0, 0x2dc6, -- 0x2dc8, 0x2dce, -- 0x2dd0, 0x2dd6, -- 0x2dd8, 0x2dde, -- 0x3005, 0x3007, -- 0x3021, 0x3029, -- 0x3031, 0x3035, -- 0x3038, 0x303c, -- 0x3041, 0x3096, -- 0x309b, 0x309f, -- 0x30a1, 0x30fa, -- 0x30fc, 0x30ff, -- 0x3105, 0x312d, -- 0x3131, 0x318e, -- 0x31a0, 0x31ba, -- 0x31f0, 0x31ff, -- 0x3400, 0x4db5, -- 0x4e00, 0x9fcb, -- 0xa000, 0xa48c, -- 0xa4d0, 0xa4fd, -- 0xa500, 0xa60c, -- 0xa610, 0xa61f, -- 0xa62a, 0xa62b, -- 0xa640, 0xa66e, -- 0xa67f, 0xa697, -- 0xa6a0, 0xa6ef, -- 0xa717, 0xa71f, -- 0xa722, 0xa788, -- 0xa78b, 0xa78e, -- 0xa790, 0xa791, -- 0xa7a0, 0xa7a9, -- 0xa7fa, 0xa801, -- 0xa803, 0xa805, -- 0xa807, 0xa80a, -- 0xa80c, 0xa822, -- 0xa840, 0xa873, -- 0xa882, 0xa8b3, -- 0xa8f2, 0xa8f7, -- 0xa8fb, 0xa8fb, -- 0xa90a, 0xa925, -- 0xa930, 0xa946, -- 0xa960, 0xa97c, -- 0xa984, 0xa9b2, -- 0xa9cf, 0xa9cf, -- 0xaa00, 0xaa28, -- 0xaa40, 0xaa42, -- 0xaa44, 0xaa4b, -- 0xaa60, 0xaa76, -- 0xaa7a, 0xaa7a, -- 0xaa80, 0xaaaf, -- 0xaab1, 0xaab1, -- 0xaab5, 0xaab6, -- 0xaab9, 0xaabd, -- 0xaac0, 0xaac0, -- 0xaac2, 0xaac2, -- 0xaadb, 0xaadd, -- 0xab01, 0xab06, -- 0xab09, 0xab0e, -- 0xab11, 0xab16, -- 0xab20, 0xab26, -- 0xab28, 0xab2e, -- 0xabc0, 0xabe2, -- 0xac00, 0xd7a3, -- 0xd7b0, 0xd7c6, -- 0xd7cb, 0xd7fb, -- 0xf900, 0xfa2d, -- 0xfa30, 0xfa6d, -- 0xfa70, 0xfad9, -- 0xfb00, 0xfb06, -- 0xfb13, 0xfb17, -- 0xfb1d, 0xfb1d, -- 0xfb1f, 0xfb28, -- 0xfb2a, 0xfb36, -- 0xfb38, 0xfb3c, -- 0xfb3e, 0xfb3e, -- 0xfb40, 0xfb41, -- 0xfb43, 0xfb44, -- 0xfb46, 0xfbb1, -- 0xfbd3, 0xfd3d, -- 0xfd50, 0xfd8f, -- 0xfd92, 0xfdc7, -- 0xfdf0, 0xfdfb, -- 0xfe70, 0xfe74, -- 0xfe76, 0xfefc, -- 0xff21, 0xff3a, -- 0xff41, 0xff5a, -- 0xff66, 0xffbe, -- 0xffc2, 0xffc7, -- 0xffca, 0xffcf, -- 0xffd2, 0xffd7, -- 0xffda, 0xffdc, -- 0x10000, 0x1000b, -- 0x1000d, 0x10026, -- 0x10028, 0x1003a, -- 0x1003c, 0x1003d, -- 0x1003f, 0x1004d, -- 0x10050, 0x1005d, -- 0x10080, 0x100fa, -- 0x10140, 0x10174, -- 0x10280, 0x1029c, -- 0x102a0, 0x102d0, -- 0x10300, 0x1031e, -- 0x10330, 0x1034a, -- 0x10380, 0x1039d, -- 0x103a0, 0x103c3, -- 0x103c8, 0x103cf, -- 0x103d1, 0x103d5, -- 0x10400, 0x1049d, -- 0x10800, 0x10805, -- 0x10808, 0x10808, -- 0x1080a, 0x10835, -- 0x10837, 0x10838, -- 0x1083c, 0x1083c, -- 0x1083f, 0x10855, -- 0x10900, 0x10915, -- 0x10920, 0x10939, -- 0x10a00, 0x10a00, -- 0x10a10, 0x10a13, -- 0x10a15, 0x10a17, -- 0x10a19, 0x10a33, -- 0x10a60, 0x10a7c, -- 0x10b00, 0x10b35, -- 0x10b40, 0x10b55, -- 0x10b60, 0x10b72, -- 0x10c00, 0x10c48, -- 0x11003, 0x11037, -- 0x11083, 0x110af, -- 0x12000, 0x1236e, -- 0x12400, 0x12462, -- 0x13000, 0x1342e, -- 0x16800, 0x16a38, -- 0x1b000, 0x1b001, -- 0x1d400, 0x1d454, -- 0x1d456, 0x1d49c, -- 0x1d49e, 0x1d49f, -- 0x1d4a2, 0x1d4a2, -- 0x1d4a5, 0x1d4a6, -- 0x1d4a9, 0x1d4ac, -- 0x1d4ae, 0x1d4b9, -- 0x1d4bb, 0x1d4bb, -- 0x1d4bd, 0x1d4c3, -- 0x1d4c5, 0x1d505, -- 0x1d507, 0x1d50a, -- 0x1d50d, 0x1d514, -- 0x1d516, 0x1d51c, -- 0x1d51e, 0x1d539, -- 0x1d53b, 0x1d53e, -- 0x1d540, 0x1d544, -- 0x1d546, 0x1d546, -- 0x1d54a, 0x1d550, -- 0x1d552, 0x1d6a5, -- 0x1d6a8, 0x1d6c0, -- 0x1d6c2, 0x1d6da, -- 0x1d6dc, 0x1d6fa, -- 0x1d6fc, 0x1d714, -- 0x1d716, 0x1d734, -- 0x1d736, 0x1d74e, -- 0x1d750, 0x1d76e, -- 0x1d770, 0x1d788, -- 0x1d78a, 0x1d7a8, -- 0x1d7aa, 0x1d7c2, -- 0x1d7c4, 0x1d7cb, -- 0x20000, 0x2a6d6, -- 0x2a700, 0x2b734, -- 0x2b740, 0x2b81d, -- 0x2f800, 0x2fa1d, --}; /* CR_ID_Start */ -- --/* 'ID_Continue': Derived Property */ --static const OnigCodePoint CR_ID_Continue[] = { -- 514, -- 0x0030, 0x0039, -- 0x0041, 0x005a, -- 0x005f, 0x005f, -- 0x0061, 0x007a, -- 0x00aa, 0x00aa, -- 0x00b5, 0x00b5, -- 0x00b7, 0x00b7, -- 0x00ba, 0x00ba, -- 0x00c0, 0x00d6, -- 0x00d8, 0x00f6, -- 0x00f8, 0x02c1, -- 0x02c6, 0x02d1, -- 0x02e0, 0x02e4, -- 0x02ec, 0x02ec, -- 0x02ee, 0x02ee, -- 0x0300, 0x0374, -- 0x0376, 0x0377, -- 0x037a, 0x037d, -- 0x0386, 0x038a, -- 0x038c, 0x038c, -- 0x038e, 0x03a1, -- 0x03a3, 0x03f5, -- 0x03f7, 0x0481, -- 0x0483, 0x0487, -- 0x048a, 0x0527, -- 0x0531, 0x0556, -- 0x0559, 0x0559, -- 0x0561, 0x0587, -- 0x0591, 0x05bd, -- 0x05bf, 0x05bf, -- 0x05c1, 0x05c2, -- 0x05c4, 0x05c5, -- 0x05c7, 0x05c7, -- 0x05d0, 0x05ea, -- 0x05f0, 0x05f2, -- 0x0610, 0x061a, -- 0x0620, 0x0669, -- 0x066e, 0x06d3, -- 0x06d5, 0x06dc, -- 0x06df, 0x06e8, -- 0x06ea, 0x06fc, -- 0x06ff, 0x06ff, -- 0x0710, 0x074a, -- 0x074d, 0x07b1, -- 0x07c0, 0x07f5, -- 0x07fa, 0x07fa, -- 0x0800, 0x082d, -- 0x0840, 0x085b, -- 0x0900, 0x0963, -- 0x0966, 0x096f, -- 0x0971, 0x0977, -- 0x0979, 0x097f, -- 0x0981, 0x0983, -- 0x0985, 0x098c, -- 0x098f, 0x0990, -- 0x0993, 0x09a8, -- 0x09aa, 0x09b0, -- 0x09b2, 0x09b2, -- 0x09b6, 0x09b9, -- 0x09bc, 0x09c4, -- 0x09c7, 0x09c8, -- 0x09cb, 0x09ce, -- 0x09d7, 0x09d7, -- 0x09dc, 0x09dd, -- 0x09df, 0x09e3, -- 0x09e6, 0x09f1, -- 0x0a01, 0x0a03, -- 0x0a05, 0x0a0a, -- 0x0a0f, 0x0a10, -- 0x0a13, 0x0a28, -- 0x0a2a, 0x0a30, -- 0x0a32, 0x0a33, -- 0x0a35, 0x0a36, -- 0x0a38, 0x0a39, -- 0x0a3c, 0x0a3c, -- 0x0a3e, 0x0a42, -- 0x0a47, 0x0a48, -- 0x0a4b, 0x0a4d, -- 0x0a51, 0x0a51, -- 0x0a59, 0x0a5c, -- 0x0a5e, 0x0a5e, -- 0x0a66, 0x0a75, -- 0x0a81, 0x0a83, -- 0x0a85, 0x0a8d, -- 0x0a8f, 0x0a91, -- 0x0a93, 0x0aa8, -- 0x0aaa, 0x0ab0, -- 0x0ab2, 0x0ab3, -- 0x0ab5, 0x0ab9, -- 0x0abc, 0x0ac5, -- 0x0ac7, 0x0ac9, -- 0x0acb, 0x0acd, -- 0x0ad0, 0x0ad0, -- 0x0ae0, 0x0ae3, -- 0x0ae6, 0x0aef, -- 0x0b01, 0x0b03, -- 0x0b05, 0x0b0c, -- 0x0b0f, 0x0b10, -- 0x0b13, 0x0b28, -- 0x0b2a, 0x0b30, -- 0x0b32, 0x0b33, -- 0x0b35, 0x0b39, -- 0x0b3c, 0x0b44, -- 0x0b47, 0x0b48, -- 0x0b4b, 0x0b4d, -- 0x0b56, 0x0b57, -- 0x0b5c, 0x0b5d, -- 0x0b5f, 0x0b63, -- 0x0b66, 0x0b6f, -- 0x0b71, 0x0b71, -- 0x0b82, 0x0b83, -- 0x0b85, 0x0b8a, -- 0x0b8e, 0x0b90, -- 0x0b92, 0x0b95, -- 0x0b99, 0x0b9a, -- 0x0b9c, 0x0b9c, -- 0x0b9e, 0x0b9f, -- 0x0ba3, 0x0ba4, -- 0x0ba8, 0x0baa, -- 0x0bae, 0x0bb9, -- 0x0bbe, 0x0bc2, -- 0x0bc6, 0x0bc8, -- 0x0bca, 0x0bcd, -- 0x0bd0, 0x0bd0, -- 0x0bd7, 0x0bd7, -- 0x0be6, 0x0bef, -- 0x0c01, 0x0c03, -- 0x0c05, 0x0c0c, -- 0x0c0e, 0x0c10, -- 0x0c12, 0x0c28, -- 0x0c2a, 0x0c33, -- 0x0c35, 0x0c39, -- 0x0c3d, 0x0c44, -- 0x0c46, 0x0c48, -- 0x0c4a, 0x0c4d, -- 0x0c55, 0x0c56, -- 0x0c58, 0x0c59, -- 0x0c60, 0x0c63, -- 0x0c66, 0x0c6f, -- 0x0c82, 0x0c83, -- 0x0c85, 0x0c8c, -- 0x0c8e, 0x0c90, -- 0x0c92, 0x0ca8, -- 0x0caa, 0x0cb3, -- 0x0cb5, 0x0cb9, -- 0x0cbc, 0x0cc4, -- 0x0cc6, 0x0cc8, -- 0x0cca, 0x0ccd, -- 0x0cd5, 0x0cd6, -- 0x0cde, 0x0cde, -- 0x0ce0, 0x0ce3, -- 0x0ce6, 0x0cef, -- 0x0cf1, 0x0cf2, -- 0x0d02, 0x0d03, -- 0x0d05, 0x0d0c, -- 0x0d0e, 0x0d10, -- 0x0d12, 0x0d3a, -- 0x0d3d, 0x0d44, -- 0x0d46, 0x0d48, -- 0x0d4a, 0x0d4e, -- 0x0d57, 0x0d57, -- 0x0d60, 0x0d63, -- 0x0d66, 0x0d6f, -- 0x0d7a, 0x0d7f, -- 0x0d82, 0x0d83, -- 0x0d85, 0x0d96, -- 0x0d9a, 0x0db1, -- 0x0db3, 0x0dbb, -- 0x0dbd, 0x0dbd, -- 0x0dc0, 0x0dc6, -- 0x0dca, 0x0dca, -- 0x0dcf, 0x0dd4, -- 0x0dd6, 0x0dd6, -- 0x0dd8, 0x0ddf, -- 0x0df2, 0x0df3, -- 0x0e01, 0x0e3a, -- 0x0e40, 0x0e4e, -- 0x0e50, 0x0e59, -- 0x0e81, 0x0e82, -- 0x0e84, 0x0e84, -- 0x0e87, 0x0e88, -- 0x0e8a, 0x0e8a, -- 0x0e8d, 0x0e8d, -- 0x0e94, 0x0e97, -- 0x0e99, 0x0e9f, -- 0x0ea1, 0x0ea3, -- 0x0ea5, 0x0ea5, -- 0x0ea7, 0x0ea7, -- 0x0eaa, 0x0eab, -- 0x0ead, 0x0eb9, -- 0x0ebb, 0x0ebd, -- 0x0ec0, 0x0ec4, -- 0x0ec6, 0x0ec6, -- 0x0ec8, 0x0ecd, -- 0x0ed0, 0x0ed9, -- 0x0edc, 0x0edd, -- 0x0f00, 0x0f00, -- 0x0f18, 0x0f19, -- 0x0f20, 0x0f29, -- 0x0f35, 0x0f35, -- 0x0f37, 0x0f37, -- 0x0f39, 0x0f39, -- 0x0f3e, 0x0f47, -- 0x0f49, 0x0f6c, -- 0x0f71, 0x0f84, -- 0x0f86, 0x0f97, -- 0x0f99, 0x0fbc, -- 0x0fc6, 0x0fc6, -- 0x1000, 0x1049, -- 0x1050, 0x109d, -- 0x10a0, 0x10c5, -- 0x10d0, 0x10fa, -- 0x10fc, 0x10fc, -- 0x1100, 0x1248, -- 0x124a, 0x124d, -- 0x1250, 0x1256, -- 0x1258, 0x1258, -- 0x125a, 0x125d, -- 0x1260, 0x1288, -- 0x128a, 0x128d, -- 0x1290, 0x12b0, -- 0x12b2, 0x12b5, -- 0x12b8, 0x12be, -- 0x12c0, 0x12c0, -- 0x12c2, 0x12c5, -- 0x12c8, 0x12d6, -- 0x12d8, 0x1310, -- 0x1312, 0x1315, -- 0x1318, 0x135a, -- 0x135d, 0x135f, -- 0x1369, 0x1371, -- 0x1380, 0x138f, -- 0x13a0, 0x13f4, -- 0x1401, 0x166c, -- 0x166f, 0x167f, -- 0x1681, 0x169a, -- 0x16a0, 0x16ea, -- 0x16ee, 0x16f0, -- 0x1700, 0x170c, -- 0x170e, 0x1714, -- 0x1720, 0x1734, -- 0x1740, 0x1753, -- 0x1760, 0x176c, -- 0x176e, 0x1770, -- 0x1772, 0x1773, -- 0x1780, 0x17b3, -- 0x17b6, 0x17d3, -- 0x17d7, 0x17d7, -- 0x17dc, 0x17dd, -- 0x17e0, 0x17e9, -- 0x180b, 0x180d, -- 0x1810, 0x1819, -- 0x1820, 0x1877, -- 0x1880, 0x18aa, -- 0x18b0, 0x18f5, -- 0x1900, 0x191c, -- 0x1920, 0x192b, -- 0x1930, 0x193b, -- 0x1946, 0x196d, -- 0x1970, 0x1974, -- 0x1980, 0x19ab, -- 0x19b0, 0x19c9, -- 0x19d0, 0x19da, -- 0x1a00, 0x1a1b, -- 0x1a20, 0x1a5e, -- 0x1a60, 0x1a7c, -- 0x1a7f, 0x1a89, -- 0x1a90, 0x1a99, -- 0x1aa7, 0x1aa7, -- 0x1b00, 0x1b4b, -- 0x1b50, 0x1b59, -- 0x1b6b, 0x1b73, -- 0x1b80, 0x1baa, -- 0x1bae, 0x1bb9, -- 0x1bc0, 0x1bf3, -- 0x1c00, 0x1c37, -- 0x1c40, 0x1c49, -- 0x1c4d, 0x1c7d, -- 0x1cd0, 0x1cd2, -- 0x1cd4, 0x1cf2, -- 0x1d00, 0x1de6, -- 0x1dfc, 0x1f15, -- 0x1f18, 0x1f1d, -- 0x1f20, 0x1f45, -- 0x1f48, 0x1f4d, -- 0x1f50, 0x1f57, -- 0x1f59, 0x1f59, -- 0x1f5b, 0x1f5b, -- 0x1f5d, 0x1f5d, -- 0x1f5f, 0x1f7d, -- 0x1f80, 0x1fb4, -- 0x1fb6, 0x1fbc, -- 0x1fbe, 0x1fbe, -- 0x1fc2, 0x1fc4, -- 0x1fc6, 0x1fcc, -- 0x1fd0, 0x1fd3, -- 0x1fd6, 0x1fdb, -- 0x1fe0, 0x1fec, -- 0x1ff2, 0x1ff4, -- 0x1ff6, 0x1ffc, -- 0x203f, 0x2040, -- 0x2054, 0x2054, -- 0x2071, 0x2071, -- 0x207f, 0x207f, -- 0x2090, 0x209c, -- 0x20d0, 0x20dc, -- 0x20e1, 0x20e1, -- 0x20e5, 0x20f0, -- 0x2102, 0x2102, -- 0x2107, 0x2107, -- 0x210a, 0x2113, -- 0x2115, 0x2115, -- 0x2118, 0x211d, -- 0x2124, 0x2124, -- 0x2126, 0x2126, -- 0x2128, 0x2128, -- 0x212a, 0x2139, -- 0x213c, 0x213f, -- 0x2145, 0x2149, -- 0x214e, 0x214e, -- 0x2160, 0x2188, -- 0x2c00, 0x2c2e, -- 0x2c30, 0x2c5e, -- 0x2c60, 0x2ce4, -- 0x2ceb, 0x2cf1, -- 0x2d00, 0x2d25, -- 0x2d30, 0x2d65, -- 0x2d6f, 0x2d6f, -- 0x2d7f, 0x2d96, -- 0x2da0, 0x2da6, -- 0x2da8, 0x2dae, -- 0x2db0, 0x2db6, -- 0x2db8, 0x2dbe, -- 0x2dc0, 0x2dc6, -- 0x2dc8, 0x2dce, -- 0x2dd0, 0x2dd6, -- 0x2dd8, 0x2dde, -- 0x2de0, 0x2dff, -- 0x3005, 0x3007, -- 0x3021, 0x302f, -- 0x3031, 0x3035, -- 0x3038, 0x303c, -- 0x3041, 0x3096, -- 0x3099, 0x309f, -- 0x30a1, 0x30fa, -- 0x30fc, 0x30ff, -- 0x3105, 0x312d, -- 0x3131, 0x318e, -- 0x31a0, 0x31ba, -- 0x31f0, 0x31ff, -- 0x3400, 0x4db5, -- 0x4e00, 0x9fcb, -- 0xa000, 0xa48c, -- 0xa4d0, 0xa4fd, -- 0xa500, 0xa60c, -- 0xa610, 0xa62b, -- 0xa640, 0xa66f, -- 0xa67c, 0xa67d, -- 0xa67f, 0xa697, -- 0xa6a0, 0xa6f1, -- 0xa717, 0xa71f, -- 0xa722, 0xa788, -- 0xa78b, 0xa78e, -- 0xa790, 0xa791, -- 0xa7a0, 0xa7a9, -- 0xa7fa, 0xa827, -- 0xa840, 0xa873, -- 0xa880, 0xa8c4, -- 0xa8d0, 0xa8d9, -- 0xa8e0, 0xa8f7, -- 0xa8fb, 0xa8fb, -- 0xa900, 0xa92d, -- 0xa930, 0xa953, -- 0xa960, 0xa97c, -- 0xa980, 0xa9c0, -- 0xa9cf, 0xa9d9, -- 0xaa00, 0xaa36, -- 0xaa40, 0xaa4d, -- 0xaa50, 0xaa59, -- 0xaa60, 0xaa76, -- 0xaa7a, 0xaa7b, -- 0xaa80, 0xaac2, -- 0xaadb, 0xaadd, -- 0xab01, 0xab06, -- 0xab09, 0xab0e, -- 0xab11, 0xab16, -- 0xab20, 0xab26, -- 0xab28, 0xab2e, -- 0xabc0, 0xabea, -- 0xabec, 0xabed, -- 0xabf0, 0xabf9, -- 0xac00, 0xd7a3, -- 0xd7b0, 0xd7c6, -- 0xd7cb, 0xd7fb, -- 0xf900, 0xfa2d, -- 0xfa30, 0xfa6d, -- 0xfa70, 0xfad9, -- 0xfb00, 0xfb06, -- 0xfb13, 0xfb17, -- 0xfb1d, 0xfb28, -- 0xfb2a, 0xfb36, -- 0xfb38, 0xfb3c, -- 0xfb3e, 0xfb3e, -- 0xfb40, 0xfb41, -- 0xfb43, 0xfb44, -- 0xfb46, 0xfbb1, -- 0xfbd3, 0xfd3d, -- 0xfd50, 0xfd8f, -- 0xfd92, 0xfdc7, -- 0xfdf0, 0xfdfb, -- 0xfe00, 0xfe0f, -- 0xfe20, 0xfe26, -- 0xfe33, 0xfe34, -- 0xfe4d, 0xfe4f, -- 0xfe70, 0xfe74, -- 0xfe76, 0xfefc, -- 0xff10, 0xff19, -- 0xff21, 0xff3a, -- 0xff3f, 0xff3f, -- 0xff41, 0xff5a, -- 0xff66, 0xffbe, -- 0xffc2, 0xffc7, -- 0xffca, 0xffcf, -- 0xffd2, 0xffd7, -- 0xffda, 0xffdc, -- 0x10000, 0x1000b, -- 0x1000d, 0x10026, -- 0x10028, 0x1003a, -- 0x1003c, 0x1003d, -- 0x1003f, 0x1004d, -- 0x10050, 0x1005d, -- 0x10080, 0x100fa, -- 0x10140, 0x10174, -- 0x101fd, 0x101fd, -- 0x10280, 0x1029c, -- 0x102a0, 0x102d0, -- 0x10300, 0x1031e, -- 0x10330, 0x1034a, -- 0x10380, 0x1039d, -- 0x103a0, 0x103c3, -- 0x103c8, 0x103cf, -- 0x103d1, 0x103d5, -- 0x10400, 0x1049d, -- 0x104a0, 0x104a9, -- 0x10800, 0x10805, -- 0x10808, 0x10808, -- 0x1080a, 0x10835, -- 0x10837, 0x10838, -- 0x1083c, 0x1083c, -- 0x1083f, 0x10855, -- 0x10900, 0x10915, -- 0x10920, 0x10939, -- 0x10a00, 0x10a03, -- 0x10a05, 0x10a06, -- 0x10a0c, 0x10a13, -- 0x10a15, 0x10a17, -- 0x10a19, 0x10a33, -- 0x10a38, 0x10a3a, -- 0x10a3f, 0x10a3f, -- 0x10a60, 0x10a7c, -- 0x10b00, 0x10b35, -- 0x10b40, 0x10b55, -- 0x10b60, 0x10b72, -- 0x10c00, 0x10c48, -- 0x11000, 0x11046, -- 0x11066, 0x1106f, -- 0x11080, 0x110ba, -- 0x12000, 0x1236e, -- 0x12400, 0x12462, -- 0x13000, 0x1342e, -- 0x16800, 0x16a38, -- 0x1b000, 0x1b001, -- 0x1d165, 0x1d169, -- 0x1d16d, 0x1d172, -- 0x1d17b, 0x1d182, -- 0x1d185, 0x1d18b, -- 0x1d1aa, 0x1d1ad, -- 0x1d242, 0x1d244, -- 0x1d400, 0x1d454, -- 0x1d456, 0x1d49c, -- 0x1d49e, 0x1d49f, -- 0x1d4a2, 0x1d4a2, -- 0x1d4a5, 0x1d4a6, -- 0x1d4a9, 0x1d4ac, -- 0x1d4ae, 0x1d4b9, -- 0x1d4bb, 0x1d4bb, -- 0x1d4bd, 0x1d4c3, -- 0x1d4c5, 0x1d505, -- 0x1d507, 0x1d50a, -- 0x1d50d, 0x1d514, -- 0x1d516, 0x1d51c, -- 0x1d51e, 0x1d539, -- 0x1d53b, 0x1d53e, -- 0x1d540, 0x1d544, -- 0x1d546, 0x1d546, -- 0x1d54a, 0x1d550, -- 0x1d552, 0x1d6a5, -- 0x1d6a8, 0x1d6c0, -- 0x1d6c2, 0x1d6da, -- 0x1d6dc, 0x1d6fa, -- 0x1d6fc, 0x1d714, -- 0x1d716, 0x1d734, -- 0x1d736, 0x1d74e, -- 0x1d750, 0x1d76e, -- 0x1d770, 0x1d788, -- 0x1d78a, 0x1d7a8, -- 0x1d7aa, 0x1d7c2, -- 0x1d7c4, 0x1d7cb, -- 0x1d7ce, 0x1d7ff, -- 0x20000, 0x2a6d6, -- 0x2a700, 0x2b734, -- 0x2b740, 0x2b81d, -- 0x2f800, 0x2fa1d, -- 0xe0100, 0xe01ef, --}; /* CR_ID_Continue */ -- --/* 'XID_Start': Derived Property */ --static const OnigCodePoint CR_XID_Start[] = { -- 444, -- 0x0041, 0x005a, -- 0x0061, 0x007a, -- 0x00aa, 0x00aa, -- 0x00b5, 0x00b5, -- 0x00ba, 0x00ba, -- 0x00c0, 0x00d6, -- 0x00d8, 0x00f6, -- 0x00f8, 0x02c1, -- 0x02c6, 0x02d1, -- 0x02e0, 0x02e4, -- 0x02ec, 0x02ec, -- 0x02ee, 0x02ee, -- 0x0370, 0x0374, -- 0x0376, 0x0377, -- 0x037b, 0x037d, -- 0x0386, 0x0386, -- 0x0388, 0x038a, -- 0x038c, 0x038c, -- 0x038e, 0x03a1, -- 0x03a3, 0x03f5, -- 0x03f7, 0x0481, -- 0x048a, 0x0527, -- 0x0531, 0x0556, -- 0x0559, 0x0559, -- 0x0561, 0x0587, -- 0x05d0, 0x05ea, -- 0x05f0, 0x05f2, -- 0x0620, 0x064a, -- 0x066e, 0x066f, -- 0x0671, 0x06d3, -- 0x06d5, 0x06d5, -- 0x06e5, 0x06e6, -- 0x06ee, 0x06ef, -- 0x06fa, 0x06fc, -- 0x06ff, 0x06ff, -- 0x0710, 0x0710, -- 0x0712, 0x072f, -- 0x074d, 0x07a5, -- 0x07b1, 0x07b1, -- 0x07ca, 0x07ea, -- 0x07f4, 0x07f5, -- 0x07fa, 0x07fa, -- 0x0800, 0x0815, -- 0x081a, 0x081a, -- 0x0824, 0x0824, -- 0x0828, 0x0828, -- 0x0840, 0x0858, -- 0x0904, 0x0939, -- 0x093d, 0x093d, -- 0x0950, 0x0950, -- 0x0958, 0x0961, -- 0x0971, 0x0977, -- 0x0979, 0x097f, -- 0x0985, 0x098c, -- 0x098f, 0x0990, -- 0x0993, 0x09a8, -- 0x09aa, 0x09b0, -- 0x09b2, 0x09b2, -- 0x09b6, 0x09b9, -- 0x09bd, 0x09bd, -- 0x09ce, 0x09ce, -- 0x09dc, 0x09dd, -- 0x09df, 0x09e1, -- 0x09f0, 0x09f1, -- 0x0a05, 0x0a0a, -- 0x0a0f, 0x0a10, -- 0x0a13, 0x0a28, -- 0x0a2a, 0x0a30, -- 0x0a32, 0x0a33, -- 0x0a35, 0x0a36, -- 0x0a38, 0x0a39, -- 0x0a59, 0x0a5c, -- 0x0a5e, 0x0a5e, -- 0x0a72, 0x0a74, -- 0x0a85, 0x0a8d, -- 0x0a8f, 0x0a91, -- 0x0a93, 0x0aa8, -- 0x0aaa, 0x0ab0, -- 0x0ab2, 0x0ab3, -- 0x0ab5, 0x0ab9, -- 0x0abd, 0x0abd, -- 0x0ad0, 0x0ad0, -- 0x0ae0, 0x0ae1, -- 0x0b05, 0x0b0c, -- 0x0b0f, 0x0b10, -- 0x0b13, 0x0b28, -- 0x0b2a, 0x0b30, -- 0x0b32, 0x0b33, -- 0x0b35, 0x0b39, -- 0x0b3d, 0x0b3d, -- 0x0b5c, 0x0b5d, -- 0x0b5f, 0x0b61, -- 0x0b71, 0x0b71, -- 0x0b83, 0x0b83, -- 0x0b85, 0x0b8a, -- 0x0b8e, 0x0b90, -- 0x0b92, 0x0b95, -- 0x0b99, 0x0b9a, -- 0x0b9c, 0x0b9c, -- 0x0b9e, 0x0b9f, -- 0x0ba3, 0x0ba4, -- 0x0ba8, 0x0baa, -- 0x0bae, 0x0bb9, -- 0x0bd0, 0x0bd0, -- 0x0c05, 0x0c0c, -- 0x0c0e, 0x0c10, -- 0x0c12, 0x0c28, -- 0x0c2a, 0x0c33, -- 0x0c35, 0x0c39, -- 0x0c3d, 0x0c3d, -- 0x0c58, 0x0c59, -- 0x0c60, 0x0c61, -- 0x0c85, 0x0c8c, -- 0x0c8e, 0x0c90, -- 0x0c92, 0x0ca8, -- 0x0caa, 0x0cb3, -- 0x0cb5, 0x0cb9, -- 0x0cbd, 0x0cbd, -- 0x0cde, 0x0cde, -- 0x0ce0, 0x0ce1, -- 0x0cf1, 0x0cf2, -- 0x0d05, 0x0d0c, -- 0x0d0e, 0x0d10, -- 0x0d12, 0x0d3a, -- 0x0d3d, 0x0d3d, -- 0x0d4e, 0x0d4e, -- 0x0d60, 0x0d61, -- 0x0d7a, 0x0d7f, -- 0x0d85, 0x0d96, -- 0x0d9a, 0x0db1, -- 0x0db3, 0x0dbb, -- 0x0dbd, 0x0dbd, -- 0x0dc0, 0x0dc6, -- 0x0e01, 0x0e30, -- 0x0e32, 0x0e32, -- 0x0e40, 0x0e46, -- 0x0e81, 0x0e82, -- 0x0e84, 0x0e84, -- 0x0e87, 0x0e88, -- 0x0e8a, 0x0e8a, -- 0x0e8d, 0x0e8d, -- 0x0e94, 0x0e97, -- 0x0e99, 0x0e9f, -- 0x0ea1, 0x0ea3, -- 0x0ea5, 0x0ea5, -- 0x0ea7, 0x0ea7, -- 0x0eaa, 0x0eab, -- 0x0ead, 0x0eb0, -- 0x0eb2, 0x0eb2, -- 0x0ebd, 0x0ebd, -- 0x0ec0, 0x0ec4, -- 0x0ec6, 0x0ec6, -- 0x0edc, 0x0edd, -- 0x0f00, 0x0f00, -- 0x0f40, 0x0f47, -- 0x0f49, 0x0f6c, -- 0x0f88, 0x0f8c, -- 0x1000, 0x102a, -- 0x103f, 0x103f, -- 0x1050, 0x1055, -- 0x105a, 0x105d, -- 0x1061, 0x1061, -- 0x1065, 0x1066, -- 0x106e, 0x1070, -- 0x1075, 0x1081, -- 0x108e, 0x108e, -- 0x10a0, 0x10c5, -- 0x10d0, 0x10fa, -- 0x10fc, 0x10fc, -- 0x1100, 0x1248, -- 0x124a, 0x124d, -- 0x1250, 0x1256, -- 0x1258, 0x1258, -- 0x125a, 0x125d, -- 0x1260, 0x1288, -- 0x128a, 0x128d, -- 0x1290, 0x12b0, -- 0x12b2, 0x12b5, -- 0x12b8, 0x12be, -- 0x12c0, 0x12c0, -- 0x12c2, 0x12c5, -- 0x12c8, 0x12d6, -- 0x12d8, 0x1310, -- 0x1312, 0x1315, -- 0x1318, 0x135a, -- 0x1380, 0x138f, -- 0x13a0, 0x13f4, -- 0x1401, 0x166c, -- 0x166f, 0x167f, -- 0x1681, 0x169a, -- 0x16a0, 0x16ea, -- 0x16ee, 0x16f0, -- 0x1700, 0x170c, -- 0x170e, 0x1711, -- 0x1720, 0x1731, -- 0x1740, 0x1751, -- 0x1760, 0x176c, -- 0x176e, 0x1770, -- 0x1780, 0x17b3, -- 0x17d7, 0x17d7, -- 0x17dc, 0x17dc, -- 0x1820, 0x1877, -- 0x1880, 0x18a8, -- 0x18aa, 0x18aa, -- 0x18b0, 0x18f5, -- 0x1900, 0x191c, -- 0x1950, 0x196d, -- 0x1970, 0x1974, -- 0x1980, 0x19ab, -- 0x19c1, 0x19c7, -- 0x1a00, 0x1a16, -- 0x1a20, 0x1a54, -- 0x1aa7, 0x1aa7, -- 0x1b05, 0x1b33, -- 0x1b45, 0x1b4b, -- 0x1b83, 0x1ba0, -- 0x1bae, 0x1baf, -- 0x1bc0, 0x1be5, -- 0x1c00, 0x1c23, -- 0x1c4d, 0x1c4f, -- 0x1c5a, 0x1c7d, -- 0x1ce9, 0x1cec, -- 0x1cee, 0x1cf1, -- 0x1d00, 0x1dbf, -- 0x1e00, 0x1f15, -- 0x1f18, 0x1f1d, -- 0x1f20, 0x1f45, -- 0x1f48, 0x1f4d, -- 0x1f50, 0x1f57, -- 0x1f59, 0x1f59, -- 0x1f5b, 0x1f5b, -- 0x1f5d, 0x1f5d, -- 0x1f5f, 0x1f7d, -- 0x1f80, 0x1fb4, -- 0x1fb6, 0x1fbc, -- 0x1fbe, 0x1fbe, -- 0x1fc2, 0x1fc4, -- 0x1fc6, 0x1fcc, -- 0x1fd0, 0x1fd3, -- 0x1fd6, 0x1fdb, -- 0x1fe0, 0x1fec, -- 0x1ff2, 0x1ff4, -- 0x1ff6, 0x1ffc, -- 0x2071, 0x2071, -- 0x207f, 0x207f, -- 0x2090, 0x209c, -- 0x2102, 0x2102, -- 0x2107, 0x2107, -- 0x210a, 0x2113, -- 0x2115, 0x2115, -- 0x2118, 0x211d, -- 0x2124, 0x2124, -- 0x2126, 0x2126, -- 0x2128, 0x2128, -- 0x212a, 0x2139, -- 0x213c, 0x213f, -- 0x2145, 0x2149, -- 0x214e, 0x214e, -- 0x2160, 0x2188, -- 0x2c00, 0x2c2e, -- 0x2c30, 0x2c5e, -- 0x2c60, 0x2ce4, -- 0x2ceb, 0x2cee, -- 0x2d00, 0x2d25, -- 0x2d30, 0x2d65, -- 0x2d6f, 0x2d6f, -- 0x2d80, 0x2d96, -- 0x2da0, 0x2da6, -- 0x2da8, 0x2dae, -- 0x2db0, 0x2db6, -- 0x2db8, 0x2dbe, -- 0x2dc0, 0x2dc6, -- 0x2dc8, 0x2dce, -- 0x2dd0, 0x2dd6, -- 0x2dd8, 0x2dde, -- 0x3005, 0x3007, -- 0x3021, 0x3029, -- 0x3031, 0x3035, -- 0x3038, 0x303c, -- 0x3041, 0x3096, -- 0x309d, 0x309f, -- 0x30a1, 0x30fa, -- 0x30fc, 0x30ff, -- 0x3105, 0x312d, -- 0x3131, 0x318e, -- 0x31a0, 0x31ba, -- 0x31f0, 0x31ff, -- 0x3400, 0x4db5, -- 0x4e00, 0x9fcb, -- 0xa000, 0xa48c, -- 0xa4d0, 0xa4fd, -- 0xa500, 0xa60c, -- 0xa610, 0xa61f, -- 0xa62a, 0xa62b, -- 0xa640, 0xa66e, -- 0xa67f, 0xa697, -- 0xa6a0, 0xa6ef, -- 0xa717, 0xa71f, -- 0xa722, 0xa788, -- 0xa78b, 0xa78e, -- 0xa790, 0xa791, -- 0xa7a0, 0xa7a9, -- 0xa7fa, 0xa801, -- 0xa803, 0xa805, -- 0xa807, 0xa80a, -- 0xa80c, 0xa822, -- 0xa840, 0xa873, -- 0xa882, 0xa8b3, -- 0xa8f2, 0xa8f7, -- 0xa8fb, 0xa8fb, -- 0xa90a, 0xa925, -- 0xa930, 0xa946, -- 0xa960, 0xa97c, -- 0xa984, 0xa9b2, -- 0xa9cf, 0xa9cf, -- 0xaa00, 0xaa28, -- 0xaa40, 0xaa42, -- 0xaa44, 0xaa4b, -- 0xaa60, 0xaa76, -- 0xaa7a, 0xaa7a, -- 0xaa80, 0xaaaf, -- 0xaab1, 0xaab1, -- 0xaab5, 0xaab6, -- 0xaab9, 0xaabd, -- 0xaac0, 0xaac0, -- 0xaac2, 0xaac2, -- 0xaadb, 0xaadd, -- 0xab01, 0xab06, -- 0xab09, 0xab0e, -- 0xab11, 0xab16, -- 0xab20, 0xab26, -- 0xab28, 0xab2e, -- 0xabc0, 0xabe2, -- 0xac00, 0xd7a3, -- 0xd7b0, 0xd7c6, -- 0xd7cb, 0xd7fb, -- 0xf900, 0xfa2d, -- 0xfa30, 0xfa6d, -- 0xfa70, 0xfad9, -- 0xfb00, 0xfb06, -- 0xfb13, 0xfb17, -- 0xfb1d, 0xfb1d, -- 0xfb1f, 0xfb28, -- 0xfb2a, 0xfb36, -- 0xfb38, 0xfb3c, -- 0xfb3e, 0xfb3e, -- 0xfb40, 0xfb41, -- 0xfb43, 0xfb44, -- 0xfb46, 0xfbb1, -- 0xfbd3, 0xfc5d, -- 0xfc64, 0xfd3d, -- 0xfd50, 0xfd8f, -- 0xfd92, 0xfdc7, -- 0xfdf0, 0xfdf9, -- 0xfe71, 0xfe71, -- 0xfe73, 0xfe73, -- 0xfe77, 0xfe77, -- 0xfe79, 0xfe79, -- 0xfe7b, 0xfe7b, -- 0xfe7d, 0xfe7d, -- 0xfe7f, 0xfefc, -- 0xff21, 0xff3a, -- 0xff41, 0xff5a, -- 0xff66, 0xff9d, -- 0xffa0, 0xffbe, -- 0xffc2, 0xffc7, -- 0xffca, 0xffcf, -- 0xffd2, 0xffd7, -- 0xffda, 0xffdc, -- 0x10000, 0x1000b, -- 0x1000d, 0x10026, -- 0x10028, 0x1003a, -- 0x1003c, 0x1003d, -- 0x1003f, 0x1004d, -- 0x10050, 0x1005d, -- 0x10080, 0x100fa, -- 0x10140, 0x10174, -- 0x10280, 0x1029c, -- 0x102a0, 0x102d0, -- 0x10300, 0x1031e, -- 0x10330, 0x1034a, -- 0x10380, 0x1039d, -- 0x103a0, 0x103c3, -- 0x103c8, 0x103cf, -- 0x103d1, 0x103d5, -- 0x10400, 0x1049d, -- 0x10800, 0x10805, -- 0x10808, 0x10808, -- 0x1080a, 0x10835, -- 0x10837, 0x10838, -- 0x1083c, 0x1083c, -- 0x1083f, 0x10855, -- 0x10900, 0x10915, -- 0x10920, 0x10939, -- 0x10a00, 0x10a00, -- 0x10a10, 0x10a13, -- 0x10a15, 0x10a17, -- 0x10a19, 0x10a33, -- 0x10a60, 0x10a7c, -- 0x10b00, 0x10b35, -- 0x10b40, 0x10b55, -- 0x10b60, 0x10b72, -- 0x10c00, 0x10c48, -- 0x11003, 0x11037, -- 0x11083, 0x110af, -- 0x12000, 0x1236e, -- 0x12400, 0x12462, -- 0x13000, 0x1342e, -- 0x16800, 0x16a38, -- 0x1b000, 0x1b001, -- 0x1d400, 0x1d454, -- 0x1d456, 0x1d49c, -- 0x1d49e, 0x1d49f, -- 0x1d4a2, 0x1d4a2, -- 0x1d4a5, 0x1d4a6, -- 0x1d4a9, 0x1d4ac, -- 0x1d4ae, 0x1d4b9, -- 0x1d4bb, 0x1d4bb, -- 0x1d4bd, 0x1d4c3, -- 0x1d4c5, 0x1d505, -- 0x1d507, 0x1d50a, -- 0x1d50d, 0x1d514, -- 0x1d516, 0x1d51c, -- 0x1d51e, 0x1d539, -- 0x1d53b, 0x1d53e, -- 0x1d540, 0x1d544, -- 0x1d546, 0x1d546, -- 0x1d54a, 0x1d550, -- 0x1d552, 0x1d6a5, -- 0x1d6a8, 0x1d6c0, -- 0x1d6c2, 0x1d6da, -- 0x1d6dc, 0x1d6fa, -- 0x1d6fc, 0x1d714, -- 0x1d716, 0x1d734, -- 0x1d736, 0x1d74e, -- 0x1d750, 0x1d76e, -- 0x1d770, 0x1d788, -- 0x1d78a, 0x1d7a8, -- 0x1d7aa, 0x1d7c2, -- 0x1d7c4, 0x1d7cb, -- 0x20000, 0x2a6d6, -- 0x2a700, 0x2b734, -- 0x2b740, 0x2b81d, -- 0x2f800, 0x2fa1d, --}; /* CR_XID_Start */ -- --/* 'XID_Continue': Derived Property */ --static const OnigCodePoint CR_XID_Continue[] = { -- 521, -- 0x0030, 0x0039, -- 0x0041, 0x005a, -- 0x005f, 0x005f, -- 0x0061, 0x007a, -- 0x00aa, 0x00aa, -- 0x00b5, 0x00b5, -- 0x00b7, 0x00b7, -- 0x00ba, 0x00ba, -- 0x00c0, 0x00d6, -- 0x00d8, 0x00f6, -- 0x00f8, 0x02c1, -- 0x02c6, 0x02d1, -- 0x02e0, 0x02e4, -- 0x02ec, 0x02ec, -- 0x02ee, 0x02ee, -- 0x0300, 0x0374, -- 0x0376, 0x0377, -- 0x037b, 0x037d, -- 0x0386, 0x038a, -- 0x038c, 0x038c, -- 0x038e, 0x03a1, -- 0x03a3, 0x03f5, -- 0x03f7, 0x0481, -- 0x0483, 0x0487, -- 0x048a, 0x0527, -- 0x0531, 0x0556, -- 0x0559, 0x0559, -- 0x0561, 0x0587, -- 0x0591, 0x05bd, -- 0x05bf, 0x05bf, -- 0x05c1, 0x05c2, -- 0x05c4, 0x05c5, -- 0x05c7, 0x05c7, -- 0x05d0, 0x05ea, -- 0x05f0, 0x05f2, -- 0x0610, 0x061a, -- 0x0620, 0x0669, -- 0x066e, 0x06d3, -- 0x06d5, 0x06dc, -- 0x06df, 0x06e8, -- 0x06ea, 0x06fc, -- 0x06ff, 0x06ff, -- 0x0710, 0x074a, -- 0x074d, 0x07b1, -- 0x07c0, 0x07f5, -- 0x07fa, 0x07fa, -- 0x0800, 0x082d, -- 0x0840, 0x085b, -- 0x0900, 0x0963, -- 0x0966, 0x096f, -- 0x0971, 0x0977, -- 0x0979, 0x097f, -- 0x0981, 0x0983, -- 0x0985, 0x098c, -- 0x098f, 0x0990, -- 0x0993, 0x09a8, -- 0x09aa, 0x09b0, -- 0x09b2, 0x09b2, -- 0x09b6, 0x09b9, -- 0x09bc, 0x09c4, -- 0x09c7, 0x09c8, -- 0x09cb, 0x09ce, -- 0x09d7, 0x09d7, -- 0x09dc, 0x09dd, -- 0x09df, 0x09e3, -- 0x09e6, 0x09f1, -- 0x0a01, 0x0a03, -- 0x0a05, 0x0a0a, -- 0x0a0f, 0x0a10, -- 0x0a13, 0x0a28, -- 0x0a2a, 0x0a30, -- 0x0a32, 0x0a33, -- 0x0a35, 0x0a36, -- 0x0a38, 0x0a39, -- 0x0a3c, 0x0a3c, -- 0x0a3e, 0x0a42, -- 0x0a47, 0x0a48, -- 0x0a4b, 0x0a4d, -- 0x0a51, 0x0a51, -- 0x0a59, 0x0a5c, -- 0x0a5e, 0x0a5e, -- 0x0a66, 0x0a75, -- 0x0a81, 0x0a83, -- 0x0a85, 0x0a8d, -- 0x0a8f, 0x0a91, -- 0x0a93, 0x0aa8, -- 0x0aaa, 0x0ab0, -- 0x0ab2, 0x0ab3, -- 0x0ab5, 0x0ab9, -- 0x0abc, 0x0ac5, -- 0x0ac7, 0x0ac9, -- 0x0acb, 0x0acd, -- 0x0ad0, 0x0ad0, -- 0x0ae0, 0x0ae3, -- 0x0ae6, 0x0aef, -- 0x0b01, 0x0b03, -- 0x0b05, 0x0b0c, -- 0x0b0f, 0x0b10, -- 0x0b13, 0x0b28, -- 0x0b2a, 0x0b30, -- 0x0b32, 0x0b33, -- 0x0b35, 0x0b39, -- 0x0b3c, 0x0b44, -- 0x0b47, 0x0b48, -- 0x0b4b, 0x0b4d, -- 0x0b56, 0x0b57, -- 0x0b5c, 0x0b5d, -- 0x0b5f, 0x0b63, -- 0x0b66, 0x0b6f, -- 0x0b71, 0x0b71, -- 0x0b82, 0x0b83, -- 0x0b85, 0x0b8a, -- 0x0b8e, 0x0b90, -- 0x0b92, 0x0b95, -- 0x0b99, 0x0b9a, -- 0x0b9c, 0x0b9c, -- 0x0b9e, 0x0b9f, -- 0x0ba3, 0x0ba4, -- 0x0ba8, 0x0baa, -- 0x0bae, 0x0bb9, -- 0x0bbe, 0x0bc2, -- 0x0bc6, 0x0bc8, -- 0x0bca, 0x0bcd, -- 0x0bd0, 0x0bd0, -- 0x0bd7, 0x0bd7, -- 0x0be6, 0x0bef, -- 0x0c01, 0x0c03, -- 0x0c05, 0x0c0c, -- 0x0c0e, 0x0c10, -- 0x0c12, 0x0c28, -- 0x0c2a, 0x0c33, -- 0x0c35, 0x0c39, -- 0x0c3d, 0x0c44, -- 0x0c46, 0x0c48, -- 0x0c4a, 0x0c4d, -- 0x0c55, 0x0c56, -- 0x0c58, 0x0c59, -- 0x0c60, 0x0c63, -- 0x0c66, 0x0c6f, -- 0x0c82, 0x0c83, -- 0x0c85, 0x0c8c, -- 0x0c8e, 0x0c90, -- 0x0c92, 0x0ca8, -- 0x0caa, 0x0cb3, -- 0x0cb5, 0x0cb9, -- 0x0cbc, 0x0cc4, -- 0x0cc6, 0x0cc8, -- 0x0cca, 0x0ccd, -- 0x0cd5, 0x0cd6, -- 0x0cde, 0x0cde, -- 0x0ce0, 0x0ce3, -- 0x0ce6, 0x0cef, -- 0x0cf1, 0x0cf2, -- 0x0d02, 0x0d03, -- 0x0d05, 0x0d0c, -- 0x0d0e, 0x0d10, -- 0x0d12, 0x0d3a, -- 0x0d3d, 0x0d44, -- 0x0d46, 0x0d48, -- 0x0d4a, 0x0d4e, -- 0x0d57, 0x0d57, -- 0x0d60, 0x0d63, -- 0x0d66, 0x0d6f, -- 0x0d7a, 0x0d7f, -- 0x0d82, 0x0d83, -- 0x0d85, 0x0d96, -- 0x0d9a, 0x0db1, -- 0x0db3, 0x0dbb, -- 0x0dbd, 0x0dbd, -- 0x0dc0, 0x0dc6, -- 0x0dca, 0x0dca, -- 0x0dcf, 0x0dd4, -- 0x0dd6, 0x0dd6, -- 0x0dd8, 0x0ddf, -- 0x0df2, 0x0df3, -- 0x0e01, 0x0e3a, -- 0x0e40, 0x0e4e, -- 0x0e50, 0x0e59, -- 0x0e81, 0x0e82, -- 0x0e84, 0x0e84, -- 0x0e87, 0x0e88, -- 0x0e8a, 0x0e8a, -- 0x0e8d, 0x0e8d, -- 0x0e94, 0x0e97, -- 0x0e99, 0x0e9f, -- 0x0ea1, 0x0ea3, -- 0x0ea5, 0x0ea5, -- 0x0ea7, 0x0ea7, -- 0x0eaa, 0x0eab, -- 0x0ead, 0x0eb9, -- 0x0ebb, 0x0ebd, -- 0x0ec0, 0x0ec4, -- 0x0ec6, 0x0ec6, -- 0x0ec8, 0x0ecd, -- 0x0ed0, 0x0ed9, -- 0x0edc, 0x0edd, -- 0x0f00, 0x0f00, -- 0x0f18, 0x0f19, -- 0x0f20, 0x0f29, -- 0x0f35, 0x0f35, -- 0x0f37, 0x0f37, -- 0x0f39, 0x0f39, -- 0x0f3e, 0x0f47, -- 0x0f49, 0x0f6c, -- 0x0f71, 0x0f84, -- 0x0f86, 0x0f97, -- 0x0f99, 0x0fbc, -- 0x0fc6, 0x0fc6, -- 0x1000, 0x1049, -- 0x1050, 0x109d, -- 0x10a0, 0x10c5, -- 0x10d0, 0x10fa, -- 0x10fc, 0x10fc, -- 0x1100, 0x1248, -- 0x124a, 0x124d, -- 0x1250, 0x1256, -- 0x1258, 0x1258, -- 0x125a, 0x125d, -- 0x1260, 0x1288, -- 0x128a, 0x128d, -- 0x1290, 0x12b0, -- 0x12b2, 0x12b5, -- 0x12b8, 0x12be, -- 0x12c0, 0x12c0, -- 0x12c2, 0x12c5, -- 0x12c8, 0x12d6, -- 0x12d8, 0x1310, -- 0x1312, 0x1315, -- 0x1318, 0x135a, -- 0x135d, 0x135f, -- 0x1369, 0x1371, -- 0x1380, 0x138f, -- 0x13a0, 0x13f4, -- 0x1401, 0x166c, -- 0x166f, 0x167f, -- 0x1681, 0x169a, -- 0x16a0, 0x16ea, -- 0x16ee, 0x16f0, -- 0x1700, 0x170c, -- 0x170e, 0x1714, -- 0x1720, 0x1734, -- 0x1740, 0x1753, -- 0x1760, 0x176c, -- 0x176e, 0x1770, -- 0x1772, 0x1773, -- 0x1780, 0x17b3, -- 0x17b6, 0x17d3, -- 0x17d7, 0x17d7, -- 0x17dc, 0x17dd, -- 0x17e0, 0x17e9, -- 0x180b, 0x180d, -- 0x1810, 0x1819, -- 0x1820, 0x1877, -- 0x1880, 0x18aa, -- 0x18b0, 0x18f5, -- 0x1900, 0x191c, -- 0x1920, 0x192b, -- 0x1930, 0x193b, -- 0x1946, 0x196d, -- 0x1970, 0x1974, -- 0x1980, 0x19ab, -- 0x19b0, 0x19c9, -- 0x19d0, 0x19da, -- 0x1a00, 0x1a1b, -- 0x1a20, 0x1a5e, -- 0x1a60, 0x1a7c, -- 0x1a7f, 0x1a89, -- 0x1a90, 0x1a99, -- 0x1aa7, 0x1aa7, -- 0x1b00, 0x1b4b, -- 0x1b50, 0x1b59, -- 0x1b6b, 0x1b73, -- 0x1b80, 0x1baa, -- 0x1bae, 0x1bb9, -- 0x1bc0, 0x1bf3, -- 0x1c00, 0x1c37, -- 0x1c40, 0x1c49, -- 0x1c4d, 0x1c7d, -- 0x1cd0, 0x1cd2, -- 0x1cd4, 0x1cf2, -- 0x1d00, 0x1de6, -- 0x1dfc, 0x1f15, -- 0x1f18, 0x1f1d, -- 0x1f20, 0x1f45, -- 0x1f48, 0x1f4d, -- 0x1f50, 0x1f57, -- 0x1f59, 0x1f59, -- 0x1f5b, 0x1f5b, -- 0x1f5d, 0x1f5d, -- 0x1f5f, 0x1f7d, -- 0x1f80, 0x1fb4, -- 0x1fb6, 0x1fbc, -- 0x1fbe, 0x1fbe, -- 0x1fc2, 0x1fc4, -- 0x1fc6, 0x1fcc, -- 0x1fd0, 0x1fd3, -- 0x1fd6, 0x1fdb, -- 0x1fe0, 0x1fec, -- 0x1ff2, 0x1ff4, -- 0x1ff6, 0x1ffc, -- 0x203f, 0x2040, -- 0x2054, 0x2054, -- 0x2071, 0x2071, -- 0x207f, 0x207f, -- 0x2090, 0x209c, -- 0x20d0, 0x20dc, -- 0x20e1, 0x20e1, -- 0x20e5, 0x20f0, -- 0x2102, 0x2102, -- 0x2107, 0x2107, -- 0x210a, 0x2113, -- 0x2115, 0x2115, -- 0x2118, 0x211d, -- 0x2124, 0x2124, -- 0x2126, 0x2126, -- 0x2128, 0x2128, -- 0x212a, 0x2139, -- 0x213c, 0x213f, -- 0x2145, 0x2149, -- 0x214e, 0x214e, -- 0x2160, 0x2188, -- 0x2c00, 0x2c2e, -- 0x2c30, 0x2c5e, -- 0x2c60, 0x2ce4, -- 0x2ceb, 0x2cf1, -- 0x2d00, 0x2d25, -- 0x2d30, 0x2d65, -- 0x2d6f, 0x2d6f, -- 0x2d7f, 0x2d96, -- 0x2da0, 0x2da6, -- 0x2da8, 0x2dae, -- 0x2db0, 0x2db6, -- 0x2db8, 0x2dbe, -- 0x2dc0, 0x2dc6, -- 0x2dc8, 0x2dce, -- 0x2dd0, 0x2dd6, -- 0x2dd8, 0x2dde, -- 0x2de0, 0x2dff, -- 0x3005, 0x3007, -- 0x3021, 0x302f, -- 0x3031, 0x3035, -- 0x3038, 0x303c, -- 0x3041, 0x3096, -- 0x3099, 0x309a, -- 0x309d, 0x309f, -- 0x30a1, 0x30fa, -- 0x30fc, 0x30ff, -- 0x3105, 0x312d, -- 0x3131, 0x318e, -- 0x31a0, 0x31ba, -- 0x31f0, 0x31ff, -- 0x3400, 0x4db5, -- 0x4e00, 0x9fcb, -- 0xa000, 0xa48c, -- 0xa4d0, 0xa4fd, -- 0xa500, 0xa60c, -- 0xa610, 0xa62b, -- 0xa640, 0xa66f, -- 0xa67c, 0xa67d, -- 0xa67f, 0xa697, -- 0xa6a0, 0xa6f1, -- 0xa717, 0xa71f, -- 0xa722, 0xa788, -- 0xa78b, 0xa78e, -- 0xa790, 0xa791, -- 0xa7a0, 0xa7a9, -- 0xa7fa, 0xa827, -- 0xa840, 0xa873, -- 0xa880, 0xa8c4, -- 0xa8d0, 0xa8d9, -- 0xa8e0, 0xa8f7, -- 0xa8fb, 0xa8fb, -- 0xa900, 0xa92d, -- 0xa930, 0xa953, -- 0xa960, 0xa97c, -- 0xa980, 0xa9c0, -- 0xa9cf, 0xa9d9, -- 0xaa00, 0xaa36, -- 0xaa40, 0xaa4d, -- 0xaa50, 0xaa59, -- 0xaa60, 0xaa76, -- 0xaa7a, 0xaa7b, -- 0xaa80, 0xaac2, -- 0xaadb, 0xaadd, -- 0xab01, 0xab06, -- 0xab09, 0xab0e, -- 0xab11, 0xab16, -- 0xab20, 0xab26, -- 0xab28, 0xab2e, -- 0xabc0, 0xabea, -- 0xabec, 0xabed, -- 0xabf0, 0xabf9, -- 0xac00, 0xd7a3, -- 0xd7b0, 0xd7c6, -- 0xd7cb, 0xd7fb, -- 0xf900, 0xfa2d, -- 0xfa30, 0xfa6d, -- 0xfa70, 0xfad9, -- 0xfb00, 0xfb06, -- 0xfb13, 0xfb17, -- 0xfb1d, 0xfb28, -- 0xfb2a, 0xfb36, -- 0xfb38, 0xfb3c, -- 0xfb3e, 0xfb3e, -- 0xfb40, 0xfb41, -- 0xfb43, 0xfb44, -- 0xfb46, 0xfbb1, -- 0xfbd3, 0xfc5d, -- 0xfc64, 0xfd3d, -- 0xfd50, 0xfd8f, -- 0xfd92, 0xfdc7, -- 0xfdf0, 0xfdf9, -- 0xfe00, 0xfe0f, -- 0xfe20, 0xfe26, -- 0xfe33, 0xfe34, -- 0xfe4d, 0xfe4f, -- 0xfe71, 0xfe71, -- 0xfe73, 0xfe73, -- 0xfe77, 0xfe77, -- 0xfe79, 0xfe79, -- 0xfe7b, 0xfe7b, -- 0xfe7d, 0xfe7d, -- 0xfe7f, 0xfefc, -- 0xff10, 0xff19, -- 0xff21, 0xff3a, -- 0xff3f, 0xff3f, -- 0xff41, 0xff5a, -- 0xff66, 0xffbe, -- 0xffc2, 0xffc7, -- 0xffca, 0xffcf, -- 0xffd2, 0xffd7, -- 0xffda, 0xffdc, -- 0x10000, 0x1000b, -- 0x1000d, 0x10026, -- 0x10028, 0x1003a, -- 0x1003c, 0x1003d, -- 0x1003f, 0x1004d, -- 0x10050, 0x1005d, -- 0x10080, 0x100fa, -- 0x10140, 0x10174, -- 0x101fd, 0x101fd, -- 0x10280, 0x1029c, -- 0x102a0, 0x102d0, -- 0x10300, 0x1031e, -- 0x10330, 0x1034a, -- 0x10380, 0x1039d, -- 0x103a0, 0x103c3, -- 0x103c8, 0x103cf, -- 0x103d1, 0x103d5, -- 0x10400, 0x1049d, -- 0x104a0, 0x104a9, -- 0x10800, 0x10805, -- 0x10808, 0x10808, -- 0x1080a, 0x10835, -- 0x10837, 0x10838, -- 0x1083c, 0x1083c, -- 0x1083f, 0x10855, -- 0x10900, 0x10915, -- 0x10920, 0x10939, -- 0x10a00, 0x10a03, -- 0x10a05, 0x10a06, -- 0x10a0c, 0x10a13, -- 0x10a15, 0x10a17, -- 0x10a19, 0x10a33, -- 0x10a38, 0x10a3a, -- 0x10a3f, 0x10a3f, -- 0x10a60, 0x10a7c, -- 0x10b00, 0x10b35, -- 0x10b40, 0x10b55, -- 0x10b60, 0x10b72, -- 0x10c00, 0x10c48, -- 0x11000, 0x11046, -- 0x11066, 0x1106f, -- 0x11080, 0x110ba, -- 0x12000, 0x1236e, -- 0x12400, 0x12462, -- 0x13000, 0x1342e, -- 0x16800, 0x16a38, -- 0x1b000, 0x1b001, -- 0x1d165, 0x1d169, -- 0x1d16d, 0x1d172, -- 0x1d17b, 0x1d182, -- 0x1d185, 0x1d18b, -- 0x1d1aa, 0x1d1ad, -- 0x1d242, 0x1d244, -- 0x1d400, 0x1d454, -- 0x1d456, 0x1d49c, -- 0x1d49e, 0x1d49f, -- 0x1d4a2, 0x1d4a2, -- 0x1d4a5, 0x1d4a6, -- 0x1d4a9, 0x1d4ac, -- 0x1d4ae, 0x1d4b9, -- 0x1d4bb, 0x1d4bb, -- 0x1d4bd, 0x1d4c3, -- 0x1d4c5, 0x1d505, -- 0x1d507, 0x1d50a, -- 0x1d50d, 0x1d514, -- 0x1d516, 0x1d51c, -- 0x1d51e, 0x1d539, -- 0x1d53b, 0x1d53e, -- 0x1d540, 0x1d544, -- 0x1d546, 0x1d546, -- 0x1d54a, 0x1d550, -- 0x1d552, 0x1d6a5, -- 0x1d6a8, 0x1d6c0, -- 0x1d6c2, 0x1d6da, -- 0x1d6dc, 0x1d6fa, -- 0x1d6fc, 0x1d714, -- 0x1d716, 0x1d734, -- 0x1d736, 0x1d74e, -- 0x1d750, 0x1d76e, -- 0x1d770, 0x1d788, -- 0x1d78a, 0x1d7a8, -- 0x1d7aa, 0x1d7c2, -- 0x1d7c4, 0x1d7cb, -- 0x1d7ce, 0x1d7ff, -- 0x20000, 0x2a6d6, -- 0x2a700, 0x2b734, -- 0x2b740, 0x2b81d, -- 0x2f800, 0x2fa1d, -- 0xe0100, 0xe01ef, --}; /* CR_XID_Continue */ -- --/* 'Default_Ignorable_Code_Point': Derived Property */ --static const OnigCodePoint CR_Default_Ignorable_Code_Point[] = { -- 15, -- 0x00ad, 0x00ad, -- 0x034f, 0x034f, -- 0x115f, 0x1160, -- 0x17b4, 0x17b5, -- 0x180b, 0x180d, -- 0x200b, 0x200f, -- 0x202a, 0x202e, -- 0x2060, 0x206f, -- 0x3164, 0x3164, -- 0xfe00, 0xfe0f, -- 0xfeff, 0xfeff, -- 0xffa0, 0xffa0, -- 0xfff0, 0xfff8, -- 0x1d173, 0x1d17a, -- 0xe0000, 0xe0fff, --}; /* CR_Default_Ignorable_Code_Point */ -- --/* 'Grapheme_Extend': Derived Property */ --static const OnigCodePoint CR_Grapheme_Extend[] = { -- 215, -- 0x0300, 0x036f, -- 0x0483, 0x0489, -- 0x0591, 0x05bd, -- 0x05bf, 0x05bf, -- 0x05c1, 0x05c2, -- 0x05c4, 0x05c5, -- 0x05c7, 0x05c7, -- 0x0610, 0x061a, -- 0x064b, 0x065f, -- 0x0670, 0x0670, -- 0x06d6, 0x06dc, -- 0x06df, 0x06e4, -- 0x06e7, 0x06e8, -- 0x06ea, 0x06ed, -- 0x0711, 0x0711, -- 0x0730, 0x074a, -- 0x07a6, 0x07b0, -- 0x07eb, 0x07f3, -- 0x0816, 0x0819, -- 0x081b, 0x0823, -- 0x0825, 0x0827, -- 0x0829, 0x082d, -- 0x0859, 0x085b, -- 0x0900, 0x0902, -- 0x093a, 0x093a, -- 0x093c, 0x093c, -- 0x0941, 0x0948, -- 0x094d, 0x094d, -- 0x0951, 0x0957, -- 0x0962, 0x0963, -- 0x0981, 0x0981, -- 0x09bc, 0x09bc, -- 0x09be, 0x09be, -- 0x09c1, 0x09c4, -- 0x09cd, 0x09cd, -- 0x09d7, 0x09d7, -- 0x09e2, 0x09e3, -- 0x0a01, 0x0a02, -- 0x0a3c, 0x0a3c, -- 0x0a41, 0x0a42, -- 0x0a47, 0x0a48, -- 0x0a4b, 0x0a4d, -- 0x0a51, 0x0a51, -- 0x0a70, 0x0a71, -- 0x0a75, 0x0a75, -- 0x0a81, 0x0a82, -- 0x0abc, 0x0abc, -- 0x0ac1, 0x0ac5, -- 0x0ac7, 0x0ac8, -- 0x0acd, 0x0acd, -- 0x0ae2, 0x0ae3, -- 0x0b01, 0x0b01, -- 0x0b3c, 0x0b3c, -- 0x0b3e, 0x0b3f, -- 0x0b41, 0x0b44, -- 0x0b4d, 0x0b4d, -- 0x0b56, 0x0b57, -- 0x0b62, 0x0b63, -- 0x0b82, 0x0b82, -- 0x0bbe, 0x0bbe, -- 0x0bc0, 0x0bc0, -- 0x0bcd, 0x0bcd, -- 0x0bd7, 0x0bd7, -- 0x0c3e, 0x0c40, -- 0x0c46, 0x0c48, -- 0x0c4a, 0x0c4d, -- 0x0c55, 0x0c56, -- 0x0c62, 0x0c63, -- 0x0cbc, 0x0cbc, -- 0x0cbf, 0x0cbf, -- 0x0cc2, 0x0cc2, -- 0x0cc6, 0x0cc6, -- 0x0ccc, 0x0ccd, -- 0x0cd5, 0x0cd6, -- 0x0ce2, 0x0ce3, -- 0x0d3e, 0x0d3e, -- 0x0d41, 0x0d44, -- 0x0d4d, 0x0d4d, -- 0x0d57, 0x0d57, -- 0x0d62, 0x0d63, -- 0x0dca, 0x0dca, -- 0x0dcf, 0x0dcf, -- 0x0dd2, 0x0dd4, -- 0x0dd6, 0x0dd6, -- 0x0ddf, 0x0ddf, -- 0x0e31, 0x0e31, -- 0x0e34, 0x0e3a, -- 0x0e47, 0x0e4e, -- 0x0eb1, 0x0eb1, -- 0x0eb4, 0x0eb9, -- 0x0ebb, 0x0ebc, -- 0x0ec8, 0x0ecd, -- 0x0f18, 0x0f19, -- 0x0f35, 0x0f35, -- 0x0f37, 0x0f37, -- 0x0f39, 0x0f39, -- 0x0f71, 0x0f7e, -- 0x0f80, 0x0f84, -- 0x0f86, 0x0f87, -- 0x0f8d, 0x0f97, -- 0x0f99, 0x0fbc, -- 0x0fc6, 0x0fc6, -- 0x102d, 0x1030, -- 0x1032, 0x1037, -- 0x1039, 0x103a, -- 0x103d, 0x103e, -- 0x1058, 0x1059, -- 0x105e, 0x1060, -- 0x1071, 0x1074, -- 0x1082, 0x1082, -- 0x1085, 0x1086, -- 0x108d, 0x108d, -- 0x109d, 0x109d, -- 0x135d, 0x135f, -- 0x1712, 0x1714, -- 0x1732, 0x1734, -- 0x1752, 0x1753, -- 0x1772, 0x1773, -- 0x17b7, 0x17bd, -- 0x17c6, 0x17c6, -- 0x17c9, 0x17d3, -- 0x17dd, 0x17dd, -- 0x180b, 0x180d, -- 0x18a9, 0x18a9, -- 0x1920, 0x1922, -- 0x1927, 0x1928, -- 0x1932, 0x1932, -- 0x1939, 0x193b, -- 0x1a17, 0x1a18, -- 0x1a56, 0x1a56, -- 0x1a58, 0x1a5e, -- 0x1a60, 0x1a60, -- 0x1a62, 0x1a62, -- 0x1a65, 0x1a6c, -- 0x1a73, 0x1a7c, -- 0x1a7f, 0x1a7f, -- 0x1b00, 0x1b03, -- 0x1b34, 0x1b34, -- 0x1b36, 0x1b3a, -- 0x1b3c, 0x1b3c, -- 0x1b42, 0x1b42, -- 0x1b6b, 0x1b73, -- 0x1b80, 0x1b81, -- 0x1ba2, 0x1ba5, -- 0x1ba8, 0x1ba9, -- 0x1be6, 0x1be6, -- 0x1be8, 0x1be9, -- 0x1bed, 0x1bed, -- 0x1bef, 0x1bf1, -- 0x1c2c, 0x1c33, -- 0x1c36, 0x1c37, -- 0x1cd0, 0x1cd2, -- 0x1cd4, 0x1ce0, -- 0x1ce2, 0x1ce8, -- 0x1ced, 0x1ced, -- 0x1dc0, 0x1de6, -- 0x1dfc, 0x1dff, -- 0x200c, 0x200d, -- 0x20d0, 0x20f0, -- 0x2cef, 0x2cf1, -- 0x2d7f, 0x2d7f, -- 0x2de0, 0x2dff, -- 0x302a, 0x302f, -- 0x3099, 0x309a, -- 0xa66f, 0xa672, -- 0xa67c, 0xa67d, -- 0xa6f0, 0xa6f1, -- 0xa802, 0xa802, -- 0xa806, 0xa806, -- 0xa80b, 0xa80b, -- 0xa825, 0xa826, -- 0xa8c4, 0xa8c4, -- 0xa8e0, 0xa8f1, -- 0xa926, 0xa92d, -- 0xa947, 0xa951, -- 0xa980, 0xa982, -- 0xa9b3, 0xa9b3, -- 0xa9b6, 0xa9b9, -- 0xa9bc, 0xa9bc, -- 0xaa29, 0xaa2e, -- 0xaa31, 0xaa32, -- 0xaa35, 0xaa36, -- 0xaa43, 0xaa43, -- 0xaa4c, 0xaa4c, -- 0xaab0, 0xaab0, -- 0xaab2, 0xaab4, -- 0xaab7, 0xaab8, -- 0xaabe, 0xaabf, -- 0xaac1, 0xaac1, -- 0xabe5, 0xabe5, -- 0xabe8, 0xabe8, -- 0xabed, 0xabed, -- 0xfb1e, 0xfb1e, -- 0xfe00, 0xfe0f, -- 0xfe20, 0xfe26, -- 0xff9e, 0xff9f, -- 0x101fd, 0x101fd, -- 0x10a01, 0x10a03, -- 0x10a05, 0x10a06, -- 0x10a0c, 0x10a0f, -- 0x10a38, 0x10a3a, -- 0x10a3f, 0x10a3f, -- 0x11001, 0x11001, -- 0x11038, 0x11046, -- 0x11080, 0x11081, -- 0x110b3, 0x110b6, -- 0x110b9, 0x110ba, -- 0x1d165, 0x1d165, -- 0x1d167, 0x1d169, -- 0x1d16e, 0x1d172, -- 0x1d17b, 0x1d182, -- 0x1d185, 0x1d18b, -- 0x1d1aa, 0x1d1ad, -- 0x1d242, 0x1d244, -- 0xe0100, 0xe01ef, --}; /* CR_Grapheme_Extend */ -- --/* 'Grapheme_Base': Derived Property */ --static const OnigCodePoint CR_Grapheme_Base[] = { -- 596, -- 0x0020, 0x007e, -- 0x00a0, 0x00ac, -- 0x00ae, 0x02ff, -- 0x0370, 0x0377, -- 0x037a, 0x037e, -- 0x0384, 0x038a, -- 0x038c, 0x038c, -- 0x038e, 0x03a1, -- 0x03a3, 0x0482, -- 0x048a, 0x0527, -- 0x0531, 0x0556, -- 0x0559, 0x055f, -- 0x0561, 0x0587, -- 0x0589, 0x058a, -- 0x05be, 0x05be, -- 0x05c0, 0x05c0, -- 0x05c3, 0x05c3, -- 0x05c6, 0x05c6, -- 0x05d0, 0x05ea, -- 0x05f0, 0x05f4, -- 0x0606, 0x060f, -- 0x061b, 0x061b, -- 0x061e, 0x064a, -- 0x0660, 0x066f, -- 0x0671, 0x06d5, -- 0x06de, 0x06de, -- 0x06e5, 0x06e6, -- 0x06e9, 0x06e9, -- 0x06ee, 0x070d, -- 0x0710, 0x0710, -- 0x0712, 0x072f, -- 0x074d, 0x07a5, -- 0x07b1, 0x07b1, -- 0x07c0, 0x07ea, -- 0x07f4, 0x07fa, -- 0x0800, 0x0815, -- 0x081a, 0x081a, -- 0x0824, 0x0824, -- 0x0828, 0x0828, -- 0x0830, 0x083e, -- 0x0840, 0x0858, -- 0x085e, 0x085e, -- 0x0903, 0x0939, -- 0x093b, 0x093b, -- 0x093d, 0x0940, -- 0x0949, 0x094c, -- 0x094e, 0x0950, -- 0x0958, 0x0961, -- 0x0964, 0x0977, -- 0x0979, 0x097f, -- 0x0982, 0x0983, -- 0x0985, 0x098c, -- 0x098f, 0x0990, -- 0x0993, 0x09a8, -- 0x09aa, 0x09b0, -- 0x09b2, 0x09b2, -- 0x09b6, 0x09b9, -- 0x09bd, 0x09bd, -- 0x09bf, 0x09c0, -- 0x09c7, 0x09c8, -- 0x09cb, 0x09cc, -- 0x09ce, 0x09ce, -- 0x09dc, 0x09dd, -- 0x09df, 0x09e1, -- 0x09e6, 0x09fb, -- 0x0a03, 0x0a03, -- 0x0a05, 0x0a0a, -- 0x0a0f, 0x0a10, -- 0x0a13, 0x0a28, -- 0x0a2a, 0x0a30, -- 0x0a32, 0x0a33, -- 0x0a35, 0x0a36, -- 0x0a38, 0x0a39, -- 0x0a3e, 0x0a40, -- 0x0a59, 0x0a5c, -- 0x0a5e, 0x0a5e, -- 0x0a66, 0x0a6f, -- 0x0a72, 0x0a74, -- 0x0a83, 0x0a83, -- 0x0a85, 0x0a8d, -- 0x0a8f, 0x0a91, -- 0x0a93, 0x0aa8, -- 0x0aaa, 0x0ab0, -- 0x0ab2, 0x0ab3, -- 0x0ab5, 0x0ab9, -- 0x0abd, 0x0ac0, -- 0x0ac9, 0x0ac9, -- 0x0acb, 0x0acc, -- 0x0ad0, 0x0ad0, -- 0x0ae0, 0x0ae1, -- 0x0ae6, 0x0aef, -- 0x0af1, 0x0af1, -- 0x0b02, 0x0b03, -- 0x0b05, 0x0b0c, -- 0x0b0f, 0x0b10, -- 0x0b13, 0x0b28, -- 0x0b2a, 0x0b30, -- 0x0b32, 0x0b33, -- 0x0b35, 0x0b39, -- 0x0b3d, 0x0b3d, -- 0x0b40, 0x0b40, -- 0x0b47, 0x0b48, -- 0x0b4b, 0x0b4c, -- 0x0b5c, 0x0b5d, -- 0x0b5f, 0x0b61, -- 0x0b66, 0x0b77, -- 0x0b83, 0x0b83, -- 0x0b85, 0x0b8a, -- 0x0b8e, 0x0b90, -- 0x0b92, 0x0b95, -- 0x0b99, 0x0b9a, -- 0x0b9c, 0x0b9c, -- 0x0b9e, 0x0b9f, -- 0x0ba3, 0x0ba4, -- 0x0ba8, 0x0baa, -- 0x0bae, 0x0bb9, -- 0x0bbf, 0x0bbf, -- 0x0bc1, 0x0bc2, -- 0x0bc6, 0x0bc8, -- 0x0bca, 0x0bcc, -- 0x0bd0, 0x0bd0, -- 0x0be6, 0x0bfa, -- 0x0c01, 0x0c03, -- 0x0c05, 0x0c0c, -- 0x0c0e, 0x0c10, -- 0x0c12, 0x0c28, -- 0x0c2a, 0x0c33, -- 0x0c35, 0x0c39, -- 0x0c3d, 0x0c3d, -- 0x0c41, 0x0c44, -- 0x0c58, 0x0c59, -- 0x0c60, 0x0c61, -- 0x0c66, 0x0c6f, -- 0x0c78, 0x0c7f, -- 0x0c82, 0x0c83, -- 0x0c85, 0x0c8c, -- 0x0c8e, 0x0c90, -- 0x0c92, 0x0ca8, -- 0x0caa, 0x0cb3, -- 0x0cb5, 0x0cb9, -- 0x0cbd, 0x0cbe, -- 0x0cc0, 0x0cc1, -- 0x0cc3, 0x0cc4, -- 0x0cc7, 0x0cc8, -- 0x0cca, 0x0ccb, -- 0x0cde, 0x0cde, -- 0x0ce0, 0x0ce1, -- 0x0ce6, 0x0cef, -- 0x0cf1, 0x0cf2, -- 0x0d02, 0x0d03, -- 0x0d05, 0x0d0c, -- 0x0d0e, 0x0d10, -- 0x0d12, 0x0d3a, -- 0x0d3d, 0x0d3d, -- 0x0d3f, 0x0d40, -- 0x0d46, 0x0d48, -- 0x0d4a, 0x0d4c, -- 0x0d4e, 0x0d4e, -- 0x0d60, 0x0d61, -- 0x0d66, 0x0d75, -- 0x0d79, 0x0d7f, -- 0x0d82, 0x0d83, -- 0x0d85, 0x0d96, -- 0x0d9a, 0x0db1, -- 0x0db3, 0x0dbb, -- 0x0dbd, 0x0dbd, -- 0x0dc0, 0x0dc6, -- 0x0dd0, 0x0dd1, -- 0x0dd8, 0x0dde, -- 0x0df2, 0x0df4, -- 0x0e01, 0x0e30, -- 0x0e32, 0x0e33, -- 0x0e3f, 0x0e46, -- 0x0e4f, 0x0e5b, -- 0x0e81, 0x0e82, -- 0x0e84, 0x0e84, -- 0x0e87, 0x0e88, -- 0x0e8a, 0x0e8a, -- 0x0e8d, 0x0e8d, -- 0x0e94, 0x0e97, -- 0x0e99, 0x0e9f, -- 0x0ea1, 0x0ea3, -- 0x0ea5, 0x0ea5, -- 0x0ea7, 0x0ea7, -- 0x0eaa, 0x0eab, -- 0x0ead, 0x0eb0, -- 0x0eb2, 0x0eb3, -- 0x0ebd, 0x0ebd, -- 0x0ec0, 0x0ec4, -- 0x0ec6, 0x0ec6, -- 0x0ed0, 0x0ed9, -- 0x0edc, 0x0edd, -- 0x0f00, 0x0f17, -- 0x0f1a, 0x0f34, -- 0x0f36, 0x0f36, -- 0x0f38, 0x0f38, -- 0x0f3a, 0x0f47, -- 0x0f49, 0x0f6c, -- 0x0f7f, 0x0f7f, -- 0x0f85, 0x0f85, -- 0x0f88, 0x0f8c, -- 0x0fbe, 0x0fc5, -- 0x0fc7, 0x0fcc, -- 0x0fce, 0x0fda, -- 0x1000, 0x102c, -- 0x1031, 0x1031, -- 0x1038, 0x1038, -- 0x103b, 0x103c, -- 0x103f, 0x1057, -- 0x105a, 0x105d, -- 0x1061, 0x1070, -- 0x1075, 0x1081, -- 0x1083, 0x1084, -- 0x1087, 0x108c, -- 0x108e, 0x109c, -- 0x109e, 0x10c5, -- 0x10d0, 0x10fc, -- 0x1100, 0x1248, -- 0x124a, 0x124d, -- 0x1250, 0x1256, -- 0x1258, 0x1258, -- 0x125a, 0x125d, -- 0x1260, 0x1288, -- 0x128a, 0x128d, -- 0x1290, 0x12b0, -- 0x12b2, 0x12b5, -- 0x12b8, 0x12be, -- 0x12c0, 0x12c0, -- 0x12c2, 0x12c5, -- 0x12c8, 0x12d6, -- 0x12d8, 0x1310, -- 0x1312, 0x1315, -- 0x1318, 0x135a, -- 0x1360, 0x137c, -- 0x1380, 0x1399, -- 0x13a0, 0x13f4, -- 0x1400, 0x169c, -- 0x16a0, 0x16f0, -- 0x1700, 0x170c, -- 0x170e, 0x1711, -- 0x1720, 0x1731, -- 0x1735, 0x1736, -- 0x1740, 0x1751, -- 0x1760, 0x176c, -- 0x176e, 0x1770, -- 0x1780, 0x17b3, -- 0x17b6, 0x17b6, -- 0x17be, 0x17c5, -- 0x17c7, 0x17c8, -- 0x17d4, 0x17dc, -- 0x17e0, 0x17e9, -- 0x17f0, 0x17f9, -- 0x1800, 0x180a, -- 0x180e, 0x180e, -- 0x1810, 0x1819, -- 0x1820, 0x1877, -- 0x1880, 0x18a8, -- 0x18aa, 0x18aa, -- 0x18b0, 0x18f5, -- 0x1900, 0x191c, -- 0x1923, 0x1926, -- 0x1929, 0x192b, -- 0x1930, 0x1931, -- 0x1933, 0x1938, -- 0x1940, 0x1940, -- 0x1944, 0x196d, -- 0x1970, 0x1974, -- 0x1980, 0x19ab, -- 0x19b0, 0x19c9, -- 0x19d0, 0x19da, -- 0x19de, 0x1a16, -- 0x1a19, 0x1a1b, -- 0x1a1e, 0x1a55, -- 0x1a57, 0x1a57, -- 0x1a61, 0x1a61, -- 0x1a63, 0x1a64, -- 0x1a6d, 0x1a72, -- 0x1a80, 0x1a89, -- 0x1a90, 0x1a99, -- 0x1aa0, 0x1aad, -- 0x1b04, 0x1b33, -- 0x1b35, 0x1b35, -- 0x1b3b, 0x1b3b, -- 0x1b3d, 0x1b41, -- 0x1b43, 0x1b4b, -- 0x1b50, 0x1b6a, -- 0x1b74, 0x1b7c, -- 0x1b82, 0x1ba1, -- 0x1ba6, 0x1ba7, -- 0x1baa, 0x1baa, -- 0x1bae, 0x1bb9, -- 0x1bc0, 0x1be5, -- 0x1be7, 0x1be7, -- 0x1bea, 0x1bec, -- 0x1bee, 0x1bee, -- 0x1bf2, 0x1bf3, -- 0x1bfc, 0x1c2b, -- 0x1c34, 0x1c35, -- 0x1c3b, 0x1c49, -- 0x1c4d, 0x1c7f, -- 0x1cd3, 0x1cd3, -- 0x1ce1, 0x1ce1, -- 0x1ce9, 0x1cec, -- 0x1cee, 0x1cf2, -- 0x1d00, 0x1dbf, -- 0x1e00, 0x1f15, -- 0x1f18, 0x1f1d, -- 0x1f20, 0x1f45, -- 0x1f48, 0x1f4d, -- 0x1f50, 0x1f57, -- 0x1f59, 0x1f59, -- 0x1f5b, 0x1f5b, -- 0x1f5d, 0x1f5d, -- 0x1f5f, 0x1f7d, -- 0x1f80, 0x1fb4, -- 0x1fb6, 0x1fc4, -- 0x1fc6, 0x1fd3, -- 0x1fd6, 0x1fdb, -- 0x1fdd, 0x1fef, -- 0x1ff2, 0x1ff4, -- 0x1ff6, 0x1ffe, -- 0x2000, 0x200a, -- 0x2010, 0x2027, -- 0x202f, 0x205f, -- 0x2070, 0x2071, -- 0x2074, 0x208e, -- 0x2090, 0x209c, -- 0x20a0, 0x20b9, -- 0x2100, 0x2189, -- 0x2190, 0x23f3, -- 0x2400, 0x2426, -- 0x2440, 0x244a, -- 0x2460, 0x26ff, -- 0x2701, 0x27ca, -- 0x27cc, 0x27cc, -- 0x27ce, 0x2b4c, -- 0x2b50, 0x2b59, -- 0x2c00, 0x2c2e, -- 0x2c30, 0x2c5e, -- 0x2c60, 0x2cee, -- 0x2cf9, 0x2d25, -- 0x2d30, 0x2d65, -- 0x2d6f, 0x2d70, -- 0x2d80, 0x2d96, -- 0x2da0, 0x2da6, -- 0x2da8, 0x2dae, -- 0x2db0, 0x2db6, -- 0x2db8, 0x2dbe, -- 0x2dc0, 0x2dc6, -- 0x2dc8, 0x2dce, -- 0x2dd0, 0x2dd6, -- 0x2dd8, 0x2dde, -- 0x2e00, 0x2e31, -- 0x2e80, 0x2e99, -- 0x2e9b, 0x2ef3, -- 0x2f00, 0x2fd5, -- 0x2ff0, 0x2ffb, -- 0x3000, 0x3029, -- 0x3030, 0x303f, -- 0x3041, 0x3096, -- 0x309b, 0x30ff, -- 0x3105, 0x312d, -- 0x3131, 0x318e, -- 0x3190, 0x31ba, -- 0x31c0, 0x31e3, -- 0x31f0, 0x321e, -- 0x3220, 0x32fe, -- 0x3300, 0x4db5, -- 0x4dc0, 0x9fcb, -- 0xa000, 0xa48c, -- 0xa490, 0xa4c6, -- 0xa4d0, 0xa62b, -- 0xa640, 0xa66e, -- 0xa673, 0xa673, -- 0xa67e, 0xa697, -- 0xa6a0, 0xa6ef, -- 0xa6f2, 0xa6f7, -- 0xa700, 0xa78e, -- 0xa790, 0xa791, -- 0xa7a0, 0xa7a9, -- 0xa7fa, 0xa801, -- 0xa803, 0xa805, -- 0xa807, 0xa80a, -- 0xa80c, 0xa824, -- 0xa827, 0xa82b, -- 0xa830, 0xa839, -- 0xa840, 0xa877, -- 0xa880, 0xa8c3, -- 0xa8ce, 0xa8d9, -- 0xa8f2, 0xa8fb, -- 0xa900, 0xa925, -- 0xa92e, 0xa946, -- 0xa952, 0xa953, -- 0xa95f, 0xa97c, -- 0xa983, 0xa9b2, -- 0xa9b4, 0xa9b5, -- 0xa9ba, 0xa9bb, -- 0xa9bd, 0xa9cd, -- 0xa9cf, 0xa9d9, -- 0xa9de, 0xa9df, -- 0xaa00, 0xaa28, -- 0xaa2f, 0xaa30, -- 0xaa33, 0xaa34, -- 0xaa40, 0xaa42, -- 0xaa44, 0xaa4b, -- 0xaa4d, 0xaa4d, -- 0xaa50, 0xaa59, -- 0xaa5c, 0xaa7b, -- 0xaa80, 0xaaaf, -- 0xaab1, 0xaab1, -- 0xaab5, 0xaab6, -- 0xaab9, 0xaabd, -- 0xaac0, 0xaac0, -- 0xaac2, 0xaac2, -- 0xaadb, 0xaadf, -- 0xab01, 0xab06, -- 0xab09, 0xab0e, -- 0xab11, 0xab16, -- 0xab20, 0xab26, -- 0xab28, 0xab2e, -- 0xabc0, 0xabe4, -- 0xabe6, 0xabe7, -- 0xabe9, 0xabec, -- 0xabf0, 0xabf9, -- 0xac00, 0xd7a3, -- 0xd7b0, 0xd7c6, -- 0xd7cb, 0xd7fb, -- 0xf900, 0xfa2d, -- 0xfa30, 0xfa6d, -- 0xfa70, 0xfad9, -- 0xfb00, 0xfb06, -- 0xfb13, 0xfb17, -- 0xfb1d, 0xfb1d, -- 0xfb1f, 0xfb36, -- 0xfb38, 0xfb3c, -- 0xfb3e, 0xfb3e, -- 0xfb40, 0xfb41, -- 0xfb43, 0xfb44, -- 0xfb46, 0xfbc1, -- 0xfbd3, 0xfd3f, -- 0xfd50, 0xfd8f, -- 0xfd92, 0xfdc7, -- 0xfdf0, 0xfdfd, -- 0xfe10, 0xfe19, -- 0xfe30, 0xfe52, -- 0xfe54, 0xfe66, -- 0xfe68, 0xfe6b, -- 0xfe70, 0xfe74, -- 0xfe76, 0xfefc, -- 0xff01, 0xff9d, -- 0xffa0, 0xffbe, -- 0xffc2, 0xffc7, -- 0xffca, 0xffcf, -- 0xffd2, 0xffd7, -- 0xffda, 0xffdc, -- 0xffe0, 0xffe6, -- 0xffe8, 0xffee, -- 0xfffc, 0xfffd, -- 0x10000, 0x1000b, -- 0x1000d, 0x10026, -- 0x10028, 0x1003a, -- 0x1003c, 0x1003d, -- 0x1003f, 0x1004d, -- 0x10050, 0x1005d, -- 0x10080, 0x100fa, -- 0x10100, 0x10102, -- 0x10107, 0x10133, -- 0x10137, 0x1018a, -- 0x10190, 0x1019b, -- 0x101d0, 0x101fc, -- 0x10280, 0x1029c, -- 0x102a0, 0x102d0, -- 0x10300, 0x1031e, -- 0x10320, 0x10323, -- 0x10330, 0x1034a, -- 0x10380, 0x1039d, -- 0x1039f, 0x103c3, -- 0x103c8, 0x103d5, -- 0x10400, 0x1049d, -- 0x104a0, 0x104a9, -- 0x10800, 0x10805, -- 0x10808, 0x10808, -- 0x1080a, 0x10835, -- 0x10837, 0x10838, -- 0x1083c, 0x1083c, -- 0x1083f, 0x10855, -- 0x10857, 0x1085f, -- 0x10900, 0x1091b, -- 0x1091f, 0x10939, -- 0x1093f, 0x1093f, -- 0x10a00, 0x10a00, -- 0x10a10, 0x10a13, -- 0x10a15, 0x10a17, -- 0x10a19, 0x10a33, -- 0x10a40, 0x10a47, -- 0x10a50, 0x10a58, -- 0x10a60, 0x10a7f, -- 0x10b00, 0x10b35, -- 0x10b39, 0x10b55, -- 0x10b58, 0x10b72, -- 0x10b78, 0x10b7f, -- 0x10c00, 0x10c48, -- 0x10e60, 0x10e7e, -- 0x11000, 0x11000, -- 0x11002, 0x11037, -- 0x11047, 0x1104d, -- 0x11052, 0x1106f, -- 0x11082, 0x110b2, -- 0x110b7, 0x110b8, -- 0x110bb, 0x110bc, -- 0x110be, 0x110c1, -- 0x12000, 0x1236e, -- 0x12400, 0x12462, -- 0x12470, 0x12473, -- 0x13000, 0x1342e, -- 0x16800, 0x16a38, -- 0x1b000, 0x1b001, -- 0x1d000, 0x1d0f5, -- 0x1d100, 0x1d126, -- 0x1d129, 0x1d164, -- 0x1d166, 0x1d166, -- 0x1d16a, 0x1d16d, -- 0x1d183, 0x1d184, -- 0x1d18c, 0x1d1a9, -- 0x1d1ae, 0x1d1dd, -- 0x1d200, 0x1d241, -- 0x1d245, 0x1d245, -- 0x1d300, 0x1d356, -- 0x1d360, 0x1d371, -- 0x1d400, 0x1d454, -- 0x1d456, 0x1d49c, -- 0x1d49e, 0x1d49f, -- 0x1d4a2, 0x1d4a2, -- 0x1d4a5, 0x1d4a6, -- 0x1d4a9, 0x1d4ac, -- 0x1d4ae, 0x1d4b9, -- 0x1d4bb, 0x1d4bb, -- 0x1d4bd, 0x1d4c3, -- 0x1d4c5, 0x1d505, -- 0x1d507, 0x1d50a, -- 0x1d50d, 0x1d514, -- 0x1d516, 0x1d51c, -- 0x1d51e, 0x1d539, -- 0x1d53b, 0x1d53e, -- 0x1d540, 0x1d544, -- 0x1d546, 0x1d546, -- 0x1d54a, 0x1d550, -- 0x1d552, 0x1d6a5, -- 0x1d6a8, 0x1d7cb, -- 0x1d7ce, 0x1d7ff, -- 0x1f000, 0x1f02b, -- 0x1f030, 0x1f093, -- 0x1f0a0, 0x1f0ae, -- 0x1f0b1, 0x1f0be, -- 0x1f0c1, 0x1f0cf, -- 0x1f0d1, 0x1f0df, -- 0x1f100, 0x1f10a, -- 0x1f110, 0x1f12e, -- 0x1f130, 0x1f169, -- 0x1f170, 0x1f19a, -- 0x1f1e6, 0x1f202, -- 0x1f210, 0x1f23a, -- 0x1f240, 0x1f248, -- 0x1f250, 0x1f251, -- 0x1f300, 0x1f320, -- 0x1f330, 0x1f335, -- 0x1f337, 0x1f37c, -- 0x1f380, 0x1f393, -- 0x1f3a0, 0x1f3c4, -- 0x1f3c6, 0x1f3ca, -- 0x1f3e0, 0x1f3f0, -- 0x1f400, 0x1f43e, -- 0x1f440, 0x1f440, -- 0x1f442, 0x1f4f7, -- 0x1f4f9, 0x1f4fc, -- 0x1f500, 0x1f53d, -- 0x1f550, 0x1f567, -- 0x1f5fb, 0x1f5ff, -- 0x1f601, 0x1f610, -- 0x1f612, 0x1f614, -- 0x1f616, 0x1f616, -- 0x1f618, 0x1f618, -- 0x1f61a, 0x1f61a, -- 0x1f61c, 0x1f61e, -- 0x1f620, 0x1f625, -- 0x1f628, 0x1f62b, -- 0x1f62d, 0x1f62d, -- 0x1f630, 0x1f633, -- 0x1f635, 0x1f640, -- 0x1f645, 0x1f64f, -- 0x1f680, 0x1f6c5, -- 0x1f700, 0x1f773, -- 0x20000, 0x2a6d6, -- 0x2a700, 0x2b734, -- 0x2b740, 0x2b81d, -- 0x2f800, 0x2fa1d, --}; /* CR_Grapheme_Base */ -- --/* 'Grapheme_Link': Derived Property */ --static const OnigCodePoint CR_Grapheme_Link[] = { -- 29, -- 0x094d, 0x094d, -- 0x09cd, 0x09cd, -- 0x0a4d, 0x0a4d, -- 0x0acd, 0x0acd, -- 0x0b4d, 0x0b4d, -- 0x0bcd, 0x0bcd, -- 0x0c4d, 0x0c4d, -- 0x0ccd, 0x0ccd, -- 0x0d4d, 0x0d4d, -- 0x0dca, 0x0dca, -- 0x0e3a, 0x0e3a, -- 0x0f84, 0x0f84, -- 0x1039, 0x103a, -- 0x1714, 0x1714, -- 0x1734, 0x1734, -- 0x17d2, 0x17d2, -- 0x1a60, 0x1a60, -- 0x1b44, 0x1b44, -- 0x1baa, 0x1baa, -- 0x1bf2, 0x1bf3, -- 0x2d7f, 0x2d7f, -- 0xa806, 0xa806, -- 0xa8c4, 0xa8c4, -- 0xa953, 0xa953, -- 0xa9c0, 0xa9c0, -- 0xabed, 0xabed, -- 0x10a3f, 0x10a3f, -- 0x11046, 0x11046, -- 0x110b9, 0x110b9, --}; /* CR_Grapheme_Link */ -- --/* 'Common': Script */ --static const OnigCodePoint CR_Common[] = { -- 169, -- 0x0000, 0x0040, -- 0x005b, 0x0060, -- 0x007b, 0x00a9, -- 0x00ab, 0x00b9, -- 0x00bb, 0x00bf, -- 0x00d7, 0x00d7, -- 0x00f7, 0x00f7, -- 0x02b9, 0x02df, -- 0x02e5, 0x02e9, -- 0x02ec, 0x02ff, -- 0x0374, 0x0374, -- 0x037e, 0x037e, -- 0x0385, 0x0385, -- 0x0387, 0x0387, -- 0x0589, 0x0589, -- 0x060c, 0x060c, -- 0x061b, 0x061b, -- 0x061f, 0x061f, -- 0x0640, 0x0640, -- 0x0660, 0x0669, -- 0x06dd, 0x06dd, -- 0x0964, 0x0965, -- 0x0970, 0x0970, -- 0x0e3f, 0x0e3f, -- 0x0fd5, 0x0fd8, -- 0x10fb, 0x10fb, -- 0x16eb, 0x16ed, -- 0x1735, 0x1736, -- 0x1802, 0x1803, -- 0x1805, 0x1805, -- 0x1cd3, 0x1cd3, -- 0x1ce1, 0x1ce1, -- 0x1ce9, 0x1cec, -- 0x1cee, 0x1cf2, -- 0x2000, 0x200b, -- 0x200e, 0x2064, -- 0x206a, 0x2070, -- 0x2074, 0x207e, -- 0x2080, 0x208e, -- 0x20a0, 0x20b9, -- 0x2100, 0x2125, -- 0x2127, 0x2129, -- 0x212c, 0x2131, -- 0x2133, 0x214d, -- 0x214f, 0x215f, -- 0x2189, 0x2189, -- 0x2190, 0x23f3, -- 0x2400, 0x2426, -- 0x2440, 0x244a, -- 0x2460, 0x26ff, -- 0x2701, 0x27ca, -- 0x27cc, 0x27cc, -- 0x27ce, 0x27ff, -- 0x2900, 0x2b4c, -- 0x2b50, 0x2b59, -- 0x2e00, 0x2e31, -- 0x2ff0, 0x2ffb, -- 0x3000, 0x3004, -- 0x3006, 0x3006, -- 0x3008, 0x3020, -- 0x3030, 0x3037, -- 0x303c, 0x303f, -- 0x309b, 0x309c, -- 0x30a0, 0x30a0, -- 0x30fb, 0x30fc, -- 0x3190, 0x319f, -- 0x31c0, 0x31e3, -- 0x3220, 0x325f, -- 0x327f, 0x32cf, -- 0x3358, 0x33ff, -- 0x4dc0, 0x4dff, -- 0xa700, 0xa721, -- 0xa788, 0xa78a, -- 0xa830, 0xa839, -- 0xfd3e, 0xfd3f, -- 0xfdfd, 0xfdfd, -- 0xfe10, 0xfe19, -- 0xfe30, 0xfe52, -- 0xfe54, 0xfe66, -- 0xfe68, 0xfe6b, -- 0xfeff, 0xfeff, -- 0xff01, 0xff20, -- 0xff3b, 0xff40, -- 0xff5b, 0xff65, -- 0xff70, 0xff70, -- 0xff9e, 0xff9f, -- 0xffe0, 0xffe6, -- 0xffe8, 0xffee, -- 0xfff9, 0xfffd, -- 0x10100, 0x10102, -- 0x10107, 0x10133, -- 0x10137, 0x1013f, -- 0x10190, 0x1019b, -- 0x101d0, 0x101fc, -- 0x1d000, 0x1d0f5, -- 0x1d100, 0x1d126, -- 0x1d129, 0x1d166, -- 0x1d16a, 0x1d17a, -- 0x1d183, 0x1d184, -- 0x1d18c, 0x1d1a9, -- 0x1d1ae, 0x1d1dd, -- 0x1d300, 0x1d356, -- 0x1d360, 0x1d371, -- 0x1d400, 0x1d454, -- 0x1d456, 0x1d49c, -- 0x1d49e, 0x1d49f, -- 0x1d4a2, 0x1d4a2, -- 0x1d4a5, 0x1d4a6, -- 0x1d4a9, 0x1d4ac, -- 0x1d4ae, 0x1d4b9, -- 0x1d4bb, 0x1d4bb, -- 0x1d4bd, 0x1d4c3, -- 0x1d4c5, 0x1d505, -- 0x1d507, 0x1d50a, -- 0x1d50d, 0x1d514, -- 0x1d516, 0x1d51c, -- 0x1d51e, 0x1d539, -- 0x1d53b, 0x1d53e, -- 0x1d540, 0x1d544, -- 0x1d546, 0x1d546, -- 0x1d54a, 0x1d550, -- 0x1d552, 0x1d6a5, -- 0x1d6a8, 0x1d7cb, -- 0x1d7ce, 0x1d7ff, -- 0x1f000, 0x1f02b, -- 0x1f030, 0x1f093, -- 0x1f0a0, 0x1f0ae, -- 0x1f0b1, 0x1f0be, -- 0x1f0c1, 0x1f0cf, -- 0x1f0d1, 0x1f0df, -- 0x1f100, 0x1f10a, -- 0x1f110, 0x1f12e, -- 0x1f130, 0x1f169, -- 0x1f170, 0x1f19a, -- 0x1f1e6, 0x1f1ff, -- 0x1f201, 0x1f202, -- 0x1f210, 0x1f23a, -- 0x1f240, 0x1f248, -- 0x1f250, 0x1f251, -- 0x1f300, 0x1f320, -- 0x1f330, 0x1f335, -- 0x1f337, 0x1f37c, -- 0x1f380, 0x1f393, -- 0x1f3a0, 0x1f3c4, -- 0x1f3c6, 0x1f3ca, -- 0x1f3e0, 0x1f3f0, -- 0x1f400, 0x1f43e, -- 0x1f440, 0x1f440, -- 0x1f442, 0x1f4f7, -- 0x1f4f9, 0x1f4fc, -- 0x1f500, 0x1f53d, -- 0x1f550, 0x1f567, -- 0x1f5fb, 0x1f5ff, -- 0x1f601, 0x1f610, -- 0x1f612, 0x1f614, -- 0x1f616, 0x1f616, -- 0x1f618, 0x1f618, -- 0x1f61a, 0x1f61a, -- 0x1f61c, 0x1f61e, -- 0x1f620, 0x1f625, -- 0x1f628, 0x1f62b, -- 0x1f62d, 0x1f62d, -- 0x1f630, 0x1f633, -- 0x1f635, 0x1f640, -- 0x1f645, 0x1f64f, -- 0x1f680, 0x1f6c5, -- 0x1f700, 0x1f773, -- 0xe0001, 0xe0001, -- 0xe0020, 0xe007f, --}; /* CR_Common */ -- --/* 'Latin': Script */ --static const OnigCodePoint CR_Latin[] = { -- 30, -- 0x0041, 0x005a, -- 0x0061, 0x007a, -- 0x00aa, 0x00aa, -- 0x00ba, 0x00ba, -- 0x00c0, 0x00d6, -- 0x00d8, 0x00f6, -- 0x00f8, 0x02b8, -- 0x02e0, 0x02e4, -- 0x1d00, 0x1d25, -- 0x1d2c, 0x1d5c, -- 0x1d62, 0x1d65, -- 0x1d6b, 0x1d77, -- 0x1d79, 0x1dbe, -- 0x1e00, 0x1eff, -- 0x2071, 0x2071, -- 0x207f, 0x207f, -- 0x2090, 0x209c, -- 0x212a, 0x212b, -- 0x2132, 0x2132, -- 0x214e, 0x214e, -- 0x2160, 0x2188, -- 0x2c60, 0x2c7f, -- 0xa722, 0xa787, -- 0xa78b, 0xa78e, -- 0xa790, 0xa791, -- 0xa7a0, 0xa7a9, -- 0xa7fa, 0xa7ff, -- 0xfb00, 0xfb06, -- 0xff21, 0xff3a, -- 0xff41, 0xff5a, --}; /* CR_Latin */ -- --/* 'Greek': Script */ --static const OnigCodePoint CR_Greek[] = { -- 33, -- 0x0370, 0x0373, -- 0x0375, 0x0377, -- 0x037a, 0x037d, -- 0x0384, 0x0384, -- 0x0386, 0x0386, -- 0x0388, 0x038a, -- 0x038c, 0x038c, -- 0x038e, 0x03a1, -- 0x03a3, 0x03e1, -- 0x03f0, 0x03ff, -- 0x1d26, 0x1d2a, -- 0x1d5d, 0x1d61, -- 0x1d66, 0x1d6a, -- 0x1dbf, 0x1dbf, -- 0x1f00, 0x1f15, -- 0x1f18, 0x1f1d, -- 0x1f20, 0x1f45, -- 0x1f48, 0x1f4d, -- 0x1f50, 0x1f57, -- 0x1f59, 0x1f59, -- 0x1f5b, 0x1f5b, -- 0x1f5d, 0x1f5d, -- 0x1f5f, 0x1f7d, -- 0x1f80, 0x1fb4, -- 0x1fb6, 0x1fc4, -- 0x1fc6, 0x1fd3, -- 0x1fd6, 0x1fdb, -- 0x1fdd, 0x1fef, -- 0x1ff2, 0x1ff4, -- 0x1ff6, 0x1ffe, -- 0x2126, 0x2126, -- 0x10140, 0x1018a, -- 0x1d200, 0x1d245, --}; /* CR_Greek */ -- --/* 'Cyrillic': Script */ --static const OnigCodePoint CR_Cyrillic[] = { -- 7, -- 0x0400, 0x0484, -- 0x0487, 0x0527, -- 0x1d2b, 0x1d2b, -- 0x1d78, 0x1d78, -- 0x2de0, 0x2dff, -- 0xa640, 0xa673, -- 0xa67c, 0xa697, --}; /* CR_Cyrillic */ -- --/* 'Armenian': Script */ --static const OnigCodePoint CR_Armenian[] = { -- 5, -- 0x0531, 0x0556, -- 0x0559, 0x055f, -- 0x0561, 0x0587, -- 0x058a, 0x058a, -- 0xfb13, 0xfb17, --}; /* CR_Armenian */ -- --/* 'Hebrew': Script */ --static const OnigCodePoint CR_Hebrew[] = { -- 9, -- 0x0591, 0x05c7, -- 0x05d0, 0x05ea, -- 0x05f0, 0x05f4, -- 0xfb1d, 0xfb36, -- 0xfb38, 0xfb3c, -- 0xfb3e, 0xfb3e, -- 0xfb40, 0xfb41, -- 0xfb43, 0xfb44, -- 0xfb46, 0xfb4f, --}; /* CR_Hebrew */ -- --/* 'Arabic': Script */ --static const OnigCodePoint CR_Arabic[] = { -- 19, -- 0x0600, 0x0603, -- 0x0606, 0x060b, -- 0x060d, 0x061a, -- 0x061e, 0x061e, -- 0x0620, 0x063f, -- 0x0641, 0x064a, -- 0x0656, 0x065e, -- 0x066a, 0x066f, -- 0x0671, 0x06dc, -- 0x06de, 0x06ff, -- 0x0750, 0x077f, -- 0xfb50, 0xfbc1, -- 0xfbd3, 0xfd3d, -- 0xfd50, 0xfd8f, -- 0xfd92, 0xfdc7, -- 0xfdf0, 0xfdfc, -- 0xfe70, 0xfe74, -- 0xfe76, 0xfefc, -- 0x10e60, 0x10e7e, --}; /* CR_Arabic */ -- --/* 'Syriac': Script */ --static const OnigCodePoint CR_Syriac[] = { -- 3, -- 0x0700, 0x070d, -- 0x070f, 0x074a, -- 0x074d, 0x074f, --}; /* CR_Syriac */ -- --/* 'Thaana': Script */ --static const OnigCodePoint CR_Thaana[] = { -- 1, -- 0x0780, 0x07b1, --}; /* CR_Thaana */ -- --/* 'Devanagari': Script */ --static const OnigCodePoint CR_Devanagari[] = { -- 6, -- 0x0900, 0x0950, -- 0x0953, 0x0963, -- 0x0966, 0x096f, -- 0x0971, 0x0977, -- 0x0979, 0x097f, -- 0xa8e0, 0xa8fb, --}; /* CR_Devanagari */ -- --/* 'Bengali': Script */ --static const OnigCodePoint CR_Bengali[] = { -- 14, -- 0x0981, 0x0983, -- 0x0985, 0x098c, -- 0x098f, 0x0990, -- 0x0993, 0x09a8, -- 0x09aa, 0x09b0, -- 0x09b2, 0x09b2, -- 0x09b6, 0x09b9, -- 0x09bc, 0x09c4, -- 0x09c7, 0x09c8, -- 0x09cb, 0x09ce, -- 0x09d7, 0x09d7, -- 0x09dc, 0x09dd, -- 0x09df, 0x09e3, -- 0x09e6, 0x09fb, --}; /* CR_Bengali */ -- --/* 'Gurmukhi': Script */ --static const OnigCodePoint CR_Gurmukhi[] = { -- 16, -- 0x0a01, 0x0a03, -- 0x0a05, 0x0a0a, -- 0x0a0f, 0x0a10, -- 0x0a13, 0x0a28, -- 0x0a2a, 0x0a30, -- 0x0a32, 0x0a33, -- 0x0a35, 0x0a36, -- 0x0a38, 0x0a39, -- 0x0a3c, 0x0a3c, -- 0x0a3e, 0x0a42, -- 0x0a47, 0x0a48, -- 0x0a4b, 0x0a4d, -- 0x0a51, 0x0a51, -- 0x0a59, 0x0a5c, -- 0x0a5e, 0x0a5e, -- 0x0a66, 0x0a75, --}; /* CR_Gurmukhi */ -- --/* 'Gujarati': Script */ --static const OnigCodePoint CR_Gujarati[] = { -- 14, -- 0x0a81, 0x0a83, -- 0x0a85, 0x0a8d, -- 0x0a8f, 0x0a91, -- 0x0a93, 0x0aa8, -- 0x0aaa, 0x0ab0, -- 0x0ab2, 0x0ab3, -- 0x0ab5, 0x0ab9, -- 0x0abc, 0x0ac5, -- 0x0ac7, 0x0ac9, -- 0x0acb, 0x0acd, -- 0x0ad0, 0x0ad0, -- 0x0ae0, 0x0ae3, -- 0x0ae6, 0x0aef, -- 0x0af1, 0x0af1, --}; /* CR_Gujarati */ -- --/* 'Oriya': Script */ --static const OnigCodePoint CR_Oriya[] = { -- 14, -- 0x0b01, 0x0b03, -- 0x0b05, 0x0b0c, -- 0x0b0f, 0x0b10, -- 0x0b13, 0x0b28, -- 0x0b2a, 0x0b30, -- 0x0b32, 0x0b33, -- 0x0b35, 0x0b39, -- 0x0b3c, 0x0b44, -- 0x0b47, 0x0b48, -- 0x0b4b, 0x0b4d, -- 0x0b56, 0x0b57, -- 0x0b5c, 0x0b5d, -- 0x0b5f, 0x0b63, -- 0x0b66, 0x0b77, --}; /* CR_Oriya */ -- --/* 'Tamil': Script */ --static const OnigCodePoint CR_Tamil[] = { -- 16, -- 0x0b82, 0x0b83, -- 0x0b85, 0x0b8a, -- 0x0b8e, 0x0b90, -- 0x0b92, 0x0b95, -- 0x0b99, 0x0b9a, -- 0x0b9c, 0x0b9c, -- 0x0b9e, 0x0b9f, -- 0x0ba3, 0x0ba4, -- 0x0ba8, 0x0baa, -- 0x0bae, 0x0bb9, -- 0x0bbe, 0x0bc2, -- 0x0bc6, 0x0bc8, -- 0x0bca, 0x0bcd, -- 0x0bd0, 0x0bd0, -- 0x0bd7, 0x0bd7, -- 0x0be6, 0x0bfa, --}; /* CR_Tamil */ -- --/* 'Telugu': Script */ --static const OnigCodePoint CR_Telugu[] = { -- 14, -- 0x0c01, 0x0c03, -- 0x0c05, 0x0c0c, -- 0x0c0e, 0x0c10, -- 0x0c12, 0x0c28, -- 0x0c2a, 0x0c33, -- 0x0c35, 0x0c39, -- 0x0c3d, 0x0c44, -- 0x0c46, 0x0c48, -- 0x0c4a, 0x0c4d, -- 0x0c55, 0x0c56, -- 0x0c58, 0x0c59, -- 0x0c60, 0x0c63, -- 0x0c66, 0x0c6f, -- 0x0c78, 0x0c7f, --}; /* CR_Telugu */ -- --/* 'Kannada': Script */ --static const OnigCodePoint CR_Kannada[] = { -- 14, -- 0x0c82, 0x0c83, -- 0x0c85, 0x0c8c, -- 0x0c8e, 0x0c90, -- 0x0c92, 0x0ca8, -- 0x0caa, 0x0cb3, -- 0x0cb5, 0x0cb9, -- 0x0cbc, 0x0cc4, -- 0x0cc6, 0x0cc8, -- 0x0cca, 0x0ccd, -- 0x0cd5, 0x0cd6, -- 0x0cde, 0x0cde, -- 0x0ce0, 0x0ce3, -- 0x0ce6, 0x0cef, -- 0x0cf1, 0x0cf2, --}; /* CR_Kannada */ -- --/* 'Malayalam': Script */ --static const OnigCodePoint CR_Malayalam[] = { -- 11, -- 0x0d02, 0x0d03, -- 0x0d05, 0x0d0c, -- 0x0d0e, 0x0d10, -- 0x0d12, 0x0d3a, -- 0x0d3d, 0x0d44, -- 0x0d46, 0x0d48, -- 0x0d4a, 0x0d4e, -- 0x0d57, 0x0d57, -- 0x0d60, 0x0d63, -- 0x0d66, 0x0d75, -- 0x0d79, 0x0d7f, --}; /* CR_Malayalam */ -- --/* 'Sinhala': Script */ --static const OnigCodePoint CR_Sinhala[] = { -- 11, -- 0x0d82, 0x0d83, -- 0x0d85, 0x0d96, -- 0x0d9a, 0x0db1, -- 0x0db3, 0x0dbb, -- 0x0dbd, 0x0dbd, -- 0x0dc0, 0x0dc6, -- 0x0dca, 0x0dca, -- 0x0dcf, 0x0dd4, -- 0x0dd6, 0x0dd6, -- 0x0dd8, 0x0ddf, -- 0x0df2, 0x0df4, --}; /* CR_Sinhala */ -- --/* 'Thai': Script */ --static const OnigCodePoint CR_Thai[] = { -- 2, -- 0x0e01, 0x0e3a, -- 0x0e40, 0x0e5b, --}; /* CR_Thai */ -- --/* 'Lao': Script */ --static const OnigCodePoint CR_Lao[] = { -- 18, -- 0x0e81, 0x0e82, -- 0x0e84, 0x0e84, -- 0x0e87, 0x0e88, -- 0x0e8a, 0x0e8a, -- 0x0e8d, 0x0e8d, -- 0x0e94, 0x0e97, -- 0x0e99, 0x0e9f, -- 0x0ea1, 0x0ea3, -- 0x0ea5, 0x0ea5, -- 0x0ea7, 0x0ea7, -- 0x0eaa, 0x0eab, -- 0x0ead, 0x0eb9, -- 0x0ebb, 0x0ebd, -- 0x0ec0, 0x0ec4, -- 0x0ec6, 0x0ec6, -- 0x0ec8, 0x0ecd, -- 0x0ed0, 0x0ed9, -- 0x0edc, 0x0edd, --}; /* CR_Lao */ -- --/* 'Tibetan': Script */ --static const OnigCodePoint CR_Tibetan[] = { -- 7, -- 0x0f00, 0x0f47, -- 0x0f49, 0x0f6c, -- 0x0f71, 0x0f97, -- 0x0f99, 0x0fbc, -- 0x0fbe, 0x0fcc, -- 0x0fce, 0x0fd4, -- 0x0fd9, 0x0fda, --}; /* CR_Tibetan */ -- --/* 'Myanmar': Script */ --static const OnigCodePoint CR_Myanmar[] = { -- 2, -- 0x1000, 0x109f, -- 0xaa60, 0xaa7b, --}; /* CR_Myanmar */ -- --/* 'Georgian': Script */ --static const OnigCodePoint CR_Georgian[] = { -- 4, -- 0x10a0, 0x10c5, -- 0x10d0, 0x10fa, -- 0x10fc, 0x10fc, -- 0x2d00, 0x2d25, --}; /* CR_Georgian */ -- --/* 'Hangul': Script */ --static const OnigCodePoint CR_Hangul[] = { -- 14, -- 0x1100, 0x11ff, -- 0x302e, 0x302f, -- 0x3131, 0x318e, -- 0x3200, 0x321e, -- 0x3260, 0x327e, -- 0xa960, 0xa97c, -- 0xac00, 0xd7a3, -- 0xd7b0, 0xd7c6, -- 0xd7cb, 0xd7fb, -- 0xffa0, 0xffbe, -- 0xffc2, 0xffc7, -- 0xffca, 0xffcf, -- 0xffd2, 0xffd7, -- 0xffda, 0xffdc, --}; /* CR_Hangul */ -- --/* 'Ethiopic': Script */ --static const OnigCodePoint CR_Ethiopic[] = { -- 32, -- 0x1200, 0x1248, -- 0x124a, 0x124d, -- 0x1250, 0x1256, -- 0x1258, 0x1258, -- 0x125a, 0x125d, -- 0x1260, 0x1288, -- 0x128a, 0x128d, -- 0x1290, 0x12b0, -- 0x12b2, 0x12b5, -- 0x12b8, 0x12be, -- 0x12c0, 0x12c0, -- 0x12c2, 0x12c5, -- 0x12c8, 0x12d6, -- 0x12d8, 0x1310, -- 0x1312, 0x1315, -- 0x1318, 0x135a, -- 0x135d, 0x137c, -- 0x1380, 0x1399, -- 0x2d80, 0x2d96, -- 0x2da0, 0x2da6, -- 0x2da8, 0x2dae, -- 0x2db0, 0x2db6, -- 0x2db8, 0x2dbe, -- 0x2dc0, 0x2dc6, -- 0x2dc8, 0x2dce, -- 0x2dd0, 0x2dd6, -- 0x2dd8, 0x2dde, -- 0xab01, 0xab06, -- 0xab09, 0xab0e, -- 0xab11, 0xab16, -- 0xab20, 0xab26, -- 0xab28, 0xab2e, --}; /* CR_Ethiopic */ -- --/* 'Cherokee': Script */ --static const OnigCodePoint CR_Cherokee[] = { -- 1, -- 0x13a0, 0x13f4, --}; /* CR_Cherokee */ -- --/* 'Canadian_Aboriginal': Script */ --static const OnigCodePoint CR_Canadian_Aboriginal[] = { -- 2, -- 0x1400, 0x167f, -- 0x18b0, 0x18f5, --}; /* CR_Canadian_Aboriginal */ -- --/* 'Ogham': Script */ --static const OnigCodePoint CR_Ogham[] = { -- 1, -- 0x1680, 0x169c, --}; /* CR_Ogham */ -- --/* 'Runic': Script */ --static const OnigCodePoint CR_Runic[] = { -- 2, -- 0x16a0, 0x16ea, -- 0x16ee, 0x16f0, --}; /* CR_Runic */ -- --/* 'Khmer': Script */ --static const OnigCodePoint CR_Khmer[] = { -- 4, -- 0x1780, 0x17dd, -- 0x17e0, 0x17e9, -- 0x17f0, 0x17f9, -- 0x19e0, 0x19ff, --}; /* CR_Khmer */ -- --/* 'Mongolian': Script */ --static const OnigCodePoint CR_Mongolian[] = { -- 6, -- 0x1800, 0x1801, -- 0x1804, 0x1804, -- 0x1806, 0x180e, -- 0x1810, 0x1819, -- 0x1820, 0x1877, -- 0x1880, 0x18aa, --}; /* CR_Mongolian */ -- --/* 'Hiragana': Script */ --static const OnigCodePoint CR_Hiragana[] = { -- 4, -- 0x3041, 0x3096, -- 0x309d, 0x309f, -- 0x1b001, 0x1b001, -- 0x1f200, 0x1f200, --}; /* CR_Hiragana */ -- --/* 'Katakana': Script */ --static const OnigCodePoint CR_Katakana[] = { -- 8, -- 0x30a1, 0x30fa, -- 0x30fd, 0x30ff, -- 0x31f0, 0x31ff, -- 0x32d0, 0x32fe, -- 0x3300, 0x3357, -- 0xff66, 0xff6f, -- 0xff71, 0xff9d, -- 0x1b000, 0x1b000, --}; /* CR_Katakana */ -- --/* 'Bopomofo': Script */ --static const OnigCodePoint CR_Bopomofo[] = { -- 3, -- 0x02ea, 0x02eb, -- 0x3105, 0x312d, -- 0x31a0, 0x31ba, --}; /* CR_Bopomofo */ -- --/* 'Han': Script */ --static const OnigCodePoint CR_Han[] = { -- 16, -- 0x2e80, 0x2e99, -- 0x2e9b, 0x2ef3, -- 0x2f00, 0x2fd5, -- 0x3005, 0x3005, -- 0x3007, 0x3007, -- 0x3021, 0x3029, -- 0x3038, 0x303b, -- 0x3400, 0x4db5, -- 0x4e00, 0x9fcb, -- 0xf900, 0xfa2d, -- 0xfa30, 0xfa6d, -- 0xfa70, 0xfad9, -- 0x20000, 0x2a6d6, -- 0x2a700, 0x2b734, -- 0x2b740, 0x2b81d, -- 0x2f800, 0x2fa1d, --}; /* CR_Han */ -- --/* 'Yi': Script */ --static const OnigCodePoint CR_Yi[] = { -- 2, -- 0xa000, 0xa48c, -- 0xa490, 0xa4c6, --}; /* CR_Yi */ -- --/* 'Old_Italic': Script */ --static const OnigCodePoint CR_Old_Italic[] = { -- 2, -- 0x10300, 0x1031e, -- 0x10320, 0x10323, --}; /* CR_Old_Italic */ -- --/* 'Gothic': Script */ --static const OnigCodePoint CR_Gothic[] = { -- 1, -- 0x10330, 0x1034a, --}; /* CR_Gothic */ -- --/* 'Deseret': Script */ --static const OnigCodePoint CR_Deseret[] = { -- 1, -- 0x10400, 0x1044f, --}; /* CR_Deseret */ -- --/* 'Inherited': Script */ --static const OnigCodePoint CR_Inherited[] = { -- 24, -- 0x0300, 0x036f, -- 0x0485, 0x0486, -- 0x064b, 0x0655, -- 0x065f, 0x065f, -- 0x0670, 0x0670, -- 0x0951, 0x0952, -- 0x1cd0, 0x1cd2, -- 0x1cd4, 0x1ce0, -- 0x1ce2, 0x1ce8, -- 0x1ced, 0x1ced, -- 0x1dc0, 0x1de6, -- 0x1dfc, 0x1dff, -- 0x200c, 0x200d, -- 0x20d0, 0x20f0, -- 0x302a, 0x302d, -- 0x3099, 0x309a, -- 0xfe00, 0xfe0f, -- 0xfe20, 0xfe26, -- 0x101fd, 0x101fd, -- 0x1d167, 0x1d169, -- 0x1d17b, 0x1d182, -- 0x1d185, 0x1d18b, -- 0x1d1aa, 0x1d1ad, -- 0xe0100, 0xe01ef, --}; /* CR_Inherited */ -- --/* 'Tagalog': Script */ --static const OnigCodePoint CR_Tagalog[] = { -- 2, -- 0x1700, 0x170c, -- 0x170e, 0x1714, --}; /* CR_Tagalog */ -- --/* 'Hanunoo': Script */ --static const OnigCodePoint CR_Hanunoo[] = { -- 1, -- 0x1720, 0x1734, --}; /* CR_Hanunoo */ -- --/* 'Buhid': Script */ --static const OnigCodePoint CR_Buhid[] = { -- 1, -- 0x1740, 0x1753, --}; /* CR_Buhid */ -- --/* 'Tagbanwa': Script */ --static const OnigCodePoint CR_Tagbanwa[] = { -- 3, -- 0x1760, 0x176c, -- 0x176e, 0x1770, -- 0x1772, 0x1773, --}; /* CR_Tagbanwa */ -- --/* 'Limbu': Script */ --static const OnigCodePoint CR_Limbu[] = { -- 5, -- 0x1900, 0x191c, -- 0x1920, 0x192b, -- 0x1930, 0x193b, -- 0x1940, 0x1940, -- 0x1944, 0x194f, --}; /* CR_Limbu */ -- --/* 'Tai_Le': Script */ --static const OnigCodePoint CR_Tai_Le[] = { -- 2, -- 0x1950, 0x196d, -- 0x1970, 0x1974, --}; /* CR_Tai_Le */ -- --/* 'Linear_B': Script */ --static const OnigCodePoint CR_Linear_B[] = { -- 7, -- 0x10000, 0x1000b, -- 0x1000d, 0x10026, -- 0x10028, 0x1003a, -- 0x1003c, 0x1003d, -- 0x1003f, 0x1004d, -- 0x10050, 0x1005d, -- 0x10080, 0x100fa, --}; /* CR_Linear_B */ -- --/* 'Ugaritic': Script */ --static const OnigCodePoint CR_Ugaritic[] = { -- 2, -- 0x10380, 0x1039d, -- 0x1039f, 0x1039f, --}; /* CR_Ugaritic */ -- --/* 'Shavian': Script */ --static const OnigCodePoint CR_Shavian[] = { -- 1, -- 0x10450, 0x1047f, --}; /* CR_Shavian */ -- --/* 'Osmanya': Script */ --static const OnigCodePoint CR_Osmanya[] = { -- 2, -- 0x10480, 0x1049d, -- 0x104a0, 0x104a9, --}; /* CR_Osmanya */ -- --/* 'Cypriot': Script */ --static const OnigCodePoint CR_Cypriot[] = { -- 6, -- 0x10800, 0x10805, -- 0x10808, 0x10808, -- 0x1080a, 0x10835, -- 0x10837, 0x10838, -- 0x1083c, 0x1083c, -- 0x1083f, 0x1083f, --}; /* CR_Cypriot */ -- --/* 'Braille': Script */ --static const OnigCodePoint CR_Braille[] = { -- 1, -- 0x2800, 0x28ff, --}; /* CR_Braille */ -- --/* 'Buginese': Script */ --static const OnigCodePoint CR_Buginese[] = { -- 2, -- 0x1a00, 0x1a1b, -- 0x1a1e, 0x1a1f, --}; /* CR_Buginese */ -- --/* 'Coptic': Script */ --static const OnigCodePoint CR_Coptic[] = { -- 3, -- 0x03e2, 0x03ef, -- 0x2c80, 0x2cf1, -- 0x2cf9, 0x2cff, --}; /* CR_Coptic */ -- --/* 'New_Tai_Lue': Script */ --static const OnigCodePoint CR_New_Tai_Lue[] = { -- 4, -- 0x1980, 0x19ab, -- 0x19b0, 0x19c9, -- 0x19d0, 0x19da, -- 0x19de, 0x19df, --}; /* CR_New_Tai_Lue */ -- --/* 'Glagolitic': Script */ --static const OnigCodePoint CR_Glagolitic[] = { -- 2, -- 0x2c00, 0x2c2e, -- 0x2c30, 0x2c5e, --}; /* CR_Glagolitic */ -- --/* 'Tifinagh': Script */ --static const OnigCodePoint CR_Tifinagh[] = { -- 3, -- 0x2d30, 0x2d65, -- 0x2d6f, 0x2d70, -- 0x2d7f, 0x2d7f, --}; /* CR_Tifinagh */ -- --/* 'Syloti_Nagri': Script */ --static const OnigCodePoint CR_Syloti_Nagri[] = { -- 1, -- 0xa800, 0xa82b, --}; /* CR_Syloti_Nagri */ -- --/* 'Old_Persian': Script */ --static const OnigCodePoint CR_Old_Persian[] = { -- 2, -- 0x103a0, 0x103c3, -- 0x103c8, 0x103d5, --}; /* CR_Old_Persian */ -- --/* 'Kharoshthi': Script */ --static const OnigCodePoint CR_Kharoshthi[] = { -- 8, -- 0x10a00, 0x10a03, -- 0x10a05, 0x10a06, -- 0x10a0c, 0x10a13, -- 0x10a15, 0x10a17, -- 0x10a19, 0x10a33, -- 0x10a38, 0x10a3a, -- 0x10a3f, 0x10a47, -- 0x10a50, 0x10a58, --}; /* CR_Kharoshthi */ -- --/* 'Balinese': Script */ --static const OnigCodePoint CR_Balinese[] = { -- 2, -- 0x1b00, 0x1b4b, -- 0x1b50, 0x1b7c, --}; /* CR_Balinese */ -- --/* 'Cuneiform': Script */ --static const OnigCodePoint CR_Cuneiform[] = { -- 3, -- 0x12000, 0x1236e, -- 0x12400, 0x12462, -- 0x12470, 0x12473, --}; /* CR_Cuneiform */ -- --/* 'Phoenician': Script */ --static const OnigCodePoint CR_Phoenician[] = { -- 2, -- 0x10900, 0x1091b, -- 0x1091f, 0x1091f, --}; /* CR_Phoenician */ -- --/* 'Phags_Pa': Script */ --static const OnigCodePoint CR_Phags_Pa[] = { -- 1, -- 0xa840, 0xa877, --}; /* CR_Phags_Pa */ -- --/* 'Nko': Script */ --static const OnigCodePoint CR_Nko[] = { -- 1, -- 0x07c0, 0x07fa, --}; /* CR_Nko */ -- --/* 'Sundanese': Script */ --static const OnigCodePoint CR_Sundanese[] = { -- 2, -- 0x1b80, 0x1baa, -- 0x1bae, 0x1bb9, --}; /* CR_Sundanese */ -- --/* 'Lepcha': Script */ --static const OnigCodePoint CR_Lepcha[] = { -- 3, -- 0x1c00, 0x1c37, -- 0x1c3b, 0x1c49, -- 0x1c4d, 0x1c4f, --}; /* CR_Lepcha */ -- --/* 'Ol_Chiki': Script */ --static const OnigCodePoint CR_Ol_Chiki[] = { -- 1, -- 0x1c50, 0x1c7f, --}; /* CR_Ol_Chiki */ -- --/* 'Vai': Script */ --static const OnigCodePoint CR_Vai[] = { -- 1, -- 0xa500, 0xa62b, --}; /* CR_Vai */ -- --/* 'Saurashtra': Script */ --static const OnigCodePoint CR_Saurashtra[] = { -- 2, -- 0xa880, 0xa8c4, -- 0xa8ce, 0xa8d9, --}; /* CR_Saurashtra */ -- --/* 'Kayah_Li': Script */ --static const OnigCodePoint CR_Kayah_Li[] = { -- 1, -- 0xa900, 0xa92f, --}; /* CR_Kayah_Li */ -- --/* 'Rejang': Script */ --static const OnigCodePoint CR_Rejang[] = { -- 2, -- 0xa930, 0xa953, -- 0xa95f, 0xa95f, --}; /* CR_Rejang */ -- --/* 'Lycian': Script */ --static const OnigCodePoint CR_Lycian[] = { -- 1, -- 0x10280, 0x1029c, --}; /* CR_Lycian */ -- --/* 'Carian': Script */ --static const OnigCodePoint CR_Carian[] = { -- 1, -- 0x102a0, 0x102d0, --}; /* CR_Carian */ -- --/* 'Lydian': Script */ --static const OnigCodePoint CR_Lydian[] = { -- 2, -- 0x10920, 0x10939, -- 0x1093f, 0x1093f, --}; /* CR_Lydian */ -- --/* 'Cham': Script */ --static const OnigCodePoint CR_Cham[] = { -- 4, -- 0xaa00, 0xaa36, -- 0xaa40, 0xaa4d, -- 0xaa50, 0xaa59, -- 0xaa5c, 0xaa5f, --}; /* CR_Cham */ -- --/* 'Tai_Tham': Script */ --static const OnigCodePoint CR_Tai_Tham[] = { -- 5, -- 0x1a20, 0x1a5e, -- 0x1a60, 0x1a7c, -- 0x1a7f, 0x1a89, -- 0x1a90, 0x1a99, -- 0x1aa0, 0x1aad, --}; /* CR_Tai_Tham */ -- --/* 'Tai_Viet': Script */ --static const OnigCodePoint CR_Tai_Viet[] = { -- 2, -- 0xaa80, 0xaac2, -- 0xaadb, 0xaadf, --}; /* CR_Tai_Viet */ -- --/* 'Avestan': Script */ --static const OnigCodePoint CR_Avestan[] = { -- 2, -- 0x10b00, 0x10b35, -- 0x10b39, 0x10b3f, --}; /* CR_Avestan */ -- --/* 'Egyptian_Hieroglyphs': Script */ --static const OnigCodePoint CR_Egyptian_Hieroglyphs[] = { -- 1, -- 0x13000, 0x1342e, --}; /* CR_Egyptian_Hieroglyphs */ -- --/* 'Samaritan': Script */ --static const OnigCodePoint CR_Samaritan[] = { -- 2, -- 0x0800, 0x082d, -- 0x0830, 0x083e, --}; /* CR_Samaritan */ -- --/* 'Lisu': Script */ --static const OnigCodePoint CR_Lisu[] = { -- 1, -- 0xa4d0, 0xa4ff, --}; /* CR_Lisu */ -- --/* 'Bamum': Script */ --static const OnigCodePoint CR_Bamum[] = { -- 2, -- 0xa6a0, 0xa6f7, -- 0x16800, 0x16a38, --}; /* CR_Bamum */ -- --/* 'Javanese': Script */ --static const OnigCodePoint CR_Javanese[] = { -- 3, -- 0xa980, 0xa9cd, -- 0xa9cf, 0xa9d9, -- 0xa9de, 0xa9df, --}; /* CR_Javanese */ -- --/* 'Meetei_Mayek': Script */ --static const OnigCodePoint CR_Meetei_Mayek[] = { -- 2, -- 0xabc0, 0xabed, -- 0xabf0, 0xabf9, --}; /* CR_Meetei_Mayek */ -- --/* 'Imperial_Aramaic': Script */ --static const OnigCodePoint CR_Imperial_Aramaic[] = { -- 2, -- 0x10840, 0x10855, -- 0x10857, 0x1085f, --}; /* CR_Imperial_Aramaic */ -- --/* 'Old_South_Arabian': Script */ --static const OnigCodePoint CR_Old_South_Arabian[] = { -- 1, -- 0x10a60, 0x10a7f, --}; /* CR_Old_South_Arabian */ -- --/* 'Inscriptional_Parthian': Script */ --static const OnigCodePoint CR_Inscriptional_Parthian[] = { -- 2, -- 0x10b40, 0x10b55, -- 0x10b58, 0x10b5f, --}; /* CR_Inscriptional_Parthian */ -- --/* 'Inscriptional_Pahlavi': Script */ --static const OnigCodePoint CR_Inscriptional_Pahlavi[] = { -- 2, -- 0x10b60, 0x10b72, -- 0x10b78, 0x10b7f, --}; /* CR_Inscriptional_Pahlavi */ -- --/* 'Old_Turkic': Script */ --static const OnigCodePoint CR_Old_Turkic[] = { -- 1, -- 0x10c00, 0x10c48, --}; /* CR_Old_Turkic */ -- --/* 'Kaithi': Script */ --static const OnigCodePoint CR_Kaithi[] = { -- 1, -- 0x11080, 0x110c1, --}; /* CR_Kaithi */ -- --/* 'Batak': Script */ --static const OnigCodePoint CR_Batak[] = { -- 2, -- 0x1bc0, 0x1bf3, -- 0x1bfc, 0x1bff, --}; /* CR_Batak */ -- --/* 'Brahmi': Script */ --static const OnigCodePoint CR_Brahmi[] = { -- 2, -- 0x11000, 0x1104d, -- 0x11052, 0x1106f, --}; /* CR_Brahmi */ -- --/* 'Mandaic': Script */ --static const OnigCodePoint CR_Mandaic[] = { -- 2, -- 0x0840, 0x085b, -- 0x085e, 0x085e, --}; /* CR_Mandaic */ -- --/* 'White_Space': Binary Property */ --static const OnigCodePoint CR_White_Space[] = { -- 11, -- 0x0009, 0x000d, -- 0x0020, 0x0020, -- 0x0085, 0x0085, -- 0x00a0, 0x00a0, -- 0x1680, 0x1680, -- 0x180e, 0x180e, -- 0x2000, 0x200a, -- 0x2028, 0x2029, -- 0x202f, 0x202f, -- 0x205f, 0x205f, -- 0x3000, 0x3000, --}; /* CR_White_Space */ -- --/* 'Bidi_Control': Binary Property */ --static const OnigCodePoint CR_Bidi_Control[] = { -- 2, -- 0x200e, 0x200f, -- 0x202a, 0x202e, --}; /* CR_Bidi_Control */ -- --/* 'Join_Control': Binary Property */ --static const OnigCodePoint CR_Join_Control[] = { -- 1, -- 0x200c, 0x200d, --}; /* CR_Join_Control */ -- --/* 'Dash': Binary Property */ --static const OnigCodePoint CR_Dash[] = { -- 19, -- 0x002d, 0x002d, -- 0x058a, 0x058a, -- 0x05be, 0x05be, -- 0x1400, 0x1400, -- 0x1806, 0x1806, -- 0x2010, 0x2015, -- 0x2053, 0x2053, -- 0x207b, 0x207b, -- 0x208b, 0x208b, -- 0x2212, 0x2212, -- 0x2e17, 0x2e17, -- 0x2e1a, 0x2e1a, -- 0x301c, 0x301c, -- 0x3030, 0x3030, -- 0x30a0, 0x30a0, -- 0xfe31, 0xfe32, -- 0xfe58, 0xfe58, -- 0xfe63, 0xfe63, -- 0xff0d, 0xff0d, --}; /* CR_Dash */ -- --/* 'Hyphen': Binary Property */ --static const OnigCodePoint CR_Hyphen[] = { -- 10, -- 0x002d, 0x002d, -- 0x00ad, 0x00ad, -- 0x058a, 0x058a, -- 0x1806, 0x1806, -- 0x2010, 0x2011, -- 0x2e17, 0x2e17, -- 0x30fb, 0x30fb, -- 0xfe63, 0xfe63, -- 0xff0d, 0xff0d, -- 0xff65, 0xff65, --}; /* CR_Hyphen */ -- --/* 'Quotation_Mark': Binary Property */ --static const OnigCodePoint CR_Quotation_Mark[] = { -- 12, -- 0x0022, 0x0022, -- 0x0027, 0x0027, -- 0x00ab, 0x00ab, -- 0x00bb, 0x00bb, -- 0x2018, 0x201f, -- 0x2039, 0x203a, -- 0x300c, 0x300f, -- 0x301d, 0x301f, -- 0xfe41, 0xfe44, -- 0xff02, 0xff02, -- 0xff07, 0xff07, -- 0xff62, 0xff63, --}; /* CR_Quotation_Mark */ -- --/* 'Terminal_Punctuation': Binary Property */ --static const OnigCodePoint CR_Terminal_Punctuation[] = { -- 67, -- 0x0021, 0x0021, -- 0x002c, 0x002c, -- 0x002e, 0x002e, -- 0x003a, 0x003b, -- 0x003f, 0x003f, -- 0x037e, 0x037e, -- 0x0387, 0x0387, -- 0x0589, 0x0589, -- 0x05c3, 0x05c3, -- 0x060c, 0x060c, -- 0x061b, 0x061b, -- 0x061f, 0x061f, -- 0x06d4, 0x06d4, -- 0x0700, 0x070a, -- 0x070c, 0x070c, -- 0x07f8, 0x07f9, -- 0x0830, 0x083e, -- 0x085e, 0x085e, -- 0x0964, 0x0965, -- 0x0e5a, 0x0e5b, -- 0x0f08, 0x0f08, -- 0x0f0d, 0x0f12, -- 0x104a, 0x104b, -- 0x1361, 0x1368, -- 0x166d, 0x166e, -- 0x16eb, 0x16ed, -- 0x17d4, 0x17d6, -- 0x17da, 0x17da, -- 0x1802, 0x1805, -- 0x1808, 0x1809, -- 0x1944, 0x1945, -- 0x1aa8, 0x1aab, -- 0x1b5a, 0x1b5b, -- 0x1b5d, 0x1b5f, -- 0x1c3b, 0x1c3f, -- 0x1c7e, 0x1c7f, -- 0x203c, 0x203d, -- 0x2047, 0x2049, -- 0x2e2e, 0x2e2e, -- 0x3001, 0x3002, -- 0xa4fe, 0xa4ff, -- 0xa60d, 0xa60f, -- 0xa6f3, 0xa6f7, -- 0xa876, 0xa877, -- 0xa8ce, 0xa8cf, -- 0xa92f, 0xa92f, -- 0xa9c7, 0xa9c9, -- 0xaa5d, 0xaa5f, -- 0xaadf, 0xaadf, -- 0xabeb, 0xabeb, -- 0xfe50, 0xfe52, -- 0xfe54, 0xfe57, -- 0xff01, 0xff01, -- 0xff0c, 0xff0c, -- 0xff0e, 0xff0e, -- 0xff1a, 0xff1b, -- 0xff1f, 0xff1f, -- 0xff61, 0xff61, -- 0xff64, 0xff64, -- 0x1039f, 0x1039f, -- 0x103d0, 0x103d0, -- 0x10857, 0x10857, -- 0x1091f, 0x1091f, -- 0x10b3a, 0x10b3f, -- 0x11047, 0x1104d, -- 0x110be, 0x110c1, -- 0x12470, 0x12473, --}; /* CR_Terminal_Punctuation */ -- --/* 'Other_Math': Binary Property */ --static const OnigCodePoint CR_Other_Math[] = { -- 100, -- 0x005e, 0x005e, -- 0x03d0, 0x03d2, -- 0x03d5, 0x03d5, -- 0x03f0, 0x03f1, -- 0x03f4, 0x03f5, -- 0x2016, 0x2016, -- 0x2032, 0x2034, -- 0x2040, 0x2040, -- 0x2061, 0x2064, -- 0x207d, 0x207e, -- 0x208d, 0x208e, -- 0x20d0, 0x20dc, -- 0x20e1, 0x20e1, -- 0x20e5, 0x20e6, -- 0x20eb, 0x20ef, -- 0x2102, 0x2102, -- 0x2107, 0x2107, -- 0x210a, 0x2113, -- 0x2115, 0x2115, -- 0x2119, 0x211d, -- 0x2124, 0x2124, -- 0x2128, 0x2129, -- 0x212c, 0x212d, -- 0x212f, 0x2131, -- 0x2133, 0x2138, -- 0x213c, 0x213f, -- 0x2145, 0x2149, -- 0x2195, 0x2199, -- 0x219c, 0x219f, -- 0x21a1, 0x21a2, -- 0x21a4, 0x21a5, -- 0x21a7, 0x21a7, -- 0x21a9, 0x21ad, -- 0x21b0, 0x21b1, -- 0x21b6, 0x21b7, -- 0x21bc, 0x21cd, -- 0x21d0, 0x21d1, -- 0x21d3, 0x21d3, -- 0x21d5, 0x21db, -- 0x21dd, 0x21dd, -- 0x21e4, 0x21e5, -- 0x23b4, 0x23b5, -- 0x23b7, 0x23b7, -- 0x23d0, 0x23d0, -- 0x23e2, 0x23e2, -- 0x25a0, 0x25a1, -- 0x25ae, 0x25b6, -- 0x25bc, 0x25c0, -- 0x25c6, 0x25c7, -- 0x25ca, 0x25cb, -- 0x25cf, 0x25d3, -- 0x25e2, 0x25e2, -- 0x25e4, 0x25e4, -- 0x25e7, 0x25ec, -- 0x2605, 0x2606, -- 0x2640, 0x2640, -- 0x2642, 0x2642, -- 0x2660, 0x2663, -- 0x266d, 0x266e, -- 0x27c5, 0x27c6, -- 0x27e6, 0x27ef, -- 0x2983, 0x2998, -- 0x29d8, 0x29db, -- 0x29fc, 0x29fd, -- 0xfe61, 0xfe61, -- 0xfe63, 0xfe63, -- 0xfe68, 0xfe68, -- 0xff3c, 0xff3c, -- 0xff3e, 0xff3e, -- 0x1d400, 0x1d454, -- 0x1d456, 0x1d49c, -- 0x1d49e, 0x1d49f, -- 0x1d4a2, 0x1d4a2, -- 0x1d4a5, 0x1d4a6, -- 0x1d4a9, 0x1d4ac, -- 0x1d4ae, 0x1d4b9, -- 0x1d4bb, 0x1d4bb, -- 0x1d4bd, 0x1d4c3, -- 0x1d4c5, 0x1d505, -- 0x1d507, 0x1d50a, -- 0x1d50d, 0x1d514, -- 0x1d516, 0x1d51c, -- 0x1d51e, 0x1d539, -- 0x1d53b, 0x1d53e, -- 0x1d540, 0x1d544, -- 0x1d546, 0x1d546, -- 0x1d54a, 0x1d550, -- 0x1d552, 0x1d6a5, -- 0x1d6a8, 0x1d6c0, -- 0x1d6c2, 0x1d6da, -- 0x1d6dc, 0x1d6fa, -- 0x1d6fc, 0x1d714, -- 0x1d716, 0x1d734, -- 0x1d736, 0x1d74e, -- 0x1d750, 0x1d76e, -- 0x1d770, 0x1d788, -- 0x1d78a, 0x1d7a8, -- 0x1d7aa, 0x1d7c2, -- 0x1d7c4, 0x1d7cb, -- 0x1d7ce, 0x1d7ff, --}; /* CR_Other_Math */ -- --/* 'Hex_Digit': Binary Property */ --static const OnigCodePoint CR_Hex_Digit[] = { -- 6, -- 0x0030, 0x0039, -- 0x0041, 0x0046, -- 0x0061, 0x0066, -- 0xff10, 0xff19, -- 0xff21, 0xff26, -- 0xff41, 0xff46, --}; /* CR_Hex_Digit */ -- --/* 'ASCII_Hex_Digit': Binary Property */ --static const OnigCodePoint CR_ASCII_Hex_Digit[] = { -- 3, -- 0x0030, 0x0039, -- 0x0041, 0x0046, -- 0x0061, 0x0066, --}; /* CR_ASCII_Hex_Digit */ -- --/* 'Other_Alphabetic': Binary Property */ --static const OnigCodePoint CR_Other_Alphabetic[] = { -- 145, -- 0x0345, 0x0345, -- 0x05b0, 0x05bd, -- 0x05bf, 0x05bf, -- 0x05c1, 0x05c2, -- 0x05c4, 0x05c5, -- 0x05c7, 0x05c7, -- 0x0610, 0x061a, -- 0x064b, 0x0657, -- 0x0659, 0x065f, -- 0x0670, 0x0670, -- 0x06d6, 0x06dc, -- 0x06e1, 0x06e4, -- 0x06e7, 0x06e8, -- 0x06ed, 0x06ed, -- 0x0711, 0x0711, -- 0x0730, 0x073f, -- 0x07a6, 0x07b0, -- 0x0816, 0x0817, -- 0x081b, 0x0823, -- 0x0825, 0x0827, -- 0x0829, 0x082c, -- 0x0900, 0x0903, -- 0x093a, 0x093b, -- 0x093e, 0x094c, -- 0x094e, 0x094f, -- 0x0955, 0x0957, -- 0x0962, 0x0963, -- 0x0981, 0x0983, -- 0x09be, 0x09c4, -- 0x09c7, 0x09c8, -- 0x09cb, 0x09cc, -- 0x09d7, 0x09d7, -- 0x09e2, 0x09e3, -- 0x0a01, 0x0a03, -- 0x0a3e, 0x0a42, -- 0x0a47, 0x0a48, -- 0x0a4b, 0x0a4c, -- 0x0a51, 0x0a51, -- 0x0a70, 0x0a71, -- 0x0a75, 0x0a75, -- 0x0a81, 0x0a83, -- 0x0abe, 0x0ac5, -- 0x0ac7, 0x0ac9, -- 0x0acb, 0x0acc, -- 0x0ae2, 0x0ae3, -- 0x0b01, 0x0b03, -- 0x0b3e, 0x0b44, -- 0x0b47, 0x0b48, -- 0x0b4b, 0x0b4c, -- 0x0b56, 0x0b57, -- 0x0b62, 0x0b63, -- 0x0b82, 0x0b82, -- 0x0bbe, 0x0bc2, -- 0x0bc6, 0x0bc8, -- 0x0bca, 0x0bcc, -- 0x0bd7, 0x0bd7, -- 0x0c01, 0x0c03, -- 0x0c3e, 0x0c44, -- 0x0c46, 0x0c48, -- 0x0c4a, 0x0c4c, -- 0x0c55, 0x0c56, -- 0x0c62, 0x0c63, -- 0x0c82, 0x0c83, -- 0x0cbe, 0x0cc4, -- 0x0cc6, 0x0cc8, -- 0x0cca, 0x0ccc, -- 0x0cd5, 0x0cd6, -- 0x0ce2, 0x0ce3, -- 0x0d02, 0x0d03, -- 0x0d3e, 0x0d44, -- 0x0d46, 0x0d48, -- 0x0d4a, 0x0d4c, -- 0x0d57, 0x0d57, -- 0x0d62, 0x0d63, -- 0x0d82, 0x0d83, -- 0x0dcf, 0x0dd4, -- 0x0dd6, 0x0dd6, -- 0x0dd8, 0x0ddf, -- 0x0df2, 0x0df3, -- 0x0e31, 0x0e31, -- 0x0e34, 0x0e3a, -- 0x0e4d, 0x0e4d, -- 0x0eb1, 0x0eb1, -- 0x0eb4, 0x0eb9, -- 0x0ebb, 0x0ebc, -- 0x0ecd, 0x0ecd, -- 0x0f71, 0x0f81, -- 0x0f8d, 0x0f97, -- 0x0f99, 0x0fbc, -- 0x102b, 0x1036, -- 0x1038, 0x1038, -- 0x103b, 0x103e, -- 0x1056, 0x1059, -- 0x105e, 0x1060, -- 0x1062, 0x1062, -- 0x1067, 0x1068, -- 0x1071, 0x1074, -- 0x1082, 0x1086, -- 0x109c, 0x109d, -- 0x135f, 0x135f, -- 0x1712, 0x1713, -- 0x1732, 0x1733, -- 0x1752, 0x1753, -- 0x1772, 0x1773, -- 0x17b6, 0x17c8, -- 0x18a9, 0x18a9, -- 0x1920, 0x192b, -- 0x1930, 0x1938, -- 0x19b0, 0x19c0, -- 0x19c8, 0x19c9, -- 0x1a17, 0x1a1b, -- 0x1a55, 0x1a5e, -- 0x1a61, 0x1a74, -- 0x1b00, 0x1b04, -- 0x1b35, 0x1b43, -- 0x1b80, 0x1b82, -- 0x1ba1, 0x1ba9, -- 0x1be7, 0x1bf1, -- 0x1c24, 0x1c35, -- 0x1cf2, 0x1cf2, -- 0x24b6, 0x24e9, -- 0x2de0, 0x2dff, -- 0xa823, 0xa827, -- 0xa880, 0xa881, -- 0xa8b4, 0xa8c3, -- 0xa926, 0xa92a, -- 0xa947, 0xa952, -- 0xa980, 0xa983, -- 0xa9b4, 0xa9bf, -- 0xaa29, 0xaa36, -- 0xaa43, 0xaa43, -- 0xaa4c, 0xaa4d, -- 0xaab0, 0xaab0, -- 0xaab2, 0xaab4, -- 0xaab7, 0xaab8, -- 0xaabe, 0xaabe, -- 0xabe3, 0xabea, -- 0xfb1e, 0xfb1e, -- 0x10a01, 0x10a03, -- 0x10a05, 0x10a06, -- 0x10a0c, 0x10a0f, -- 0x11000, 0x11002, -- 0x11038, 0x11045, -- 0x11082, 0x11082, -- 0x110b0, 0x110b8, --}; /* CR_Other_Alphabetic */ -- --/* 'Ideographic': Binary Property */ --static const OnigCodePoint CR_Ideographic[] = { -- 12, -- 0x3006, 0x3007, -- 0x3021, 0x3029, -- 0x3038, 0x303a, -- 0x3400, 0x4db5, -- 0x4e00, 0x9fcb, -- 0xf900, 0xfa2d, -- 0xfa30, 0xfa6d, -- 0xfa70, 0xfad9, -- 0x20000, 0x2a6d6, -- 0x2a700, 0x2b734, -- 0x2b740, 0x2b81d, -- 0x2f800, 0x2fa1d, --}; /* CR_Ideographic */ -- --/* 'Diacritic': Binary Property */ --static const OnigCodePoint CR_Diacritic[] = { -- 117, -- 0x005e, 0x005e, -- 0x0060, 0x0060, -- 0x00a8, 0x00a8, -- 0x00af, 0x00af, -- 0x00b4, 0x00b4, -- 0x00b7, 0x00b8, -- 0x02b0, 0x034e, -- 0x0350, 0x0357, -- 0x035d, 0x0362, -- 0x0374, 0x0375, -- 0x037a, 0x037a, -- 0x0384, 0x0385, -- 0x0483, 0x0487, -- 0x0559, 0x0559, -- 0x0591, 0x05a1, -- 0x05a3, 0x05bd, -- 0x05bf, 0x05bf, -- 0x05c1, 0x05c2, -- 0x05c4, 0x05c4, -- 0x064b, 0x0652, -- 0x0657, 0x0658, -- 0x06df, 0x06e0, -- 0x06e5, 0x06e6, -- 0x06ea, 0x06ec, -- 0x0730, 0x074a, -- 0x07a6, 0x07b0, -- 0x07eb, 0x07f5, -- 0x0818, 0x0819, -- 0x093c, 0x093c, -- 0x094d, 0x094d, -- 0x0951, 0x0954, -- 0x0971, 0x0971, -- 0x09bc, 0x09bc, -- 0x09cd, 0x09cd, -- 0x0a3c, 0x0a3c, -- 0x0a4d, 0x0a4d, -- 0x0abc, 0x0abc, -- 0x0acd, 0x0acd, -- 0x0b3c, 0x0b3c, -- 0x0b4d, 0x0b4d, -- 0x0bcd, 0x0bcd, -- 0x0c4d, 0x0c4d, -- 0x0cbc, 0x0cbc, -- 0x0ccd, 0x0ccd, -- 0x0d4d, 0x0d4d, -- 0x0dca, 0x0dca, -- 0x0e47, 0x0e4c, -- 0x0e4e, 0x0e4e, -- 0x0ec8, 0x0ecc, -- 0x0f18, 0x0f19, -- 0x0f35, 0x0f35, -- 0x0f37, 0x0f37, -- 0x0f39, 0x0f39, -- 0x0f3e, 0x0f3f, -- 0x0f82, 0x0f84, -- 0x0f86, 0x0f87, -- 0x0fc6, 0x0fc6, -- 0x1037, 0x1037, -- 0x1039, 0x103a, -- 0x1087, 0x108d, -- 0x108f, 0x108f, -- 0x109a, 0x109b, -- 0x17c9, 0x17d3, -- 0x17dd, 0x17dd, -- 0x1939, 0x193b, -- 0x1a75, 0x1a7c, -- 0x1a7f, 0x1a7f, -- 0x1b34, 0x1b34, -- 0x1b44, 0x1b44, -- 0x1b6b, 0x1b73, -- 0x1baa, 0x1baa, -- 0x1c36, 0x1c37, -- 0x1c78, 0x1c7d, -- 0x1cd0, 0x1ce8, -- 0x1ced, 0x1ced, -- 0x1d2c, 0x1d6a, -- 0x1dc4, 0x1dcf, -- 0x1dfd, 0x1dff, -- 0x1fbd, 0x1fbd, -- 0x1fbf, 0x1fc1, -- 0x1fcd, 0x1fcf, -- 0x1fdd, 0x1fdf, -- 0x1fed, 0x1fef, -- 0x1ffd, 0x1ffe, -- 0x2cef, 0x2cf1, -- 0x2e2f, 0x2e2f, -- 0x302a, 0x302f, -- 0x3099, 0x309c, -- 0x30fc, 0x30fc, -- 0xa66f, 0xa66f, -- 0xa67c, 0xa67d, -- 0xa67f, 0xa67f, -- 0xa6f0, 0xa6f1, -- 0xa717, 0xa721, -- 0xa788, 0xa788, -- 0xa8c4, 0xa8c4, -- 0xa8e0, 0xa8f1, -- 0xa92b, 0xa92e, -- 0xa953, 0xa953, -- 0xa9b3, 0xa9b3, -- 0xa9c0, 0xa9c0, -- 0xaa7b, 0xaa7b, -- 0xaabf, 0xaac2, -- 0xabec, 0xabed, -- 0xfb1e, 0xfb1e, -- 0xfe20, 0xfe26, -- 0xff3e, 0xff3e, -- 0xff40, 0xff40, -- 0xff70, 0xff70, -- 0xff9e, 0xff9f, -- 0xffe3, 0xffe3, -- 0x110b9, 0x110ba, -- 0x1d167, 0x1d169, -- 0x1d16d, 0x1d172, -- 0x1d17b, 0x1d182, -- 0x1d185, 0x1d18b, -- 0x1d1aa, 0x1d1ad, --}; /* CR_Diacritic */ -- --/* 'Extender': Binary Property */ --static const OnigCodePoint CR_Extender[] = { -- 20, -- 0x00b7, 0x00b7, -- 0x02d0, 0x02d1, -- 0x0640, 0x0640, -- 0x07fa, 0x07fa, -- 0x0e46, 0x0e46, -- 0x0ec6, 0x0ec6, -- 0x1843, 0x1843, -- 0x1aa7, 0x1aa7, -- 0x1c36, 0x1c36, -- 0x1c7b, 0x1c7b, -- 0x3005, 0x3005, -- 0x3031, 0x3035, -- 0x309d, 0x309e, -- 0x30fc, 0x30fe, -- 0xa015, 0xa015, -- 0xa60c, 0xa60c, -- 0xa9cf, 0xa9cf, -- 0xaa70, 0xaa70, -- 0xaadd, 0xaadd, -- 0xff70, 0xff70, --}; /* CR_Extender */ -- --/* 'Other_Lowercase': Binary Property */ --static const OnigCodePoint CR_Other_Lowercase[] = { -- 13, -- 0x02b0, 0x02b8, -- 0x02c0, 0x02c1, -- 0x02e0, 0x02e4, -- 0x0345, 0x0345, -- 0x037a, 0x037a, -- 0x1d2c, 0x1d61, -- 0x1d78, 0x1d78, -- 0x1d9b, 0x1dbf, -- 0x2090, 0x2094, -- 0x2170, 0x217f, -- 0x24d0, 0x24e9, -- 0x2c7d, 0x2c7d, -- 0xa770, 0xa770, --}; /* CR_Other_Lowercase */ -- --/* 'Other_Uppercase': Binary Property */ --static const OnigCodePoint CR_Other_Uppercase[] = { -- 2, -- 0x2160, 0x216f, -- 0x24b6, 0x24cf, --}; /* CR_Other_Uppercase */ -- --/* 'Noncharacter_Code_Point': Binary Property */ --static const OnigCodePoint CR_Noncharacter_Code_Point[] = { -- 18, -- 0xfdd0, 0xfdef, -- 0xfffe, 0xffff, -- 0x1fffe, 0x1ffff, -- 0x2fffe, 0x2ffff, -- 0x3fffe, 0x3ffff, -- 0x4fffe, 0x4ffff, -- 0x5fffe, 0x5ffff, -- 0x6fffe, 0x6ffff, -- 0x7fffe, 0x7ffff, -- 0x8fffe, 0x8ffff, -- 0x9fffe, 0x9ffff, -- 0xafffe, 0xaffff, -- 0xbfffe, 0xbffff, -- 0xcfffe, 0xcffff, -- 0xdfffe, 0xdffff, -- 0xefffe, 0xeffff, -- 0xffffe, 0xfffff, -- 0x10fffe, 0x10ffff, --}; /* CR_Noncharacter_Code_Point */ -- --/* 'Other_Grapheme_Extend': Binary Property */ --static const OnigCodePoint CR_Other_Grapheme_Extend[] = { -- 16, -- 0x09be, 0x09be, -- 0x09d7, 0x09d7, -- 0x0b3e, 0x0b3e, -- 0x0b57, 0x0b57, -- 0x0bbe, 0x0bbe, -- 0x0bd7, 0x0bd7, -- 0x0cc2, 0x0cc2, -- 0x0cd5, 0x0cd6, -- 0x0d3e, 0x0d3e, -- 0x0d57, 0x0d57, -- 0x0dcf, 0x0dcf, -- 0x0ddf, 0x0ddf, -- 0x200c, 0x200d, -- 0xff9e, 0xff9f, -- 0x1d165, 0x1d165, -- 0x1d16e, 0x1d172, --}; /* CR_Other_Grapheme_Extend */ -- --/* 'IDS_Binary_Operator': Binary Property */ --static const OnigCodePoint CR_IDS_Binary_Operator[] = { -- 2, -- 0x2ff0, 0x2ff1, -- 0x2ff4, 0x2ffb, --}; /* CR_IDS_Binary_Operator */ -- --/* 'IDS_Trinary_Operator': Binary Property */ --static const OnigCodePoint CR_IDS_Trinary_Operator[] = { -- 1, -- 0x2ff2, 0x2ff3, --}; /* CR_IDS_Trinary_Operator */ -- --/* 'Radical': Binary Property */ --static const OnigCodePoint CR_Radical[] = { -- 3, -- 0x2e80, 0x2e99, -- 0x2e9b, 0x2ef3, -- 0x2f00, 0x2fd5, --}; /* CR_Radical */ -- --/* 'Unified_Ideograph': Binary Property */ --static const OnigCodePoint CR_Unified_Ideograph[] = { -- 12, -- 0x3400, 0x4db5, -- 0x4e00, 0x9fcb, -- 0xfa0e, 0xfa0f, -- 0xfa11, 0xfa11, -- 0xfa13, 0xfa14, -- 0xfa1f, 0xfa1f, -- 0xfa21, 0xfa21, -- 0xfa23, 0xfa24, -- 0xfa27, 0xfa29, -- 0x20000, 0x2a6d6, -- 0x2a700, 0x2b734, -- 0x2b740, 0x2b81d, --}; /* CR_Unified_Ideograph */ -- --/* 'Other_Default_Ignorable_Code_Point': Binary Property */ --static const OnigCodePoint CR_Other_Default_Ignorable_Code_Point[] = { -- 10, -- 0x034f, 0x034f, -- 0x115f, 0x1160, -- 0x2065, 0x2069, -- 0x3164, 0x3164, -- 0xffa0, 0xffa0, -- 0xfff0, 0xfff8, -- 0xe0000, 0xe0000, -- 0xe0002, 0xe001f, -- 0xe0080, 0xe00ff, -- 0xe01f0, 0xe0fff, --}; /* CR_Other_Default_Ignorable_Code_Point */ -- --/* 'Deprecated': Binary Property */ --static const OnigCodePoint CR_Deprecated[] = { -- 9, -- 0x0149, 0x0149, -- 0x0673, 0x0673, -- 0x0f77, 0x0f77, -- 0x0f79, 0x0f79, -- 0x17a3, 0x17a4, -- 0x206a, 0x206f, -- 0x2329, 0x232a, -- 0xe0001, 0xe0001, -- 0xe0020, 0xe007f, --}; /* CR_Deprecated */ -- --/* 'Soft_Dotted': Binary Property */ --static const OnigCodePoint CR_Soft_Dotted[] = { -- 31, -- 0x0069, 0x006a, -- 0x012f, 0x012f, -- 0x0249, 0x0249, -- 0x0268, 0x0268, -- 0x029d, 0x029d, -- 0x02b2, 0x02b2, -- 0x03f3, 0x03f3, -- 0x0456, 0x0456, -- 0x0458, 0x0458, -- 0x1d62, 0x1d62, -- 0x1d96, 0x1d96, -- 0x1da4, 0x1da4, -- 0x1da8, 0x1da8, -- 0x1e2d, 0x1e2d, -- 0x1ecb, 0x1ecb, -- 0x2071, 0x2071, -- 0x2148, 0x2149, -- 0x2c7c, 0x2c7c, -- 0x1d422, 0x1d423, -- 0x1d456, 0x1d457, -- 0x1d48a, 0x1d48b, -- 0x1d4be, 0x1d4bf, -- 0x1d4f2, 0x1d4f3, -- 0x1d526, 0x1d527, -- 0x1d55a, 0x1d55b, -- 0x1d58e, 0x1d58f, -- 0x1d5c2, 0x1d5c3, -- 0x1d5f6, 0x1d5f7, -- 0x1d62a, 0x1d62b, -- 0x1d65e, 0x1d65f, -- 0x1d692, 0x1d693, --}; /* CR_Soft_Dotted */ -- --/* 'Logical_Order_Exception': Binary Property */ --static const OnigCodePoint CR_Logical_Order_Exception[] = { -- 5, -- 0x0e40, 0x0e44, -- 0x0ec0, 0x0ec4, -- 0xaab5, 0xaab6, -- 0xaab9, 0xaab9, -- 0xaabb, 0xaabc, --}; /* CR_Logical_Order_Exception */ -- --/* 'Other_ID_Start': Binary Property */ --static const OnigCodePoint CR_Other_ID_Start[] = { -- 3, -- 0x2118, 0x2118, -- 0x212e, 0x212e, -- 0x309b, 0x309c, --}; /* CR_Other_ID_Start */ -- --/* 'Other_ID_Continue': Binary Property */ --static const OnigCodePoint CR_Other_ID_Continue[] = { -- 4, -- 0x00b7, 0x00b7, -- 0x0387, 0x0387, -- 0x1369, 0x1371, -- 0x19da, 0x19da, --}; /* CR_Other_ID_Continue */ -- --/* 'STerm': Binary Property */ --static const OnigCodePoint CR_STerm[] = { -- 47, -- 0x0021, 0x0021, -- 0x002e, 0x002e, -- 0x003f, 0x003f, -- 0x055c, 0x055c, -- 0x055e, 0x055e, -- 0x0589, 0x0589, -- 0x061f, 0x061f, -- 0x06d4, 0x06d4, -- 0x0700, 0x0702, -- 0x07f9, 0x07f9, -- 0x0964, 0x0965, -- 0x104a, 0x104b, -- 0x1362, 0x1362, -- 0x1367, 0x1368, -- 0x166e, 0x166e, -- 0x1735, 0x1736, -- 0x1803, 0x1803, -- 0x1809, 0x1809, -- 0x1944, 0x1945, -- 0x1aa8, 0x1aab, -- 0x1b5a, 0x1b5b, -- 0x1b5e, 0x1b5f, -- 0x1c3b, 0x1c3c, -- 0x1c7e, 0x1c7f, -- 0x203c, 0x203d, -- 0x2047, 0x2049, -- 0x2e2e, 0x2e2e, -- 0x3002, 0x3002, -- 0xa4ff, 0xa4ff, -- 0xa60e, 0xa60f, -- 0xa6f3, 0xa6f3, -- 0xa6f7, 0xa6f7, -- 0xa876, 0xa877, -- 0xa8ce, 0xa8cf, -- 0xa92f, 0xa92f, -- 0xa9c8, 0xa9c9, -- 0xaa5d, 0xaa5f, -- 0xabeb, 0xabeb, -- 0xfe52, 0xfe52, -- 0xfe56, 0xfe57, -- 0xff01, 0xff01, -- 0xff0e, 0xff0e, -- 0xff1f, 0xff1f, -- 0xff61, 0xff61, -- 0x10a56, 0x10a57, -- 0x11047, 0x11048, -- 0x110be, 0x110c1, --}; /* CR_STerm */ -- --/* 'Variation_Selector': Binary Property */ --static const OnigCodePoint CR_Variation_Selector[] = { -- 3, -- 0x180b, 0x180d, -- 0xfe00, 0xfe0f, -- 0xe0100, 0xe01ef, --}; /* CR_Variation_Selector */ -- --/* 'Pattern_White_Space': Binary Property */ --static const OnigCodePoint CR_Pattern_White_Space[] = { -- 5, -- 0x0009, 0x000d, -- 0x0020, 0x0020, -- 0x0085, 0x0085, -- 0x200e, 0x200f, -- 0x2028, 0x2029, --}; /* CR_Pattern_White_Space */ -- --/* 'Pattern_Syntax': Binary Property */ --static const OnigCodePoint CR_Pattern_Syntax[] = { -- 28, -- 0x0021, 0x002f, -- 0x003a, 0x0040, -- 0x005b, 0x005e, -- 0x0060, 0x0060, -- 0x007b, 0x007e, -- 0x00a1, 0x00a7, -- 0x00a9, 0x00a9, -- 0x00ab, 0x00ac, -- 0x00ae, 0x00ae, -- 0x00b0, 0x00b1, -- 0x00b6, 0x00b6, -- 0x00bb, 0x00bb, -- 0x00bf, 0x00bf, -- 0x00d7, 0x00d7, -- 0x00f7, 0x00f7, -- 0x2010, 0x2027, -- 0x2030, 0x203e, -- 0x2041, 0x2053, -- 0x2055, 0x205e, -- 0x2190, 0x245f, -- 0x2500, 0x2775, -- 0x2794, 0x2bff, -- 0x2e00, 0x2e7f, -- 0x3001, 0x3003, -- 0x3008, 0x3020, -- 0x3030, 0x3030, -- 0xfd3e, 0xfd3f, -- 0xfe45, 0xfe46, --}; /* CR_Pattern_Syntax */ -- --/* 'Unknown': Script */ --static const OnigCodePoint CR_Unknown[] = { -- 499, -- 0x0378, 0x0379, -- 0x037f, 0x0383, -- 0x038b, 0x038b, -- 0x038d, 0x038d, -- 0x03a2, 0x03a2, -- 0x0528, 0x0530, -- 0x0557, 0x0558, -- 0x0560, 0x0560, -- 0x0588, 0x0588, -- 0x058b, 0x0590, -- 0x05c8, 0x05cf, -- 0x05eb, 0x05ef, -- 0x05f5, 0x05ff, -- 0x0604, 0x0605, -- 0x061c, 0x061d, -- 0x070e, 0x070e, -- 0x074b, 0x074c, -- 0x07b2, 0x07bf, -- 0x07fb, 0x07ff, -- 0x082e, 0x082f, -- 0x083f, 0x083f, -- 0x085c, 0x085d, -- 0x085f, 0x08ff, -- 0x0978, 0x0978, -- 0x0980, 0x0980, -- 0x0984, 0x0984, -- 0x098d, 0x098e, -- 0x0991, 0x0992, -- 0x09a9, 0x09a9, -- 0x09b1, 0x09b1, -- 0x09b3, 0x09b5, -- 0x09ba, 0x09bb, -- 0x09c5, 0x09c6, -- 0x09c9, 0x09ca, -- 0x09cf, 0x09d6, -- 0x09d8, 0x09db, -- 0x09de, 0x09de, -- 0x09e4, 0x09e5, -- 0x09fc, 0x0a00, -- 0x0a04, 0x0a04, -- 0x0a0b, 0x0a0e, -- 0x0a11, 0x0a12, -- 0x0a29, 0x0a29, -- 0x0a31, 0x0a31, -- 0x0a34, 0x0a34, -- 0x0a37, 0x0a37, -- 0x0a3a, 0x0a3b, -- 0x0a3d, 0x0a3d, -- 0x0a43, 0x0a46, -- 0x0a49, 0x0a4a, -- 0x0a4e, 0x0a50, -- 0x0a52, 0x0a58, -- 0x0a5d, 0x0a5d, -- 0x0a5f, 0x0a65, -- 0x0a76, 0x0a80, -- 0x0a84, 0x0a84, -- 0x0a8e, 0x0a8e, -- 0x0a92, 0x0a92, -- 0x0aa9, 0x0aa9, -- 0x0ab1, 0x0ab1, -- 0x0ab4, 0x0ab4, -- 0x0aba, 0x0abb, -- 0x0ac6, 0x0ac6, -- 0x0aca, 0x0aca, -- 0x0ace, 0x0acf, -- 0x0ad1, 0x0adf, -- 0x0ae4, 0x0ae5, -- 0x0af0, 0x0af0, -- 0x0af2, 0x0b00, -- 0x0b04, 0x0b04, -- 0x0b0d, 0x0b0e, -- 0x0b11, 0x0b12, -- 0x0b29, 0x0b29, -- 0x0b31, 0x0b31, -- 0x0b34, 0x0b34, -- 0x0b3a, 0x0b3b, -- 0x0b45, 0x0b46, -- 0x0b49, 0x0b4a, -- 0x0b4e, 0x0b55, -- 0x0b58, 0x0b5b, -- 0x0b5e, 0x0b5e, -- 0x0b64, 0x0b65, -- 0x0b78, 0x0b81, -- 0x0b84, 0x0b84, -- 0x0b8b, 0x0b8d, -- 0x0b91, 0x0b91, -- 0x0b96, 0x0b98, -- 0x0b9b, 0x0b9b, -- 0x0b9d, 0x0b9d, -- 0x0ba0, 0x0ba2, -- 0x0ba5, 0x0ba7, -- 0x0bab, 0x0bad, -- 0x0bba, 0x0bbd, -- 0x0bc3, 0x0bc5, -- 0x0bc9, 0x0bc9, -- 0x0bce, 0x0bcf, -- 0x0bd1, 0x0bd6, -- 0x0bd8, 0x0be5, -- 0x0bfb, 0x0c00, -- 0x0c04, 0x0c04, -- 0x0c0d, 0x0c0d, -- 0x0c11, 0x0c11, -- 0x0c29, 0x0c29, -- 0x0c34, 0x0c34, -- 0x0c3a, 0x0c3c, -- 0x0c45, 0x0c45, -- 0x0c49, 0x0c49, -- 0x0c4e, 0x0c54, -- 0x0c57, 0x0c57, -- 0x0c5a, 0x0c5f, -- 0x0c64, 0x0c65, -- 0x0c70, 0x0c77, -- 0x0c80, 0x0c81, -- 0x0c84, 0x0c84, -- 0x0c8d, 0x0c8d, -- 0x0c91, 0x0c91, -- 0x0ca9, 0x0ca9, -- 0x0cb4, 0x0cb4, -- 0x0cba, 0x0cbb, -- 0x0cc5, 0x0cc5, -- 0x0cc9, 0x0cc9, -- 0x0cce, 0x0cd4, -- 0x0cd7, 0x0cdd, -- 0x0cdf, 0x0cdf, -- 0x0ce4, 0x0ce5, -- 0x0cf0, 0x0cf0, -- 0x0cf3, 0x0d01, -- 0x0d04, 0x0d04, -- 0x0d0d, 0x0d0d, -- 0x0d11, 0x0d11, -- 0x0d3b, 0x0d3c, -- 0x0d45, 0x0d45, -- 0x0d49, 0x0d49, -- 0x0d4f, 0x0d56, -- 0x0d58, 0x0d5f, -- 0x0d64, 0x0d65, -- 0x0d76, 0x0d78, -- 0x0d80, 0x0d81, -- 0x0d84, 0x0d84, -- 0x0d97, 0x0d99, -- 0x0db2, 0x0db2, -- 0x0dbc, 0x0dbc, -- 0x0dbe, 0x0dbf, -- 0x0dc7, 0x0dc9, -- 0x0dcb, 0x0dce, -- 0x0dd5, 0x0dd5, -- 0x0dd7, 0x0dd7, -- 0x0de0, 0x0df1, -- 0x0df5, 0x0e00, -- 0x0e3b, 0x0e3e, -- 0x0e5c, 0x0e80, -- 0x0e83, 0x0e83, -- 0x0e85, 0x0e86, -- 0x0e89, 0x0e89, -- 0x0e8b, 0x0e8c, -- 0x0e8e, 0x0e93, -- 0x0e98, 0x0e98, -- 0x0ea0, 0x0ea0, -- 0x0ea4, 0x0ea4, -- 0x0ea6, 0x0ea6, -- 0x0ea8, 0x0ea9, -- 0x0eac, 0x0eac, -- 0x0eba, 0x0eba, -- 0x0ebe, 0x0ebf, -- 0x0ec5, 0x0ec5, -- 0x0ec7, 0x0ec7, -- 0x0ece, 0x0ecf, -- 0x0eda, 0x0edb, -- 0x0ede, 0x0eff, -- 0x0f48, 0x0f48, -- 0x0f6d, 0x0f70, -- 0x0f98, 0x0f98, -- 0x0fbd, 0x0fbd, -- 0x0fcd, 0x0fcd, -- 0x0fdb, 0x0fff, -- 0x10c6, 0x10cf, -- 0x10fd, 0x10ff, -- 0x1249, 0x1249, -- 0x124e, 0x124f, -- 0x1257, 0x1257, -- 0x1259, 0x1259, -- 0x125e, 0x125f, -- 0x1289, 0x1289, -- 0x128e, 0x128f, -- 0x12b1, 0x12b1, -- 0x12b6, 0x12b7, -- 0x12bf, 0x12bf, -- 0x12c1, 0x12c1, -- 0x12c6, 0x12c7, -- 0x12d7, 0x12d7, -- 0x1311, 0x1311, -- 0x1316, 0x1317, -- 0x135b, 0x135c, -- 0x137d, 0x137f, -- 0x139a, 0x139f, -- 0x13f5, 0x13ff, -- 0x169d, 0x169f, -- 0x16f1, 0x16ff, -- 0x170d, 0x170d, -- 0x1715, 0x171f, -- 0x1737, 0x173f, -- 0x1754, 0x175f, -- 0x176d, 0x176d, -- 0x1771, 0x1771, -- 0x1774, 0x177f, -- 0x17de, 0x17df, -- 0x17ea, 0x17ef, -- 0x17fa, 0x17ff, -- 0x180f, 0x180f, -- 0x181a, 0x181f, -- 0x1878, 0x187f, -- 0x18ab, 0x18af, -- 0x18f6, 0x18ff, -- 0x191d, 0x191f, -- 0x192c, 0x192f, -- 0x193c, 0x193f, -- 0x1941, 0x1943, -- 0x196e, 0x196f, -- 0x1975, 0x197f, -- 0x19ac, 0x19af, -- 0x19ca, 0x19cf, -- 0x19db, 0x19dd, -- 0x1a1c, 0x1a1d, -- 0x1a5f, 0x1a5f, -- 0x1a7d, 0x1a7e, -- 0x1a8a, 0x1a8f, -- 0x1a9a, 0x1a9f, -- 0x1aae, 0x1aff, -- 0x1b4c, 0x1b4f, -- 0x1b7d, 0x1b7f, -- 0x1bab, 0x1bad, -- 0x1bba, 0x1bbf, -- 0x1bf4, 0x1bfb, -- 0x1c38, 0x1c3a, -- 0x1c4a, 0x1c4c, -- 0x1c80, 0x1ccf, -- 0x1cf3, 0x1cff, -- 0x1de7, 0x1dfb, -- 0x1f16, 0x1f17, -- 0x1f1e, 0x1f1f, -- 0x1f46, 0x1f47, -- 0x1f4e, 0x1f4f, -- 0x1f58, 0x1f58, -- 0x1f5a, 0x1f5a, -- 0x1f5c, 0x1f5c, -- 0x1f5e, 0x1f5e, -- 0x1f7e, 0x1f7f, -- 0x1fb5, 0x1fb5, -- 0x1fc5, 0x1fc5, -- 0x1fd4, 0x1fd5, -- 0x1fdc, 0x1fdc, -- 0x1ff0, 0x1ff1, -- 0x1ff5, 0x1ff5, -- 0x1fff, 0x1fff, -- 0x2065, 0x2069, -- 0x2072, 0x2073, -- 0x208f, 0x208f, -- 0x209d, 0x209f, -- 0x20ba, 0x20cf, -- 0x20f1, 0x20ff, -- 0x218a, 0x218f, -- 0x23f4, 0x23ff, -- 0x2427, 0x243f, -- 0x244b, 0x245f, -- 0x2700, 0x2700, -- 0x27cb, 0x27cb, -- 0x27cd, 0x27cd, -- 0x2b4d, 0x2b4f, -- 0x2b5a, 0x2bff, -- 0x2c2f, 0x2c2f, -- 0x2c5f, 0x2c5f, -- 0x2cf2, 0x2cf8, -- 0x2d26, 0x2d2f, -- 0x2d66, 0x2d6e, -- 0x2d71, 0x2d7e, -- 0x2d97, 0x2d9f, -- 0x2da7, 0x2da7, -- 0x2daf, 0x2daf, -- 0x2db7, 0x2db7, -- 0x2dbf, 0x2dbf, -- 0x2dc7, 0x2dc7, -- 0x2dcf, 0x2dcf, -- 0x2dd7, 0x2dd7, -- 0x2ddf, 0x2ddf, -- 0x2e32, 0x2e7f, -- 0x2e9a, 0x2e9a, -- 0x2ef4, 0x2eff, -- 0x2fd6, 0x2fef, -- 0x2ffc, 0x2fff, -- 0x3040, 0x3040, -- 0x3097, 0x3098, -- 0x3100, 0x3104, -- 0x312e, 0x3130, -- 0x318f, 0x318f, -- 0x31bb, 0x31bf, -- 0x31e4, 0x31ef, -- 0x321f, 0x321f, -- 0x32ff, 0x32ff, -- 0x4db6, 0x4dbf, -- 0x9fcc, 0x9fff, -- 0xa48d, 0xa48f, -- 0xa4c7, 0xa4cf, -- 0xa62c, 0xa63f, -- 0xa674, 0xa67b, -- 0xa698, 0xa69f, -- 0xa6f8, 0xa6ff, -- 0xa78f, 0xa78f, -- 0xa792, 0xa79f, -- 0xa7aa, 0xa7f9, -- 0xa82c, 0xa82f, -- 0xa83a, 0xa83f, -- 0xa878, 0xa87f, -- 0xa8c5, 0xa8cd, -- 0xa8da, 0xa8df, -- 0xa8fc, 0xa8ff, -- 0xa954, 0xa95e, -- 0xa97d, 0xa97f, -- 0xa9ce, 0xa9ce, -- 0xa9da, 0xa9dd, -- 0xa9e0, 0xa9ff, -- 0xaa37, 0xaa3f, -- 0xaa4e, 0xaa4f, -- 0xaa5a, 0xaa5b, -- 0xaa7c, 0xaa7f, -- 0xaac3, 0xaada, -- 0xaae0, 0xab00, -- 0xab07, 0xab08, -- 0xab0f, 0xab10, -- 0xab17, 0xab1f, -- 0xab27, 0xab27, -- 0xab2f, 0xabbf, -- 0xabee, 0xabef, -- 0xabfa, 0xabff, -- 0xd7a4, 0xd7af, -- 0xd7c7, 0xd7ca, -- 0xd7fc, 0xf8ff, -- 0xfa2e, 0xfa2f, -- 0xfa6e, 0xfa6f, -- 0xfada, 0xfaff, -- 0xfb07, 0xfb12, -- 0xfb18, 0xfb1c, -- 0xfb37, 0xfb37, -- 0xfb3d, 0xfb3d, -- 0xfb3f, 0xfb3f, -- 0xfb42, 0xfb42, -- 0xfb45, 0xfb45, -- 0xfbc2, 0xfbd2, -- 0xfd40, 0xfd4f, -- 0xfd90, 0xfd91, -- 0xfdc8, 0xfdef, -- 0xfdfe, 0xfdff, -- 0xfe1a, 0xfe1f, -- 0xfe27, 0xfe2f, -- 0xfe53, 0xfe53, -- 0xfe67, 0xfe67, -- 0xfe6c, 0xfe6f, -- 0xfe75, 0xfe75, -- 0xfefd, 0xfefe, -- 0xff00, 0xff00, -- 0xffbf, 0xffc1, -- 0xffc8, 0xffc9, -- 0xffd0, 0xffd1, -- 0xffd8, 0xffd9, -- 0xffdd, 0xffdf, -- 0xffe7, 0xffe7, -- 0xffef, 0xfff8, -- 0xfffe, 0xffff, -- 0x1000c, 0x1000c, -- 0x10027, 0x10027, -- 0x1003b, 0x1003b, -- 0x1003e, 0x1003e, -- 0x1004e, 0x1004f, -- 0x1005e, 0x1007f, -- 0x100fb, 0x100ff, -- 0x10103, 0x10106, -- 0x10134, 0x10136, -- 0x1018b, 0x1018f, -- 0x1019c, 0x101cf, -- 0x101fe, 0x1027f, -- 0x1029d, 0x1029f, -- 0x102d1, 0x102ff, -- 0x1031f, 0x1031f, -- 0x10324, 0x1032f, -- 0x1034b, 0x1037f, -- 0x1039e, 0x1039e, -- 0x103c4, 0x103c7, -- 0x103d6, 0x103ff, -- 0x1049e, 0x1049f, -- 0x104aa, 0x107ff, -- 0x10806, 0x10807, -- 0x10809, 0x10809, -- 0x10836, 0x10836, -- 0x10839, 0x1083b, -- 0x1083d, 0x1083e, -- 0x10856, 0x10856, -- 0x10860, 0x108ff, -- 0x1091c, 0x1091e, -- 0x1093a, 0x1093e, -- 0x10940, 0x109ff, -- 0x10a04, 0x10a04, -- 0x10a07, 0x10a0b, -- 0x10a14, 0x10a14, -- 0x10a18, 0x10a18, -- 0x10a34, 0x10a37, -- 0x10a3b, 0x10a3e, -- 0x10a48, 0x10a4f, -- 0x10a59, 0x10a5f, -- 0x10a80, 0x10aff, -- 0x10b36, 0x10b38, -- 0x10b56, 0x10b57, -- 0x10b73, 0x10b77, -- 0x10b80, 0x10bff, -- 0x10c49, 0x10e5f, -- 0x10e7f, 0x10fff, -- 0x1104e, 0x11051, -- 0x11070, 0x1107f, -- 0x110c2, 0x11fff, -- 0x1236f, 0x123ff, -- 0x12463, 0x1246f, -- 0x12474, 0x12fff, -- 0x1342f, 0x167ff, -- 0x16a39, 0x1afff, -- 0x1b002, 0x1cfff, -- 0x1d0f6, 0x1d0ff, -- 0x1d127, 0x1d128, -- 0x1d1de, 0x1d1ff, -- 0x1d246, 0x1d2ff, -- 0x1d357, 0x1d35f, -- 0x1d372, 0x1d3ff, -- 0x1d455, 0x1d455, -- 0x1d49d, 0x1d49d, -- 0x1d4a0, 0x1d4a1, -- 0x1d4a3, 0x1d4a4, -- 0x1d4a7, 0x1d4a8, -- 0x1d4ad, 0x1d4ad, -- 0x1d4ba, 0x1d4ba, -- 0x1d4bc, 0x1d4bc, -- 0x1d4c4, 0x1d4c4, -- 0x1d506, 0x1d506, -- 0x1d50b, 0x1d50c, -- 0x1d515, 0x1d515, -- 0x1d51d, 0x1d51d, -- 0x1d53a, 0x1d53a, -- 0x1d53f, 0x1d53f, -- 0x1d545, 0x1d545, -- 0x1d547, 0x1d549, -- 0x1d551, 0x1d551, -- 0x1d6a6, 0x1d6a7, -- 0x1d7cc, 0x1d7cd, -- 0x1d800, 0x1efff, -- 0x1f02c, 0x1f02f, -- 0x1f094, 0x1f09f, -- 0x1f0af, 0x1f0b0, -- 0x1f0bf, 0x1f0c0, -- 0x1f0d0, 0x1f0d0, -- 0x1f0e0, 0x1f0ff, -- 0x1f10b, 0x1f10f, -- 0x1f12f, 0x1f12f, -- 0x1f16a, 0x1f16f, -- 0x1f19b, 0x1f1e5, -- 0x1f203, 0x1f20f, -- 0x1f23b, 0x1f23f, -- 0x1f249, 0x1f24f, -- 0x1f252, 0x1f2ff, -- 0x1f321, 0x1f32f, -- 0x1f336, 0x1f336, -- 0x1f37d, 0x1f37f, -- 0x1f394, 0x1f39f, -- 0x1f3c5, 0x1f3c5, -- 0x1f3cb, 0x1f3df, -- 0x1f3f1, 0x1f3ff, -- 0x1f43f, 0x1f43f, -- 0x1f441, 0x1f441, -- 0x1f4f8, 0x1f4f8, -- 0x1f4fd, 0x1f4ff, -- 0x1f53e, 0x1f54f, -- 0x1f568, 0x1f5fa, -- 0x1f600, 0x1f600, -- 0x1f611, 0x1f611, -- 0x1f615, 0x1f615, -- 0x1f617, 0x1f617, -- 0x1f619, 0x1f619, -- 0x1f61b, 0x1f61b, -- 0x1f61f, 0x1f61f, -- 0x1f626, 0x1f627, -- 0x1f62c, 0x1f62c, -- 0x1f62e, 0x1f62f, -- 0x1f634, 0x1f634, -- 0x1f641, 0x1f644, -- 0x1f650, 0x1f67f, -- 0x1f6c6, 0x1f6ff, -- 0x1f774, 0x1ffff, -- 0x2a6d7, 0x2a6ff, -- 0x2b735, 0x2b73f, -- 0x2b81e, 0x2f7ff, -- 0x2fa1e, 0xe0000, -- 0xe0002, 0xe001f, -- 0xe0080, 0xe00ff, -- 0xe01f0, 0x10ffff, --}; /* CR_Unknown */ --#endif /* USE_UNICODE_PROPERTIES */ --#endif /* USE_UNICODE_PROPERTIES */ -- --/* 'Age_1_1': Derived Age 1.1 */ --static const OnigCodePoint CR_Age_1_1[] = { -- 288, -- 0x0000, 0x01f5, -- 0x01fa, 0x0217, -- 0x0250, 0x02a8, -- 0x02b0, 0x02de, -- 0x02e0, 0x02e9, -- 0x0300, 0x0345, -- 0x0360, 0x0361, -- 0x0374, 0x0375, -- 0x037a, 0x037a, -- 0x037e, 0x037e, -- 0x0384, 0x038a, -- 0x038c, 0x038c, -- 0x038e, 0x03a1, -- 0x03a3, 0x03ce, -- 0x03d0, 0x03d6, -- 0x03da, 0x03da, -- 0x03dc, 0x03dc, -- 0x03de, 0x03de, -- 0x03e0, 0x03e0, -- 0x03e2, 0x03f3, -- 0x0401, 0x040c, -- 0x040e, 0x044f, -- 0x0451, 0x045c, -- 0x045e, 0x0486, -- 0x0490, 0x04c4, -- 0x04c7, 0x04c8, -- 0x04cb, 0x04cc, -- 0x04d0, 0x04eb, -- 0x04ee, 0x04f5, -- 0x04f8, 0x04f9, -- 0x0531, 0x0556, -- 0x0559, 0x055f, -- 0x0561, 0x0587, -- 0x0589, 0x0589, -- 0x05b0, 0x05b9, -- 0x05bb, 0x05c3, -- 0x05d0, 0x05ea, -- 0x05f0, 0x05f4, -- 0x060c, 0x060c, -- 0x061b, 0x061b, -- 0x061f, 0x061f, -- 0x0621, 0x063a, -- 0x0640, 0x0652, -- 0x0660, 0x066d, -- 0x0670, 0x06b7, -- 0x06ba, 0x06be, -- 0x06c0, 0x06ce, -- 0x06d0, 0x06ed, -- 0x06f0, 0x06f9, -- 0x0901, 0x0903, -- 0x0905, 0x0939, -- 0x093c, 0x094d, -- 0x0950, 0x0954, -- 0x0958, 0x0970, -- 0x0981, 0x0983, -- 0x0985, 0x098c, -- 0x098f, 0x0990, -- 0x0993, 0x09a8, -- 0x09aa, 0x09b0, -- 0x09b2, 0x09b2, -- 0x09b6, 0x09b9, -- 0x09bc, 0x09bc, -- 0x09be, 0x09c4, -- 0x09c7, 0x09c8, -- 0x09cb, 0x09cd, -- 0x09d7, 0x09d7, -- 0x09dc, 0x09dd, -- 0x09df, 0x09e3, -- 0x09e6, 0x09fa, -- 0x0a02, 0x0a02, -- 0x0a05, 0x0a0a, -- 0x0a0f, 0x0a10, -- 0x0a13, 0x0a28, -- 0x0a2a, 0x0a30, -- 0x0a32, 0x0a33, -- 0x0a35, 0x0a36, -- 0x0a38, 0x0a39, -- 0x0a3c, 0x0a3c, -- 0x0a3e, 0x0a42, -- 0x0a47, 0x0a48, -- 0x0a4b, 0x0a4d, -- 0x0a59, 0x0a5c, -- 0x0a5e, 0x0a5e, -- 0x0a66, 0x0a74, -- 0x0a81, 0x0a83, -- 0x0a85, 0x0a8b, -- 0x0a8d, 0x0a8d, -- 0x0a8f, 0x0a91, -- 0x0a93, 0x0aa8, -- 0x0aaa, 0x0ab0, -- 0x0ab2, 0x0ab3, -- 0x0ab5, 0x0ab9, -- 0x0abc, 0x0ac5, -- 0x0ac7, 0x0ac9, -- 0x0acb, 0x0acd, -- 0x0ad0, 0x0ad0, -- 0x0ae0, 0x0ae0, -- 0x0ae6, 0x0aef, -- 0x0b01, 0x0b03, -- 0x0b05, 0x0b0c, -- 0x0b0f, 0x0b10, -- 0x0b13, 0x0b28, -- 0x0b2a, 0x0b30, -- 0x0b32, 0x0b33, -- 0x0b36, 0x0b39, -- 0x0b3c, 0x0b43, -- 0x0b47, 0x0b48, -- 0x0b4b, 0x0b4d, -- 0x0b56, 0x0b57, -- 0x0b5c, 0x0b5d, -- 0x0b5f, 0x0b61, -- 0x0b66, 0x0b70, -- 0x0b82, 0x0b83, -- 0x0b85, 0x0b8a, -- 0x0b8e, 0x0b90, -- 0x0b92, 0x0b95, -- 0x0b99, 0x0b9a, -- 0x0b9c, 0x0b9c, -- 0x0b9e, 0x0b9f, -- 0x0ba3, 0x0ba4, -- 0x0ba8, 0x0baa, -- 0x0bae, 0x0bb5, -- 0x0bb7, 0x0bb9, -- 0x0bbe, 0x0bc2, -- 0x0bc6, 0x0bc8, -- 0x0bca, 0x0bcd, -- 0x0bd7, 0x0bd7, -- 0x0be7, 0x0bf2, -- 0x0c01, 0x0c03, -- 0x0c05, 0x0c0c, -- 0x0c0e, 0x0c10, -- 0x0c12, 0x0c28, -- 0x0c2a, 0x0c33, -- 0x0c35, 0x0c39, -- 0x0c3e, 0x0c44, -- 0x0c46, 0x0c48, -- 0x0c4a, 0x0c4d, -- 0x0c55, 0x0c56, -- 0x0c60, 0x0c61, -- 0x0c66, 0x0c6f, -- 0x0c82, 0x0c83, -- 0x0c85, 0x0c8c, -- 0x0c8e, 0x0c90, -- 0x0c92, 0x0ca8, -- 0x0caa, 0x0cb3, -- 0x0cb5, 0x0cb9, -- 0x0cbe, 0x0cc4, -- 0x0cc6, 0x0cc8, -- 0x0cca, 0x0ccd, -- 0x0cd5, 0x0cd6, -- 0x0cde, 0x0cde, -- 0x0ce0, 0x0ce1, -- 0x0ce6, 0x0cef, -- 0x0d02, 0x0d03, -- 0x0d05, 0x0d0c, -- 0x0d0e, 0x0d10, -- 0x0d12, 0x0d28, -- 0x0d2a, 0x0d39, -- 0x0d3e, 0x0d43, -- 0x0d46, 0x0d48, -- 0x0d4a, 0x0d4d, -- 0x0d57, 0x0d57, -- 0x0d60, 0x0d61, -- 0x0d66, 0x0d6f, -- 0x0e01, 0x0e3a, -- 0x0e3f, 0x0e5b, -- 0x0e81, 0x0e82, -- 0x0e84, 0x0e84, -- 0x0e87, 0x0e88, -- 0x0e8a, 0x0e8a, -- 0x0e8d, 0x0e8d, -- 0x0e94, 0x0e97, -- 0x0e99, 0x0e9f, -- 0x0ea1, 0x0ea3, -- 0x0ea5, 0x0ea5, -- 0x0ea7, 0x0ea7, -- 0x0eaa, 0x0eab, -- 0x0ead, 0x0eb9, -- 0x0ebb, 0x0ebd, -- 0x0ec0, 0x0ec4, -- 0x0ec6, 0x0ec6, -- 0x0ec8, 0x0ecd, -- 0x0ed0, 0x0ed9, -- 0x0edc, 0x0edd, -- 0x10a0, 0x10c5, -- 0x10d0, 0x10f6, -- 0x10fb, 0x10fb, -- 0x1100, 0x1159, -- 0x115f, 0x11a2, -- 0x11a8, 0x11f9, -- 0x1e00, 0x1e9a, -- 0x1ea0, 0x1ef9, -- 0x1f00, 0x1f15, -- 0x1f18, 0x1f1d, -- 0x1f20, 0x1f45, -- 0x1f48, 0x1f4d, -- 0x1f50, 0x1f57, -- 0x1f59, 0x1f59, -- 0x1f5b, 0x1f5b, -- 0x1f5d, 0x1f5d, -- 0x1f5f, 0x1f7d, -- 0x1f80, 0x1fb4, -- 0x1fb6, 0x1fc4, -- 0x1fc6, 0x1fd3, -- 0x1fd6, 0x1fdb, -- 0x1fdd, 0x1fef, -- 0x1ff2, 0x1ff4, -- 0x1ff6, 0x1ffe, -- 0x2000, 0x202e, -- 0x2030, 0x2046, -- 0x206a, 0x2070, -- 0x2074, 0x208e, -- 0x20a0, 0x20aa, -- 0x20d0, 0x20e1, -- 0x2100, 0x2138, -- 0x2153, 0x2182, -- 0x2190, 0x21ea, -- 0x2200, 0x22f1, -- 0x2300, 0x2300, -- 0x2302, 0x237a, -- 0x2400, 0x2424, -- 0x2440, 0x244a, -- 0x2460, 0x24ea, -- 0x2500, 0x2595, -- 0x25a0, 0x25ef, -- 0x2600, 0x2613, -- 0x261a, 0x266f, -- 0x2701, 0x2704, -- 0x2706, 0x2709, -- 0x270c, 0x2727, -- 0x2729, 0x274b, -- 0x274d, 0x274d, -- 0x274f, 0x2752, -- 0x2756, 0x2756, -- 0x2758, 0x275e, -- 0x2761, 0x2767, -- 0x2776, 0x2794, -- 0x2798, 0x27af, -- 0x27b1, 0x27be, -- 0x3000, 0x3037, -- 0x303f, 0x303f, -- 0x3041, 0x3094, -- 0x3099, 0x309e, -- 0x30a1, 0x30fe, -- 0x3105, 0x312c, -- 0x3131, 0x318e, -- 0x3190, 0x319f, -- 0x3200, 0x321c, -- 0x3220, 0x3243, -- 0x3260, 0x327b, -- 0x327f, 0x32b0, -- 0x32c0, 0x32cb, -- 0x32d0, 0x32fe, -- 0x3300, 0x3376, -- 0x337b, 0x33dd, -- 0x33e0, 0x33fe, -- 0x4e00, 0x9fa5, -- 0xe000, 0xfa2d, -- 0xfb00, 0xfb06, -- 0xfb13, 0xfb17, -- 0xfb1e, 0xfb36, -- 0xfb38, 0xfb3c, -- 0xfb3e, 0xfb3e, -- 0xfb40, 0xfb41, -- 0xfb43, 0xfb44, -- 0xfb46, 0xfbb1, -- 0xfbd3, 0xfd3f, -- 0xfd50, 0xfd8f, -- 0xfd92, 0xfdc7, -- 0xfdf0, 0xfdfb, -- 0xfe20, 0xfe23, -- 0xfe30, 0xfe44, -- 0xfe49, 0xfe52, -- 0xfe54, 0xfe66, -- 0xfe68, 0xfe6b, -- 0xfe70, 0xfe72, -- 0xfe74, 0xfe74, -- 0xfe76, 0xfefc, -- 0xfeff, 0xfeff, -- 0xff01, 0xff5e, -- 0xff61, 0xffbe, -- 0xffc2, 0xffc7, -- 0xffca, 0xffcf, -- 0xffd2, 0xffd7, -- 0xffda, 0xffdc, -- 0xffe0, 0xffe6, -- 0xffe8, 0xffee, -- 0xfffd, 0xffff, --}; /* CR_Age_1_1 */ -- --/* 'Age_2_0': Derived Age 2.0 */ --static const OnigCodePoint CR_Age_2_0[] = { -- 312, -- 0x0000, 0x01f5, -- 0x01fa, 0x0217, -- 0x0250, 0x02a8, -- 0x02b0, 0x02de, -- 0x02e0, 0x02e9, -- 0x0300, 0x0345, -- 0x0360, 0x0361, -- 0x0374, 0x0375, -- 0x037a, 0x037a, -- 0x037e, 0x037e, -- 0x0384, 0x038a, -- 0x038c, 0x038c, -- 0x038e, 0x03a1, -- 0x03a3, 0x03ce, -- 0x03d0, 0x03d6, -- 0x03da, 0x03da, -- 0x03dc, 0x03dc, -- 0x03de, 0x03de, -- 0x03e0, 0x03e0, -- 0x03e2, 0x03f3, -- 0x0401, 0x040c, -- 0x040e, 0x044f, -- 0x0451, 0x045c, -- 0x045e, 0x0486, -- 0x0490, 0x04c4, -- 0x04c7, 0x04c8, -- 0x04cb, 0x04cc, -- 0x04d0, 0x04eb, -- 0x04ee, 0x04f5, -- 0x04f8, 0x04f9, -- 0x0531, 0x0556, -- 0x0559, 0x055f, -- 0x0561, 0x0587, -- 0x0589, 0x0589, -- 0x0591, 0x05a1, -- 0x05a3, 0x05b9, -- 0x05bb, 0x05c4, -- 0x05d0, 0x05ea, -- 0x05f0, 0x05f4, -- 0x060c, 0x060c, -- 0x061b, 0x061b, -- 0x061f, 0x061f, -- 0x0621, 0x063a, -- 0x0640, 0x0652, -- 0x0660, 0x066d, -- 0x0670, 0x06b7, -- 0x06ba, 0x06be, -- 0x06c0, 0x06ce, -- 0x06d0, 0x06ed, -- 0x06f0, 0x06f9, -- 0x0901, 0x0903, -- 0x0905, 0x0939, -- 0x093c, 0x094d, -- 0x0950, 0x0954, -- 0x0958, 0x0970, -- 0x0981, 0x0983, -- 0x0985, 0x098c, -- 0x098f, 0x0990, -- 0x0993, 0x09a8, -- 0x09aa, 0x09b0, -- 0x09b2, 0x09b2, -- 0x09b6, 0x09b9, -- 0x09bc, 0x09bc, -- 0x09be, 0x09c4, -- 0x09c7, 0x09c8, -- 0x09cb, 0x09cd, -- 0x09d7, 0x09d7, -- 0x09dc, 0x09dd, -- 0x09df, 0x09e3, -- 0x09e6, 0x09fa, -- 0x0a02, 0x0a02, -- 0x0a05, 0x0a0a, -- 0x0a0f, 0x0a10, -- 0x0a13, 0x0a28, -- 0x0a2a, 0x0a30, -- 0x0a32, 0x0a33, -- 0x0a35, 0x0a36, -- 0x0a38, 0x0a39, -- 0x0a3c, 0x0a3c, -- 0x0a3e, 0x0a42, -- 0x0a47, 0x0a48, -- 0x0a4b, 0x0a4d, -- 0x0a59, 0x0a5c, -- 0x0a5e, 0x0a5e, -- 0x0a66, 0x0a74, -- 0x0a81, 0x0a83, -- 0x0a85, 0x0a8b, -- 0x0a8d, 0x0a8d, -- 0x0a8f, 0x0a91, -- 0x0a93, 0x0aa8, -- 0x0aaa, 0x0ab0, -- 0x0ab2, 0x0ab3, -- 0x0ab5, 0x0ab9, -- 0x0abc, 0x0ac5, -- 0x0ac7, 0x0ac9, -- 0x0acb, 0x0acd, -- 0x0ad0, 0x0ad0, -- 0x0ae0, 0x0ae0, -- 0x0ae6, 0x0aef, -- 0x0b01, 0x0b03, -- 0x0b05, 0x0b0c, -- 0x0b0f, 0x0b10, -- 0x0b13, 0x0b28, -- 0x0b2a, 0x0b30, -- 0x0b32, 0x0b33, -- 0x0b36, 0x0b39, -- 0x0b3c, 0x0b43, -- 0x0b47, 0x0b48, -- 0x0b4b, 0x0b4d, -- 0x0b56, 0x0b57, -- 0x0b5c, 0x0b5d, -- 0x0b5f, 0x0b61, -- 0x0b66, 0x0b70, -- 0x0b82, 0x0b83, -- 0x0b85, 0x0b8a, -- 0x0b8e, 0x0b90, -- 0x0b92, 0x0b95, -- 0x0b99, 0x0b9a, -- 0x0b9c, 0x0b9c, -- 0x0b9e, 0x0b9f, -- 0x0ba3, 0x0ba4, -- 0x0ba8, 0x0baa, -- 0x0bae, 0x0bb5, -- 0x0bb7, 0x0bb9, -- 0x0bbe, 0x0bc2, -- 0x0bc6, 0x0bc8, -- 0x0bca, 0x0bcd, -- 0x0bd7, 0x0bd7, -- 0x0be7, 0x0bf2, -- 0x0c01, 0x0c03, -- 0x0c05, 0x0c0c, -- 0x0c0e, 0x0c10, -- 0x0c12, 0x0c28, -- 0x0c2a, 0x0c33, -- 0x0c35, 0x0c39, -- 0x0c3e, 0x0c44, -- 0x0c46, 0x0c48, -- 0x0c4a, 0x0c4d, -- 0x0c55, 0x0c56, -- 0x0c60, 0x0c61, -- 0x0c66, 0x0c6f, -- 0x0c82, 0x0c83, -- 0x0c85, 0x0c8c, -- 0x0c8e, 0x0c90, -- 0x0c92, 0x0ca8, -- 0x0caa, 0x0cb3, -- 0x0cb5, 0x0cb9, -- 0x0cbe, 0x0cc4, -- 0x0cc6, 0x0cc8, -- 0x0cca, 0x0ccd, -- 0x0cd5, 0x0cd6, -- 0x0cde, 0x0cde, -- 0x0ce0, 0x0ce1, -- 0x0ce6, 0x0cef, -- 0x0d02, 0x0d03, -- 0x0d05, 0x0d0c, -- 0x0d0e, 0x0d10, -- 0x0d12, 0x0d28, -- 0x0d2a, 0x0d39, -- 0x0d3e, 0x0d43, -- 0x0d46, 0x0d48, -- 0x0d4a, 0x0d4d, -- 0x0d57, 0x0d57, -- 0x0d60, 0x0d61, -- 0x0d66, 0x0d6f, -- 0x0e01, 0x0e3a, -- 0x0e3f, 0x0e5b, -- 0x0e81, 0x0e82, -- 0x0e84, 0x0e84, -- 0x0e87, 0x0e88, -- 0x0e8a, 0x0e8a, -- 0x0e8d, 0x0e8d, -- 0x0e94, 0x0e97, -- 0x0e99, 0x0e9f, -- 0x0ea1, 0x0ea3, -- 0x0ea5, 0x0ea5, -- 0x0ea7, 0x0ea7, -- 0x0eaa, 0x0eab, -- 0x0ead, 0x0eb9, -- 0x0ebb, 0x0ebd, -- 0x0ec0, 0x0ec4, -- 0x0ec6, 0x0ec6, -- 0x0ec8, 0x0ecd, -- 0x0ed0, 0x0ed9, -- 0x0edc, 0x0edd, -- 0x0f00, 0x0f47, -- 0x0f49, 0x0f69, -- 0x0f71, 0x0f8b, -- 0x0f90, 0x0f95, -- 0x0f97, 0x0f97, -- 0x0f99, 0x0fad, -- 0x0fb1, 0x0fb7, -- 0x0fb9, 0x0fb9, -- 0x10a0, 0x10c5, -- 0x10d0, 0x10f6, -- 0x10fb, 0x10fb, -- 0x1100, 0x1159, -- 0x115f, 0x11a2, -- 0x11a8, 0x11f9, -- 0x1e00, 0x1e9b, -- 0x1ea0, 0x1ef9, -- 0x1f00, 0x1f15, -- 0x1f18, 0x1f1d, -- 0x1f20, 0x1f45, -- 0x1f48, 0x1f4d, -- 0x1f50, 0x1f57, -- 0x1f59, 0x1f59, -- 0x1f5b, 0x1f5b, -- 0x1f5d, 0x1f5d, -- 0x1f5f, 0x1f7d, -- 0x1f80, 0x1fb4, -- 0x1fb6, 0x1fc4, -- 0x1fc6, 0x1fd3, -- 0x1fd6, 0x1fdb, -- 0x1fdd, 0x1fef, -- 0x1ff2, 0x1ff4, -- 0x1ff6, 0x1ffe, -- 0x2000, 0x202e, -- 0x2030, 0x2046, -- 0x206a, 0x2070, -- 0x2074, 0x208e, -- 0x20a0, 0x20ab, -- 0x20d0, 0x20e1, -- 0x2100, 0x2138, -- 0x2153, 0x2182, -- 0x2190, 0x21ea, -- 0x2200, 0x22f1, -- 0x2300, 0x2300, -- 0x2302, 0x237a, -- 0x2400, 0x2424, -- 0x2440, 0x244a, -- 0x2460, 0x24ea, -- 0x2500, 0x2595, -- 0x25a0, 0x25ef, -- 0x2600, 0x2613, -- 0x261a, 0x266f, -- 0x2701, 0x2704, -- 0x2706, 0x2709, -- 0x270c, 0x2727, -- 0x2729, 0x274b, -- 0x274d, 0x274d, -- 0x274f, 0x2752, -- 0x2756, 0x2756, -- 0x2758, 0x275e, -- 0x2761, 0x2767, -- 0x2776, 0x2794, -- 0x2798, 0x27af, -- 0x27b1, 0x27be, -- 0x3000, 0x3037, -- 0x303f, 0x303f, -- 0x3041, 0x3094, -- 0x3099, 0x309e, -- 0x30a1, 0x30fe, -- 0x3105, 0x312c, -- 0x3131, 0x318e, -- 0x3190, 0x319f, -- 0x3200, 0x321c, -- 0x3220, 0x3243, -- 0x3260, 0x327b, -- 0x327f, 0x32b0, -- 0x32c0, 0x32cb, -- 0x32d0, 0x32fe, -- 0x3300, 0x3376, -- 0x337b, 0x33dd, -- 0x33e0, 0x33fe, -- 0x4e00, 0x9fa5, -- 0xac00, 0xd7a3, -- 0xd800, 0xfa2d, -- 0xfb00, 0xfb06, -- 0xfb13, 0xfb17, -- 0xfb1e, 0xfb36, -- 0xfb38, 0xfb3c, -- 0xfb3e, 0xfb3e, -- 0xfb40, 0xfb41, -- 0xfb43, 0xfb44, -- 0xfb46, 0xfbb1, -- 0xfbd3, 0xfd3f, -- 0xfd50, 0xfd8f, -- 0xfd92, 0xfdc7, -- 0xfdf0, 0xfdfb, -- 0xfe20, 0xfe23, -- 0xfe30, 0xfe44, -- 0xfe49, 0xfe52, -- 0xfe54, 0xfe66, -- 0xfe68, 0xfe6b, -- 0xfe70, 0xfe72, -- 0xfe74, 0xfe74, -- 0xfe76, 0xfefc, -- 0xfeff, 0xfeff, -- 0xff01, 0xff5e, -- 0xff61, 0xffbe, -- 0xffc2, 0xffc7, -- 0xffca, 0xffcf, -- 0xffd2, 0xffd7, -- 0xffda, 0xffdc, -- 0xffe0, 0xffe6, -- 0xffe8, 0xffee, -- 0xfffd, 0xffff, -- 0x1fffe, 0x1ffff, -- 0x2fffe, 0x2ffff, -- 0x3fffe, 0x3ffff, -- 0x4fffe, 0x4ffff, -- 0x5fffe, 0x5ffff, -- 0x6fffe, 0x6ffff, -- 0x7fffe, 0x7ffff, -- 0x8fffe, 0x8ffff, -- 0x9fffe, 0x9ffff, -- 0xafffe, 0xaffff, -- 0xbfffe, 0xbffff, -- 0xcfffe, 0xcffff, -- 0xdfffe, 0xdffff, -- 0xefffe, 0x10ffff, --}; /* CR_Age_2_0 */ -- --/* 'Age_2_1': Derived Age 2.1 */ --static const OnigCodePoint CR_Age_2_1[] = { -- 312, -- 0x0000, 0x01f5, -- 0x01fa, 0x0217, -- 0x0250, 0x02a8, -- 0x02b0, 0x02de, -- 0x02e0, 0x02e9, -- 0x0300, 0x0345, -- 0x0360, 0x0361, -- 0x0374, 0x0375, -- 0x037a, 0x037a, -- 0x037e, 0x037e, -- 0x0384, 0x038a, -- 0x038c, 0x038c, -- 0x038e, 0x03a1, -- 0x03a3, 0x03ce, -- 0x03d0, 0x03d6, -- 0x03da, 0x03da, -- 0x03dc, 0x03dc, -- 0x03de, 0x03de, -- 0x03e0, 0x03e0, -- 0x03e2, 0x03f3, -- 0x0401, 0x040c, -- 0x040e, 0x044f, -- 0x0451, 0x045c, -- 0x045e, 0x0486, -- 0x0490, 0x04c4, -- 0x04c7, 0x04c8, -- 0x04cb, 0x04cc, -- 0x04d0, 0x04eb, -- 0x04ee, 0x04f5, -- 0x04f8, 0x04f9, -- 0x0531, 0x0556, -- 0x0559, 0x055f, -- 0x0561, 0x0587, -- 0x0589, 0x0589, -- 0x0591, 0x05a1, -- 0x05a3, 0x05b9, -- 0x05bb, 0x05c4, -- 0x05d0, 0x05ea, -- 0x05f0, 0x05f4, -- 0x060c, 0x060c, -- 0x061b, 0x061b, -- 0x061f, 0x061f, -- 0x0621, 0x063a, -- 0x0640, 0x0652, -- 0x0660, 0x066d, -- 0x0670, 0x06b7, -- 0x06ba, 0x06be, -- 0x06c0, 0x06ce, -- 0x06d0, 0x06ed, -- 0x06f0, 0x06f9, -- 0x0901, 0x0903, -- 0x0905, 0x0939, -- 0x093c, 0x094d, -- 0x0950, 0x0954, -- 0x0958, 0x0970, -- 0x0981, 0x0983, -- 0x0985, 0x098c, -- 0x098f, 0x0990, -- 0x0993, 0x09a8, -- 0x09aa, 0x09b0, -- 0x09b2, 0x09b2, -- 0x09b6, 0x09b9, -- 0x09bc, 0x09bc, -- 0x09be, 0x09c4, -- 0x09c7, 0x09c8, -- 0x09cb, 0x09cd, -- 0x09d7, 0x09d7, -- 0x09dc, 0x09dd, -- 0x09df, 0x09e3, -- 0x09e6, 0x09fa, -- 0x0a02, 0x0a02, -- 0x0a05, 0x0a0a, -- 0x0a0f, 0x0a10, -- 0x0a13, 0x0a28, -- 0x0a2a, 0x0a30, -- 0x0a32, 0x0a33, -- 0x0a35, 0x0a36, -- 0x0a38, 0x0a39, -- 0x0a3c, 0x0a3c, -- 0x0a3e, 0x0a42, -- 0x0a47, 0x0a48, -- 0x0a4b, 0x0a4d, -- 0x0a59, 0x0a5c, -- 0x0a5e, 0x0a5e, -- 0x0a66, 0x0a74, -- 0x0a81, 0x0a83, -- 0x0a85, 0x0a8b, -- 0x0a8d, 0x0a8d, -- 0x0a8f, 0x0a91, -- 0x0a93, 0x0aa8, -- 0x0aaa, 0x0ab0, -- 0x0ab2, 0x0ab3, -- 0x0ab5, 0x0ab9, -- 0x0abc, 0x0ac5, -- 0x0ac7, 0x0ac9, -- 0x0acb, 0x0acd, -- 0x0ad0, 0x0ad0, -- 0x0ae0, 0x0ae0, -- 0x0ae6, 0x0aef, -- 0x0b01, 0x0b03, -- 0x0b05, 0x0b0c, -- 0x0b0f, 0x0b10, -- 0x0b13, 0x0b28, -- 0x0b2a, 0x0b30, -- 0x0b32, 0x0b33, -- 0x0b36, 0x0b39, -- 0x0b3c, 0x0b43, -- 0x0b47, 0x0b48, -- 0x0b4b, 0x0b4d, -- 0x0b56, 0x0b57, -- 0x0b5c, 0x0b5d, -- 0x0b5f, 0x0b61, -- 0x0b66, 0x0b70, -- 0x0b82, 0x0b83, -- 0x0b85, 0x0b8a, -- 0x0b8e, 0x0b90, -- 0x0b92, 0x0b95, -- 0x0b99, 0x0b9a, -- 0x0b9c, 0x0b9c, -- 0x0b9e, 0x0b9f, -- 0x0ba3, 0x0ba4, -- 0x0ba8, 0x0baa, -- 0x0bae, 0x0bb5, -- 0x0bb7, 0x0bb9, -- 0x0bbe, 0x0bc2, -- 0x0bc6, 0x0bc8, -- 0x0bca, 0x0bcd, -- 0x0bd7, 0x0bd7, -- 0x0be7, 0x0bf2, -- 0x0c01, 0x0c03, -- 0x0c05, 0x0c0c, -- 0x0c0e, 0x0c10, -- 0x0c12, 0x0c28, -- 0x0c2a, 0x0c33, -- 0x0c35, 0x0c39, -- 0x0c3e, 0x0c44, -- 0x0c46, 0x0c48, -- 0x0c4a, 0x0c4d, -- 0x0c55, 0x0c56, -- 0x0c60, 0x0c61, -- 0x0c66, 0x0c6f, -- 0x0c82, 0x0c83, -- 0x0c85, 0x0c8c, -- 0x0c8e, 0x0c90, -- 0x0c92, 0x0ca8, -- 0x0caa, 0x0cb3, -- 0x0cb5, 0x0cb9, -- 0x0cbe, 0x0cc4, -- 0x0cc6, 0x0cc8, -- 0x0cca, 0x0ccd, -- 0x0cd5, 0x0cd6, -- 0x0cde, 0x0cde, -- 0x0ce0, 0x0ce1, -- 0x0ce6, 0x0cef, -- 0x0d02, 0x0d03, -- 0x0d05, 0x0d0c, -- 0x0d0e, 0x0d10, -- 0x0d12, 0x0d28, -- 0x0d2a, 0x0d39, -- 0x0d3e, 0x0d43, -- 0x0d46, 0x0d48, -- 0x0d4a, 0x0d4d, -- 0x0d57, 0x0d57, -- 0x0d60, 0x0d61, -- 0x0d66, 0x0d6f, -- 0x0e01, 0x0e3a, -- 0x0e3f, 0x0e5b, -- 0x0e81, 0x0e82, -- 0x0e84, 0x0e84, -- 0x0e87, 0x0e88, -- 0x0e8a, 0x0e8a, -- 0x0e8d, 0x0e8d, -- 0x0e94, 0x0e97, -- 0x0e99, 0x0e9f, -- 0x0ea1, 0x0ea3, -- 0x0ea5, 0x0ea5, -- 0x0ea7, 0x0ea7, -- 0x0eaa, 0x0eab, -- 0x0ead, 0x0eb9, -- 0x0ebb, 0x0ebd, -- 0x0ec0, 0x0ec4, -- 0x0ec6, 0x0ec6, -- 0x0ec8, 0x0ecd, -- 0x0ed0, 0x0ed9, -- 0x0edc, 0x0edd, -- 0x0f00, 0x0f47, -- 0x0f49, 0x0f69, -- 0x0f71, 0x0f8b, -- 0x0f90, 0x0f95, -- 0x0f97, 0x0f97, -- 0x0f99, 0x0fad, -- 0x0fb1, 0x0fb7, -- 0x0fb9, 0x0fb9, -- 0x10a0, 0x10c5, -- 0x10d0, 0x10f6, -- 0x10fb, 0x10fb, -- 0x1100, 0x1159, -- 0x115f, 0x11a2, -- 0x11a8, 0x11f9, -- 0x1e00, 0x1e9b, -- 0x1ea0, 0x1ef9, -- 0x1f00, 0x1f15, -- 0x1f18, 0x1f1d, -- 0x1f20, 0x1f45, -- 0x1f48, 0x1f4d, -- 0x1f50, 0x1f57, -- 0x1f59, 0x1f59, -- 0x1f5b, 0x1f5b, -- 0x1f5d, 0x1f5d, -- 0x1f5f, 0x1f7d, -- 0x1f80, 0x1fb4, -- 0x1fb6, 0x1fc4, -- 0x1fc6, 0x1fd3, -- 0x1fd6, 0x1fdb, -- 0x1fdd, 0x1fef, -- 0x1ff2, 0x1ff4, -- 0x1ff6, 0x1ffe, -- 0x2000, 0x202e, -- 0x2030, 0x2046, -- 0x206a, 0x2070, -- 0x2074, 0x208e, -- 0x20a0, 0x20ac, -- 0x20d0, 0x20e1, -- 0x2100, 0x2138, -- 0x2153, 0x2182, -- 0x2190, 0x21ea, -- 0x2200, 0x22f1, -- 0x2300, 0x2300, -- 0x2302, 0x237a, -- 0x2400, 0x2424, -- 0x2440, 0x244a, -- 0x2460, 0x24ea, -- 0x2500, 0x2595, -- 0x25a0, 0x25ef, -- 0x2600, 0x2613, -- 0x261a, 0x266f, -- 0x2701, 0x2704, -- 0x2706, 0x2709, -- 0x270c, 0x2727, -- 0x2729, 0x274b, -- 0x274d, 0x274d, -- 0x274f, 0x2752, -- 0x2756, 0x2756, -- 0x2758, 0x275e, -- 0x2761, 0x2767, -- 0x2776, 0x2794, -- 0x2798, 0x27af, -- 0x27b1, 0x27be, -- 0x3000, 0x3037, -- 0x303f, 0x303f, -- 0x3041, 0x3094, -- 0x3099, 0x309e, -- 0x30a1, 0x30fe, -- 0x3105, 0x312c, -- 0x3131, 0x318e, -- 0x3190, 0x319f, -- 0x3200, 0x321c, -- 0x3220, 0x3243, -- 0x3260, 0x327b, -- 0x327f, 0x32b0, -- 0x32c0, 0x32cb, -- 0x32d0, 0x32fe, -- 0x3300, 0x3376, -- 0x337b, 0x33dd, -- 0x33e0, 0x33fe, -- 0x4e00, 0x9fa5, -- 0xac00, 0xd7a3, -- 0xd800, 0xfa2d, -- 0xfb00, 0xfb06, -- 0xfb13, 0xfb17, -- 0xfb1e, 0xfb36, -- 0xfb38, 0xfb3c, -- 0xfb3e, 0xfb3e, -- 0xfb40, 0xfb41, -- 0xfb43, 0xfb44, -- 0xfb46, 0xfbb1, -- 0xfbd3, 0xfd3f, -- 0xfd50, 0xfd8f, -- 0xfd92, 0xfdc7, -- 0xfdf0, 0xfdfb, -- 0xfe20, 0xfe23, -- 0xfe30, 0xfe44, -- 0xfe49, 0xfe52, -- 0xfe54, 0xfe66, -- 0xfe68, 0xfe6b, -- 0xfe70, 0xfe72, -- 0xfe74, 0xfe74, -- 0xfe76, 0xfefc, -- 0xfeff, 0xfeff, -- 0xff01, 0xff5e, -- 0xff61, 0xffbe, -- 0xffc2, 0xffc7, -- 0xffca, 0xffcf, -- 0xffd2, 0xffd7, -- 0xffda, 0xffdc, -- 0xffe0, 0xffe6, -- 0xffe8, 0xffee, -- 0xfffc, 0xffff, -- 0x1fffe, 0x1ffff, -- 0x2fffe, 0x2ffff, -- 0x3fffe, 0x3ffff, -- 0x4fffe, 0x4ffff, -- 0x5fffe, 0x5ffff, -- 0x6fffe, 0x6ffff, -- 0x7fffe, 0x7ffff, -- 0x8fffe, 0x8ffff, -- 0x9fffe, 0x9ffff, -- 0xafffe, 0xaffff, -- 0xbfffe, 0xbffff, -- 0xcfffe, 0xcffff, -- 0xdfffe, 0xdffff, -- 0xefffe, 0x10ffff, --}; /* CR_Age_2_1 */ -- --/* 'Age_3_0': Derived Age 3.0 */ --static const OnigCodePoint CR_Age_3_0[] = { -- 369, -- 0x0000, 0x021f, -- 0x0222, 0x0233, -- 0x0250, 0x02ad, -- 0x02b0, 0x02ee, -- 0x0300, 0x034e, -- 0x0360, 0x0362, -- 0x0374, 0x0375, -- 0x037a, 0x037a, -- 0x037e, 0x037e, -- 0x0384, 0x038a, -- 0x038c, 0x038c, -- 0x038e, 0x03a1, -- 0x03a3, 0x03ce, -- 0x03d0, 0x03d7, -- 0x03da, 0x03f3, -- 0x0400, 0x0486, -- 0x0488, 0x0489, -- 0x048c, 0x04c4, -- 0x04c7, 0x04c8, -- 0x04cb, 0x04cc, -- 0x04d0, 0x04f5, -- 0x04f8, 0x04f9, -- 0x0531, 0x0556, -- 0x0559, 0x055f, -- 0x0561, 0x0587, -- 0x0589, 0x058a, -- 0x0591, 0x05a1, -- 0x05a3, 0x05b9, -- 0x05bb, 0x05c4, -- 0x05d0, 0x05ea, -- 0x05f0, 0x05f4, -- 0x060c, 0x060c, -- 0x061b, 0x061b, -- 0x061f, 0x061f, -- 0x0621, 0x063a, -- 0x0640, 0x0655, -- 0x0660, 0x066d, -- 0x0670, 0x06ed, -- 0x06f0, 0x06fe, -- 0x0700, 0x070d, -- 0x070f, 0x072c, -- 0x0730, 0x074a, -- 0x0780, 0x07b0, -- 0x0901, 0x0903, -- 0x0905, 0x0939, -- 0x093c, 0x094d, -- 0x0950, 0x0954, -- 0x0958, 0x0970, -- 0x0981, 0x0983, -- 0x0985, 0x098c, -- 0x098f, 0x0990, -- 0x0993, 0x09a8, -- 0x09aa, 0x09b0, -- 0x09b2, 0x09b2, -- 0x09b6, 0x09b9, -- 0x09bc, 0x09bc, -- 0x09be, 0x09c4, -- 0x09c7, 0x09c8, -- 0x09cb, 0x09cd, -- 0x09d7, 0x09d7, -- 0x09dc, 0x09dd, -- 0x09df, 0x09e3, -- 0x09e6, 0x09fa, -- 0x0a02, 0x0a02, -- 0x0a05, 0x0a0a, -- 0x0a0f, 0x0a10, -- 0x0a13, 0x0a28, -- 0x0a2a, 0x0a30, -- 0x0a32, 0x0a33, -- 0x0a35, 0x0a36, -- 0x0a38, 0x0a39, -- 0x0a3c, 0x0a3c, -- 0x0a3e, 0x0a42, -- 0x0a47, 0x0a48, -- 0x0a4b, 0x0a4d, -- 0x0a59, 0x0a5c, -- 0x0a5e, 0x0a5e, -- 0x0a66, 0x0a74, -- 0x0a81, 0x0a83, -- 0x0a85, 0x0a8b, -- 0x0a8d, 0x0a8d, -- 0x0a8f, 0x0a91, -- 0x0a93, 0x0aa8, -- 0x0aaa, 0x0ab0, -- 0x0ab2, 0x0ab3, -- 0x0ab5, 0x0ab9, -- 0x0abc, 0x0ac5, -- 0x0ac7, 0x0ac9, -- 0x0acb, 0x0acd, -- 0x0ad0, 0x0ad0, -- 0x0ae0, 0x0ae0, -- 0x0ae6, 0x0aef, -- 0x0b01, 0x0b03, -- 0x0b05, 0x0b0c, -- 0x0b0f, 0x0b10, -- 0x0b13, 0x0b28, -- 0x0b2a, 0x0b30, -- 0x0b32, 0x0b33, -- 0x0b36, 0x0b39, -- 0x0b3c, 0x0b43, -- 0x0b47, 0x0b48, -- 0x0b4b, 0x0b4d, -- 0x0b56, 0x0b57, -- 0x0b5c, 0x0b5d, -- 0x0b5f, 0x0b61, -- 0x0b66, 0x0b70, -- 0x0b82, 0x0b83, -- 0x0b85, 0x0b8a, -- 0x0b8e, 0x0b90, -- 0x0b92, 0x0b95, -- 0x0b99, 0x0b9a, -- 0x0b9c, 0x0b9c, -- 0x0b9e, 0x0b9f, -- 0x0ba3, 0x0ba4, -- 0x0ba8, 0x0baa, -- 0x0bae, 0x0bb5, -- 0x0bb7, 0x0bb9, -- 0x0bbe, 0x0bc2, -- 0x0bc6, 0x0bc8, -- 0x0bca, 0x0bcd, -- 0x0bd7, 0x0bd7, -- 0x0be7, 0x0bf2, -- 0x0c01, 0x0c03, -- 0x0c05, 0x0c0c, -- 0x0c0e, 0x0c10, -- 0x0c12, 0x0c28, -- 0x0c2a, 0x0c33, -- 0x0c35, 0x0c39, -- 0x0c3e, 0x0c44, -- 0x0c46, 0x0c48, -- 0x0c4a, 0x0c4d, -- 0x0c55, 0x0c56, -- 0x0c60, 0x0c61, -- 0x0c66, 0x0c6f, -- 0x0c82, 0x0c83, -- 0x0c85, 0x0c8c, -- 0x0c8e, 0x0c90, -- 0x0c92, 0x0ca8, -- 0x0caa, 0x0cb3, -- 0x0cb5, 0x0cb9, -- 0x0cbe, 0x0cc4, -- 0x0cc6, 0x0cc8, -- 0x0cca, 0x0ccd, -- 0x0cd5, 0x0cd6, -- 0x0cde, 0x0cde, -- 0x0ce0, 0x0ce1, -- 0x0ce6, 0x0cef, -- 0x0d02, 0x0d03, -- 0x0d05, 0x0d0c, -- 0x0d0e, 0x0d10, -- 0x0d12, 0x0d28, -- 0x0d2a, 0x0d39, -- 0x0d3e, 0x0d43, -- 0x0d46, 0x0d48, -- 0x0d4a, 0x0d4d, -- 0x0d57, 0x0d57, -- 0x0d60, 0x0d61, -- 0x0d66, 0x0d6f, -- 0x0d82, 0x0d83, -- 0x0d85, 0x0d96, -- 0x0d9a, 0x0db1, -- 0x0db3, 0x0dbb, -- 0x0dbd, 0x0dbd, -- 0x0dc0, 0x0dc6, -- 0x0dca, 0x0dca, -- 0x0dcf, 0x0dd4, -- 0x0dd6, 0x0dd6, -- 0x0dd8, 0x0ddf, -- 0x0df2, 0x0df4, -- 0x0e01, 0x0e3a, -- 0x0e3f, 0x0e5b, -- 0x0e81, 0x0e82, -- 0x0e84, 0x0e84, -- 0x0e87, 0x0e88, -- 0x0e8a, 0x0e8a, -- 0x0e8d, 0x0e8d, -- 0x0e94, 0x0e97, -- 0x0e99, 0x0e9f, -- 0x0ea1, 0x0ea3, -- 0x0ea5, 0x0ea5, -- 0x0ea7, 0x0ea7, -- 0x0eaa, 0x0eab, -- 0x0ead, 0x0eb9, -- 0x0ebb, 0x0ebd, -- 0x0ec0, 0x0ec4, -- 0x0ec6, 0x0ec6, -- 0x0ec8, 0x0ecd, -- 0x0ed0, 0x0ed9, -- 0x0edc, 0x0edd, -- 0x0f00, 0x0f47, -- 0x0f49, 0x0f6a, -- 0x0f71, 0x0f8b, -- 0x0f90, 0x0f97, -- 0x0f99, 0x0fbc, -- 0x0fbe, 0x0fcc, -- 0x0fcf, 0x0fcf, -- 0x1000, 0x1021, -- 0x1023, 0x1027, -- 0x1029, 0x102a, -- 0x102c, 0x1032, -- 0x1036, 0x1039, -- 0x1040, 0x1059, -- 0x10a0, 0x10c5, -- 0x10d0, 0x10f6, -- 0x10fb, 0x10fb, -- 0x1100, 0x1159, -- 0x115f, 0x11a2, -- 0x11a8, 0x11f9, -- 0x1200, 0x1206, -- 0x1208, 0x1246, -- 0x1248, 0x1248, -- 0x124a, 0x124d, -- 0x1250, 0x1256, -- 0x1258, 0x1258, -- 0x125a, 0x125d, -- 0x1260, 0x1286, -- 0x1288, 0x1288, -- 0x128a, 0x128d, -- 0x1290, 0x12ae, -- 0x12b0, 0x12b0, -- 0x12b2, 0x12b5, -- 0x12b8, 0x12be, -- 0x12c0, 0x12c0, -- 0x12c2, 0x12c5, -- 0x12c8, 0x12ce, -- 0x12d0, 0x12d6, -- 0x12d8, 0x12ee, -- 0x12f0, 0x130e, -- 0x1310, 0x1310, -- 0x1312, 0x1315, -- 0x1318, 0x131e, -- 0x1320, 0x1346, -- 0x1348, 0x135a, -- 0x1361, 0x137c, -- 0x13a0, 0x13f4, -- 0x1401, 0x1676, -- 0x1680, 0x169c, -- 0x16a0, 0x16f0, -- 0x1780, 0x17dc, -- 0x17e0, 0x17e9, -- 0x1800, 0x180e, -- 0x1810, 0x1819, -- 0x1820, 0x1877, -- 0x1880, 0x18a9, -- 0x1e00, 0x1e9b, -- 0x1ea0, 0x1ef9, -- 0x1f00, 0x1f15, -- 0x1f18, 0x1f1d, -- 0x1f20, 0x1f45, -- 0x1f48, 0x1f4d, -- 0x1f50, 0x1f57, -- 0x1f59, 0x1f59, -- 0x1f5b, 0x1f5b, -- 0x1f5d, 0x1f5d, -- 0x1f5f, 0x1f7d, -- 0x1f80, 0x1fb4, -- 0x1fb6, 0x1fc4, -- 0x1fc6, 0x1fd3, -- 0x1fd6, 0x1fdb, -- 0x1fdd, 0x1fef, -- 0x1ff2, 0x1ff4, -- 0x1ff6, 0x1ffe, -- 0x2000, 0x2046, -- 0x2048, 0x204d, -- 0x206a, 0x2070, -- 0x2074, 0x208e, -- 0x20a0, 0x20af, -- 0x20d0, 0x20e3, -- 0x2100, 0x213a, -- 0x2153, 0x2183, -- 0x2190, 0x21f3, -- 0x2200, 0x22f1, -- 0x2300, 0x237b, -- 0x237d, 0x239a, -- 0x2400, 0x2426, -- 0x2440, 0x244a, -- 0x2460, 0x24ea, -- 0x2500, 0x2595, -- 0x25a0, 0x25f7, -- 0x2600, 0x2613, -- 0x2619, 0x2671, -- 0x2701, 0x2704, -- 0x2706, 0x2709, -- 0x270c, 0x2727, -- 0x2729, 0x274b, -- 0x274d, 0x274d, -- 0x274f, 0x2752, -- 0x2756, 0x2756, -- 0x2758, 0x275e, -- 0x2761, 0x2767, -- 0x2776, 0x2794, -- 0x2798, 0x27af, -- 0x27b1, 0x27be, -- 0x2800, 0x28ff, -- 0x2e80, 0x2e99, -- 0x2e9b, 0x2ef3, -- 0x2f00, 0x2fd5, -- 0x2ff0, 0x2ffb, -- 0x3000, 0x303a, -- 0x303e, 0x303f, -- 0x3041, 0x3094, -- 0x3099, 0x309e, -- 0x30a1, 0x30fe, -- 0x3105, 0x312c, -- 0x3131, 0x318e, -- 0x3190, 0x31b7, -- 0x3200, 0x321c, -- 0x3220, 0x3243, -- 0x3260, 0x327b, -- 0x327f, 0x32b0, -- 0x32c0, 0x32cb, -- 0x32d0, 0x32fe, -- 0x3300, 0x3376, -- 0x337b, 0x33dd, -- 0x33e0, 0x33fe, -- 0x3400, 0x4db5, -- 0x4e00, 0x9fa5, -- 0xa000, 0xa48c, -- 0xa490, 0xa4a1, -- 0xa4a4, 0xa4b3, -- 0xa4b5, 0xa4c0, -- 0xa4c2, 0xa4c4, -- 0xa4c6, 0xa4c6, -- 0xac00, 0xd7a3, -- 0xd800, 0xfa2d, -- 0xfb00, 0xfb06, -- 0xfb13, 0xfb17, -- 0xfb1d, 0xfb36, -- 0xfb38, 0xfb3c, -- 0xfb3e, 0xfb3e, -- 0xfb40, 0xfb41, -- 0xfb43, 0xfb44, -- 0xfb46, 0xfbb1, -- 0xfbd3, 0xfd3f, -- 0xfd50, 0xfd8f, -- 0xfd92, 0xfdc7, -- 0xfdf0, 0xfdfb, -- 0xfe20, 0xfe23, -- 0xfe30, 0xfe44, -- 0xfe49, 0xfe52, -- 0xfe54, 0xfe66, -- 0xfe68, 0xfe6b, -- 0xfe70, 0xfe72, -- 0xfe74, 0xfe74, -- 0xfe76, 0xfefc, -- 0xfeff, 0xfeff, -- 0xff01, 0xff5e, -- 0xff61, 0xffbe, -- 0xffc2, 0xffc7, -- 0xffca, 0xffcf, -- 0xffd2, 0xffd7, -- 0xffda, 0xffdc, -- 0xffe0, 0xffe6, -- 0xffe8, 0xffee, -- 0xfff9, 0xffff, -- 0x1fffe, 0x1ffff, -- 0x2fffe, 0x2ffff, -- 0x3fffe, 0x3ffff, -- 0x4fffe, 0x4ffff, -- 0x5fffe, 0x5ffff, -- 0x6fffe, 0x6ffff, -- 0x7fffe, 0x7ffff, -- 0x8fffe, 0x8ffff, -- 0x9fffe, 0x9ffff, -- 0xafffe, 0xaffff, -- 0xbfffe, 0xbffff, -- 0xcfffe, 0xcffff, -- 0xdfffe, 0xdffff, -- 0xefffe, 0x10ffff, --}; /* CR_Age_3_0 */ -- --/* 'Age_3_1': Derived Age 3.1 */ --static const OnigCodePoint CR_Age_3_1[] = { -- 402, -- 0x0000, 0x021f, -- 0x0222, 0x0233, -- 0x0250, 0x02ad, -- 0x02b0, 0x02ee, -- 0x0300, 0x034e, -- 0x0360, 0x0362, -- 0x0374, 0x0375, -- 0x037a, 0x037a, -- 0x037e, 0x037e, -- 0x0384, 0x038a, -- 0x038c, 0x038c, -- 0x038e, 0x03a1, -- 0x03a3, 0x03ce, -- 0x03d0, 0x03d7, -- 0x03da, 0x03f5, -- 0x0400, 0x0486, -- 0x0488, 0x0489, -- 0x048c, 0x04c4, -- 0x04c7, 0x04c8, -- 0x04cb, 0x04cc, -- 0x04d0, 0x04f5, -- 0x04f8, 0x04f9, -- 0x0531, 0x0556, -- 0x0559, 0x055f, -- 0x0561, 0x0587, -- 0x0589, 0x058a, -- 0x0591, 0x05a1, -- 0x05a3, 0x05b9, -- 0x05bb, 0x05c4, -- 0x05d0, 0x05ea, -- 0x05f0, 0x05f4, -- 0x060c, 0x060c, -- 0x061b, 0x061b, -- 0x061f, 0x061f, -- 0x0621, 0x063a, -- 0x0640, 0x0655, -- 0x0660, 0x066d, -- 0x0670, 0x06ed, -- 0x06f0, 0x06fe, -- 0x0700, 0x070d, -- 0x070f, 0x072c, -- 0x0730, 0x074a, -- 0x0780, 0x07b0, -- 0x0901, 0x0903, -- 0x0905, 0x0939, -- 0x093c, 0x094d, -- 0x0950, 0x0954, -- 0x0958, 0x0970, -- 0x0981, 0x0983, -- 0x0985, 0x098c, -- 0x098f, 0x0990, -- 0x0993, 0x09a8, -- 0x09aa, 0x09b0, -- 0x09b2, 0x09b2, -- 0x09b6, 0x09b9, -- 0x09bc, 0x09bc, -- 0x09be, 0x09c4, -- 0x09c7, 0x09c8, -- 0x09cb, 0x09cd, -- 0x09d7, 0x09d7, -- 0x09dc, 0x09dd, -- 0x09df, 0x09e3, -- 0x09e6, 0x09fa, -- 0x0a02, 0x0a02, -- 0x0a05, 0x0a0a, -- 0x0a0f, 0x0a10, -- 0x0a13, 0x0a28, -- 0x0a2a, 0x0a30, -- 0x0a32, 0x0a33, -- 0x0a35, 0x0a36, -- 0x0a38, 0x0a39, -- 0x0a3c, 0x0a3c, -- 0x0a3e, 0x0a42, -- 0x0a47, 0x0a48, -- 0x0a4b, 0x0a4d, -- 0x0a59, 0x0a5c, -- 0x0a5e, 0x0a5e, -- 0x0a66, 0x0a74, -- 0x0a81, 0x0a83, -- 0x0a85, 0x0a8b, -- 0x0a8d, 0x0a8d, -- 0x0a8f, 0x0a91, -- 0x0a93, 0x0aa8, -- 0x0aaa, 0x0ab0, -- 0x0ab2, 0x0ab3, -- 0x0ab5, 0x0ab9, -- 0x0abc, 0x0ac5, -- 0x0ac7, 0x0ac9, -- 0x0acb, 0x0acd, -- 0x0ad0, 0x0ad0, -- 0x0ae0, 0x0ae0, -- 0x0ae6, 0x0aef, -- 0x0b01, 0x0b03, -- 0x0b05, 0x0b0c, -- 0x0b0f, 0x0b10, -- 0x0b13, 0x0b28, -- 0x0b2a, 0x0b30, -- 0x0b32, 0x0b33, -- 0x0b36, 0x0b39, -- 0x0b3c, 0x0b43, -- 0x0b47, 0x0b48, -- 0x0b4b, 0x0b4d, -- 0x0b56, 0x0b57, -- 0x0b5c, 0x0b5d, -- 0x0b5f, 0x0b61, -- 0x0b66, 0x0b70, -- 0x0b82, 0x0b83, -- 0x0b85, 0x0b8a, -- 0x0b8e, 0x0b90, -- 0x0b92, 0x0b95, -- 0x0b99, 0x0b9a, -- 0x0b9c, 0x0b9c, -- 0x0b9e, 0x0b9f, -- 0x0ba3, 0x0ba4, -- 0x0ba8, 0x0baa, -- 0x0bae, 0x0bb5, -- 0x0bb7, 0x0bb9, -- 0x0bbe, 0x0bc2, -- 0x0bc6, 0x0bc8, -- 0x0bca, 0x0bcd, -- 0x0bd7, 0x0bd7, -- 0x0be7, 0x0bf2, -- 0x0c01, 0x0c03, -- 0x0c05, 0x0c0c, -- 0x0c0e, 0x0c10, -- 0x0c12, 0x0c28, -- 0x0c2a, 0x0c33, -- 0x0c35, 0x0c39, -- 0x0c3e, 0x0c44, -- 0x0c46, 0x0c48, -- 0x0c4a, 0x0c4d, -- 0x0c55, 0x0c56, -- 0x0c60, 0x0c61, -- 0x0c66, 0x0c6f, -- 0x0c82, 0x0c83, -- 0x0c85, 0x0c8c, -- 0x0c8e, 0x0c90, -- 0x0c92, 0x0ca8, -- 0x0caa, 0x0cb3, -- 0x0cb5, 0x0cb9, -- 0x0cbe, 0x0cc4, -- 0x0cc6, 0x0cc8, -- 0x0cca, 0x0ccd, -- 0x0cd5, 0x0cd6, -- 0x0cde, 0x0cde, -- 0x0ce0, 0x0ce1, -- 0x0ce6, 0x0cef, -- 0x0d02, 0x0d03, -- 0x0d05, 0x0d0c, -- 0x0d0e, 0x0d10, -- 0x0d12, 0x0d28, -- 0x0d2a, 0x0d39, -- 0x0d3e, 0x0d43, -- 0x0d46, 0x0d48, -- 0x0d4a, 0x0d4d, -- 0x0d57, 0x0d57, -- 0x0d60, 0x0d61, -- 0x0d66, 0x0d6f, -- 0x0d82, 0x0d83, -- 0x0d85, 0x0d96, -- 0x0d9a, 0x0db1, -- 0x0db3, 0x0dbb, -- 0x0dbd, 0x0dbd, -- 0x0dc0, 0x0dc6, -- 0x0dca, 0x0dca, -- 0x0dcf, 0x0dd4, -- 0x0dd6, 0x0dd6, -- 0x0dd8, 0x0ddf, -- 0x0df2, 0x0df4, -- 0x0e01, 0x0e3a, -- 0x0e3f, 0x0e5b, -- 0x0e81, 0x0e82, -- 0x0e84, 0x0e84, -- 0x0e87, 0x0e88, -- 0x0e8a, 0x0e8a, -- 0x0e8d, 0x0e8d, -- 0x0e94, 0x0e97, -- 0x0e99, 0x0e9f, -- 0x0ea1, 0x0ea3, -- 0x0ea5, 0x0ea5, -- 0x0ea7, 0x0ea7, -- 0x0eaa, 0x0eab, -- 0x0ead, 0x0eb9, -- 0x0ebb, 0x0ebd, -- 0x0ec0, 0x0ec4, -- 0x0ec6, 0x0ec6, -- 0x0ec8, 0x0ecd, -- 0x0ed0, 0x0ed9, -- 0x0edc, 0x0edd, -- 0x0f00, 0x0f47, -- 0x0f49, 0x0f6a, -- 0x0f71, 0x0f8b, -- 0x0f90, 0x0f97, -- 0x0f99, 0x0fbc, -- 0x0fbe, 0x0fcc, -- 0x0fcf, 0x0fcf, -- 0x1000, 0x1021, -- 0x1023, 0x1027, -- 0x1029, 0x102a, -- 0x102c, 0x1032, -- 0x1036, 0x1039, -- 0x1040, 0x1059, -- 0x10a0, 0x10c5, -- 0x10d0, 0x10f6, -- 0x10fb, 0x10fb, -- 0x1100, 0x1159, -- 0x115f, 0x11a2, -- 0x11a8, 0x11f9, -- 0x1200, 0x1206, -- 0x1208, 0x1246, -- 0x1248, 0x1248, -- 0x124a, 0x124d, -- 0x1250, 0x1256, -- 0x1258, 0x1258, -- 0x125a, 0x125d, -- 0x1260, 0x1286, -- 0x1288, 0x1288, -- 0x128a, 0x128d, -- 0x1290, 0x12ae, -- 0x12b0, 0x12b0, -- 0x12b2, 0x12b5, -- 0x12b8, 0x12be, -- 0x12c0, 0x12c0, -- 0x12c2, 0x12c5, -- 0x12c8, 0x12ce, -- 0x12d0, 0x12d6, -- 0x12d8, 0x12ee, -- 0x12f0, 0x130e, -- 0x1310, 0x1310, -- 0x1312, 0x1315, -- 0x1318, 0x131e, -- 0x1320, 0x1346, -- 0x1348, 0x135a, -- 0x1361, 0x137c, -- 0x13a0, 0x13f4, -- 0x1401, 0x1676, -- 0x1680, 0x169c, -- 0x16a0, 0x16f0, -- 0x1780, 0x17dc, -- 0x17e0, 0x17e9, -- 0x1800, 0x180e, -- 0x1810, 0x1819, -- 0x1820, 0x1877, -- 0x1880, 0x18a9, -- 0x1e00, 0x1e9b, -- 0x1ea0, 0x1ef9, -- 0x1f00, 0x1f15, -- 0x1f18, 0x1f1d, -- 0x1f20, 0x1f45, -- 0x1f48, 0x1f4d, -- 0x1f50, 0x1f57, -- 0x1f59, 0x1f59, -- 0x1f5b, 0x1f5b, -- 0x1f5d, 0x1f5d, -- 0x1f5f, 0x1f7d, -- 0x1f80, 0x1fb4, -- 0x1fb6, 0x1fc4, -- 0x1fc6, 0x1fd3, -- 0x1fd6, 0x1fdb, -- 0x1fdd, 0x1fef, -- 0x1ff2, 0x1ff4, -- 0x1ff6, 0x1ffe, -- 0x2000, 0x2046, -- 0x2048, 0x204d, -- 0x206a, 0x2070, -- 0x2074, 0x208e, -- 0x20a0, 0x20af, -- 0x20d0, 0x20e3, -- 0x2100, 0x213a, -- 0x2153, 0x2183, -- 0x2190, 0x21f3, -- 0x2200, 0x22f1, -- 0x2300, 0x237b, -- 0x237d, 0x239a, -- 0x2400, 0x2426, -- 0x2440, 0x244a, -- 0x2460, 0x24ea, -- 0x2500, 0x2595, -- 0x25a0, 0x25f7, -- 0x2600, 0x2613, -- 0x2619, 0x2671, -- 0x2701, 0x2704, -- 0x2706, 0x2709, -- 0x270c, 0x2727, -- 0x2729, 0x274b, -- 0x274d, 0x274d, -- 0x274f, 0x2752, -- 0x2756, 0x2756, -- 0x2758, 0x275e, -- 0x2761, 0x2767, -- 0x2776, 0x2794, -- 0x2798, 0x27af, -- 0x27b1, 0x27be, -- 0x2800, 0x28ff, -- 0x2e80, 0x2e99, -- 0x2e9b, 0x2ef3, -- 0x2f00, 0x2fd5, -- 0x2ff0, 0x2ffb, -- 0x3000, 0x303a, -- 0x303e, 0x303f, -- 0x3041, 0x3094, -- 0x3099, 0x309e, -- 0x30a1, 0x30fe, -- 0x3105, 0x312c, -- 0x3131, 0x318e, -- 0x3190, 0x31b7, -- 0x3200, 0x321c, -- 0x3220, 0x3243, -- 0x3260, 0x327b, -- 0x327f, 0x32b0, -- 0x32c0, 0x32cb, -- 0x32d0, 0x32fe, -- 0x3300, 0x3376, -- 0x337b, 0x33dd, -- 0x33e0, 0x33fe, -- 0x3400, 0x4db5, -- 0x4e00, 0x9fa5, -- 0xa000, 0xa48c, -- 0xa490, 0xa4a1, -- 0xa4a4, 0xa4b3, -- 0xa4b5, 0xa4c0, -- 0xa4c2, 0xa4c4, -- 0xa4c6, 0xa4c6, -- 0xac00, 0xd7a3, -- 0xd800, 0xfa2d, -- 0xfb00, 0xfb06, -- 0xfb13, 0xfb17, -- 0xfb1d, 0xfb36, -- 0xfb38, 0xfb3c, -- 0xfb3e, 0xfb3e, -- 0xfb40, 0xfb41, -- 0xfb43, 0xfb44, -- 0xfb46, 0xfbb1, -- 0xfbd3, 0xfd3f, -- 0xfd50, 0xfd8f, -- 0xfd92, 0xfdc7, -- 0xfdd0, 0xfdfb, -- 0xfe20, 0xfe23, -- 0xfe30, 0xfe44, -- 0xfe49, 0xfe52, -- 0xfe54, 0xfe66, -- 0xfe68, 0xfe6b, -- 0xfe70, 0xfe72, -- 0xfe74, 0xfe74, -- 0xfe76, 0xfefc, -- 0xfeff, 0xfeff, -- 0xff01, 0xff5e, -- 0xff61, 0xffbe, -- 0xffc2, 0xffc7, -- 0xffca, 0xffcf, -- 0xffd2, 0xffd7, -- 0xffda, 0xffdc, -- 0xffe0, 0xffe6, -- 0xffe8, 0xffee, -- 0xfff9, 0xffff, -- 0x10300, 0x1031e, -- 0x10320, 0x10323, -- 0x10330, 0x1034a, -- 0x10400, 0x10425, -- 0x10428, 0x1044d, -- 0x1d000, 0x1d0f5, -- 0x1d100, 0x1d126, -- 0x1d12a, 0x1d1dd, -- 0x1d400, 0x1d454, -- 0x1d456, 0x1d49c, -- 0x1d49e, 0x1d49f, -- 0x1d4a2, 0x1d4a2, -- 0x1d4a5, 0x1d4a6, -- 0x1d4a9, 0x1d4ac, -- 0x1d4ae, 0x1d4b9, -- 0x1d4bb, 0x1d4bb, -- 0x1d4bd, 0x1d4c0, -- 0x1d4c2, 0x1d4c3, -- 0x1d4c5, 0x1d505, -- 0x1d507, 0x1d50a, -- 0x1d50d, 0x1d514, -- 0x1d516, 0x1d51c, -- 0x1d51e, 0x1d539, -- 0x1d53b, 0x1d53e, -- 0x1d540, 0x1d544, -- 0x1d546, 0x1d546, -- 0x1d54a, 0x1d550, -- 0x1d552, 0x1d6a3, -- 0x1d6a8, 0x1d7c9, -- 0x1d7ce, 0x1d7ff, -- 0x1fffe, 0x2a6d6, -- 0x2f800, 0x2fa1d, -- 0x2fffe, 0x2ffff, -- 0x3fffe, 0x3ffff, -- 0x4fffe, 0x4ffff, -- 0x5fffe, 0x5ffff, -- 0x6fffe, 0x6ffff, -- 0x7fffe, 0x7ffff, -- 0x8fffe, 0x8ffff, -- 0x9fffe, 0x9ffff, -- 0xafffe, 0xaffff, -- 0xbfffe, 0xbffff, -- 0xcfffe, 0xcffff, -- 0xdfffe, 0xdffff, -- 0xe0001, 0xe0001, -- 0xe0020, 0xe007f, -- 0xefffe, 0x10ffff, --}; /* CR_Age_3_1 */ -- --/* 'Age_3_2': Derived Age 3.2 */ --static const OnigCodePoint CR_Age_3_2[] = { -- 397, -- 0x0000, 0x0220, -- 0x0222, 0x0233, -- 0x0250, 0x02ad, -- 0x02b0, 0x02ee, -- 0x0300, 0x034f, -- 0x0360, 0x036f, -- 0x0374, 0x0375, -- 0x037a, 0x037a, -- 0x037e, 0x037e, -- 0x0384, 0x038a, -- 0x038c, 0x038c, -- 0x038e, 0x03a1, -- 0x03a3, 0x03ce, -- 0x03d0, 0x03f6, -- 0x0400, 0x0486, -- 0x0488, 0x04ce, -- 0x04d0, 0x04f5, -- 0x04f8, 0x04f9, -- 0x0500, 0x050f, -- 0x0531, 0x0556, -- 0x0559, 0x055f, -- 0x0561, 0x0587, -- 0x0589, 0x058a, -- 0x0591, 0x05a1, -- 0x05a3, 0x05b9, -- 0x05bb, 0x05c4, -- 0x05d0, 0x05ea, -- 0x05f0, 0x05f4, -- 0x060c, 0x060c, -- 0x061b, 0x061b, -- 0x061f, 0x061f, -- 0x0621, 0x063a, -- 0x0640, 0x0655, -- 0x0660, 0x06ed, -- 0x06f0, 0x06fe, -- 0x0700, 0x070d, -- 0x070f, 0x072c, -- 0x0730, 0x074a, -- 0x0780, 0x07b1, -- 0x0901, 0x0903, -- 0x0905, 0x0939, -- 0x093c, 0x094d, -- 0x0950, 0x0954, -- 0x0958, 0x0970, -- 0x0981, 0x0983, -- 0x0985, 0x098c, -- 0x098f, 0x0990, -- 0x0993, 0x09a8, -- 0x09aa, 0x09b0, -- 0x09b2, 0x09b2, -- 0x09b6, 0x09b9, -- 0x09bc, 0x09bc, -- 0x09be, 0x09c4, -- 0x09c7, 0x09c8, -- 0x09cb, 0x09cd, -- 0x09d7, 0x09d7, -- 0x09dc, 0x09dd, -- 0x09df, 0x09e3, -- 0x09e6, 0x09fa, -- 0x0a02, 0x0a02, -- 0x0a05, 0x0a0a, -- 0x0a0f, 0x0a10, -- 0x0a13, 0x0a28, -- 0x0a2a, 0x0a30, -- 0x0a32, 0x0a33, -- 0x0a35, 0x0a36, -- 0x0a38, 0x0a39, -- 0x0a3c, 0x0a3c, -- 0x0a3e, 0x0a42, -- 0x0a47, 0x0a48, -- 0x0a4b, 0x0a4d, -- 0x0a59, 0x0a5c, -- 0x0a5e, 0x0a5e, -- 0x0a66, 0x0a74, -- 0x0a81, 0x0a83, -- 0x0a85, 0x0a8b, -- 0x0a8d, 0x0a8d, -- 0x0a8f, 0x0a91, -- 0x0a93, 0x0aa8, -- 0x0aaa, 0x0ab0, -- 0x0ab2, 0x0ab3, -- 0x0ab5, 0x0ab9, -- 0x0abc, 0x0ac5, -- 0x0ac7, 0x0ac9, -- 0x0acb, 0x0acd, -- 0x0ad0, 0x0ad0, -- 0x0ae0, 0x0ae0, -- 0x0ae6, 0x0aef, -- 0x0b01, 0x0b03, -- 0x0b05, 0x0b0c, -- 0x0b0f, 0x0b10, -- 0x0b13, 0x0b28, -- 0x0b2a, 0x0b30, -- 0x0b32, 0x0b33, -- 0x0b36, 0x0b39, -- 0x0b3c, 0x0b43, -- 0x0b47, 0x0b48, -- 0x0b4b, 0x0b4d, -- 0x0b56, 0x0b57, -- 0x0b5c, 0x0b5d, -- 0x0b5f, 0x0b61, -- 0x0b66, 0x0b70, -- 0x0b82, 0x0b83, -- 0x0b85, 0x0b8a, -- 0x0b8e, 0x0b90, -- 0x0b92, 0x0b95, -- 0x0b99, 0x0b9a, -- 0x0b9c, 0x0b9c, -- 0x0b9e, 0x0b9f, -- 0x0ba3, 0x0ba4, -- 0x0ba8, 0x0baa, -- 0x0bae, 0x0bb5, -- 0x0bb7, 0x0bb9, -- 0x0bbe, 0x0bc2, -- 0x0bc6, 0x0bc8, -- 0x0bca, 0x0bcd, -- 0x0bd7, 0x0bd7, -- 0x0be7, 0x0bf2, -- 0x0c01, 0x0c03, -- 0x0c05, 0x0c0c, -- 0x0c0e, 0x0c10, -- 0x0c12, 0x0c28, -- 0x0c2a, 0x0c33, -- 0x0c35, 0x0c39, -- 0x0c3e, 0x0c44, -- 0x0c46, 0x0c48, -- 0x0c4a, 0x0c4d, -- 0x0c55, 0x0c56, -- 0x0c60, 0x0c61, -- 0x0c66, 0x0c6f, -- 0x0c82, 0x0c83, -- 0x0c85, 0x0c8c, -- 0x0c8e, 0x0c90, -- 0x0c92, 0x0ca8, -- 0x0caa, 0x0cb3, -- 0x0cb5, 0x0cb9, -- 0x0cbe, 0x0cc4, -- 0x0cc6, 0x0cc8, -- 0x0cca, 0x0ccd, -- 0x0cd5, 0x0cd6, -- 0x0cde, 0x0cde, -- 0x0ce0, 0x0ce1, -- 0x0ce6, 0x0cef, -- 0x0d02, 0x0d03, -- 0x0d05, 0x0d0c, -- 0x0d0e, 0x0d10, -- 0x0d12, 0x0d28, -- 0x0d2a, 0x0d39, -- 0x0d3e, 0x0d43, -- 0x0d46, 0x0d48, -- 0x0d4a, 0x0d4d, -- 0x0d57, 0x0d57, -- 0x0d60, 0x0d61, -- 0x0d66, 0x0d6f, -- 0x0d82, 0x0d83, -- 0x0d85, 0x0d96, -- 0x0d9a, 0x0db1, -- 0x0db3, 0x0dbb, -- 0x0dbd, 0x0dbd, -- 0x0dc0, 0x0dc6, -- 0x0dca, 0x0dca, -- 0x0dcf, 0x0dd4, -- 0x0dd6, 0x0dd6, -- 0x0dd8, 0x0ddf, -- 0x0df2, 0x0df4, -- 0x0e01, 0x0e3a, -- 0x0e3f, 0x0e5b, -- 0x0e81, 0x0e82, -- 0x0e84, 0x0e84, -- 0x0e87, 0x0e88, -- 0x0e8a, 0x0e8a, -- 0x0e8d, 0x0e8d, -- 0x0e94, 0x0e97, -- 0x0e99, 0x0e9f, -- 0x0ea1, 0x0ea3, -- 0x0ea5, 0x0ea5, -- 0x0ea7, 0x0ea7, -- 0x0eaa, 0x0eab, -- 0x0ead, 0x0eb9, -- 0x0ebb, 0x0ebd, -- 0x0ec0, 0x0ec4, -- 0x0ec6, 0x0ec6, -- 0x0ec8, 0x0ecd, -- 0x0ed0, 0x0ed9, -- 0x0edc, 0x0edd, -- 0x0f00, 0x0f47, -- 0x0f49, 0x0f6a, -- 0x0f71, 0x0f8b, -- 0x0f90, 0x0f97, -- 0x0f99, 0x0fbc, -- 0x0fbe, 0x0fcc, -- 0x0fcf, 0x0fcf, -- 0x1000, 0x1021, -- 0x1023, 0x1027, -- 0x1029, 0x102a, -- 0x102c, 0x1032, -- 0x1036, 0x1039, -- 0x1040, 0x1059, -- 0x10a0, 0x10c5, -- 0x10d0, 0x10f8, -- 0x10fb, 0x10fb, -- 0x1100, 0x1159, -- 0x115f, 0x11a2, -- 0x11a8, 0x11f9, -- 0x1200, 0x1206, -- 0x1208, 0x1246, -- 0x1248, 0x1248, -- 0x124a, 0x124d, -- 0x1250, 0x1256, -- 0x1258, 0x1258, -- 0x125a, 0x125d, -- 0x1260, 0x1286, -- 0x1288, 0x1288, -- 0x128a, 0x128d, -- 0x1290, 0x12ae, -- 0x12b0, 0x12b0, -- 0x12b2, 0x12b5, -- 0x12b8, 0x12be, -- 0x12c0, 0x12c0, -- 0x12c2, 0x12c5, -- 0x12c8, 0x12ce, -- 0x12d0, 0x12d6, -- 0x12d8, 0x12ee, -- 0x12f0, 0x130e, -- 0x1310, 0x1310, -- 0x1312, 0x1315, -- 0x1318, 0x131e, -- 0x1320, 0x1346, -- 0x1348, 0x135a, -- 0x1361, 0x137c, -- 0x13a0, 0x13f4, -- 0x1401, 0x1676, -- 0x1680, 0x169c, -- 0x16a0, 0x16f0, -- 0x1700, 0x170c, -- 0x170e, 0x1714, -- 0x1720, 0x1736, -- 0x1740, 0x1753, -- 0x1760, 0x176c, -- 0x176e, 0x1770, -- 0x1772, 0x1773, -- 0x1780, 0x17dc, -- 0x17e0, 0x17e9, -- 0x1800, 0x180e, -- 0x1810, 0x1819, -- 0x1820, 0x1877, -- 0x1880, 0x18a9, -- 0x1e00, 0x1e9b, -- 0x1ea0, 0x1ef9, -- 0x1f00, 0x1f15, -- 0x1f18, 0x1f1d, -- 0x1f20, 0x1f45, -- 0x1f48, 0x1f4d, -- 0x1f50, 0x1f57, -- 0x1f59, 0x1f59, -- 0x1f5b, 0x1f5b, -- 0x1f5d, 0x1f5d, -- 0x1f5f, 0x1f7d, -- 0x1f80, 0x1fb4, -- 0x1fb6, 0x1fc4, -- 0x1fc6, 0x1fd3, -- 0x1fd6, 0x1fdb, -- 0x1fdd, 0x1fef, -- 0x1ff2, 0x1ff4, -- 0x1ff6, 0x1ffe, -- 0x2000, 0x2052, -- 0x2057, 0x2057, -- 0x205f, 0x2063, -- 0x206a, 0x2071, -- 0x2074, 0x208e, -- 0x20a0, 0x20b1, -- 0x20d0, 0x20ea, -- 0x2100, 0x213a, -- 0x213d, 0x214b, -- 0x2153, 0x2183, -- 0x2190, 0x23ce, -- 0x2400, 0x2426, -- 0x2440, 0x244a, -- 0x2460, 0x24fe, -- 0x2500, 0x2613, -- 0x2616, 0x2617, -- 0x2619, 0x267d, -- 0x2680, 0x2689, -- 0x2701, 0x2704, -- 0x2706, 0x2709, -- 0x270c, 0x2727, -- 0x2729, 0x274b, -- 0x274d, 0x274d, -- 0x274f, 0x2752, -- 0x2756, 0x2756, -- 0x2758, 0x275e, -- 0x2761, 0x2794, -- 0x2798, 0x27af, -- 0x27b1, 0x27be, -- 0x27d0, 0x27eb, -- 0x27f0, 0x2aff, -- 0x2e80, 0x2e99, -- 0x2e9b, 0x2ef3, -- 0x2f00, 0x2fd5, -- 0x2ff0, 0x2ffb, -- 0x3000, 0x303f, -- 0x3041, 0x3096, -- 0x3099, 0x30ff, -- 0x3105, 0x312c, -- 0x3131, 0x318e, -- 0x3190, 0x31b7, -- 0x31f0, 0x321c, -- 0x3220, 0x3243, -- 0x3251, 0x327b, -- 0x327f, 0x32cb, -- 0x32d0, 0x32fe, -- 0x3300, 0x3376, -- 0x337b, 0x33dd, -- 0x33e0, 0x33fe, -- 0x3400, 0x4db5, -- 0x4e00, 0x9fa5, -- 0xa000, 0xa48c, -- 0xa490, 0xa4c6, -- 0xac00, 0xd7a3, -- 0xd800, 0xfa2d, -- 0xfa30, 0xfa6a, -- 0xfb00, 0xfb06, -- 0xfb13, 0xfb17, -- 0xfb1d, 0xfb36, -- 0xfb38, 0xfb3c, -- 0xfb3e, 0xfb3e, -- 0xfb40, 0xfb41, -- 0xfb43, 0xfb44, -- 0xfb46, 0xfbb1, -- 0xfbd3, 0xfd3f, -- 0xfd50, 0xfd8f, -- 0xfd92, 0xfdc7, -- 0xfdd0, 0xfdfc, -- 0xfe00, 0xfe0f, -- 0xfe20, 0xfe23, -- 0xfe30, 0xfe46, -- 0xfe49, 0xfe52, -- 0xfe54, 0xfe66, -- 0xfe68, 0xfe6b, -- 0xfe70, 0xfe74, -- 0xfe76, 0xfefc, -- 0xfeff, 0xfeff, -- 0xff01, 0xffbe, -- 0xffc2, 0xffc7, -- 0xffca, 0xffcf, -- 0xffd2, 0xffd7, -- 0xffda, 0xffdc, -- 0xffe0, 0xffe6, -- 0xffe8, 0xffee, -- 0xfff9, 0xffff, -- 0x10300, 0x1031e, -- 0x10320, 0x10323, -- 0x10330, 0x1034a, -- 0x10400, 0x10425, -- 0x10428, 0x1044d, -- 0x1d000, 0x1d0f5, -- 0x1d100, 0x1d126, -- 0x1d12a, 0x1d1dd, -- 0x1d400, 0x1d454, -- 0x1d456, 0x1d49c, -- 0x1d49e, 0x1d49f, -- 0x1d4a2, 0x1d4a2, -- 0x1d4a5, 0x1d4a6, -- 0x1d4a9, 0x1d4ac, -- 0x1d4ae, 0x1d4b9, -- 0x1d4bb, 0x1d4bb, -- 0x1d4bd, 0x1d4c0, -- 0x1d4c2, 0x1d4c3, -- 0x1d4c5, 0x1d505, -- 0x1d507, 0x1d50a, -- 0x1d50d, 0x1d514, -- 0x1d516, 0x1d51c, -- 0x1d51e, 0x1d539, -- 0x1d53b, 0x1d53e, -- 0x1d540, 0x1d544, -- 0x1d546, 0x1d546, -- 0x1d54a, 0x1d550, -- 0x1d552, 0x1d6a3, -- 0x1d6a8, 0x1d7c9, -- 0x1d7ce, 0x1d7ff, -- 0x1fffe, 0x2a6d6, -- 0x2f800, 0x2fa1d, -- 0x2fffe, 0x2ffff, -- 0x3fffe, 0x3ffff, -- 0x4fffe, 0x4ffff, -- 0x5fffe, 0x5ffff, -- 0x6fffe, 0x6ffff, -- 0x7fffe, 0x7ffff, -- 0x8fffe, 0x8ffff, -- 0x9fffe, 0x9ffff, -- 0xafffe, 0xaffff, -- 0xbfffe, 0xbffff, -- 0xcfffe, 0xcffff, -- 0xdfffe, 0xdffff, -- 0xe0001, 0xe0001, -- 0xe0020, 0xe007f, -- 0xefffe, 0x10ffff, --}; /* CR_Age_3_2 */ -- --/* 'Age_4_0': Derived Age 4.0 */ --static const OnigCodePoint CR_Age_4_0[] = { -- 412, -- 0x0000, 0x0236, -- 0x0250, 0x0357, -- 0x035d, 0x036f, -- 0x0374, 0x0375, -- 0x037a, 0x037a, -- 0x037e, 0x037e, -- 0x0384, 0x038a, -- 0x038c, 0x038c, -- 0x038e, 0x03a1, -- 0x03a3, 0x03ce, -- 0x03d0, 0x03fb, -- 0x0400, 0x0486, -- 0x0488, 0x04ce, -- 0x04d0, 0x04f5, -- 0x04f8, 0x04f9, -- 0x0500, 0x050f, -- 0x0531, 0x0556, -- 0x0559, 0x055f, -- 0x0561, 0x0587, -- 0x0589, 0x058a, -- 0x0591, 0x05a1, -- 0x05a3, 0x05b9, -- 0x05bb, 0x05c4, -- 0x05d0, 0x05ea, -- 0x05f0, 0x05f4, -- 0x0600, 0x0603, -- 0x060c, 0x0615, -- 0x061b, 0x061b, -- 0x061f, 0x061f, -- 0x0621, 0x063a, -- 0x0640, 0x0658, -- 0x0660, 0x070d, -- 0x070f, 0x074a, -- 0x074d, 0x074f, -- 0x0780, 0x07b1, -- 0x0901, 0x0939, -- 0x093c, 0x094d, -- 0x0950, 0x0954, -- 0x0958, 0x0970, -- 0x0981, 0x0983, -- 0x0985, 0x098c, -- 0x098f, 0x0990, -- 0x0993, 0x09a8, -- 0x09aa, 0x09b0, -- 0x09b2, 0x09b2, -- 0x09b6, 0x09b9, -- 0x09bc, 0x09c4, -- 0x09c7, 0x09c8, -- 0x09cb, 0x09cd, -- 0x09d7, 0x09d7, -- 0x09dc, 0x09dd, -- 0x09df, 0x09e3, -- 0x09e6, 0x09fa, -- 0x0a01, 0x0a03, -- 0x0a05, 0x0a0a, -- 0x0a0f, 0x0a10, -- 0x0a13, 0x0a28, -- 0x0a2a, 0x0a30, -- 0x0a32, 0x0a33, -- 0x0a35, 0x0a36, -- 0x0a38, 0x0a39, -- 0x0a3c, 0x0a3c, -- 0x0a3e, 0x0a42, -- 0x0a47, 0x0a48, -- 0x0a4b, 0x0a4d, -- 0x0a59, 0x0a5c, -- 0x0a5e, 0x0a5e, -- 0x0a66, 0x0a74, -- 0x0a81, 0x0a83, -- 0x0a85, 0x0a8d, -- 0x0a8f, 0x0a91, -- 0x0a93, 0x0aa8, -- 0x0aaa, 0x0ab0, -- 0x0ab2, 0x0ab3, -- 0x0ab5, 0x0ab9, -- 0x0abc, 0x0ac5, -- 0x0ac7, 0x0ac9, -- 0x0acb, 0x0acd, -- 0x0ad0, 0x0ad0, -- 0x0ae0, 0x0ae3, -- 0x0ae6, 0x0aef, -- 0x0af1, 0x0af1, -- 0x0b01, 0x0b03, -- 0x0b05, 0x0b0c, -- 0x0b0f, 0x0b10, -- 0x0b13, 0x0b28, -- 0x0b2a, 0x0b30, -- 0x0b32, 0x0b33, -- 0x0b35, 0x0b39, -- 0x0b3c, 0x0b43, -- 0x0b47, 0x0b48, -- 0x0b4b, 0x0b4d, -- 0x0b56, 0x0b57, -- 0x0b5c, 0x0b5d, -- 0x0b5f, 0x0b61, -- 0x0b66, 0x0b71, -- 0x0b82, 0x0b83, -- 0x0b85, 0x0b8a, -- 0x0b8e, 0x0b90, -- 0x0b92, 0x0b95, -- 0x0b99, 0x0b9a, -- 0x0b9c, 0x0b9c, -- 0x0b9e, 0x0b9f, -- 0x0ba3, 0x0ba4, -- 0x0ba8, 0x0baa, -- 0x0bae, 0x0bb5, -- 0x0bb7, 0x0bb9, -- 0x0bbe, 0x0bc2, -- 0x0bc6, 0x0bc8, -- 0x0bca, 0x0bcd, -- 0x0bd7, 0x0bd7, -- 0x0be7, 0x0bfa, -- 0x0c01, 0x0c03, -- 0x0c05, 0x0c0c, -- 0x0c0e, 0x0c10, -- 0x0c12, 0x0c28, -- 0x0c2a, 0x0c33, -- 0x0c35, 0x0c39, -- 0x0c3e, 0x0c44, -- 0x0c46, 0x0c48, -- 0x0c4a, 0x0c4d, -- 0x0c55, 0x0c56, -- 0x0c60, 0x0c61, -- 0x0c66, 0x0c6f, -- 0x0c82, 0x0c83, -- 0x0c85, 0x0c8c, -- 0x0c8e, 0x0c90, -- 0x0c92, 0x0ca8, -- 0x0caa, 0x0cb3, -- 0x0cb5, 0x0cb9, -- 0x0cbc, 0x0cc4, -- 0x0cc6, 0x0cc8, -- 0x0cca, 0x0ccd, -- 0x0cd5, 0x0cd6, -- 0x0cde, 0x0cde, -- 0x0ce0, 0x0ce1, -- 0x0ce6, 0x0cef, -- 0x0d02, 0x0d03, -- 0x0d05, 0x0d0c, -- 0x0d0e, 0x0d10, -- 0x0d12, 0x0d28, -- 0x0d2a, 0x0d39, -- 0x0d3e, 0x0d43, -- 0x0d46, 0x0d48, -- 0x0d4a, 0x0d4d, -- 0x0d57, 0x0d57, -- 0x0d60, 0x0d61, -- 0x0d66, 0x0d6f, -- 0x0d82, 0x0d83, -- 0x0d85, 0x0d96, -- 0x0d9a, 0x0db1, -- 0x0db3, 0x0dbb, -- 0x0dbd, 0x0dbd, -- 0x0dc0, 0x0dc6, -- 0x0dca, 0x0dca, -- 0x0dcf, 0x0dd4, -- 0x0dd6, 0x0dd6, -- 0x0dd8, 0x0ddf, -- 0x0df2, 0x0df4, -- 0x0e01, 0x0e3a, -- 0x0e3f, 0x0e5b, -- 0x0e81, 0x0e82, -- 0x0e84, 0x0e84, -- 0x0e87, 0x0e88, -- 0x0e8a, 0x0e8a, -- 0x0e8d, 0x0e8d, -- 0x0e94, 0x0e97, -- 0x0e99, 0x0e9f, -- 0x0ea1, 0x0ea3, -- 0x0ea5, 0x0ea5, -- 0x0ea7, 0x0ea7, -- 0x0eaa, 0x0eab, -- 0x0ead, 0x0eb9, -- 0x0ebb, 0x0ebd, -- 0x0ec0, 0x0ec4, -- 0x0ec6, 0x0ec6, -- 0x0ec8, 0x0ecd, -- 0x0ed0, 0x0ed9, -- 0x0edc, 0x0edd, -- 0x0f00, 0x0f47, -- 0x0f49, 0x0f6a, -- 0x0f71, 0x0f8b, -- 0x0f90, 0x0f97, -- 0x0f99, 0x0fbc, -- 0x0fbe, 0x0fcc, -- 0x0fcf, 0x0fcf, -- 0x1000, 0x1021, -- 0x1023, 0x1027, -- 0x1029, 0x102a, -- 0x102c, 0x1032, -- 0x1036, 0x1039, -- 0x1040, 0x1059, -- 0x10a0, 0x10c5, -- 0x10d0, 0x10f8, -- 0x10fb, 0x10fb, -- 0x1100, 0x1159, -- 0x115f, 0x11a2, -- 0x11a8, 0x11f9, -- 0x1200, 0x1206, -- 0x1208, 0x1246, -- 0x1248, 0x1248, -- 0x124a, 0x124d, -- 0x1250, 0x1256, -- 0x1258, 0x1258, -- 0x125a, 0x125d, -- 0x1260, 0x1286, -- 0x1288, 0x1288, -- 0x128a, 0x128d, -- 0x1290, 0x12ae, -- 0x12b0, 0x12b0, -- 0x12b2, 0x12b5, -- 0x12b8, 0x12be, -- 0x12c0, 0x12c0, -- 0x12c2, 0x12c5, -- 0x12c8, 0x12ce, -- 0x12d0, 0x12d6, -- 0x12d8, 0x12ee, -- 0x12f0, 0x130e, -- 0x1310, 0x1310, -- 0x1312, 0x1315, -- 0x1318, 0x131e, -- 0x1320, 0x1346, -- 0x1348, 0x135a, -- 0x1361, 0x137c, -- 0x13a0, 0x13f4, -- 0x1401, 0x1676, -- 0x1680, 0x169c, -- 0x16a0, 0x16f0, -- 0x1700, 0x170c, -- 0x170e, 0x1714, -- 0x1720, 0x1736, -- 0x1740, 0x1753, -- 0x1760, 0x176c, -- 0x176e, 0x1770, -- 0x1772, 0x1773, -- 0x1780, 0x17dd, -- 0x17e0, 0x17e9, -- 0x17f0, 0x17f9, -- 0x1800, 0x180e, -- 0x1810, 0x1819, -- 0x1820, 0x1877, -- 0x1880, 0x18a9, -- 0x1900, 0x191c, -- 0x1920, 0x192b, -- 0x1930, 0x193b, -- 0x1940, 0x1940, -- 0x1944, 0x196d, -- 0x1970, 0x1974, -- 0x19e0, 0x19ff, -- 0x1d00, 0x1d6b, -- 0x1e00, 0x1e9b, -- 0x1ea0, 0x1ef9, -- 0x1f00, 0x1f15, -- 0x1f18, 0x1f1d, -- 0x1f20, 0x1f45, -- 0x1f48, 0x1f4d, -- 0x1f50, 0x1f57, -- 0x1f59, 0x1f59, -- 0x1f5b, 0x1f5b, -- 0x1f5d, 0x1f5d, -- 0x1f5f, 0x1f7d, -- 0x1f80, 0x1fb4, -- 0x1fb6, 0x1fc4, -- 0x1fc6, 0x1fd3, -- 0x1fd6, 0x1fdb, -- 0x1fdd, 0x1fef, -- 0x1ff2, 0x1ff4, -- 0x1ff6, 0x1ffe, -- 0x2000, 0x2054, -- 0x2057, 0x2057, -- 0x205f, 0x2063, -- 0x206a, 0x2071, -- 0x2074, 0x208e, -- 0x20a0, 0x20b1, -- 0x20d0, 0x20ea, -- 0x2100, 0x213b, -- 0x213d, 0x214b, -- 0x2153, 0x2183, -- 0x2190, 0x23d0, -- 0x2400, 0x2426, -- 0x2440, 0x244a, -- 0x2460, 0x2617, -- 0x2619, 0x267d, -- 0x2680, 0x2691, -- 0x26a0, 0x26a1, -- 0x2701, 0x2704, -- 0x2706, 0x2709, -- 0x270c, 0x2727, -- 0x2729, 0x274b, -- 0x274d, 0x274d, -- 0x274f, 0x2752, -- 0x2756, 0x2756, -- 0x2758, 0x275e, -- 0x2761, 0x2794, -- 0x2798, 0x27af, -- 0x27b1, 0x27be, -- 0x27d0, 0x27eb, -- 0x27f0, 0x2b0d, -- 0x2e80, 0x2e99, -- 0x2e9b, 0x2ef3, -- 0x2f00, 0x2fd5, -- 0x2ff0, 0x2ffb, -- 0x3000, 0x303f, -- 0x3041, 0x3096, -- 0x3099, 0x30ff, -- 0x3105, 0x312c, -- 0x3131, 0x318e, -- 0x3190, 0x31b7, -- 0x31f0, 0x321e, -- 0x3220, 0x3243, -- 0x3250, 0x327d, -- 0x327f, 0x32fe, -- 0x3300, 0x4db5, -- 0x4dc0, 0x9fa5, -- 0xa000, 0xa48c, -- 0xa490, 0xa4c6, -- 0xac00, 0xd7a3, -- 0xd800, 0xfa2d, -- 0xfa30, 0xfa6a, -- 0xfb00, 0xfb06, -- 0xfb13, 0xfb17, -- 0xfb1d, 0xfb36, -- 0xfb38, 0xfb3c, -- 0xfb3e, 0xfb3e, -- 0xfb40, 0xfb41, -- 0xfb43, 0xfb44, -- 0xfb46, 0xfbb1, -- 0xfbd3, 0xfd3f, -- 0xfd50, 0xfd8f, -- 0xfd92, 0xfdc7, -- 0xfdd0, 0xfdfd, -- 0xfe00, 0xfe0f, -- 0xfe20, 0xfe23, -- 0xfe30, 0xfe52, -- 0xfe54, 0xfe66, -- 0xfe68, 0xfe6b, -- 0xfe70, 0xfe74, -- 0xfe76, 0xfefc, -- 0xfeff, 0xfeff, -- 0xff01, 0xffbe, -- 0xffc2, 0xffc7, -- 0xffca, 0xffcf, -- 0xffd2, 0xffd7, -- 0xffda, 0xffdc, -- 0xffe0, 0xffe6, -- 0xffe8, 0xffee, -- 0xfff9, 0x1000b, -- 0x1000d, 0x10026, -- 0x10028, 0x1003a, -- 0x1003c, 0x1003d, -- 0x1003f, 0x1004d, -- 0x10050, 0x1005d, -- 0x10080, 0x100fa, -- 0x10100, 0x10102, -- 0x10107, 0x10133, -- 0x10137, 0x1013f, -- 0x10300, 0x1031e, -- 0x10320, 0x10323, -- 0x10330, 0x1034a, -- 0x10380, 0x1039d, -- 0x1039f, 0x1039f, -- 0x10400, 0x1049d, -- 0x104a0, 0x104a9, -- 0x10800, 0x10805, -- 0x10808, 0x10808, -- 0x1080a, 0x10835, -- 0x10837, 0x10838, -- 0x1083c, 0x1083c, -- 0x1083f, 0x1083f, -- 0x1d000, 0x1d0f5, -- 0x1d100, 0x1d126, -- 0x1d12a, 0x1d1dd, -- 0x1d300, 0x1d356, -- 0x1d400, 0x1d454, -- 0x1d456, 0x1d49c, -- 0x1d49e, 0x1d49f, -- 0x1d4a2, 0x1d4a2, -- 0x1d4a5, 0x1d4a6, -- 0x1d4a9, 0x1d4ac, -- 0x1d4ae, 0x1d4b9, -- 0x1d4bb, 0x1d4bb, -- 0x1d4bd, 0x1d4c3, -- 0x1d4c5, 0x1d505, -- 0x1d507, 0x1d50a, -- 0x1d50d, 0x1d514, -- 0x1d516, 0x1d51c, -- 0x1d51e, 0x1d539, -- 0x1d53b, 0x1d53e, -- 0x1d540, 0x1d544, -- 0x1d546, 0x1d546, -- 0x1d54a, 0x1d550, -- 0x1d552, 0x1d6a3, -- 0x1d6a8, 0x1d7c9, -- 0x1d7ce, 0x1d7ff, -- 0x1fffe, 0x2a6d6, -- 0x2f800, 0x2fa1d, -- 0x2fffe, 0x2ffff, -- 0x3fffe, 0x3ffff, -- 0x4fffe, 0x4ffff, -- 0x5fffe, 0x5ffff, -- 0x6fffe, 0x6ffff, -- 0x7fffe, 0x7ffff, -- 0x8fffe, 0x8ffff, -- 0x9fffe, 0x9ffff, -- 0xafffe, 0xaffff, -- 0xbfffe, 0xbffff, -- 0xcfffe, 0xcffff, -- 0xdfffe, 0xdffff, -- 0xe0001, 0xe0001, -- 0xe0020, 0xe007f, -- 0xe0100, 0xe01ef, -- 0xefffe, 0x10ffff, --}; /* CR_Age_4_0 */ -- --/* 'Age_4_1': Derived Age 4.1 */ --static const OnigCodePoint CR_Age_4_1[] = { -- 430, -- 0x0000, 0x0241, -- 0x0250, 0x036f, -- 0x0374, 0x0375, -- 0x037a, 0x037a, -- 0x037e, 0x037e, -- 0x0384, 0x038a, -- 0x038c, 0x038c, -- 0x038e, 0x03a1, -- 0x03a3, 0x03ce, -- 0x03d0, 0x0486, -- 0x0488, 0x04ce, -- 0x04d0, 0x04f9, -- 0x0500, 0x050f, -- 0x0531, 0x0556, -- 0x0559, 0x055f, -- 0x0561, 0x0587, -- 0x0589, 0x058a, -- 0x0591, 0x05b9, -- 0x05bb, 0x05c7, -- 0x05d0, 0x05ea, -- 0x05f0, 0x05f4, -- 0x0600, 0x0603, -- 0x060b, 0x0615, -- 0x061b, 0x061b, -- 0x061e, 0x061f, -- 0x0621, 0x063a, -- 0x0640, 0x065e, -- 0x0660, 0x070d, -- 0x070f, 0x074a, -- 0x074d, 0x076d, -- 0x0780, 0x07b1, -- 0x0901, 0x0939, -- 0x093c, 0x094d, -- 0x0950, 0x0954, -- 0x0958, 0x0970, -- 0x097d, 0x097d, -- 0x0981, 0x0983, -- 0x0985, 0x098c, -- 0x098f, 0x0990, -- 0x0993, 0x09a8, -- 0x09aa, 0x09b0, -- 0x09b2, 0x09b2, -- 0x09b6, 0x09b9, -- 0x09bc, 0x09c4, -- 0x09c7, 0x09c8, -- 0x09cb, 0x09ce, -- 0x09d7, 0x09d7, -- 0x09dc, 0x09dd, -- 0x09df, 0x09e3, -- 0x09e6, 0x09fa, -- 0x0a01, 0x0a03, -- 0x0a05, 0x0a0a, -- 0x0a0f, 0x0a10, -- 0x0a13, 0x0a28, -- 0x0a2a, 0x0a30, -- 0x0a32, 0x0a33, -- 0x0a35, 0x0a36, -- 0x0a38, 0x0a39, -- 0x0a3c, 0x0a3c, -- 0x0a3e, 0x0a42, -- 0x0a47, 0x0a48, -- 0x0a4b, 0x0a4d, -- 0x0a59, 0x0a5c, -- 0x0a5e, 0x0a5e, -- 0x0a66, 0x0a74, -- 0x0a81, 0x0a83, -- 0x0a85, 0x0a8d, -- 0x0a8f, 0x0a91, -- 0x0a93, 0x0aa8, -- 0x0aaa, 0x0ab0, -- 0x0ab2, 0x0ab3, -- 0x0ab5, 0x0ab9, -- 0x0abc, 0x0ac5, -- 0x0ac7, 0x0ac9, -- 0x0acb, 0x0acd, -- 0x0ad0, 0x0ad0, -- 0x0ae0, 0x0ae3, -- 0x0ae6, 0x0aef, -- 0x0af1, 0x0af1, -- 0x0b01, 0x0b03, -- 0x0b05, 0x0b0c, -- 0x0b0f, 0x0b10, -- 0x0b13, 0x0b28, -- 0x0b2a, 0x0b30, -- 0x0b32, 0x0b33, -- 0x0b35, 0x0b39, -- 0x0b3c, 0x0b43, -- 0x0b47, 0x0b48, -- 0x0b4b, 0x0b4d, -- 0x0b56, 0x0b57, -- 0x0b5c, 0x0b5d, -- 0x0b5f, 0x0b61, -- 0x0b66, 0x0b71, -- 0x0b82, 0x0b83, -- 0x0b85, 0x0b8a, -- 0x0b8e, 0x0b90, -- 0x0b92, 0x0b95, -- 0x0b99, 0x0b9a, -- 0x0b9c, 0x0b9c, -- 0x0b9e, 0x0b9f, -- 0x0ba3, 0x0ba4, -- 0x0ba8, 0x0baa, -- 0x0bae, 0x0bb9, -- 0x0bbe, 0x0bc2, -- 0x0bc6, 0x0bc8, -- 0x0bca, 0x0bcd, -- 0x0bd7, 0x0bd7, -- 0x0be6, 0x0bfa, -- 0x0c01, 0x0c03, -- 0x0c05, 0x0c0c, -- 0x0c0e, 0x0c10, -- 0x0c12, 0x0c28, -- 0x0c2a, 0x0c33, -- 0x0c35, 0x0c39, -- 0x0c3e, 0x0c44, -- 0x0c46, 0x0c48, -- 0x0c4a, 0x0c4d, -- 0x0c55, 0x0c56, -- 0x0c60, 0x0c61, -- 0x0c66, 0x0c6f, -- 0x0c82, 0x0c83, -- 0x0c85, 0x0c8c, -- 0x0c8e, 0x0c90, -- 0x0c92, 0x0ca8, -- 0x0caa, 0x0cb3, -- 0x0cb5, 0x0cb9, -- 0x0cbc, 0x0cc4, -- 0x0cc6, 0x0cc8, -- 0x0cca, 0x0ccd, -- 0x0cd5, 0x0cd6, -- 0x0cde, 0x0cde, -- 0x0ce0, 0x0ce1, -- 0x0ce6, 0x0cef, -- 0x0d02, 0x0d03, -- 0x0d05, 0x0d0c, -- 0x0d0e, 0x0d10, -- 0x0d12, 0x0d28, -- 0x0d2a, 0x0d39, -- 0x0d3e, 0x0d43, -- 0x0d46, 0x0d48, -- 0x0d4a, 0x0d4d, -- 0x0d57, 0x0d57, -- 0x0d60, 0x0d61, -- 0x0d66, 0x0d6f, -- 0x0d82, 0x0d83, -- 0x0d85, 0x0d96, -- 0x0d9a, 0x0db1, -- 0x0db3, 0x0dbb, -- 0x0dbd, 0x0dbd, -- 0x0dc0, 0x0dc6, -- 0x0dca, 0x0dca, -- 0x0dcf, 0x0dd4, -- 0x0dd6, 0x0dd6, -- 0x0dd8, 0x0ddf, -- 0x0df2, 0x0df4, -- 0x0e01, 0x0e3a, -- 0x0e3f, 0x0e5b, -- 0x0e81, 0x0e82, -- 0x0e84, 0x0e84, -- 0x0e87, 0x0e88, -- 0x0e8a, 0x0e8a, -- 0x0e8d, 0x0e8d, -- 0x0e94, 0x0e97, -- 0x0e99, 0x0e9f, -- 0x0ea1, 0x0ea3, -- 0x0ea5, 0x0ea5, -- 0x0ea7, 0x0ea7, -- 0x0eaa, 0x0eab, -- 0x0ead, 0x0eb9, -- 0x0ebb, 0x0ebd, -- 0x0ec0, 0x0ec4, -- 0x0ec6, 0x0ec6, -- 0x0ec8, 0x0ecd, -- 0x0ed0, 0x0ed9, -- 0x0edc, 0x0edd, -- 0x0f00, 0x0f47, -- 0x0f49, 0x0f6a, -- 0x0f71, 0x0f8b, -- 0x0f90, 0x0f97, -- 0x0f99, 0x0fbc, -- 0x0fbe, 0x0fcc, -- 0x0fcf, 0x0fd1, -- 0x1000, 0x1021, -- 0x1023, 0x1027, -- 0x1029, 0x102a, -- 0x102c, 0x1032, -- 0x1036, 0x1039, -- 0x1040, 0x1059, -- 0x10a0, 0x10c5, -- 0x10d0, 0x10fc, -- 0x1100, 0x1159, -- 0x115f, 0x11a2, -- 0x11a8, 0x11f9, -- 0x1200, 0x1248, -- 0x124a, 0x124d, -- 0x1250, 0x1256, -- 0x1258, 0x1258, -- 0x125a, 0x125d, -- 0x1260, 0x1288, -- 0x128a, 0x128d, -- 0x1290, 0x12b0, -- 0x12b2, 0x12b5, -- 0x12b8, 0x12be, -- 0x12c0, 0x12c0, -- 0x12c2, 0x12c5, -- 0x12c8, 0x12d6, -- 0x12d8, 0x1310, -- 0x1312, 0x1315, -- 0x1318, 0x135a, -- 0x135f, 0x137c, -- 0x1380, 0x1399, -- 0x13a0, 0x13f4, -- 0x1401, 0x1676, -- 0x1680, 0x169c, -- 0x16a0, 0x16f0, -- 0x1700, 0x170c, -- 0x170e, 0x1714, -- 0x1720, 0x1736, -- 0x1740, 0x1753, -- 0x1760, 0x176c, -- 0x176e, 0x1770, -- 0x1772, 0x1773, -- 0x1780, 0x17dd, -- 0x17e0, 0x17e9, -- 0x17f0, 0x17f9, -- 0x1800, 0x180e, -- 0x1810, 0x1819, -- 0x1820, 0x1877, -- 0x1880, 0x18a9, -- 0x1900, 0x191c, -- 0x1920, 0x192b, -- 0x1930, 0x193b, -- 0x1940, 0x1940, -- 0x1944, 0x196d, -- 0x1970, 0x1974, -- 0x1980, 0x19a9, -- 0x19b0, 0x19c9, -- 0x19d0, 0x19d9, -- 0x19de, 0x1a1b, -- 0x1a1e, 0x1a1f, -- 0x1d00, 0x1dc3, -- 0x1e00, 0x1e9b, -- 0x1ea0, 0x1ef9, -- 0x1f00, 0x1f15, -- 0x1f18, 0x1f1d, -- 0x1f20, 0x1f45, -- 0x1f48, 0x1f4d, -- 0x1f50, 0x1f57, -- 0x1f59, 0x1f59, -- 0x1f5b, 0x1f5b, -- 0x1f5d, 0x1f5d, -- 0x1f5f, 0x1f7d, -- 0x1f80, 0x1fb4, -- 0x1fb6, 0x1fc4, -- 0x1fc6, 0x1fd3, -- 0x1fd6, 0x1fdb, -- 0x1fdd, 0x1fef, -- 0x1ff2, 0x1ff4, -- 0x1ff6, 0x1ffe, -- 0x2000, 0x2063, -- 0x206a, 0x2071, -- 0x2074, 0x208e, -- 0x2090, 0x2094, -- 0x20a0, 0x20b5, -- 0x20d0, 0x20eb, -- 0x2100, 0x214c, -- 0x2153, 0x2183, -- 0x2190, 0x23db, -- 0x2400, 0x2426, -- 0x2440, 0x244a, -- 0x2460, 0x269c, -- 0x26a0, 0x26b1, -- 0x2701, 0x2704, -- 0x2706, 0x2709, -- 0x270c, 0x2727, -- 0x2729, 0x274b, -- 0x274d, 0x274d, -- 0x274f, 0x2752, -- 0x2756, 0x2756, -- 0x2758, 0x275e, -- 0x2761, 0x2794, -- 0x2798, 0x27af, -- 0x27b1, 0x27be, -- 0x27c0, 0x27c6, -- 0x27d0, 0x27eb, -- 0x27f0, 0x2b13, -- 0x2c00, 0x2c2e, -- 0x2c30, 0x2c5e, -- 0x2c80, 0x2cea, -- 0x2cf9, 0x2d25, -- 0x2d30, 0x2d65, -- 0x2d6f, 0x2d6f, -- 0x2d80, 0x2d96, -- 0x2da0, 0x2da6, -- 0x2da8, 0x2dae, -- 0x2db0, 0x2db6, -- 0x2db8, 0x2dbe, -- 0x2dc0, 0x2dc6, -- 0x2dc8, 0x2dce, -- 0x2dd0, 0x2dd6, -- 0x2dd8, 0x2dde, -- 0x2e00, 0x2e17, -- 0x2e1c, 0x2e1d, -- 0x2e80, 0x2e99, -- 0x2e9b, 0x2ef3, -- 0x2f00, 0x2fd5, -- 0x2ff0, 0x2ffb, -- 0x3000, 0x303f, -- 0x3041, 0x3096, -- 0x3099, 0x30ff, -- 0x3105, 0x312c, -- 0x3131, 0x318e, -- 0x3190, 0x31b7, -- 0x31c0, 0x31cf, -- 0x31f0, 0x321e, -- 0x3220, 0x3243, -- 0x3250, 0x32fe, -- 0x3300, 0x4db5, -- 0x4dc0, 0x9fbb, -- 0xa000, 0xa48c, -- 0xa490, 0xa4c6, -- 0xa700, 0xa716, -- 0xa800, 0xa82b, -- 0xac00, 0xd7a3, -- 0xd800, 0xfa2d, -- 0xfa30, 0xfa6a, -- 0xfa70, 0xfad9, -- 0xfb00, 0xfb06, -- 0xfb13, 0xfb17, -- 0xfb1d, 0xfb36, -- 0xfb38, 0xfb3c, -- 0xfb3e, 0xfb3e, -- 0xfb40, 0xfb41, -- 0xfb43, 0xfb44, -- 0xfb46, 0xfbb1, -- 0xfbd3, 0xfd3f, -- 0xfd50, 0xfd8f, -- 0xfd92, 0xfdc7, -- 0xfdd0, 0xfdfd, -- 0xfe00, 0xfe19, -- 0xfe20, 0xfe23, -- 0xfe30, 0xfe52, -- 0xfe54, 0xfe66, -- 0xfe68, 0xfe6b, -- 0xfe70, 0xfe74, -- 0xfe76, 0xfefc, -- 0xfeff, 0xfeff, -- 0xff01, 0xffbe, -- 0xffc2, 0xffc7, -- 0xffca, 0xffcf, -- 0xffd2, 0xffd7, -- 0xffda, 0xffdc, -- 0xffe0, 0xffe6, -- 0xffe8, 0xffee, -- 0xfff9, 0x1000b, -- 0x1000d, 0x10026, -- 0x10028, 0x1003a, -- 0x1003c, 0x1003d, -- 0x1003f, 0x1004d, -- 0x10050, 0x1005d, -- 0x10080, 0x100fa, -- 0x10100, 0x10102, -- 0x10107, 0x10133, -- 0x10137, 0x1018a, -- 0x10300, 0x1031e, -- 0x10320, 0x10323, -- 0x10330, 0x1034a, -- 0x10380, 0x1039d, -- 0x1039f, 0x103c3, -- 0x103c8, 0x103d5, -- 0x10400, 0x1049d, -- 0x104a0, 0x104a9, -- 0x10800, 0x10805, -- 0x10808, 0x10808, -- 0x1080a, 0x10835, -- 0x10837, 0x10838, -- 0x1083c, 0x1083c, -- 0x1083f, 0x1083f, -- 0x10a00, 0x10a03, -- 0x10a05, 0x10a06, -- 0x10a0c, 0x10a13, -- 0x10a15, 0x10a17, -- 0x10a19, 0x10a33, -- 0x10a38, 0x10a3a, -- 0x10a3f, 0x10a47, -- 0x10a50, 0x10a58, -- 0x1d000, 0x1d0f5, -- 0x1d100, 0x1d126, -- 0x1d12a, 0x1d1dd, -- 0x1d200, 0x1d245, -- 0x1d300, 0x1d356, -- 0x1d400, 0x1d454, -- 0x1d456, 0x1d49c, -- 0x1d49e, 0x1d49f, -- 0x1d4a2, 0x1d4a2, -- 0x1d4a5, 0x1d4a6, -- 0x1d4a9, 0x1d4ac, -- 0x1d4ae, 0x1d4b9, -- 0x1d4bb, 0x1d4bb, -- 0x1d4bd, 0x1d4c3, -- 0x1d4c5, 0x1d505, -- 0x1d507, 0x1d50a, -- 0x1d50d, 0x1d514, -- 0x1d516, 0x1d51c, -- 0x1d51e, 0x1d539, -- 0x1d53b, 0x1d53e, -- 0x1d540, 0x1d544, -- 0x1d546, 0x1d546, -- 0x1d54a, 0x1d550, -- 0x1d552, 0x1d6a5, -- 0x1d6a8, 0x1d7c9, -- 0x1d7ce, 0x1d7ff, -- 0x1fffe, 0x2a6d6, -- 0x2f800, 0x2fa1d, -- 0x2fffe, 0x2ffff, -- 0x3fffe, 0x3ffff, -- 0x4fffe, 0x4ffff, -- 0x5fffe, 0x5ffff, -- 0x6fffe, 0x6ffff, -- 0x7fffe, 0x7ffff, -- 0x8fffe, 0x8ffff, -- 0x9fffe, 0x9ffff, -- 0xafffe, 0xaffff, -- 0xbfffe, 0xbffff, -- 0xcfffe, 0xcffff, -- 0xdfffe, 0xdffff, -- 0xe0001, 0xe0001, -- 0xe0020, 0xe007f, -- 0xe0100, 0xe01ef, -- 0xefffe, 0x10ffff, --}; /* CR_Age_4_1 */ -- --/* 'Age_5_0': Derived Age 5.0 */ --static const OnigCodePoint CR_Age_5_0[] = { -- 440, -- 0x0000, 0x036f, -- 0x0374, 0x0375, -- 0x037a, 0x037e, -- 0x0384, 0x038a, -- 0x038c, 0x038c, -- 0x038e, 0x03a1, -- 0x03a3, 0x03ce, -- 0x03d0, 0x0486, -- 0x0488, 0x0513, -- 0x0531, 0x0556, -- 0x0559, 0x055f, -- 0x0561, 0x0587, -- 0x0589, 0x058a, -- 0x0591, 0x05c7, -- 0x05d0, 0x05ea, -- 0x05f0, 0x05f4, -- 0x0600, 0x0603, -- 0x060b, 0x0615, -- 0x061b, 0x061b, -- 0x061e, 0x061f, -- 0x0621, 0x063a, -- 0x0640, 0x065e, -- 0x0660, 0x070d, -- 0x070f, 0x074a, -- 0x074d, 0x076d, -- 0x0780, 0x07b1, -- 0x07c0, 0x07fa, -- 0x0901, 0x0939, -- 0x093c, 0x094d, -- 0x0950, 0x0954, -- 0x0958, 0x0970, -- 0x097b, 0x097f, -- 0x0981, 0x0983, -- 0x0985, 0x098c, -- 0x098f, 0x0990, -- 0x0993, 0x09a8, -- 0x09aa, 0x09b0, -- 0x09b2, 0x09b2, -- 0x09b6, 0x09b9, -- 0x09bc, 0x09c4, -- 0x09c7, 0x09c8, -- 0x09cb, 0x09ce, -- 0x09d7, 0x09d7, -- 0x09dc, 0x09dd, -- 0x09df, 0x09e3, -- 0x09e6, 0x09fa, -- 0x0a01, 0x0a03, -- 0x0a05, 0x0a0a, -- 0x0a0f, 0x0a10, -- 0x0a13, 0x0a28, -- 0x0a2a, 0x0a30, -- 0x0a32, 0x0a33, -- 0x0a35, 0x0a36, -- 0x0a38, 0x0a39, -- 0x0a3c, 0x0a3c, -- 0x0a3e, 0x0a42, -- 0x0a47, 0x0a48, -- 0x0a4b, 0x0a4d, -- 0x0a59, 0x0a5c, -- 0x0a5e, 0x0a5e, -- 0x0a66, 0x0a74, -- 0x0a81, 0x0a83, -- 0x0a85, 0x0a8d, -- 0x0a8f, 0x0a91, -- 0x0a93, 0x0aa8, -- 0x0aaa, 0x0ab0, -- 0x0ab2, 0x0ab3, -- 0x0ab5, 0x0ab9, -- 0x0abc, 0x0ac5, -- 0x0ac7, 0x0ac9, -- 0x0acb, 0x0acd, -- 0x0ad0, 0x0ad0, -- 0x0ae0, 0x0ae3, -- 0x0ae6, 0x0aef, -- 0x0af1, 0x0af1, -- 0x0b01, 0x0b03, -- 0x0b05, 0x0b0c, -- 0x0b0f, 0x0b10, -- 0x0b13, 0x0b28, -- 0x0b2a, 0x0b30, -- 0x0b32, 0x0b33, -- 0x0b35, 0x0b39, -- 0x0b3c, 0x0b43, -- 0x0b47, 0x0b48, -- 0x0b4b, 0x0b4d, -- 0x0b56, 0x0b57, -- 0x0b5c, 0x0b5d, -- 0x0b5f, 0x0b61, -- 0x0b66, 0x0b71, -- 0x0b82, 0x0b83, -- 0x0b85, 0x0b8a, -- 0x0b8e, 0x0b90, -- 0x0b92, 0x0b95, -- 0x0b99, 0x0b9a, -- 0x0b9c, 0x0b9c, -- 0x0b9e, 0x0b9f, -- 0x0ba3, 0x0ba4, -- 0x0ba8, 0x0baa, -- 0x0bae, 0x0bb9, -- 0x0bbe, 0x0bc2, -- 0x0bc6, 0x0bc8, -- 0x0bca, 0x0bcd, -- 0x0bd7, 0x0bd7, -- 0x0be6, 0x0bfa, -- 0x0c01, 0x0c03, -- 0x0c05, 0x0c0c, -- 0x0c0e, 0x0c10, -- 0x0c12, 0x0c28, -- 0x0c2a, 0x0c33, -- 0x0c35, 0x0c39, -- 0x0c3e, 0x0c44, -- 0x0c46, 0x0c48, -- 0x0c4a, 0x0c4d, -- 0x0c55, 0x0c56, -- 0x0c60, 0x0c61, -- 0x0c66, 0x0c6f, -- 0x0c82, 0x0c83, -- 0x0c85, 0x0c8c, -- 0x0c8e, 0x0c90, -- 0x0c92, 0x0ca8, -- 0x0caa, 0x0cb3, -- 0x0cb5, 0x0cb9, -- 0x0cbc, 0x0cc4, -- 0x0cc6, 0x0cc8, -- 0x0cca, 0x0ccd, -- 0x0cd5, 0x0cd6, -- 0x0cde, 0x0cde, -- 0x0ce0, 0x0ce3, -- 0x0ce6, 0x0cef, -- 0x0cf1, 0x0cf2, -- 0x0d02, 0x0d03, -- 0x0d05, 0x0d0c, -- 0x0d0e, 0x0d10, -- 0x0d12, 0x0d28, -- 0x0d2a, 0x0d39, -- 0x0d3e, 0x0d43, -- 0x0d46, 0x0d48, -- 0x0d4a, 0x0d4d, -- 0x0d57, 0x0d57, -- 0x0d60, 0x0d61, -- 0x0d66, 0x0d6f, -- 0x0d82, 0x0d83, -- 0x0d85, 0x0d96, -- 0x0d9a, 0x0db1, -- 0x0db3, 0x0dbb, -- 0x0dbd, 0x0dbd, -- 0x0dc0, 0x0dc6, -- 0x0dca, 0x0dca, -- 0x0dcf, 0x0dd4, -- 0x0dd6, 0x0dd6, -- 0x0dd8, 0x0ddf, -- 0x0df2, 0x0df4, -- 0x0e01, 0x0e3a, -- 0x0e3f, 0x0e5b, -- 0x0e81, 0x0e82, -- 0x0e84, 0x0e84, -- 0x0e87, 0x0e88, -- 0x0e8a, 0x0e8a, -- 0x0e8d, 0x0e8d, -- 0x0e94, 0x0e97, -- 0x0e99, 0x0e9f, -- 0x0ea1, 0x0ea3, -- 0x0ea5, 0x0ea5, -- 0x0ea7, 0x0ea7, -- 0x0eaa, 0x0eab, -- 0x0ead, 0x0eb9, -- 0x0ebb, 0x0ebd, -- 0x0ec0, 0x0ec4, -- 0x0ec6, 0x0ec6, -- 0x0ec8, 0x0ecd, -- 0x0ed0, 0x0ed9, -- 0x0edc, 0x0edd, -- 0x0f00, 0x0f47, -- 0x0f49, 0x0f6a, -- 0x0f71, 0x0f8b, -- 0x0f90, 0x0f97, -- 0x0f99, 0x0fbc, -- 0x0fbe, 0x0fcc, -- 0x0fcf, 0x0fd1, -- 0x1000, 0x1021, -- 0x1023, 0x1027, -- 0x1029, 0x102a, -- 0x102c, 0x1032, -- 0x1036, 0x1039, -- 0x1040, 0x1059, -- 0x10a0, 0x10c5, -- 0x10d0, 0x10fc, -- 0x1100, 0x1159, -- 0x115f, 0x11a2, -- 0x11a8, 0x11f9, -- 0x1200, 0x1248, -- 0x124a, 0x124d, -- 0x1250, 0x1256, -- 0x1258, 0x1258, -- 0x125a, 0x125d, -- 0x1260, 0x1288, -- 0x128a, 0x128d, -- 0x1290, 0x12b0, -- 0x12b2, 0x12b5, -- 0x12b8, 0x12be, -- 0x12c0, 0x12c0, -- 0x12c2, 0x12c5, -- 0x12c8, 0x12d6, -- 0x12d8, 0x1310, -- 0x1312, 0x1315, -- 0x1318, 0x135a, -- 0x135f, 0x137c, -- 0x1380, 0x1399, -- 0x13a0, 0x13f4, -- 0x1401, 0x1676, -- 0x1680, 0x169c, -- 0x16a0, 0x16f0, -- 0x1700, 0x170c, -- 0x170e, 0x1714, -- 0x1720, 0x1736, -- 0x1740, 0x1753, -- 0x1760, 0x176c, -- 0x176e, 0x1770, -- 0x1772, 0x1773, -- 0x1780, 0x17dd, -- 0x17e0, 0x17e9, -- 0x17f0, 0x17f9, -- 0x1800, 0x180e, -- 0x1810, 0x1819, -- 0x1820, 0x1877, -- 0x1880, 0x18a9, -- 0x1900, 0x191c, -- 0x1920, 0x192b, -- 0x1930, 0x193b, -- 0x1940, 0x1940, -- 0x1944, 0x196d, -- 0x1970, 0x1974, -- 0x1980, 0x19a9, -- 0x19b0, 0x19c9, -- 0x19d0, 0x19d9, -- 0x19de, 0x1a1b, -- 0x1a1e, 0x1a1f, -- 0x1b00, 0x1b4b, -- 0x1b50, 0x1b7c, -- 0x1d00, 0x1dca, -- 0x1dfe, 0x1e9b, -- 0x1ea0, 0x1ef9, -- 0x1f00, 0x1f15, -- 0x1f18, 0x1f1d, -- 0x1f20, 0x1f45, -- 0x1f48, 0x1f4d, -- 0x1f50, 0x1f57, -- 0x1f59, 0x1f59, -- 0x1f5b, 0x1f5b, -- 0x1f5d, 0x1f5d, -- 0x1f5f, 0x1f7d, -- 0x1f80, 0x1fb4, -- 0x1fb6, 0x1fc4, -- 0x1fc6, 0x1fd3, -- 0x1fd6, 0x1fdb, -- 0x1fdd, 0x1fef, -- 0x1ff2, 0x1ff4, -- 0x1ff6, 0x1ffe, -- 0x2000, 0x2063, -- 0x206a, 0x2071, -- 0x2074, 0x208e, -- 0x2090, 0x2094, -- 0x20a0, 0x20b5, -- 0x20d0, 0x20ef, -- 0x2100, 0x214e, -- 0x2153, 0x2184, -- 0x2190, 0x23e7, -- 0x2400, 0x2426, -- 0x2440, 0x244a, -- 0x2460, 0x269c, -- 0x26a0, 0x26b2, -- 0x2701, 0x2704, -- 0x2706, 0x2709, -- 0x270c, 0x2727, -- 0x2729, 0x274b, -- 0x274d, 0x274d, -- 0x274f, 0x2752, -- 0x2756, 0x2756, -- 0x2758, 0x275e, -- 0x2761, 0x2794, -- 0x2798, 0x27af, -- 0x27b1, 0x27be, -- 0x27c0, 0x27ca, -- 0x27d0, 0x27eb, -- 0x27f0, 0x2b1a, -- 0x2b20, 0x2b23, -- 0x2c00, 0x2c2e, -- 0x2c30, 0x2c5e, -- 0x2c60, 0x2c6c, -- 0x2c74, 0x2c77, -- 0x2c80, 0x2cea, -- 0x2cf9, 0x2d25, -- 0x2d30, 0x2d65, -- 0x2d6f, 0x2d6f, -- 0x2d80, 0x2d96, -- 0x2da0, 0x2da6, -- 0x2da8, 0x2dae, -- 0x2db0, 0x2db6, -- 0x2db8, 0x2dbe, -- 0x2dc0, 0x2dc6, -- 0x2dc8, 0x2dce, -- 0x2dd0, 0x2dd6, -- 0x2dd8, 0x2dde, -- 0x2e00, 0x2e17, -- 0x2e1c, 0x2e1d, -- 0x2e80, 0x2e99, -- 0x2e9b, 0x2ef3, -- 0x2f00, 0x2fd5, -- 0x2ff0, 0x2ffb, -- 0x3000, 0x303f, -- 0x3041, 0x3096, -- 0x3099, 0x30ff, -- 0x3105, 0x312c, -- 0x3131, 0x318e, -- 0x3190, 0x31b7, -- 0x31c0, 0x31cf, -- 0x31f0, 0x321e, -- 0x3220, 0x3243, -- 0x3250, 0x32fe, -- 0x3300, 0x4db5, -- 0x4dc0, 0x9fbb, -- 0xa000, 0xa48c, -- 0xa490, 0xa4c6, -- 0xa700, 0xa71a, -- 0xa720, 0xa721, -- 0xa800, 0xa82b, -- 0xa840, 0xa877, -- 0xac00, 0xd7a3, -- 0xd800, 0xfa2d, -- 0xfa30, 0xfa6a, -- 0xfa70, 0xfad9, -- 0xfb00, 0xfb06, -- 0xfb13, 0xfb17, -- 0xfb1d, 0xfb36, -- 0xfb38, 0xfb3c, -- 0xfb3e, 0xfb3e, -- 0xfb40, 0xfb41, -- 0xfb43, 0xfb44, -- 0xfb46, 0xfbb1, -- 0xfbd3, 0xfd3f, -- 0xfd50, 0xfd8f, -- 0xfd92, 0xfdc7, -- 0xfdd0, 0xfdfd, -- 0xfe00, 0xfe19, -- 0xfe20, 0xfe23, -- 0xfe30, 0xfe52, -- 0xfe54, 0xfe66, -- 0xfe68, 0xfe6b, -- 0xfe70, 0xfe74, -- 0xfe76, 0xfefc, -- 0xfeff, 0xfeff, -- 0xff01, 0xffbe, -- 0xffc2, 0xffc7, -- 0xffca, 0xffcf, -- 0xffd2, 0xffd7, -- 0xffda, 0xffdc, -- 0xffe0, 0xffe6, -- 0xffe8, 0xffee, -- 0xfff9, 0x1000b, -- 0x1000d, 0x10026, -- 0x10028, 0x1003a, -- 0x1003c, 0x1003d, -- 0x1003f, 0x1004d, -- 0x10050, 0x1005d, -- 0x10080, 0x100fa, -- 0x10100, 0x10102, -- 0x10107, 0x10133, -- 0x10137, 0x1018a, -- 0x10300, 0x1031e, -- 0x10320, 0x10323, -- 0x10330, 0x1034a, -- 0x10380, 0x1039d, -- 0x1039f, 0x103c3, -- 0x103c8, 0x103d5, -- 0x10400, 0x1049d, -- 0x104a0, 0x104a9, -- 0x10800, 0x10805, -- 0x10808, 0x10808, -- 0x1080a, 0x10835, -- 0x10837, 0x10838, -- 0x1083c, 0x1083c, -- 0x1083f, 0x1083f, -- 0x10900, 0x10919, -- 0x1091f, 0x1091f, -- 0x10a00, 0x10a03, -- 0x10a05, 0x10a06, -- 0x10a0c, 0x10a13, -- 0x10a15, 0x10a17, -- 0x10a19, 0x10a33, -- 0x10a38, 0x10a3a, -- 0x10a3f, 0x10a47, -- 0x10a50, 0x10a58, -- 0x12000, 0x1236e, -- 0x12400, 0x12462, -- 0x12470, 0x12473, -- 0x1d000, 0x1d0f5, -- 0x1d100, 0x1d126, -- 0x1d12a, 0x1d1dd, -- 0x1d200, 0x1d245, -- 0x1d300, 0x1d356, -- 0x1d360, 0x1d371, -- 0x1d400, 0x1d454, -- 0x1d456, 0x1d49c, -- 0x1d49e, 0x1d49f, -- 0x1d4a2, 0x1d4a2, -- 0x1d4a5, 0x1d4a6, -- 0x1d4a9, 0x1d4ac, -- 0x1d4ae, 0x1d4b9, -- 0x1d4bb, 0x1d4bb, -- 0x1d4bd, 0x1d4c3, -- 0x1d4c5, 0x1d505, -- 0x1d507, 0x1d50a, -- 0x1d50d, 0x1d514, -- 0x1d516, 0x1d51c, -- 0x1d51e, 0x1d539, -- 0x1d53b, 0x1d53e, -- 0x1d540, 0x1d544, -- 0x1d546, 0x1d546, -- 0x1d54a, 0x1d550, -- 0x1d552, 0x1d6a5, -- 0x1d6a8, 0x1d7cb, -- 0x1d7ce, 0x1d7ff, -- 0x1fffe, 0x2a6d6, -- 0x2f800, 0x2fa1d, -- 0x2fffe, 0x2ffff, -- 0x3fffe, 0x3ffff, -- 0x4fffe, 0x4ffff, -- 0x5fffe, 0x5ffff, -- 0x6fffe, 0x6ffff, -- 0x7fffe, 0x7ffff, -- 0x8fffe, 0x8ffff, -- 0x9fffe, 0x9ffff, -- 0xafffe, 0xaffff, -- 0xbfffe, 0xbffff, -- 0xcfffe, 0xcffff, -- 0xdfffe, 0xdffff, -- 0xe0001, 0xe0001, -- 0xe0020, 0xe007f, -- 0xe0100, 0xe01ef, -- 0xefffe, 0x10ffff, --}; /* CR_Age_5_0 */ -- --/* 'Age_5_1': Derived Age 5.1 */ --static const OnigCodePoint CR_Age_5_1[] = { -- 455, -- 0x0000, 0x0377, -- 0x037a, 0x037e, -- 0x0384, 0x038a, -- 0x038c, 0x038c, -- 0x038e, 0x03a1, -- 0x03a3, 0x0523, -- 0x0531, 0x0556, -- 0x0559, 0x055f, -- 0x0561, 0x0587, -- 0x0589, 0x058a, -- 0x0591, 0x05c7, -- 0x05d0, 0x05ea, -- 0x05f0, 0x05f4, -- 0x0600, 0x0603, -- 0x0606, 0x061b, -- 0x061e, 0x061f, -- 0x0621, 0x065e, -- 0x0660, 0x070d, -- 0x070f, 0x074a, -- 0x074d, 0x07b1, -- 0x07c0, 0x07fa, -- 0x0901, 0x0939, -- 0x093c, 0x094d, -- 0x0950, 0x0954, -- 0x0958, 0x0972, -- 0x097b, 0x097f, -- 0x0981, 0x0983, -- 0x0985, 0x098c, -- 0x098f, 0x0990, -- 0x0993, 0x09a8, -- 0x09aa, 0x09b0, -- 0x09b2, 0x09b2, -- 0x09b6, 0x09b9, -- 0x09bc, 0x09c4, -- 0x09c7, 0x09c8, -- 0x09cb, 0x09ce, -- 0x09d7, 0x09d7, -- 0x09dc, 0x09dd, -- 0x09df, 0x09e3, -- 0x09e6, 0x09fa, -- 0x0a01, 0x0a03, -- 0x0a05, 0x0a0a, -- 0x0a0f, 0x0a10, -- 0x0a13, 0x0a28, -- 0x0a2a, 0x0a30, -- 0x0a32, 0x0a33, -- 0x0a35, 0x0a36, -- 0x0a38, 0x0a39, -- 0x0a3c, 0x0a3c, -- 0x0a3e, 0x0a42, -- 0x0a47, 0x0a48, -- 0x0a4b, 0x0a4d, -- 0x0a51, 0x0a51, -- 0x0a59, 0x0a5c, -- 0x0a5e, 0x0a5e, -- 0x0a66, 0x0a75, -- 0x0a81, 0x0a83, -- 0x0a85, 0x0a8d, -- 0x0a8f, 0x0a91, -- 0x0a93, 0x0aa8, -- 0x0aaa, 0x0ab0, -- 0x0ab2, 0x0ab3, -- 0x0ab5, 0x0ab9, -- 0x0abc, 0x0ac5, -- 0x0ac7, 0x0ac9, -- 0x0acb, 0x0acd, -- 0x0ad0, 0x0ad0, -- 0x0ae0, 0x0ae3, -- 0x0ae6, 0x0aef, -- 0x0af1, 0x0af1, -- 0x0b01, 0x0b03, -- 0x0b05, 0x0b0c, -- 0x0b0f, 0x0b10, -- 0x0b13, 0x0b28, -- 0x0b2a, 0x0b30, -- 0x0b32, 0x0b33, -- 0x0b35, 0x0b39, -- 0x0b3c, 0x0b44, -- 0x0b47, 0x0b48, -- 0x0b4b, 0x0b4d, -- 0x0b56, 0x0b57, -- 0x0b5c, 0x0b5d, -- 0x0b5f, 0x0b63, -- 0x0b66, 0x0b71, -- 0x0b82, 0x0b83, -- 0x0b85, 0x0b8a, -- 0x0b8e, 0x0b90, -- 0x0b92, 0x0b95, -- 0x0b99, 0x0b9a, -- 0x0b9c, 0x0b9c, -- 0x0b9e, 0x0b9f, -- 0x0ba3, 0x0ba4, -- 0x0ba8, 0x0baa, -- 0x0bae, 0x0bb9, -- 0x0bbe, 0x0bc2, -- 0x0bc6, 0x0bc8, -- 0x0bca, 0x0bcd, -- 0x0bd0, 0x0bd0, -- 0x0bd7, 0x0bd7, -- 0x0be6, 0x0bfa, -- 0x0c01, 0x0c03, -- 0x0c05, 0x0c0c, -- 0x0c0e, 0x0c10, -- 0x0c12, 0x0c28, -- 0x0c2a, 0x0c33, -- 0x0c35, 0x0c39, -- 0x0c3d, 0x0c44, -- 0x0c46, 0x0c48, -- 0x0c4a, 0x0c4d, -- 0x0c55, 0x0c56, -- 0x0c58, 0x0c59, -- 0x0c60, 0x0c63, -- 0x0c66, 0x0c6f, -- 0x0c78, 0x0c7f, -- 0x0c82, 0x0c83, -- 0x0c85, 0x0c8c, -- 0x0c8e, 0x0c90, -- 0x0c92, 0x0ca8, -- 0x0caa, 0x0cb3, -- 0x0cb5, 0x0cb9, -- 0x0cbc, 0x0cc4, -- 0x0cc6, 0x0cc8, -- 0x0cca, 0x0ccd, -- 0x0cd5, 0x0cd6, -- 0x0cde, 0x0cde, -- 0x0ce0, 0x0ce3, -- 0x0ce6, 0x0cef, -- 0x0cf1, 0x0cf2, -- 0x0d02, 0x0d03, -- 0x0d05, 0x0d0c, -- 0x0d0e, 0x0d10, -- 0x0d12, 0x0d28, -- 0x0d2a, 0x0d39, -- 0x0d3d, 0x0d44, -- 0x0d46, 0x0d48, -- 0x0d4a, 0x0d4d, -- 0x0d57, 0x0d57, -- 0x0d60, 0x0d63, -- 0x0d66, 0x0d75, -- 0x0d79, 0x0d7f, -- 0x0d82, 0x0d83, -- 0x0d85, 0x0d96, -- 0x0d9a, 0x0db1, -- 0x0db3, 0x0dbb, -- 0x0dbd, 0x0dbd, -- 0x0dc0, 0x0dc6, -- 0x0dca, 0x0dca, -- 0x0dcf, 0x0dd4, -- 0x0dd6, 0x0dd6, -- 0x0dd8, 0x0ddf, -- 0x0df2, 0x0df4, -- 0x0e01, 0x0e3a, -- 0x0e3f, 0x0e5b, -- 0x0e81, 0x0e82, -- 0x0e84, 0x0e84, -- 0x0e87, 0x0e88, -- 0x0e8a, 0x0e8a, -- 0x0e8d, 0x0e8d, -- 0x0e94, 0x0e97, -- 0x0e99, 0x0e9f, -- 0x0ea1, 0x0ea3, -- 0x0ea5, 0x0ea5, -- 0x0ea7, 0x0ea7, -- 0x0eaa, 0x0eab, -- 0x0ead, 0x0eb9, -- 0x0ebb, 0x0ebd, -- 0x0ec0, 0x0ec4, -- 0x0ec6, 0x0ec6, -- 0x0ec8, 0x0ecd, -- 0x0ed0, 0x0ed9, -- 0x0edc, 0x0edd, -- 0x0f00, 0x0f47, -- 0x0f49, 0x0f6c, -- 0x0f71, 0x0f8b, -- 0x0f90, 0x0f97, -- 0x0f99, 0x0fbc, -- 0x0fbe, 0x0fcc, -- 0x0fce, 0x0fd4, -- 0x1000, 0x1099, -- 0x109e, 0x10c5, -- 0x10d0, 0x10fc, -- 0x1100, 0x1159, -- 0x115f, 0x11a2, -- 0x11a8, 0x11f9, -- 0x1200, 0x1248, -- 0x124a, 0x124d, -- 0x1250, 0x1256, -- 0x1258, 0x1258, -- 0x125a, 0x125d, -- 0x1260, 0x1288, -- 0x128a, 0x128d, -- 0x1290, 0x12b0, -- 0x12b2, 0x12b5, -- 0x12b8, 0x12be, -- 0x12c0, 0x12c0, -- 0x12c2, 0x12c5, -- 0x12c8, 0x12d6, -- 0x12d8, 0x1310, -- 0x1312, 0x1315, -- 0x1318, 0x135a, -- 0x135f, 0x137c, -- 0x1380, 0x1399, -- 0x13a0, 0x13f4, -- 0x1401, 0x1676, -- 0x1680, 0x169c, -- 0x16a0, 0x16f0, -- 0x1700, 0x170c, -- 0x170e, 0x1714, -- 0x1720, 0x1736, -- 0x1740, 0x1753, -- 0x1760, 0x176c, -- 0x176e, 0x1770, -- 0x1772, 0x1773, -- 0x1780, 0x17dd, -- 0x17e0, 0x17e9, -- 0x17f0, 0x17f9, -- 0x1800, 0x180e, -- 0x1810, 0x1819, -- 0x1820, 0x1877, -- 0x1880, 0x18aa, -- 0x1900, 0x191c, -- 0x1920, 0x192b, -- 0x1930, 0x193b, -- 0x1940, 0x1940, -- 0x1944, 0x196d, -- 0x1970, 0x1974, -- 0x1980, 0x19a9, -- 0x19b0, 0x19c9, -- 0x19d0, 0x19d9, -- 0x19de, 0x1a1b, -- 0x1a1e, 0x1a1f, -- 0x1b00, 0x1b4b, -- 0x1b50, 0x1b7c, -- 0x1b80, 0x1baa, -- 0x1bae, 0x1bb9, -- 0x1c00, 0x1c37, -- 0x1c3b, 0x1c49, -- 0x1c4d, 0x1c7f, -- 0x1d00, 0x1de6, -- 0x1dfe, 0x1f15, -- 0x1f18, 0x1f1d, -- 0x1f20, 0x1f45, -- 0x1f48, 0x1f4d, -- 0x1f50, 0x1f57, -- 0x1f59, 0x1f59, -- 0x1f5b, 0x1f5b, -- 0x1f5d, 0x1f5d, -- 0x1f5f, 0x1f7d, -- 0x1f80, 0x1fb4, -- 0x1fb6, 0x1fc4, -- 0x1fc6, 0x1fd3, -- 0x1fd6, 0x1fdb, -- 0x1fdd, 0x1fef, -- 0x1ff2, 0x1ff4, -- 0x1ff6, 0x1ffe, -- 0x2000, 0x2064, -- 0x206a, 0x2071, -- 0x2074, 0x208e, -- 0x2090, 0x2094, -- 0x20a0, 0x20b5, -- 0x20d0, 0x20f0, -- 0x2100, 0x214f, -- 0x2153, 0x2188, -- 0x2190, 0x23e7, -- 0x2400, 0x2426, -- 0x2440, 0x244a, -- 0x2460, 0x269d, -- 0x26a0, 0x26bc, -- 0x26c0, 0x26c3, -- 0x2701, 0x2704, -- 0x2706, 0x2709, -- 0x270c, 0x2727, -- 0x2729, 0x274b, -- 0x274d, 0x274d, -- 0x274f, 0x2752, -- 0x2756, 0x2756, -- 0x2758, 0x275e, -- 0x2761, 0x2794, -- 0x2798, 0x27af, -- 0x27b1, 0x27be, -- 0x27c0, 0x27ca, -- 0x27cc, 0x27cc, -- 0x27d0, 0x2b4c, -- 0x2b50, 0x2b54, -- 0x2c00, 0x2c2e, -- 0x2c30, 0x2c5e, -- 0x2c60, 0x2c6f, -- 0x2c71, 0x2c7d, -- 0x2c80, 0x2cea, -- 0x2cf9, 0x2d25, -- 0x2d30, 0x2d65, -- 0x2d6f, 0x2d6f, -- 0x2d80, 0x2d96, -- 0x2da0, 0x2da6, -- 0x2da8, 0x2dae, -- 0x2db0, 0x2db6, -- 0x2db8, 0x2dbe, -- 0x2dc0, 0x2dc6, -- 0x2dc8, 0x2dce, -- 0x2dd0, 0x2dd6, -- 0x2dd8, 0x2dde, -- 0x2de0, 0x2e30, -- 0x2e80, 0x2e99, -- 0x2e9b, 0x2ef3, -- 0x2f00, 0x2fd5, -- 0x2ff0, 0x2ffb, -- 0x3000, 0x303f, -- 0x3041, 0x3096, -- 0x3099, 0x30ff, -- 0x3105, 0x312d, -- 0x3131, 0x318e, -- 0x3190, 0x31b7, -- 0x31c0, 0x31e3, -- 0x31f0, 0x321e, -- 0x3220, 0x3243, -- 0x3250, 0x32fe, -- 0x3300, 0x4db5, -- 0x4dc0, 0x9fc3, -- 0xa000, 0xa48c, -- 0xa490, 0xa4c6, -- 0xa500, 0xa62b, -- 0xa640, 0xa65f, -- 0xa662, 0xa673, -- 0xa67c, 0xa697, -- 0xa700, 0xa78c, -- 0xa7fb, 0xa82b, -- 0xa840, 0xa877, -- 0xa880, 0xa8c4, -- 0xa8ce, 0xa8d9, -- 0xa900, 0xa953, -- 0xa95f, 0xa95f, -- 0xaa00, 0xaa36, -- 0xaa40, 0xaa4d, -- 0xaa50, 0xaa59, -- 0xaa5c, 0xaa5f, -- 0xac00, 0xd7a3, -- 0xd800, 0xfa2d, -- 0xfa30, 0xfa6a, -- 0xfa70, 0xfad9, -- 0xfb00, 0xfb06, -- 0xfb13, 0xfb17, -- 0xfb1d, 0xfb36, -- 0xfb38, 0xfb3c, -- 0xfb3e, 0xfb3e, -- 0xfb40, 0xfb41, -- 0xfb43, 0xfb44, -- 0xfb46, 0xfbb1, -- 0xfbd3, 0xfd3f, -- 0xfd50, 0xfd8f, -- 0xfd92, 0xfdc7, -- 0xfdd0, 0xfdfd, -- 0xfe00, 0xfe19, -- 0xfe20, 0xfe26, -- 0xfe30, 0xfe52, -- 0xfe54, 0xfe66, -- 0xfe68, 0xfe6b, -- 0xfe70, 0xfe74, -- 0xfe76, 0xfefc, -- 0xfeff, 0xfeff, -- 0xff01, 0xffbe, -- 0xffc2, 0xffc7, -- 0xffca, 0xffcf, -- 0xffd2, 0xffd7, -- 0xffda, 0xffdc, -- 0xffe0, 0xffe6, -- 0xffe8, 0xffee, -- 0xfff9, 0x1000b, -- 0x1000d, 0x10026, -- 0x10028, 0x1003a, -- 0x1003c, 0x1003d, -- 0x1003f, 0x1004d, -- 0x10050, 0x1005d, -- 0x10080, 0x100fa, -- 0x10100, 0x10102, -- 0x10107, 0x10133, -- 0x10137, 0x1018a, -- 0x10190, 0x1019b, -- 0x101d0, 0x101fd, -- 0x10280, 0x1029c, -- 0x102a0, 0x102d0, -- 0x10300, 0x1031e, -- 0x10320, 0x10323, -- 0x10330, 0x1034a, -- 0x10380, 0x1039d, -- 0x1039f, 0x103c3, -- 0x103c8, 0x103d5, -- 0x10400, 0x1049d, -- 0x104a0, 0x104a9, -- 0x10800, 0x10805, -- 0x10808, 0x10808, -- 0x1080a, 0x10835, -- 0x10837, 0x10838, -- 0x1083c, 0x1083c, -- 0x1083f, 0x1083f, -- 0x10900, 0x10919, -- 0x1091f, 0x10939, -- 0x1093f, 0x1093f, -- 0x10a00, 0x10a03, -- 0x10a05, 0x10a06, -- 0x10a0c, 0x10a13, -- 0x10a15, 0x10a17, -- 0x10a19, 0x10a33, -- 0x10a38, 0x10a3a, -- 0x10a3f, 0x10a47, -- 0x10a50, 0x10a58, -- 0x12000, 0x1236e, -- 0x12400, 0x12462, -- 0x12470, 0x12473, -- 0x1d000, 0x1d0f5, -- 0x1d100, 0x1d126, -- 0x1d129, 0x1d1dd, -- 0x1d200, 0x1d245, -- 0x1d300, 0x1d356, -- 0x1d360, 0x1d371, -- 0x1d400, 0x1d454, -- 0x1d456, 0x1d49c, -- 0x1d49e, 0x1d49f, -- 0x1d4a2, 0x1d4a2, -- 0x1d4a5, 0x1d4a6, -- 0x1d4a9, 0x1d4ac, -- 0x1d4ae, 0x1d4b9, -- 0x1d4bb, 0x1d4bb, -- 0x1d4bd, 0x1d4c3, -- 0x1d4c5, 0x1d505, -- 0x1d507, 0x1d50a, -- 0x1d50d, 0x1d514, -- 0x1d516, 0x1d51c, -- 0x1d51e, 0x1d539, -- 0x1d53b, 0x1d53e, -- 0x1d540, 0x1d544, -- 0x1d546, 0x1d546, -- 0x1d54a, 0x1d550, -- 0x1d552, 0x1d6a5, -- 0x1d6a8, 0x1d7cb, -- 0x1d7ce, 0x1d7ff, -- 0x1f000, 0x1f02b, -- 0x1f030, 0x1f093, -- 0x1fffe, 0x2a6d6, -- 0x2f800, 0x2fa1d, -- 0x2fffe, 0x2ffff, -- 0x3fffe, 0x3ffff, -- 0x4fffe, 0x4ffff, -- 0x5fffe, 0x5ffff, -- 0x6fffe, 0x6ffff, -- 0x7fffe, 0x7ffff, -- 0x8fffe, 0x8ffff, -- 0x9fffe, 0x9ffff, -- 0xafffe, 0xaffff, -- 0xbfffe, 0xbffff, -- 0xcfffe, 0xcffff, -- 0xdfffe, 0xdffff, -- 0xe0001, 0xe0001, -- 0xe0020, 0xe007f, -- 0xe0100, 0xe01ef, -- 0xefffe, 0x10ffff, --}; /* CR_Age_5_1 */ -- --/* 'Age_5_2': Derived Age 5.2 */ --static const OnigCodePoint CR_Age_5_2[] = { -- 495, -- 0x0000, 0x0377, -- 0x037a, 0x037e, -- 0x0384, 0x038a, -- 0x038c, 0x038c, -- 0x038e, 0x03a1, -- 0x03a3, 0x0525, -- 0x0531, 0x0556, -- 0x0559, 0x055f, -- 0x0561, 0x0587, -- 0x0589, 0x058a, -- 0x0591, 0x05c7, -- 0x05d0, 0x05ea, -- 0x05f0, 0x05f4, -- 0x0600, 0x0603, -- 0x0606, 0x061b, -- 0x061e, 0x061f, -- 0x0621, 0x065e, -- 0x0660, 0x070d, -- 0x070f, 0x074a, -- 0x074d, 0x07b1, -- 0x07c0, 0x07fa, -- 0x0800, 0x082d, -- 0x0830, 0x083e, -- 0x0900, 0x0939, -- 0x093c, 0x094e, -- 0x0950, 0x0955, -- 0x0958, 0x0972, -- 0x0979, 0x097f, -- 0x0981, 0x0983, -- 0x0985, 0x098c, -- 0x098f, 0x0990, -- 0x0993, 0x09a8, -- 0x09aa, 0x09b0, -- 0x09b2, 0x09b2, -- 0x09b6, 0x09b9, -- 0x09bc, 0x09c4, -- 0x09c7, 0x09c8, -- 0x09cb, 0x09ce, -- 0x09d7, 0x09d7, -- 0x09dc, 0x09dd, -- 0x09df, 0x09e3, -- 0x09e6, 0x09fb, -- 0x0a01, 0x0a03, -- 0x0a05, 0x0a0a, -- 0x0a0f, 0x0a10, -- 0x0a13, 0x0a28, -- 0x0a2a, 0x0a30, -- 0x0a32, 0x0a33, -- 0x0a35, 0x0a36, -- 0x0a38, 0x0a39, -- 0x0a3c, 0x0a3c, -- 0x0a3e, 0x0a42, -- 0x0a47, 0x0a48, -- 0x0a4b, 0x0a4d, -- 0x0a51, 0x0a51, -- 0x0a59, 0x0a5c, -- 0x0a5e, 0x0a5e, -- 0x0a66, 0x0a75, -- 0x0a81, 0x0a83, -- 0x0a85, 0x0a8d, -- 0x0a8f, 0x0a91, -- 0x0a93, 0x0aa8, -- 0x0aaa, 0x0ab0, -- 0x0ab2, 0x0ab3, -- 0x0ab5, 0x0ab9, -- 0x0abc, 0x0ac5, -- 0x0ac7, 0x0ac9, -- 0x0acb, 0x0acd, -- 0x0ad0, 0x0ad0, -- 0x0ae0, 0x0ae3, -- 0x0ae6, 0x0aef, -- 0x0af1, 0x0af1, -- 0x0b01, 0x0b03, -- 0x0b05, 0x0b0c, -- 0x0b0f, 0x0b10, -- 0x0b13, 0x0b28, -- 0x0b2a, 0x0b30, -- 0x0b32, 0x0b33, -- 0x0b35, 0x0b39, -- 0x0b3c, 0x0b44, -- 0x0b47, 0x0b48, -- 0x0b4b, 0x0b4d, -- 0x0b56, 0x0b57, -- 0x0b5c, 0x0b5d, -- 0x0b5f, 0x0b63, -- 0x0b66, 0x0b71, -- 0x0b82, 0x0b83, -- 0x0b85, 0x0b8a, -- 0x0b8e, 0x0b90, -- 0x0b92, 0x0b95, -- 0x0b99, 0x0b9a, -- 0x0b9c, 0x0b9c, -- 0x0b9e, 0x0b9f, -- 0x0ba3, 0x0ba4, -- 0x0ba8, 0x0baa, -- 0x0bae, 0x0bb9, -- 0x0bbe, 0x0bc2, -- 0x0bc6, 0x0bc8, -- 0x0bca, 0x0bcd, -- 0x0bd0, 0x0bd0, -- 0x0bd7, 0x0bd7, -- 0x0be6, 0x0bfa, -- 0x0c01, 0x0c03, -- 0x0c05, 0x0c0c, -- 0x0c0e, 0x0c10, -- 0x0c12, 0x0c28, -- 0x0c2a, 0x0c33, -- 0x0c35, 0x0c39, -- 0x0c3d, 0x0c44, -- 0x0c46, 0x0c48, -- 0x0c4a, 0x0c4d, -- 0x0c55, 0x0c56, -- 0x0c58, 0x0c59, -- 0x0c60, 0x0c63, -- 0x0c66, 0x0c6f, -- 0x0c78, 0x0c7f, -- 0x0c82, 0x0c83, -- 0x0c85, 0x0c8c, -- 0x0c8e, 0x0c90, -- 0x0c92, 0x0ca8, -- 0x0caa, 0x0cb3, -- 0x0cb5, 0x0cb9, -- 0x0cbc, 0x0cc4, -- 0x0cc6, 0x0cc8, -- 0x0cca, 0x0ccd, -- 0x0cd5, 0x0cd6, -- 0x0cde, 0x0cde, -- 0x0ce0, 0x0ce3, -- 0x0ce6, 0x0cef, -- 0x0cf1, 0x0cf2, -- 0x0d02, 0x0d03, -- 0x0d05, 0x0d0c, -- 0x0d0e, 0x0d10, -- 0x0d12, 0x0d28, -- 0x0d2a, 0x0d39, -- 0x0d3d, 0x0d44, -- 0x0d46, 0x0d48, -- 0x0d4a, 0x0d4d, -- 0x0d57, 0x0d57, -- 0x0d60, 0x0d63, -- 0x0d66, 0x0d75, -- 0x0d79, 0x0d7f, -- 0x0d82, 0x0d83, -- 0x0d85, 0x0d96, -- 0x0d9a, 0x0db1, -- 0x0db3, 0x0dbb, -- 0x0dbd, 0x0dbd, -- 0x0dc0, 0x0dc6, -- 0x0dca, 0x0dca, -- 0x0dcf, 0x0dd4, -- 0x0dd6, 0x0dd6, -- 0x0dd8, 0x0ddf, -- 0x0df2, 0x0df4, -- 0x0e01, 0x0e3a, -- 0x0e3f, 0x0e5b, -- 0x0e81, 0x0e82, -- 0x0e84, 0x0e84, -- 0x0e87, 0x0e88, -- 0x0e8a, 0x0e8a, -- 0x0e8d, 0x0e8d, -- 0x0e94, 0x0e97, -- 0x0e99, 0x0e9f, -- 0x0ea1, 0x0ea3, -- 0x0ea5, 0x0ea5, -- 0x0ea7, 0x0ea7, -- 0x0eaa, 0x0eab, -- 0x0ead, 0x0eb9, -- 0x0ebb, 0x0ebd, -- 0x0ec0, 0x0ec4, -- 0x0ec6, 0x0ec6, -- 0x0ec8, 0x0ecd, -- 0x0ed0, 0x0ed9, -- 0x0edc, 0x0edd, -- 0x0f00, 0x0f47, -- 0x0f49, 0x0f6c, -- 0x0f71, 0x0f8b, -- 0x0f90, 0x0f97, -- 0x0f99, 0x0fbc, -- 0x0fbe, 0x0fcc, -- 0x0fce, 0x0fd8, -- 0x1000, 0x10c5, -- 0x10d0, 0x10fc, -- 0x1100, 0x1248, -- 0x124a, 0x124d, -- 0x1250, 0x1256, -- 0x1258, 0x1258, -- 0x125a, 0x125d, -- 0x1260, 0x1288, -- 0x128a, 0x128d, -- 0x1290, 0x12b0, -- 0x12b2, 0x12b5, -- 0x12b8, 0x12be, -- 0x12c0, 0x12c0, -- 0x12c2, 0x12c5, -- 0x12c8, 0x12d6, -- 0x12d8, 0x1310, -- 0x1312, 0x1315, -- 0x1318, 0x135a, -- 0x135f, 0x137c, -- 0x1380, 0x1399, -- 0x13a0, 0x13f4, -- 0x1400, 0x169c, -- 0x16a0, 0x16f0, -- 0x1700, 0x170c, -- 0x170e, 0x1714, -- 0x1720, 0x1736, -- 0x1740, 0x1753, -- 0x1760, 0x176c, -- 0x176e, 0x1770, -- 0x1772, 0x1773, -- 0x1780, 0x17dd, -- 0x17e0, 0x17e9, -- 0x17f0, 0x17f9, -- 0x1800, 0x180e, -- 0x1810, 0x1819, -- 0x1820, 0x1877, -- 0x1880, 0x18aa, -- 0x18b0, 0x18f5, -- 0x1900, 0x191c, -- 0x1920, 0x192b, -- 0x1930, 0x193b, -- 0x1940, 0x1940, -- 0x1944, 0x196d, -- 0x1970, 0x1974, -- 0x1980, 0x19ab, -- 0x19b0, 0x19c9, -- 0x19d0, 0x19da, -- 0x19de, 0x1a1b, -- 0x1a1e, 0x1a5e, -- 0x1a60, 0x1a7c, -- 0x1a7f, 0x1a89, -- 0x1a90, 0x1a99, -- 0x1aa0, 0x1aad, -- 0x1b00, 0x1b4b, -- 0x1b50, 0x1b7c, -- 0x1b80, 0x1baa, -- 0x1bae, 0x1bb9, -- 0x1c00, 0x1c37, -- 0x1c3b, 0x1c49, -- 0x1c4d, 0x1c7f, -- 0x1cd0, 0x1cf2, -- 0x1d00, 0x1de6, -- 0x1dfd, 0x1f15, -- 0x1f18, 0x1f1d, -- 0x1f20, 0x1f45, -- 0x1f48, 0x1f4d, -- 0x1f50, 0x1f57, -- 0x1f59, 0x1f59, -- 0x1f5b, 0x1f5b, -- 0x1f5d, 0x1f5d, -- 0x1f5f, 0x1f7d, -- 0x1f80, 0x1fb4, -- 0x1fb6, 0x1fc4, -- 0x1fc6, 0x1fd3, -- 0x1fd6, 0x1fdb, -- 0x1fdd, 0x1fef, -- 0x1ff2, 0x1ff4, -- 0x1ff6, 0x1ffe, -- 0x2000, 0x2064, -- 0x206a, 0x2071, -- 0x2074, 0x208e, -- 0x2090, 0x2094, -- 0x20a0, 0x20b8, -- 0x20d0, 0x20f0, -- 0x2100, 0x2189, -- 0x2190, 0x23e8, -- 0x2400, 0x2426, -- 0x2440, 0x244a, -- 0x2460, 0x26cd, -- 0x26cf, 0x26e1, -- 0x26e3, 0x26e3, -- 0x26e8, 0x26ff, -- 0x2701, 0x2704, -- 0x2706, 0x2709, -- 0x270c, 0x2727, -- 0x2729, 0x274b, -- 0x274d, 0x274d, -- 0x274f, 0x2752, -- 0x2756, 0x275e, -- 0x2761, 0x2794, -- 0x2798, 0x27af, -- 0x27b1, 0x27be, -- 0x27c0, 0x27ca, -- 0x27cc, 0x27cc, -- 0x27d0, 0x2b4c, -- 0x2b50, 0x2b59, -- 0x2c00, 0x2c2e, -- 0x2c30, 0x2c5e, -- 0x2c60, 0x2cf1, -- 0x2cf9, 0x2d25, -- 0x2d30, 0x2d65, -- 0x2d6f, 0x2d6f, -- 0x2d80, 0x2d96, -- 0x2da0, 0x2da6, -- 0x2da8, 0x2dae, -- 0x2db0, 0x2db6, -- 0x2db8, 0x2dbe, -- 0x2dc0, 0x2dc6, -- 0x2dc8, 0x2dce, -- 0x2dd0, 0x2dd6, -- 0x2dd8, 0x2dde, -- 0x2de0, 0x2e31, -- 0x2e80, 0x2e99, -- 0x2e9b, 0x2ef3, -- 0x2f00, 0x2fd5, -- 0x2ff0, 0x2ffb, -- 0x3000, 0x303f, -- 0x3041, 0x3096, -- 0x3099, 0x30ff, -- 0x3105, 0x312d, -- 0x3131, 0x318e, -- 0x3190, 0x31b7, -- 0x31c0, 0x31e3, -- 0x31f0, 0x321e, -- 0x3220, 0x32fe, -- 0x3300, 0x4db5, -- 0x4dc0, 0x9fcb, -- 0xa000, 0xa48c, -- 0xa490, 0xa4c6, -- 0xa4d0, 0xa62b, -- 0xa640, 0xa65f, -- 0xa662, 0xa673, -- 0xa67c, 0xa697, -- 0xa6a0, 0xa6f7, -- 0xa700, 0xa78c, -- 0xa7fb, 0xa82b, -- 0xa830, 0xa839, -- 0xa840, 0xa877, -- 0xa880, 0xa8c4, -- 0xa8ce, 0xa8d9, -- 0xa8e0, 0xa8fb, -- 0xa900, 0xa953, -- 0xa95f, 0xa97c, -- 0xa980, 0xa9cd, -- 0xa9cf, 0xa9d9, -- 0xa9de, 0xa9df, -- 0xaa00, 0xaa36, -- 0xaa40, 0xaa4d, -- 0xaa50, 0xaa59, -- 0xaa5c, 0xaa7b, -- 0xaa80, 0xaac2, -- 0xaadb, 0xaadf, -- 0xabc0, 0xabed, -- 0xabf0, 0xabf9, -- 0xac00, 0xd7a3, -- 0xd7b0, 0xd7c6, -- 0xd7cb, 0xd7fb, -- 0xd800, 0xfa2d, -- 0xfa30, 0xfa6d, -- 0xfa70, 0xfad9, -- 0xfb00, 0xfb06, -- 0xfb13, 0xfb17, -- 0xfb1d, 0xfb36, -- 0xfb38, 0xfb3c, -- 0xfb3e, 0xfb3e, -- 0xfb40, 0xfb41, -- 0xfb43, 0xfb44, -- 0xfb46, 0xfbb1, -- 0xfbd3, 0xfd3f, -- 0xfd50, 0xfd8f, -- 0xfd92, 0xfdc7, -- 0xfdd0, 0xfdfd, -- 0xfe00, 0xfe19, -- 0xfe20, 0xfe26, -- 0xfe30, 0xfe52, -- 0xfe54, 0xfe66, -- 0xfe68, 0xfe6b, -- 0xfe70, 0xfe74, -- 0xfe76, 0xfefc, -- 0xfeff, 0xfeff, -- 0xff01, 0xffbe, -- 0xffc2, 0xffc7, -- 0xffca, 0xffcf, -- 0xffd2, 0xffd7, -- 0xffda, 0xffdc, -- 0xffe0, 0xffe6, -- 0xffe8, 0xffee, -- 0xfff9, 0x1000b, -- 0x1000d, 0x10026, -- 0x10028, 0x1003a, -- 0x1003c, 0x1003d, -- 0x1003f, 0x1004d, -- 0x10050, 0x1005d, -- 0x10080, 0x100fa, -- 0x10100, 0x10102, -- 0x10107, 0x10133, -- 0x10137, 0x1018a, -- 0x10190, 0x1019b, -- 0x101d0, 0x101fd, -- 0x10280, 0x1029c, -- 0x102a0, 0x102d0, -- 0x10300, 0x1031e, -- 0x10320, 0x10323, -- 0x10330, 0x1034a, -- 0x10380, 0x1039d, -- 0x1039f, 0x103c3, -- 0x103c8, 0x103d5, -- 0x10400, 0x1049d, -- 0x104a0, 0x104a9, -- 0x10800, 0x10805, -- 0x10808, 0x10808, -- 0x1080a, 0x10835, -- 0x10837, 0x10838, -- 0x1083c, 0x1083c, -- 0x1083f, 0x10855, -- 0x10857, 0x1085f, -- 0x10900, 0x1091b, -- 0x1091f, 0x10939, -- 0x1093f, 0x1093f, -- 0x10a00, 0x10a03, -- 0x10a05, 0x10a06, -- 0x10a0c, 0x10a13, -- 0x10a15, 0x10a17, -- 0x10a19, 0x10a33, -- 0x10a38, 0x10a3a, -- 0x10a3f, 0x10a47, -- 0x10a50, 0x10a58, -- 0x10a60, 0x10a7f, -- 0x10b00, 0x10b35, -- 0x10b39, 0x10b55, -- 0x10b58, 0x10b72, -- 0x10b78, 0x10b7f, -- 0x10c00, 0x10c48, -- 0x10e60, 0x10e7e, -- 0x11080, 0x110c1, -- 0x12000, 0x1236e, -- 0x12400, 0x12462, -- 0x12470, 0x12473, -- 0x13000, 0x1342e, -- 0x1d000, 0x1d0f5, -- 0x1d100, 0x1d126, -- 0x1d129, 0x1d1dd, -- 0x1d200, 0x1d245, -- 0x1d300, 0x1d356, -- 0x1d360, 0x1d371, -- 0x1d400, 0x1d454, -- 0x1d456, 0x1d49c, -- 0x1d49e, 0x1d49f, -- 0x1d4a2, 0x1d4a2, -- 0x1d4a5, 0x1d4a6, -- 0x1d4a9, 0x1d4ac, -- 0x1d4ae, 0x1d4b9, -- 0x1d4bb, 0x1d4bb, -- 0x1d4bd, 0x1d4c3, -- 0x1d4c5, 0x1d505, -- 0x1d507, 0x1d50a, -- 0x1d50d, 0x1d514, -- 0x1d516, 0x1d51c, -- 0x1d51e, 0x1d539, -- 0x1d53b, 0x1d53e, -- 0x1d540, 0x1d544, -- 0x1d546, 0x1d546, -- 0x1d54a, 0x1d550, -- 0x1d552, 0x1d6a5, -- 0x1d6a8, 0x1d7cb, -- 0x1d7ce, 0x1d7ff, -- 0x1f000, 0x1f02b, -- 0x1f030, 0x1f093, -- 0x1f100, 0x1f10a, -- 0x1f110, 0x1f12e, -- 0x1f131, 0x1f131, -- 0x1f13d, 0x1f13d, -- 0x1f13f, 0x1f13f, -- 0x1f142, 0x1f142, -- 0x1f146, 0x1f146, -- 0x1f14a, 0x1f14e, -- 0x1f157, 0x1f157, -- 0x1f15f, 0x1f15f, -- 0x1f179, 0x1f179, -- 0x1f17b, 0x1f17c, -- 0x1f17f, 0x1f17f, -- 0x1f18a, 0x1f18d, -- 0x1f190, 0x1f190, -- 0x1f200, 0x1f200, -- 0x1f210, 0x1f231, -- 0x1f240, 0x1f248, -- 0x1fffe, 0x2a6d6, -- 0x2a700, 0x2b734, -- 0x2f800, 0x2fa1d, -- 0x2fffe, 0x2ffff, -- 0x3fffe, 0x3ffff, -- 0x4fffe, 0x4ffff, -- 0x5fffe, 0x5ffff, -- 0x6fffe, 0x6ffff, -- 0x7fffe, 0x7ffff, -- 0x8fffe, 0x8ffff, -- 0x9fffe, 0x9ffff, -- 0xafffe, 0xaffff, -- 0xbfffe, 0xbffff, -- 0xcfffe, 0xcffff, -- 0xdfffe, 0xdffff, -- 0xe0001, 0xe0001, -- 0xe0020, 0xe007f, -- 0xe0100, 0xe01ef, -- 0xefffe, 0x10ffff, --}; /* CR_Age_5_2 */ -- --/* 'Age_6_0': Derived Age 6.0 */ --static const OnigCodePoint CR_Age_6_0[] = { -- 511, -- 0x0000, 0x0377, -- 0x037a, 0x037e, -- 0x0384, 0x038a, -- 0x038c, 0x038c, -- 0x038e, 0x03a1, -- 0x03a3, 0x0527, -- 0x0531, 0x0556, -- 0x0559, 0x055f, -- 0x0561, 0x0587, -- 0x0589, 0x058a, -- 0x0591, 0x05c7, -- 0x05d0, 0x05ea, -- 0x05f0, 0x05f4, -- 0x0600, 0x0603, -- 0x0606, 0x061b, -- 0x061e, 0x070d, -- 0x070f, 0x074a, -- 0x074d, 0x07b1, -- 0x07c0, 0x07fa, -- 0x0800, 0x082d, -- 0x0830, 0x083e, -- 0x0840, 0x085b, -- 0x085e, 0x085e, -- 0x0900, 0x0977, -- 0x0979, 0x097f, -- 0x0981, 0x0983, -- 0x0985, 0x098c, -- 0x098f, 0x0990, -- 0x0993, 0x09a8, -- 0x09aa, 0x09b0, -- 0x09b2, 0x09b2, -- 0x09b6, 0x09b9, -- 0x09bc, 0x09c4, -- 0x09c7, 0x09c8, -- 0x09cb, 0x09ce, -- 0x09d7, 0x09d7, -- 0x09dc, 0x09dd, -- 0x09df, 0x09e3, -- 0x09e6, 0x09fb, -- 0x0a01, 0x0a03, -- 0x0a05, 0x0a0a, -- 0x0a0f, 0x0a10, -- 0x0a13, 0x0a28, -- 0x0a2a, 0x0a30, -- 0x0a32, 0x0a33, -- 0x0a35, 0x0a36, -- 0x0a38, 0x0a39, -- 0x0a3c, 0x0a3c, -- 0x0a3e, 0x0a42, -- 0x0a47, 0x0a48, -- 0x0a4b, 0x0a4d, -- 0x0a51, 0x0a51, -- 0x0a59, 0x0a5c, -- 0x0a5e, 0x0a5e, -- 0x0a66, 0x0a75, -- 0x0a81, 0x0a83, -- 0x0a85, 0x0a8d, -- 0x0a8f, 0x0a91, -- 0x0a93, 0x0aa8, -- 0x0aaa, 0x0ab0, -- 0x0ab2, 0x0ab3, -- 0x0ab5, 0x0ab9, -- 0x0abc, 0x0ac5, -- 0x0ac7, 0x0ac9, -- 0x0acb, 0x0acd, -- 0x0ad0, 0x0ad0, -- 0x0ae0, 0x0ae3, -- 0x0ae6, 0x0aef, -- 0x0af1, 0x0af1, -- 0x0b01, 0x0b03, -- 0x0b05, 0x0b0c, -- 0x0b0f, 0x0b10, -- 0x0b13, 0x0b28, -- 0x0b2a, 0x0b30, -- 0x0b32, 0x0b33, -- 0x0b35, 0x0b39, -- 0x0b3c, 0x0b44, -- 0x0b47, 0x0b48, -- 0x0b4b, 0x0b4d, -- 0x0b56, 0x0b57, -- 0x0b5c, 0x0b5d, -- 0x0b5f, 0x0b63, -- 0x0b66, 0x0b77, -- 0x0b82, 0x0b83, -- 0x0b85, 0x0b8a, -- 0x0b8e, 0x0b90, -- 0x0b92, 0x0b95, -- 0x0b99, 0x0b9a, -- 0x0b9c, 0x0b9c, -- 0x0b9e, 0x0b9f, -- 0x0ba3, 0x0ba4, -- 0x0ba8, 0x0baa, -- 0x0bae, 0x0bb9, -- 0x0bbe, 0x0bc2, -- 0x0bc6, 0x0bc8, -- 0x0bca, 0x0bcd, -- 0x0bd0, 0x0bd0, -- 0x0bd7, 0x0bd7, -- 0x0be6, 0x0bfa, -- 0x0c01, 0x0c03, -- 0x0c05, 0x0c0c, -- 0x0c0e, 0x0c10, -- 0x0c12, 0x0c28, -- 0x0c2a, 0x0c33, -- 0x0c35, 0x0c39, -- 0x0c3d, 0x0c44, -- 0x0c46, 0x0c48, -- 0x0c4a, 0x0c4d, -- 0x0c55, 0x0c56, -- 0x0c58, 0x0c59, -- 0x0c60, 0x0c63, -- 0x0c66, 0x0c6f, -- 0x0c78, 0x0c7f, -- 0x0c82, 0x0c83, -- 0x0c85, 0x0c8c, -- 0x0c8e, 0x0c90, -- 0x0c92, 0x0ca8, -- 0x0caa, 0x0cb3, -- 0x0cb5, 0x0cb9, -- 0x0cbc, 0x0cc4, -- 0x0cc6, 0x0cc8, -- 0x0cca, 0x0ccd, -- 0x0cd5, 0x0cd6, -- 0x0cde, 0x0cde, -- 0x0ce0, 0x0ce3, -- 0x0ce6, 0x0cef, -- 0x0cf1, 0x0cf2, -- 0x0d02, 0x0d03, -- 0x0d05, 0x0d0c, -- 0x0d0e, 0x0d10, -- 0x0d12, 0x0d3a, -- 0x0d3d, 0x0d44, -- 0x0d46, 0x0d48, -- 0x0d4a, 0x0d4e, -- 0x0d57, 0x0d57, -- 0x0d60, 0x0d63, -- 0x0d66, 0x0d75, -- 0x0d79, 0x0d7f, -- 0x0d82, 0x0d83, -- 0x0d85, 0x0d96, -- 0x0d9a, 0x0db1, -- 0x0db3, 0x0dbb, -- 0x0dbd, 0x0dbd, -- 0x0dc0, 0x0dc6, -- 0x0dca, 0x0dca, -- 0x0dcf, 0x0dd4, -- 0x0dd6, 0x0dd6, -- 0x0dd8, 0x0ddf, -- 0x0df2, 0x0df4, -- 0x0e01, 0x0e3a, -- 0x0e3f, 0x0e5b, -- 0x0e81, 0x0e82, -- 0x0e84, 0x0e84, -- 0x0e87, 0x0e88, -- 0x0e8a, 0x0e8a, -- 0x0e8d, 0x0e8d, -- 0x0e94, 0x0e97, -- 0x0e99, 0x0e9f, -- 0x0ea1, 0x0ea3, -- 0x0ea5, 0x0ea5, -- 0x0ea7, 0x0ea7, -- 0x0eaa, 0x0eab, -- 0x0ead, 0x0eb9, -- 0x0ebb, 0x0ebd, -- 0x0ec0, 0x0ec4, -- 0x0ec6, 0x0ec6, -- 0x0ec8, 0x0ecd, -- 0x0ed0, 0x0ed9, -- 0x0edc, 0x0edd, -- 0x0f00, 0x0f47, -- 0x0f49, 0x0f6c, -- 0x0f71, 0x0f97, -- 0x0f99, 0x0fbc, -- 0x0fbe, 0x0fcc, -- 0x0fce, 0x0fda, -- 0x1000, 0x10c5, -- 0x10d0, 0x10fc, -- 0x1100, 0x1248, -- 0x124a, 0x124d, -- 0x1250, 0x1256, -- 0x1258, 0x1258, -- 0x125a, 0x125d, -- 0x1260, 0x1288, -- 0x128a, 0x128d, -- 0x1290, 0x12b0, -- 0x12b2, 0x12b5, -- 0x12b8, 0x12be, -- 0x12c0, 0x12c0, -- 0x12c2, 0x12c5, -- 0x12c8, 0x12d6, -- 0x12d8, 0x1310, -- 0x1312, 0x1315, -- 0x1318, 0x135a, -- 0x135d, 0x137c, -- 0x1380, 0x1399, -- 0x13a0, 0x13f4, -- 0x1400, 0x169c, -- 0x16a0, 0x16f0, -- 0x1700, 0x170c, -- 0x170e, 0x1714, -- 0x1720, 0x1736, -- 0x1740, 0x1753, -- 0x1760, 0x176c, -- 0x176e, 0x1770, -- 0x1772, 0x1773, -- 0x1780, 0x17dd, -- 0x17e0, 0x17e9, -- 0x17f0, 0x17f9, -- 0x1800, 0x180e, -- 0x1810, 0x1819, -- 0x1820, 0x1877, -- 0x1880, 0x18aa, -- 0x18b0, 0x18f5, -- 0x1900, 0x191c, -- 0x1920, 0x192b, -- 0x1930, 0x193b, -- 0x1940, 0x1940, -- 0x1944, 0x196d, -- 0x1970, 0x1974, -- 0x1980, 0x19ab, -- 0x19b0, 0x19c9, -- 0x19d0, 0x19da, -- 0x19de, 0x1a1b, -- 0x1a1e, 0x1a5e, -- 0x1a60, 0x1a7c, -- 0x1a7f, 0x1a89, -- 0x1a90, 0x1a99, -- 0x1aa0, 0x1aad, -- 0x1b00, 0x1b4b, -- 0x1b50, 0x1b7c, -- 0x1b80, 0x1baa, -- 0x1bae, 0x1bb9, -- 0x1bc0, 0x1bf3, -- 0x1bfc, 0x1c37, -- 0x1c3b, 0x1c49, -- 0x1c4d, 0x1c7f, -- 0x1cd0, 0x1cf2, -- 0x1d00, 0x1de6, -- 0x1dfc, 0x1f15, -- 0x1f18, 0x1f1d, -- 0x1f20, 0x1f45, -- 0x1f48, 0x1f4d, -- 0x1f50, 0x1f57, -- 0x1f59, 0x1f59, -- 0x1f5b, 0x1f5b, -- 0x1f5d, 0x1f5d, -- 0x1f5f, 0x1f7d, -- 0x1f80, 0x1fb4, -- 0x1fb6, 0x1fc4, -- 0x1fc6, 0x1fd3, -- 0x1fd6, 0x1fdb, -- 0x1fdd, 0x1fef, -- 0x1ff2, 0x1ff4, -- 0x1ff6, 0x1ffe, -- 0x2000, 0x2064, -- 0x206a, 0x2071, -- 0x2074, 0x208e, -- 0x2090, 0x209c, -- 0x20a0, 0x20b9, -- 0x20d0, 0x20f0, -- 0x2100, 0x2189, -- 0x2190, 0x23f3, -- 0x2400, 0x2426, -- 0x2440, 0x244a, -- 0x2460, 0x26ff, -- 0x2701, 0x27ca, -- 0x27cc, 0x27cc, -- 0x27ce, 0x2b4c, -- 0x2b50, 0x2b59, -- 0x2c00, 0x2c2e, -- 0x2c30, 0x2c5e, -- 0x2c60, 0x2cf1, -- 0x2cf9, 0x2d25, -- 0x2d30, 0x2d65, -- 0x2d6f, 0x2d70, -- 0x2d7f, 0x2d96, -- 0x2da0, 0x2da6, -- 0x2da8, 0x2dae, -- 0x2db0, 0x2db6, -- 0x2db8, 0x2dbe, -- 0x2dc0, 0x2dc6, -- 0x2dc8, 0x2dce, -- 0x2dd0, 0x2dd6, -- 0x2dd8, 0x2dde, -- 0x2de0, 0x2e31, -- 0x2e80, 0x2e99, -- 0x2e9b, 0x2ef3, -- 0x2f00, 0x2fd5, -- 0x2ff0, 0x2ffb, -- 0x3000, 0x303f, -- 0x3041, 0x3096, -- 0x3099, 0x30ff, -- 0x3105, 0x312d, -- 0x3131, 0x318e, -- 0x3190, 0x31ba, -- 0x31c0, 0x31e3, -- 0x31f0, 0x321e, -- 0x3220, 0x32fe, -- 0x3300, 0x4db5, -- 0x4dc0, 0x9fcb, -- 0xa000, 0xa48c, -- 0xa490, 0xa4c6, -- 0xa4d0, 0xa62b, -- 0xa640, 0xa673, -- 0xa67c, 0xa697, -- 0xa6a0, 0xa6f7, -- 0xa700, 0xa78e, -- 0xa790, 0xa791, -- 0xa7a0, 0xa7a9, -- 0xa7fa, 0xa82b, -- 0xa830, 0xa839, -- 0xa840, 0xa877, -- 0xa880, 0xa8c4, -- 0xa8ce, 0xa8d9, -- 0xa8e0, 0xa8fb, -- 0xa900, 0xa953, -- 0xa95f, 0xa97c, -- 0xa980, 0xa9cd, -- 0xa9cf, 0xa9d9, -- 0xa9de, 0xa9df, -- 0xaa00, 0xaa36, -- 0xaa40, 0xaa4d, -- 0xaa50, 0xaa59, -- 0xaa5c, 0xaa7b, -- 0xaa80, 0xaac2, -- 0xaadb, 0xaadf, -- 0xab01, 0xab06, -- 0xab09, 0xab0e, -- 0xab11, 0xab16, -- 0xab20, 0xab26, -- 0xab28, 0xab2e, -- 0xabc0, 0xabed, -- 0xabf0, 0xabf9, -- 0xac00, 0xd7a3, -- 0xd7b0, 0xd7c6, -- 0xd7cb, 0xd7fb, -- 0xd800, 0xfa2d, -- 0xfa30, 0xfa6d, -- 0xfa70, 0xfad9, -- 0xfb00, 0xfb06, -- 0xfb13, 0xfb17, -- 0xfb1d, 0xfb36, -- 0xfb38, 0xfb3c, -- 0xfb3e, 0xfb3e, -- 0xfb40, 0xfb41, -- 0xfb43, 0xfb44, -- 0xfb46, 0xfbc1, -- 0xfbd3, 0xfd3f, -- 0xfd50, 0xfd8f, -- 0xfd92, 0xfdc7, -- 0xfdd0, 0xfdfd, -- 0xfe00, 0xfe19, -- 0xfe20, 0xfe26, -- 0xfe30, 0xfe52, -- 0xfe54, 0xfe66, -- 0xfe68, 0xfe6b, -- 0xfe70, 0xfe74, -- 0xfe76, 0xfefc, -- 0xfeff, 0xfeff, -- 0xff01, 0xffbe, -- 0xffc2, 0xffc7, -- 0xffca, 0xffcf, -- 0xffd2, 0xffd7, -- 0xffda, 0xffdc, -- 0xffe0, 0xffe6, -- 0xffe8, 0xffee, -- 0xfff9, 0x1000b, -- 0x1000d, 0x10026, -- 0x10028, 0x1003a, -- 0x1003c, 0x1003d, -- 0x1003f, 0x1004d, -- 0x10050, 0x1005d, -- 0x10080, 0x100fa, -- 0x10100, 0x10102, -- 0x10107, 0x10133, -- 0x10137, 0x1018a, -- 0x10190, 0x1019b, -- 0x101d0, 0x101fd, -- 0x10280, 0x1029c, -- 0x102a0, 0x102d0, -- 0x10300, 0x1031e, -- 0x10320, 0x10323, -- 0x10330, 0x1034a, -- 0x10380, 0x1039d, -- 0x1039f, 0x103c3, -- 0x103c8, 0x103d5, -- 0x10400, 0x1049d, -- 0x104a0, 0x104a9, -- 0x10800, 0x10805, -- 0x10808, 0x10808, -- 0x1080a, 0x10835, -- 0x10837, 0x10838, -- 0x1083c, 0x1083c, -- 0x1083f, 0x10855, -- 0x10857, 0x1085f, -- 0x10900, 0x1091b, -- 0x1091f, 0x10939, -- 0x1093f, 0x1093f, -- 0x10a00, 0x10a03, -- 0x10a05, 0x10a06, -- 0x10a0c, 0x10a13, -- 0x10a15, 0x10a17, -- 0x10a19, 0x10a33, -- 0x10a38, 0x10a3a, -- 0x10a3f, 0x10a47, -- 0x10a50, 0x10a58, -- 0x10a60, 0x10a7f, -- 0x10b00, 0x10b35, -- 0x10b39, 0x10b55, -- 0x10b58, 0x10b72, -- 0x10b78, 0x10b7f, -- 0x10c00, 0x10c48, -- 0x10e60, 0x10e7e, -- 0x11000, 0x1104d, -- 0x11052, 0x1106f, -- 0x11080, 0x110c1, -- 0x12000, 0x1236e, -- 0x12400, 0x12462, -- 0x12470, 0x12473, -- 0x13000, 0x1342e, -- 0x16800, 0x16a38, -- 0x1b000, 0x1b001, -- 0x1d000, 0x1d0f5, -- 0x1d100, 0x1d126, -- 0x1d129, 0x1d1dd, -- 0x1d200, 0x1d245, -- 0x1d300, 0x1d356, -- 0x1d360, 0x1d371, -- 0x1d400, 0x1d454, -- 0x1d456, 0x1d49c, -- 0x1d49e, 0x1d49f, -- 0x1d4a2, 0x1d4a2, -- 0x1d4a5, 0x1d4a6, -- 0x1d4a9, 0x1d4ac, -- 0x1d4ae, 0x1d4b9, -- 0x1d4bb, 0x1d4bb, -- 0x1d4bd, 0x1d4c3, -- 0x1d4c5, 0x1d505, -- 0x1d507, 0x1d50a, -- 0x1d50d, 0x1d514, -- 0x1d516, 0x1d51c, -- 0x1d51e, 0x1d539, -- 0x1d53b, 0x1d53e, -- 0x1d540, 0x1d544, -- 0x1d546, 0x1d546, -- 0x1d54a, 0x1d550, -- 0x1d552, 0x1d6a5, -- 0x1d6a8, 0x1d7cb, -- 0x1d7ce, 0x1d7ff, -- 0x1f000, 0x1f02b, -- 0x1f030, 0x1f093, -- 0x1f0a0, 0x1f0ae, -- 0x1f0b1, 0x1f0be, -- 0x1f0c1, 0x1f0cf, -- 0x1f0d1, 0x1f0df, -- 0x1f100, 0x1f10a, -- 0x1f110, 0x1f12e, -- 0x1f130, 0x1f169, -- 0x1f170, 0x1f19a, -- 0x1f1e6, 0x1f202, -- 0x1f210, 0x1f23a, -- 0x1f240, 0x1f248, -- 0x1f250, 0x1f251, -- 0x1f300, 0x1f320, -- 0x1f330, 0x1f335, -- 0x1f337, 0x1f37c, -- 0x1f380, 0x1f393, -- 0x1f3a0, 0x1f3c4, -- 0x1f3c6, 0x1f3ca, -- 0x1f3e0, 0x1f3f0, -- 0x1f400, 0x1f43e, -- 0x1f440, 0x1f440, -- 0x1f442, 0x1f4f7, -- 0x1f4f9, 0x1f4fc, -- 0x1f500, 0x1f53d, -- 0x1f550, 0x1f567, -- 0x1f5fb, 0x1f5ff, -- 0x1f601, 0x1f610, -- 0x1f612, 0x1f614, -- 0x1f616, 0x1f616, -- 0x1f618, 0x1f618, -- 0x1f61a, 0x1f61a, -- 0x1f61c, 0x1f61e, -- 0x1f620, 0x1f625, -- 0x1f628, 0x1f62b, -- 0x1f62d, 0x1f62d, -- 0x1f630, 0x1f633, -- 0x1f635, 0x1f640, -- 0x1f645, 0x1f64f, -- 0x1f680, 0x1f6c5, -- 0x1f700, 0x1f773, -- 0x1fffe, 0x2a6d6, -- 0x2a700, 0x2b734, -- 0x2b740, 0x2b81d, -- 0x2f800, 0x2fa1d, -- 0x2fffe, 0x2ffff, -- 0x3fffe, 0x3ffff, -- 0x4fffe, 0x4ffff, -- 0x5fffe, 0x5ffff, -- 0x6fffe, 0x6ffff, -- 0x7fffe, 0x7ffff, -- 0x8fffe, 0x8ffff, -- 0x9fffe, 0x9ffff, -- 0xafffe, 0xaffff, -- 0xbfffe, 0xbffff, -- 0xcfffe, 0xcffff, -- 0xdfffe, 0xdffff, -- 0xe0001, 0xe0001, -- 0xe0020, 0xe007f, -- 0xe0100, 0xe01ef, -- 0xefffe, 0x10ffff, --}; /* CR_Age_6_0 */ -- --/* 'NEWLINE': [[:NEWLINE:]] */ --static const OnigCodePoint CR_NEWLINE[] = { -- 1, -- 0x000a, 0x000a, --}; /* CR_NEWLINE */ -- --/* 'Alpha': [[:Alpha:]] */ --#define CR_Alpha CR_Alphabetic -- --/* 'Blank': [[:Blank:]] */ --static const OnigCodePoint CR_Blank[] = { -- 9, -- 0x0009, 0x0009, -- 0x0020, 0x0020, -- 0x00a0, 0x00a0, -- 0x1680, 0x1680, -- 0x180e, 0x180e, -- 0x2000, 0x200a, -- 0x202f, 0x202f, -- 0x205f, 0x205f, -- 0x3000, 0x3000, --}; /* CR_Blank */ -- --/* 'Cntrl': [[:Cntrl:]] */ --#define CR_Cntrl CR_Cc -- --/* 'Digit': [[:Digit:]] */ --#define CR_Digit CR_Nd -- --/* 'Graph': [[:Graph:]] */ --static const OnigCodePoint CR_Graph[] = { -- 506, -- 0x0021, 0x007e, -- 0x00a1, 0x0377, -- 0x037a, 0x037e, -- 0x0384, 0x038a, -- 0x038c, 0x038c, -- 0x038e, 0x03a1, -- 0x03a3, 0x0527, -- 0x0531, 0x0556, -- 0x0559, 0x055f, -- 0x0561, 0x0587, -- 0x0589, 0x058a, -- 0x0591, 0x05c7, -- 0x05d0, 0x05ea, -- 0x05f0, 0x05f4, -- 0x0600, 0x0603, -- 0x0606, 0x061b, -- 0x061e, 0x070d, -- 0x070f, 0x074a, -- 0x074d, 0x07b1, -- 0x07c0, 0x07fa, -- 0x0800, 0x082d, -- 0x0830, 0x083e, -- 0x0840, 0x085b, -- 0x085e, 0x085e, -- 0x0900, 0x0977, -- 0x0979, 0x097f, -- 0x0981, 0x0983, -- 0x0985, 0x098c, -- 0x098f, 0x0990, -- 0x0993, 0x09a8, -- 0x09aa, 0x09b0, -- 0x09b2, 0x09b2, -- 0x09b6, 0x09b9, -- 0x09bc, 0x09c4, -- 0x09c7, 0x09c8, -- 0x09cb, 0x09ce, -- 0x09d7, 0x09d7, -- 0x09dc, 0x09dd, -- 0x09df, 0x09e3, -- 0x09e6, 0x09fb, -- 0x0a01, 0x0a03, -- 0x0a05, 0x0a0a, -- 0x0a0f, 0x0a10, -- 0x0a13, 0x0a28, -- 0x0a2a, 0x0a30, -- 0x0a32, 0x0a33, -- 0x0a35, 0x0a36, -- 0x0a38, 0x0a39, -- 0x0a3c, 0x0a3c, -- 0x0a3e, 0x0a42, -- 0x0a47, 0x0a48, -- 0x0a4b, 0x0a4d, -- 0x0a51, 0x0a51, -- 0x0a59, 0x0a5c, -- 0x0a5e, 0x0a5e, -- 0x0a66, 0x0a75, -- 0x0a81, 0x0a83, -- 0x0a85, 0x0a8d, -- 0x0a8f, 0x0a91, -- 0x0a93, 0x0aa8, -- 0x0aaa, 0x0ab0, -- 0x0ab2, 0x0ab3, -- 0x0ab5, 0x0ab9, -- 0x0abc, 0x0ac5, -- 0x0ac7, 0x0ac9, -- 0x0acb, 0x0acd, -- 0x0ad0, 0x0ad0, -- 0x0ae0, 0x0ae3, -- 0x0ae6, 0x0aef, -- 0x0af1, 0x0af1, -- 0x0b01, 0x0b03, -- 0x0b05, 0x0b0c, -- 0x0b0f, 0x0b10, -- 0x0b13, 0x0b28, -- 0x0b2a, 0x0b30, -- 0x0b32, 0x0b33, -- 0x0b35, 0x0b39, -- 0x0b3c, 0x0b44, -- 0x0b47, 0x0b48, -- 0x0b4b, 0x0b4d, -- 0x0b56, 0x0b57, -- 0x0b5c, 0x0b5d, -- 0x0b5f, 0x0b63, -- 0x0b66, 0x0b77, -- 0x0b82, 0x0b83, -- 0x0b85, 0x0b8a, -- 0x0b8e, 0x0b90, -- 0x0b92, 0x0b95, -- 0x0b99, 0x0b9a, -- 0x0b9c, 0x0b9c, -- 0x0b9e, 0x0b9f, -- 0x0ba3, 0x0ba4, -- 0x0ba8, 0x0baa, -- 0x0bae, 0x0bb9, -- 0x0bbe, 0x0bc2, -- 0x0bc6, 0x0bc8, -- 0x0bca, 0x0bcd, -- 0x0bd0, 0x0bd0, -- 0x0bd7, 0x0bd7, -- 0x0be6, 0x0bfa, -- 0x0c01, 0x0c03, -- 0x0c05, 0x0c0c, -- 0x0c0e, 0x0c10, -- 0x0c12, 0x0c28, -- 0x0c2a, 0x0c33, -- 0x0c35, 0x0c39, -- 0x0c3d, 0x0c44, -- 0x0c46, 0x0c48, -- 0x0c4a, 0x0c4d, -- 0x0c55, 0x0c56, -- 0x0c58, 0x0c59, -- 0x0c60, 0x0c63, -- 0x0c66, 0x0c6f, -- 0x0c78, 0x0c7f, -- 0x0c82, 0x0c83, -- 0x0c85, 0x0c8c, -- 0x0c8e, 0x0c90, -- 0x0c92, 0x0ca8, -- 0x0caa, 0x0cb3, -- 0x0cb5, 0x0cb9, -- 0x0cbc, 0x0cc4, -- 0x0cc6, 0x0cc8, -- 0x0cca, 0x0ccd, -- 0x0cd5, 0x0cd6, -- 0x0cde, 0x0cde, -- 0x0ce0, 0x0ce3, -- 0x0ce6, 0x0cef, -- 0x0cf1, 0x0cf2, -- 0x0d02, 0x0d03, -- 0x0d05, 0x0d0c, -- 0x0d0e, 0x0d10, -- 0x0d12, 0x0d3a, -- 0x0d3d, 0x0d44, -- 0x0d46, 0x0d48, -- 0x0d4a, 0x0d4e, -- 0x0d57, 0x0d57, -- 0x0d60, 0x0d63, -- 0x0d66, 0x0d75, -- 0x0d79, 0x0d7f, -- 0x0d82, 0x0d83, -- 0x0d85, 0x0d96, -- 0x0d9a, 0x0db1, -- 0x0db3, 0x0dbb, -- 0x0dbd, 0x0dbd, -- 0x0dc0, 0x0dc6, -- 0x0dca, 0x0dca, -- 0x0dcf, 0x0dd4, -- 0x0dd6, 0x0dd6, -- 0x0dd8, 0x0ddf, -- 0x0df2, 0x0df4, -- 0x0e01, 0x0e3a, -- 0x0e3f, 0x0e5b, -- 0x0e81, 0x0e82, -- 0x0e84, 0x0e84, -- 0x0e87, 0x0e88, -- 0x0e8a, 0x0e8a, -- 0x0e8d, 0x0e8d, -- 0x0e94, 0x0e97, -- 0x0e99, 0x0e9f, -- 0x0ea1, 0x0ea3, -- 0x0ea5, 0x0ea5, -- 0x0ea7, 0x0ea7, -- 0x0eaa, 0x0eab, -- 0x0ead, 0x0eb9, -- 0x0ebb, 0x0ebd, -- 0x0ec0, 0x0ec4, -- 0x0ec6, 0x0ec6, -- 0x0ec8, 0x0ecd, -- 0x0ed0, 0x0ed9, -- 0x0edc, 0x0edd, -- 0x0f00, 0x0f47, -- 0x0f49, 0x0f6c, -- 0x0f71, 0x0f97, -- 0x0f99, 0x0fbc, -- 0x0fbe, 0x0fcc, -- 0x0fce, 0x0fda, -- 0x1000, 0x10c5, -- 0x10d0, 0x10fc, -- 0x1100, 0x1248, -- 0x124a, 0x124d, -- 0x1250, 0x1256, -- 0x1258, 0x1258, -- 0x125a, 0x125d, -- 0x1260, 0x1288, -- 0x128a, 0x128d, -- 0x1290, 0x12b0, -- 0x12b2, 0x12b5, -- 0x12b8, 0x12be, -- 0x12c0, 0x12c0, -- 0x12c2, 0x12c5, -- 0x12c8, 0x12d6, -- 0x12d8, 0x1310, -- 0x1312, 0x1315, -- 0x1318, 0x135a, -- 0x135d, 0x137c, -- 0x1380, 0x1399, -- 0x13a0, 0x13f4, -- 0x1400, 0x167f, -- 0x1681, 0x169c, -- 0x16a0, 0x16f0, -- 0x1700, 0x170c, -- 0x170e, 0x1714, -- 0x1720, 0x1736, -- 0x1740, 0x1753, -- 0x1760, 0x176c, -- 0x176e, 0x1770, -- 0x1772, 0x1773, -- 0x1780, 0x17dd, -- 0x17e0, 0x17e9, -- 0x17f0, 0x17f9, -- 0x1800, 0x180d, -- 0x1810, 0x1819, -- 0x1820, 0x1877, -- 0x1880, 0x18aa, -- 0x18b0, 0x18f5, -- 0x1900, 0x191c, -- 0x1920, 0x192b, -- 0x1930, 0x193b, -- 0x1940, 0x1940, -- 0x1944, 0x196d, -- 0x1970, 0x1974, -- 0x1980, 0x19ab, -- 0x19b0, 0x19c9, -- 0x19d0, 0x19da, -- 0x19de, 0x1a1b, -- 0x1a1e, 0x1a5e, -- 0x1a60, 0x1a7c, -- 0x1a7f, 0x1a89, -- 0x1a90, 0x1a99, -- 0x1aa0, 0x1aad, -- 0x1b00, 0x1b4b, -- 0x1b50, 0x1b7c, -- 0x1b80, 0x1baa, -- 0x1bae, 0x1bb9, -- 0x1bc0, 0x1bf3, -- 0x1bfc, 0x1c37, -- 0x1c3b, 0x1c49, -- 0x1c4d, 0x1c7f, -- 0x1cd0, 0x1cf2, -- 0x1d00, 0x1de6, -- 0x1dfc, 0x1f15, -- 0x1f18, 0x1f1d, -- 0x1f20, 0x1f45, -- 0x1f48, 0x1f4d, -- 0x1f50, 0x1f57, -- 0x1f59, 0x1f59, -- 0x1f5b, 0x1f5b, -- 0x1f5d, 0x1f5d, -- 0x1f5f, 0x1f7d, -- 0x1f80, 0x1fb4, -- 0x1fb6, 0x1fc4, -- 0x1fc6, 0x1fd3, -- 0x1fd6, 0x1fdb, -- 0x1fdd, 0x1fef, -- 0x1ff2, 0x1ff4, -- 0x1ff6, 0x1ffe, -- 0x200b, 0x2027, -- 0x202a, 0x202e, -- 0x2030, 0x205e, -- 0x2060, 0x2064, -- 0x206a, 0x2071, -- 0x2074, 0x208e, -- 0x2090, 0x209c, -- 0x20a0, 0x20b9, -- 0x20d0, 0x20f0, -- 0x2100, 0x2189, -- 0x2190, 0x23f3, -- 0x2400, 0x2426, -- 0x2440, 0x244a, -- 0x2460, 0x26ff, -- 0x2701, 0x27ca, -- 0x27cc, 0x27cc, -- 0x27ce, 0x2b4c, -- 0x2b50, 0x2b59, -- 0x2c00, 0x2c2e, -- 0x2c30, 0x2c5e, -- 0x2c60, 0x2cf1, -- 0x2cf9, 0x2d25, -- 0x2d30, 0x2d65, -- 0x2d6f, 0x2d70, -- 0x2d7f, 0x2d96, -- 0x2da0, 0x2da6, -- 0x2da8, 0x2dae, -- 0x2db0, 0x2db6, -- 0x2db8, 0x2dbe, -- 0x2dc0, 0x2dc6, -- 0x2dc8, 0x2dce, -- 0x2dd0, 0x2dd6, -- 0x2dd8, 0x2dde, -- 0x2de0, 0x2e31, -- 0x2e80, 0x2e99, -- 0x2e9b, 0x2ef3, -- 0x2f00, 0x2fd5, -- 0x2ff0, 0x2ffb, -- 0x3001, 0x303f, -- 0x3041, 0x3096, -- 0x3099, 0x30ff, -- 0x3105, 0x312d, -- 0x3131, 0x318e, -- 0x3190, 0x31ba, -- 0x31c0, 0x31e3, -- 0x31f0, 0x321e, -- 0x3220, 0x32fe, -- 0x3300, 0x4db5, -- 0x4dc0, 0x9fcb, -- 0xa000, 0xa48c, -- 0xa490, 0xa4c6, -- 0xa4d0, 0xa62b, -- 0xa640, 0xa673, -- 0xa67c, 0xa697, -- 0xa6a0, 0xa6f7, -- 0xa700, 0xa78e, -- 0xa790, 0xa791, -- 0xa7a0, 0xa7a9, -- 0xa7fa, 0xa82b, -- 0xa830, 0xa839, -- 0xa840, 0xa877, -- 0xa880, 0xa8c4, -- 0xa8ce, 0xa8d9, -- 0xa8e0, 0xa8fb, -- 0xa900, 0xa953, -- 0xa95f, 0xa97c, -- 0xa980, 0xa9cd, -- 0xa9cf, 0xa9d9, -- 0xa9de, 0xa9df, -- 0xaa00, 0xaa36, -- 0xaa40, 0xaa4d, -- 0xaa50, 0xaa59, -- 0xaa5c, 0xaa7b, -- 0xaa80, 0xaac2, -- 0xaadb, 0xaadf, -- 0xab01, 0xab06, -- 0xab09, 0xab0e, -- 0xab11, 0xab16, -- 0xab20, 0xab26, -- 0xab28, 0xab2e, -- 0xabc0, 0xabed, -- 0xabf0, 0xabf9, -- 0xac00, 0xd7a3, -- 0xd7b0, 0xd7c6, -- 0xd7cb, 0xd7fb, -- 0xe000, 0xfa2d, -- 0xfa30, 0xfa6d, -- 0xfa70, 0xfad9, -- 0xfb00, 0xfb06, -- 0xfb13, 0xfb17, -- 0xfb1d, 0xfb36, -- 0xfb38, 0xfb3c, -- 0xfb3e, 0xfb3e, -- 0xfb40, 0xfb41, -- 0xfb43, 0xfb44, -- 0xfb46, 0xfbc1, -- 0xfbd3, 0xfd3f, -- 0xfd50, 0xfd8f, -- 0xfd92, 0xfdc7, -- 0xfdf0, 0xfdfd, -- 0xfe00, 0xfe19, -- 0xfe20, 0xfe26, -- 0xfe30, 0xfe52, -- 0xfe54, 0xfe66, -- 0xfe68, 0xfe6b, -- 0xfe70, 0xfe74, -- 0xfe76, 0xfefc, -- 0xfeff, 0xfeff, -- 0xff01, 0xffbe, -- 0xffc2, 0xffc7, -- 0xffca, 0xffcf, -- 0xffd2, 0xffd7, -- 0xffda, 0xffdc, -- 0xffe0, 0xffe6, -- 0xffe8, 0xffee, -- 0xfff9, 0xfffd, -- 0x10000, 0x1000b, -- 0x1000d, 0x10026, -- 0x10028, 0x1003a, -- 0x1003c, 0x1003d, -- 0x1003f, 0x1004d, -- 0x10050, 0x1005d, -- 0x10080, 0x100fa, -- 0x10100, 0x10102, -- 0x10107, 0x10133, -- 0x10137, 0x1018a, -- 0x10190, 0x1019b, -- 0x101d0, 0x101fd, -- 0x10280, 0x1029c, -- 0x102a0, 0x102d0, -- 0x10300, 0x1031e, -- 0x10320, 0x10323, -- 0x10330, 0x1034a, -- 0x10380, 0x1039d, -- 0x1039f, 0x103c3, -- 0x103c8, 0x103d5, -- 0x10400, 0x1049d, -- 0x104a0, 0x104a9, -- 0x10800, 0x10805, -- 0x10808, 0x10808, -- 0x1080a, 0x10835, -- 0x10837, 0x10838, -- 0x1083c, 0x1083c, -- 0x1083f, 0x10855, -- 0x10857, 0x1085f, -- 0x10900, 0x1091b, -- 0x1091f, 0x10939, -- 0x1093f, 0x1093f, -- 0x10a00, 0x10a03, -- 0x10a05, 0x10a06, -- 0x10a0c, 0x10a13, -- 0x10a15, 0x10a17, -- 0x10a19, 0x10a33, -- 0x10a38, 0x10a3a, -- 0x10a3f, 0x10a47, -- 0x10a50, 0x10a58, -- 0x10a60, 0x10a7f, -- 0x10b00, 0x10b35, -- 0x10b39, 0x10b55, -- 0x10b58, 0x10b72, -- 0x10b78, 0x10b7f, -- 0x10c00, 0x10c48, -- 0x10e60, 0x10e7e, -- 0x11000, 0x1104d, -- 0x11052, 0x1106f, -- 0x11080, 0x110c1, -- 0x12000, 0x1236e, -- 0x12400, 0x12462, -- 0x12470, 0x12473, -- 0x13000, 0x1342e, -- 0x16800, 0x16a38, -- 0x1b000, 0x1b001, -- 0x1d000, 0x1d0f5, -- 0x1d100, 0x1d126, -- 0x1d129, 0x1d1dd, -- 0x1d200, 0x1d245, -- 0x1d300, 0x1d356, -- 0x1d360, 0x1d371, -- 0x1d400, 0x1d454, -- 0x1d456, 0x1d49c, -- 0x1d49e, 0x1d49f, -- 0x1d4a2, 0x1d4a2, -- 0x1d4a5, 0x1d4a6, -- 0x1d4a9, 0x1d4ac, -- 0x1d4ae, 0x1d4b9, -- 0x1d4bb, 0x1d4bb, -- 0x1d4bd, 0x1d4c3, -- 0x1d4c5, 0x1d505, -- 0x1d507, 0x1d50a, -- 0x1d50d, 0x1d514, -- 0x1d516, 0x1d51c, -- 0x1d51e, 0x1d539, -- 0x1d53b, 0x1d53e, -- 0x1d540, 0x1d544, -- 0x1d546, 0x1d546, -- 0x1d54a, 0x1d550, -- 0x1d552, 0x1d6a5, -- 0x1d6a8, 0x1d7cb, -- 0x1d7ce, 0x1d7ff, -- 0x1f000, 0x1f02b, -- 0x1f030, 0x1f093, -- 0x1f0a0, 0x1f0ae, -- 0x1f0b1, 0x1f0be, -- 0x1f0c1, 0x1f0cf, -- 0x1f0d1, 0x1f0df, -- 0x1f100, 0x1f10a, -- 0x1f110, 0x1f12e, -- 0x1f130, 0x1f169, -- 0x1f170, 0x1f19a, -- 0x1f1e6, 0x1f202, -- 0x1f210, 0x1f23a, -- 0x1f240, 0x1f248, -- 0x1f250, 0x1f251, -- 0x1f300, 0x1f320, -- 0x1f330, 0x1f335, -- 0x1f337, 0x1f37c, -- 0x1f380, 0x1f393, -- 0x1f3a0, 0x1f3c4, -- 0x1f3c6, 0x1f3ca, -- 0x1f3e0, 0x1f3f0, -- 0x1f400, 0x1f43e, -- 0x1f440, 0x1f440, -- 0x1f442, 0x1f4f7, -- 0x1f4f9, 0x1f4fc, -- 0x1f500, 0x1f53d, -- 0x1f550, 0x1f567, -- 0x1f5fb, 0x1f5ff, -- 0x1f601, 0x1f610, -- 0x1f612, 0x1f614, -- 0x1f616, 0x1f616, -- 0x1f618, 0x1f618, -- 0x1f61a, 0x1f61a, -- 0x1f61c, 0x1f61e, -- 0x1f620, 0x1f625, -- 0x1f628, 0x1f62b, -- 0x1f62d, 0x1f62d, -- 0x1f630, 0x1f633, -- 0x1f635, 0x1f640, -- 0x1f645, 0x1f64f, -- 0x1f680, 0x1f6c5, -- 0x1f700, 0x1f773, -- 0x20000, 0x2a6d6, -- 0x2a700, 0x2b734, -- 0x2b740, 0x2b81d, -- 0x2f800, 0x2fa1d, -- 0xe0001, 0xe0001, -- 0xe0020, 0xe007f, -- 0xe0100, 0xe01ef, -- 0xf0000, 0xffffd, -- 0x100000, 0x10fffd, --}; /* CR_Graph */ -- --/* 'Lower': [[:Lower:]] */ --#define CR_Lower CR_Lowercase -- --/* 'Print': [[:Print:]] */ --static const OnigCodePoint CR_Print[] = { -- 503, -- 0x0020, 0x007e, -- 0x00a0, 0x0377, -- 0x037a, 0x037e, -- 0x0384, 0x038a, -- 0x038c, 0x038c, -- 0x038e, 0x03a1, -- 0x03a3, 0x0527, -- 0x0531, 0x0556, -- 0x0559, 0x055f, -- 0x0561, 0x0587, -- 0x0589, 0x058a, -- 0x0591, 0x05c7, -- 0x05d0, 0x05ea, -- 0x05f0, 0x05f4, -- 0x0600, 0x0603, -- 0x0606, 0x061b, -- 0x061e, 0x070d, -- 0x070f, 0x074a, -- 0x074d, 0x07b1, -- 0x07c0, 0x07fa, -- 0x0800, 0x082d, -- 0x0830, 0x083e, -- 0x0840, 0x085b, -- 0x085e, 0x085e, -- 0x0900, 0x0977, -- 0x0979, 0x097f, -- 0x0981, 0x0983, -- 0x0985, 0x098c, -- 0x098f, 0x0990, -- 0x0993, 0x09a8, -- 0x09aa, 0x09b0, -- 0x09b2, 0x09b2, -- 0x09b6, 0x09b9, -- 0x09bc, 0x09c4, -- 0x09c7, 0x09c8, -- 0x09cb, 0x09ce, -- 0x09d7, 0x09d7, -- 0x09dc, 0x09dd, -- 0x09df, 0x09e3, -- 0x09e6, 0x09fb, -- 0x0a01, 0x0a03, -- 0x0a05, 0x0a0a, -- 0x0a0f, 0x0a10, -- 0x0a13, 0x0a28, -- 0x0a2a, 0x0a30, -- 0x0a32, 0x0a33, -- 0x0a35, 0x0a36, -- 0x0a38, 0x0a39, -- 0x0a3c, 0x0a3c, -- 0x0a3e, 0x0a42, -- 0x0a47, 0x0a48, -- 0x0a4b, 0x0a4d, -- 0x0a51, 0x0a51, -- 0x0a59, 0x0a5c, -- 0x0a5e, 0x0a5e, -- 0x0a66, 0x0a75, -- 0x0a81, 0x0a83, -- 0x0a85, 0x0a8d, -- 0x0a8f, 0x0a91, -- 0x0a93, 0x0aa8, -- 0x0aaa, 0x0ab0, -- 0x0ab2, 0x0ab3, -- 0x0ab5, 0x0ab9, -- 0x0abc, 0x0ac5, -- 0x0ac7, 0x0ac9, -- 0x0acb, 0x0acd, -- 0x0ad0, 0x0ad0, -- 0x0ae0, 0x0ae3, -- 0x0ae6, 0x0aef, -- 0x0af1, 0x0af1, -- 0x0b01, 0x0b03, -- 0x0b05, 0x0b0c, -- 0x0b0f, 0x0b10, -- 0x0b13, 0x0b28, -- 0x0b2a, 0x0b30, -- 0x0b32, 0x0b33, -- 0x0b35, 0x0b39, -- 0x0b3c, 0x0b44, -- 0x0b47, 0x0b48, -- 0x0b4b, 0x0b4d, -- 0x0b56, 0x0b57, -- 0x0b5c, 0x0b5d, -- 0x0b5f, 0x0b63, -- 0x0b66, 0x0b77, -- 0x0b82, 0x0b83, -- 0x0b85, 0x0b8a, -- 0x0b8e, 0x0b90, -- 0x0b92, 0x0b95, -- 0x0b99, 0x0b9a, -- 0x0b9c, 0x0b9c, -- 0x0b9e, 0x0b9f, -- 0x0ba3, 0x0ba4, -- 0x0ba8, 0x0baa, -- 0x0bae, 0x0bb9, -- 0x0bbe, 0x0bc2, -- 0x0bc6, 0x0bc8, -- 0x0bca, 0x0bcd, -- 0x0bd0, 0x0bd0, -- 0x0bd7, 0x0bd7, -- 0x0be6, 0x0bfa, -- 0x0c01, 0x0c03, -- 0x0c05, 0x0c0c, -- 0x0c0e, 0x0c10, -- 0x0c12, 0x0c28, -- 0x0c2a, 0x0c33, -- 0x0c35, 0x0c39, -- 0x0c3d, 0x0c44, -- 0x0c46, 0x0c48, -- 0x0c4a, 0x0c4d, -- 0x0c55, 0x0c56, -- 0x0c58, 0x0c59, -- 0x0c60, 0x0c63, -- 0x0c66, 0x0c6f, -- 0x0c78, 0x0c7f, -- 0x0c82, 0x0c83, -- 0x0c85, 0x0c8c, -- 0x0c8e, 0x0c90, -- 0x0c92, 0x0ca8, -- 0x0caa, 0x0cb3, -- 0x0cb5, 0x0cb9, -- 0x0cbc, 0x0cc4, -- 0x0cc6, 0x0cc8, -- 0x0cca, 0x0ccd, -- 0x0cd5, 0x0cd6, -- 0x0cde, 0x0cde, -- 0x0ce0, 0x0ce3, -- 0x0ce6, 0x0cef, -- 0x0cf1, 0x0cf2, -- 0x0d02, 0x0d03, -- 0x0d05, 0x0d0c, -- 0x0d0e, 0x0d10, -- 0x0d12, 0x0d3a, -- 0x0d3d, 0x0d44, -- 0x0d46, 0x0d48, -- 0x0d4a, 0x0d4e, -- 0x0d57, 0x0d57, -- 0x0d60, 0x0d63, -- 0x0d66, 0x0d75, -- 0x0d79, 0x0d7f, -- 0x0d82, 0x0d83, -- 0x0d85, 0x0d96, -- 0x0d9a, 0x0db1, -- 0x0db3, 0x0dbb, -- 0x0dbd, 0x0dbd, -- 0x0dc0, 0x0dc6, -- 0x0dca, 0x0dca, -- 0x0dcf, 0x0dd4, -- 0x0dd6, 0x0dd6, -- 0x0dd8, 0x0ddf, -- 0x0df2, 0x0df4, -- 0x0e01, 0x0e3a, -- 0x0e3f, 0x0e5b, -- 0x0e81, 0x0e82, -- 0x0e84, 0x0e84, -- 0x0e87, 0x0e88, -- 0x0e8a, 0x0e8a, -- 0x0e8d, 0x0e8d, -- 0x0e94, 0x0e97, -- 0x0e99, 0x0e9f, -- 0x0ea1, 0x0ea3, -- 0x0ea5, 0x0ea5, -- 0x0ea7, 0x0ea7, -- 0x0eaa, 0x0eab, -- 0x0ead, 0x0eb9, -- 0x0ebb, 0x0ebd, -- 0x0ec0, 0x0ec4, -- 0x0ec6, 0x0ec6, -- 0x0ec8, 0x0ecd, -- 0x0ed0, 0x0ed9, -- 0x0edc, 0x0edd, -- 0x0f00, 0x0f47, -- 0x0f49, 0x0f6c, -- 0x0f71, 0x0f97, -- 0x0f99, 0x0fbc, -- 0x0fbe, 0x0fcc, -- 0x0fce, 0x0fda, -- 0x1000, 0x10c5, -- 0x10d0, 0x10fc, -- 0x1100, 0x1248, -- 0x124a, 0x124d, -- 0x1250, 0x1256, -- 0x1258, 0x1258, -- 0x125a, 0x125d, -- 0x1260, 0x1288, -- 0x128a, 0x128d, -- 0x1290, 0x12b0, -- 0x12b2, 0x12b5, -- 0x12b8, 0x12be, -- 0x12c0, 0x12c0, -- 0x12c2, 0x12c5, -- 0x12c8, 0x12d6, -- 0x12d8, 0x1310, -- 0x1312, 0x1315, -- 0x1318, 0x135a, -- 0x135d, 0x137c, -- 0x1380, 0x1399, -- 0x13a0, 0x13f4, -- 0x1400, 0x169c, -- 0x16a0, 0x16f0, -- 0x1700, 0x170c, -- 0x170e, 0x1714, -- 0x1720, 0x1736, -- 0x1740, 0x1753, -- 0x1760, 0x176c, -- 0x176e, 0x1770, -- 0x1772, 0x1773, -- 0x1780, 0x17dd, -- 0x17e0, 0x17e9, -- 0x17f0, 0x17f9, -- 0x1800, 0x180e, -- 0x1810, 0x1819, -- 0x1820, 0x1877, -- 0x1880, 0x18aa, -- 0x18b0, 0x18f5, -- 0x1900, 0x191c, -- 0x1920, 0x192b, -- 0x1930, 0x193b, -- 0x1940, 0x1940, -- 0x1944, 0x196d, -- 0x1970, 0x1974, -- 0x1980, 0x19ab, -- 0x19b0, 0x19c9, -- 0x19d0, 0x19da, -- 0x19de, 0x1a1b, -- 0x1a1e, 0x1a5e, -- 0x1a60, 0x1a7c, -- 0x1a7f, 0x1a89, -- 0x1a90, 0x1a99, -- 0x1aa0, 0x1aad, -- 0x1b00, 0x1b4b, -- 0x1b50, 0x1b7c, -- 0x1b80, 0x1baa, -- 0x1bae, 0x1bb9, -- 0x1bc0, 0x1bf3, -- 0x1bfc, 0x1c37, -- 0x1c3b, 0x1c49, -- 0x1c4d, 0x1c7f, -- 0x1cd0, 0x1cf2, -- 0x1d00, 0x1de6, -- 0x1dfc, 0x1f15, -- 0x1f18, 0x1f1d, -- 0x1f20, 0x1f45, -- 0x1f48, 0x1f4d, -- 0x1f50, 0x1f57, -- 0x1f59, 0x1f59, -- 0x1f5b, 0x1f5b, -- 0x1f5d, 0x1f5d, -- 0x1f5f, 0x1f7d, -- 0x1f80, 0x1fb4, -- 0x1fb6, 0x1fc4, -- 0x1fc6, 0x1fd3, -- 0x1fd6, 0x1fdb, -- 0x1fdd, 0x1fef, -- 0x1ff2, 0x1ff4, -- 0x1ff6, 0x1ffe, -- 0x2000, 0x2027, -- 0x202a, 0x2064, -- 0x206a, 0x2071, -- 0x2074, 0x208e, -- 0x2090, 0x209c, -- 0x20a0, 0x20b9, -- 0x20d0, 0x20f0, -- 0x2100, 0x2189, -- 0x2190, 0x23f3, -- 0x2400, 0x2426, -- 0x2440, 0x244a, -- 0x2460, 0x26ff, -- 0x2701, 0x27ca, -- 0x27cc, 0x27cc, -- 0x27ce, 0x2b4c, -- 0x2b50, 0x2b59, -- 0x2c00, 0x2c2e, -- 0x2c30, 0x2c5e, -- 0x2c60, 0x2cf1, -- 0x2cf9, 0x2d25, -- 0x2d30, 0x2d65, -- 0x2d6f, 0x2d70, -- 0x2d7f, 0x2d96, -- 0x2da0, 0x2da6, -- 0x2da8, 0x2dae, -- 0x2db0, 0x2db6, -- 0x2db8, 0x2dbe, -- 0x2dc0, 0x2dc6, -- 0x2dc8, 0x2dce, -- 0x2dd0, 0x2dd6, -- 0x2dd8, 0x2dde, -- 0x2de0, 0x2e31, -- 0x2e80, 0x2e99, -- 0x2e9b, 0x2ef3, -- 0x2f00, 0x2fd5, -- 0x2ff0, 0x2ffb, -- 0x3000, 0x303f, -- 0x3041, 0x3096, -- 0x3099, 0x30ff, -- 0x3105, 0x312d, -- 0x3131, 0x318e, -- 0x3190, 0x31ba, -- 0x31c0, 0x31e3, -- 0x31f0, 0x321e, -- 0x3220, 0x32fe, -- 0x3300, 0x4db5, -- 0x4dc0, 0x9fcb, -- 0xa000, 0xa48c, -- 0xa490, 0xa4c6, -- 0xa4d0, 0xa62b, -- 0xa640, 0xa673, -- 0xa67c, 0xa697, -- 0xa6a0, 0xa6f7, -- 0xa700, 0xa78e, -- 0xa790, 0xa791, -- 0xa7a0, 0xa7a9, -- 0xa7fa, 0xa82b, -- 0xa830, 0xa839, -- 0xa840, 0xa877, -- 0xa880, 0xa8c4, -- 0xa8ce, 0xa8d9, -- 0xa8e0, 0xa8fb, -- 0xa900, 0xa953, -- 0xa95f, 0xa97c, -- 0xa980, 0xa9cd, -- 0xa9cf, 0xa9d9, -- 0xa9de, 0xa9df, -- 0xaa00, 0xaa36, -- 0xaa40, 0xaa4d, -- 0xaa50, 0xaa59, -- 0xaa5c, 0xaa7b, -- 0xaa80, 0xaac2, -- 0xaadb, 0xaadf, -- 0xab01, 0xab06, -- 0xab09, 0xab0e, -- 0xab11, 0xab16, -- 0xab20, 0xab26, -- 0xab28, 0xab2e, -- 0xabc0, 0xabed, -- 0xabf0, 0xabf9, -- 0xac00, 0xd7a3, -- 0xd7b0, 0xd7c6, -- 0xd7cb, 0xd7fb, -- 0xe000, 0xfa2d, -- 0xfa30, 0xfa6d, -- 0xfa70, 0xfad9, -- 0xfb00, 0xfb06, -- 0xfb13, 0xfb17, -- 0xfb1d, 0xfb36, -- 0xfb38, 0xfb3c, -- 0xfb3e, 0xfb3e, -- 0xfb40, 0xfb41, -- 0xfb43, 0xfb44, -- 0xfb46, 0xfbc1, -- 0xfbd3, 0xfd3f, -- 0xfd50, 0xfd8f, -- 0xfd92, 0xfdc7, -- 0xfdf0, 0xfdfd, -- 0xfe00, 0xfe19, -- 0xfe20, 0xfe26, -- 0xfe30, 0xfe52, -- 0xfe54, 0xfe66, -- 0xfe68, 0xfe6b, -- 0xfe70, 0xfe74, -- 0xfe76, 0xfefc, -- 0xfeff, 0xfeff, -- 0xff01, 0xffbe, -- 0xffc2, 0xffc7, -- 0xffca, 0xffcf, -- 0xffd2, 0xffd7, -- 0xffda, 0xffdc, -- 0xffe0, 0xffe6, -- 0xffe8, 0xffee, -- 0xfff9, 0xfffd, -- 0x10000, 0x1000b, -- 0x1000d, 0x10026, -- 0x10028, 0x1003a, -- 0x1003c, 0x1003d, -- 0x1003f, 0x1004d, -- 0x10050, 0x1005d, -- 0x10080, 0x100fa, -- 0x10100, 0x10102, -- 0x10107, 0x10133, -- 0x10137, 0x1018a, -- 0x10190, 0x1019b, -- 0x101d0, 0x101fd, -- 0x10280, 0x1029c, -- 0x102a0, 0x102d0, -- 0x10300, 0x1031e, -- 0x10320, 0x10323, -- 0x10330, 0x1034a, -- 0x10380, 0x1039d, -- 0x1039f, 0x103c3, -- 0x103c8, 0x103d5, -- 0x10400, 0x1049d, -- 0x104a0, 0x104a9, -- 0x10800, 0x10805, -- 0x10808, 0x10808, -- 0x1080a, 0x10835, -- 0x10837, 0x10838, -- 0x1083c, 0x1083c, -- 0x1083f, 0x10855, -- 0x10857, 0x1085f, -- 0x10900, 0x1091b, -- 0x1091f, 0x10939, -- 0x1093f, 0x1093f, -- 0x10a00, 0x10a03, -- 0x10a05, 0x10a06, -- 0x10a0c, 0x10a13, -- 0x10a15, 0x10a17, -- 0x10a19, 0x10a33, -- 0x10a38, 0x10a3a, -- 0x10a3f, 0x10a47, -- 0x10a50, 0x10a58, -- 0x10a60, 0x10a7f, -- 0x10b00, 0x10b35, -- 0x10b39, 0x10b55, -- 0x10b58, 0x10b72, -- 0x10b78, 0x10b7f, -- 0x10c00, 0x10c48, -- 0x10e60, 0x10e7e, -- 0x11000, 0x1104d, -- 0x11052, 0x1106f, -- 0x11080, 0x110c1, -- 0x12000, 0x1236e, -- 0x12400, 0x12462, -- 0x12470, 0x12473, -- 0x13000, 0x1342e, -- 0x16800, 0x16a38, -- 0x1b000, 0x1b001, -- 0x1d000, 0x1d0f5, -- 0x1d100, 0x1d126, -- 0x1d129, 0x1d1dd, -- 0x1d200, 0x1d245, -- 0x1d300, 0x1d356, -- 0x1d360, 0x1d371, -- 0x1d400, 0x1d454, -- 0x1d456, 0x1d49c, -- 0x1d49e, 0x1d49f, -- 0x1d4a2, 0x1d4a2, -- 0x1d4a5, 0x1d4a6, -- 0x1d4a9, 0x1d4ac, -- 0x1d4ae, 0x1d4b9, -- 0x1d4bb, 0x1d4bb, -- 0x1d4bd, 0x1d4c3, -- 0x1d4c5, 0x1d505, -- 0x1d507, 0x1d50a, -- 0x1d50d, 0x1d514, -- 0x1d516, 0x1d51c, -- 0x1d51e, 0x1d539, -- 0x1d53b, 0x1d53e, -- 0x1d540, 0x1d544, -- 0x1d546, 0x1d546, -- 0x1d54a, 0x1d550, -- 0x1d552, 0x1d6a5, -- 0x1d6a8, 0x1d7cb, -- 0x1d7ce, 0x1d7ff, -- 0x1f000, 0x1f02b, -- 0x1f030, 0x1f093, -- 0x1f0a0, 0x1f0ae, -- 0x1f0b1, 0x1f0be, -- 0x1f0c1, 0x1f0cf, -- 0x1f0d1, 0x1f0df, -- 0x1f100, 0x1f10a, -- 0x1f110, 0x1f12e, -- 0x1f130, 0x1f169, -- 0x1f170, 0x1f19a, -- 0x1f1e6, 0x1f202, -- 0x1f210, 0x1f23a, -- 0x1f240, 0x1f248, -- 0x1f250, 0x1f251, -- 0x1f300, 0x1f320, -- 0x1f330, 0x1f335, -- 0x1f337, 0x1f37c, -- 0x1f380, 0x1f393, -- 0x1f3a0, 0x1f3c4, -- 0x1f3c6, 0x1f3ca, -- 0x1f3e0, 0x1f3f0, -- 0x1f400, 0x1f43e, -- 0x1f440, 0x1f440, -- 0x1f442, 0x1f4f7, -- 0x1f4f9, 0x1f4fc, -- 0x1f500, 0x1f53d, -- 0x1f550, 0x1f567, -- 0x1f5fb, 0x1f5ff, -- 0x1f601, 0x1f610, -- 0x1f612, 0x1f614, -- 0x1f616, 0x1f616, -- 0x1f618, 0x1f618, -- 0x1f61a, 0x1f61a, -- 0x1f61c, 0x1f61e, -- 0x1f620, 0x1f625, -- 0x1f628, 0x1f62b, -- 0x1f62d, 0x1f62d, -- 0x1f630, 0x1f633, -- 0x1f635, 0x1f640, -- 0x1f645, 0x1f64f, -- 0x1f680, 0x1f6c5, -- 0x1f700, 0x1f773, -- 0x20000, 0x2a6d6, -- 0x2a700, 0x2b734, -- 0x2b740, 0x2b81d, -- 0x2f800, 0x2fa1d, -- 0xe0001, 0xe0001, -- 0xe0020, 0xe007f, -- 0xe0100, 0xe01ef, -- 0xf0000, 0xffffd, -- 0x100000, 0x10fffd, --}; /* CR_Print */ -- --/* 'Punct': [[:Punct:]] */ --#define CR_Punct CR_P -- --/* 'Space': [[:Space:]] */ --#define CR_Space CR_White_Space -- --/* 'Upper': [[:Upper:]] */ --#define CR_Upper CR_Uppercase -- --/* 'XDigit': [[:XDigit:]] */ --#define CR_XDigit CR_ASCII_Hex_Digit -- --/* 'Word': [[:Word:]] */ --static const OnigCodePoint CR_Word[] = { -- 514, -- 0x0030, 0x0039, -- 0x0041, 0x005a, -- 0x005f, 0x005f, -- 0x0061, 0x007a, -- 0x00aa, 0x00aa, -- 0x00b5, 0x00b5, -- 0x00ba, 0x00ba, -- 0x00c0, 0x00d6, -- 0x00d8, 0x00f6, -- 0x00f8, 0x02c1, -- 0x02c6, 0x02d1, -- 0x02e0, 0x02e4, -- 0x02ec, 0x02ec, -- 0x02ee, 0x02ee, -- 0x0300, 0x0374, -- 0x0376, 0x0377, -- 0x037a, 0x037d, -- 0x0386, 0x0386, -- 0x0388, 0x038a, -- 0x038c, 0x038c, -- 0x038e, 0x03a1, -- 0x03a3, 0x03f5, -- 0x03f7, 0x0481, -- 0x0483, 0x0527, -- 0x0531, 0x0556, -- 0x0559, 0x0559, -- 0x0561, 0x0587, -- 0x0591, 0x05bd, -- 0x05bf, 0x05bf, -- 0x05c1, 0x05c2, -- 0x05c4, 0x05c5, -- 0x05c7, 0x05c7, -- 0x05d0, 0x05ea, -- 0x05f0, 0x05f2, -- 0x0610, 0x061a, -- 0x0620, 0x0669, -- 0x066e, 0x06d3, -- 0x06d5, 0x06dc, -- 0x06df, 0x06e8, -- 0x06ea, 0x06fc, -- 0x06ff, 0x06ff, -- 0x0710, 0x074a, -- 0x074d, 0x07b1, -- 0x07c0, 0x07f5, -- 0x07fa, 0x07fa, -- 0x0800, 0x082d, -- 0x0840, 0x085b, -- 0x0900, 0x0963, -- 0x0966, 0x096f, -- 0x0971, 0x0977, -- 0x0979, 0x097f, -- 0x0981, 0x0983, -- 0x0985, 0x098c, -- 0x098f, 0x0990, -- 0x0993, 0x09a8, -- 0x09aa, 0x09b0, -- 0x09b2, 0x09b2, -- 0x09b6, 0x09b9, -- 0x09bc, 0x09c4, -- 0x09c7, 0x09c8, -- 0x09cb, 0x09ce, -- 0x09d7, 0x09d7, -- 0x09dc, 0x09dd, -- 0x09df, 0x09e3, -- 0x09e6, 0x09f1, -- 0x0a01, 0x0a03, -- 0x0a05, 0x0a0a, -- 0x0a0f, 0x0a10, -- 0x0a13, 0x0a28, -- 0x0a2a, 0x0a30, -- 0x0a32, 0x0a33, -- 0x0a35, 0x0a36, -- 0x0a38, 0x0a39, -- 0x0a3c, 0x0a3c, -- 0x0a3e, 0x0a42, -- 0x0a47, 0x0a48, -- 0x0a4b, 0x0a4d, -- 0x0a51, 0x0a51, -- 0x0a59, 0x0a5c, -- 0x0a5e, 0x0a5e, -- 0x0a66, 0x0a75, -- 0x0a81, 0x0a83, -- 0x0a85, 0x0a8d, -- 0x0a8f, 0x0a91, -- 0x0a93, 0x0aa8, -- 0x0aaa, 0x0ab0, -- 0x0ab2, 0x0ab3, -- 0x0ab5, 0x0ab9, -- 0x0abc, 0x0ac5, -- 0x0ac7, 0x0ac9, -- 0x0acb, 0x0acd, -- 0x0ad0, 0x0ad0, -- 0x0ae0, 0x0ae3, -- 0x0ae6, 0x0aef, -- 0x0b01, 0x0b03, -- 0x0b05, 0x0b0c, -- 0x0b0f, 0x0b10, -- 0x0b13, 0x0b28, -- 0x0b2a, 0x0b30, -- 0x0b32, 0x0b33, -- 0x0b35, 0x0b39, -- 0x0b3c, 0x0b44, -- 0x0b47, 0x0b48, -- 0x0b4b, 0x0b4d, -- 0x0b56, 0x0b57, -- 0x0b5c, 0x0b5d, -- 0x0b5f, 0x0b63, -- 0x0b66, 0x0b6f, -- 0x0b71, 0x0b71, -- 0x0b82, 0x0b83, -- 0x0b85, 0x0b8a, -- 0x0b8e, 0x0b90, -- 0x0b92, 0x0b95, -- 0x0b99, 0x0b9a, -- 0x0b9c, 0x0b9c, -- 0x0b9e, 0x0b9f, -- 0x0ba3, 0x0ba4, -- 0x0ba8, 0x0baa, -- 0x0bae, 0x0bb9, -- 0x0bbe, 0x0bc2, -- 0x0bc6, 0x0bc8, -- 0x0bca, 0x0bcd, -- 0x0bd0, 0x0bd0, -- 0x0bd7, 0x0bd7, -- 0x0be6, 0x0bef, -- 0x0c01, 0x0c03, -- 0x0c05, 0x0c0c, -- 0x0c0e, 0x0c10, -- 0x0c12, 0x0c28, -- 0x0c2a, 0x0c33, -- 0x0c35, 0x0c39, -- 0x0c3d, 0x0c44, -- 0x0c46, 0x0c48, -- 0x0c4a, 0x0c4d, -- 0x0c55, 0x0c56, -- 0x0c58, 0x0c59, -- 0x0c60, 0x0c63, -- 0x0c66, 0x0c6f, -- 0x0c82, 0x0c83, -- 0x0c85, 0x0c8c, -- 0x0c8e, 0x0c90, -- 0x0c92, 0x0ca8, -- 0x0caa, 0x0cb3, -- 0x0cb5, 0x0cb9, -- 0x0cbc, 0x0cc4, -- 0x0cc6, 0x0cc8, -- 0x0cca, 0x0ccd, -- 0x0cd5, 0x0cd6, -- 0x0cde, 0x0cde, -- 0x0ce0, 0x0ce3, -- 0x0ce6, 0x0cef, -- 0x0cf1, 0x0cf2, -- 0x0d02, 0x0d03, -- 0x0d05, 0x0d0c, -- 0x0d0e, 0x0d10, -- 0x0d12, 0x0d3a, -- 0x0d3d, 0x0d44, -- 0x0d46, 0x0d48, -- 0x0d4a, 0x0d4e, -- 0x0d57, 0x0d57, -- 0x0d60, 0x0d63, -- 0x0d66, 0x0d6f, -- 0x0d7a, 0x0d7f, -- 0x0d82, 0x0d83, -- 0x0d85, 0x0d96, -- 0x0d9a, 0x0db1, -- 0x0db3, 0x0dbb, -- 0x0dbd, 0x0dbd, -- 0x0dc0, 0x0dc6, -- 0x0dca, 0x0dca, -- 0x0dcf, 0x0dd4, -- 0x0dd6, 0x0dd6, -- 0x0dd8, 0x0ddf, -- 0x0df2, 0x0df3, -- 0x0e01, 0x0e3a, -- 0x0e40, 0x0e4e, -- 0x0e50, 0x0e59, -- 0x0e81, 0x0e82, -- 0x0e84, 0x0e84, -- 0x0e87, 0x0e88, -- 0x0e8a, 0x0e8a, -- 0x0e8d, 0x0e8d, -- 0x0e94, 0x0e97, -- 0x0e99, 0x0e9f, -- 0x0ea1, 0x0ea3, -- 0x0ea5, 0x0ea5, -- 0x0ea7, 0x0ea7, -- 0x0eaa, 0x0eab, -- 0x0ead, 0x0eb9, -- 0x0ebb, 0x0ebd, -- 0x0ec0, 0x0ec4, -- 0x0ec6, 0x0ec6, -- 0x0ec8, 0x0ecd, -- 0x0ed0, 0x0ed9, -- 0x0edc, 0x0edd, -- 0x0f00, 0x0f00, -- 0x0f18, 0x0f19, -- 0x0f20, 0x0f29, -- 0x0f35, 0x0f35, -- 0x0f37, 0x0f37, -- 0x0f39, 0x0f39, -- 0x0f3e, 0x0f47, -- 0x0f49, 0x0f6c, -- 0x0f71, 0x0f84, -- 0x0f86, 0x0f97, -- 0x0f99, 0x0fbc, -- 0x0fc6, 0x0fc6, -- 0x1000, 0x1049, -- 0x1050, 0x109d, -- 0x10a0, 0x10c5, -- 0x10d0, 0x10fa, -- 0x10fc, 0x10fc, -- 0x1100, 0x1248, -- 0x124a, 0x124d, -- 0x1250, 0x1256, -- 0x1258, 0x1258, -- 0x125a, 0x125d, -- 0x1260, 0x1288, -- 0x128a, 0x128d, -- 0x1290, 0x12b0, -- 0x12b2, 0x12b5, -- 0x12b8, 0x12be, -- 0x12c0, 0x12c0, -- 0x12c2, 0x12c5, -- 0x12c8, 0x12d6, -- 0x12d8, 0x1310, -- 0x1312, 0x1315, -- 0x1318, 0x135a, -- 0x135d, 0x135f, -- 0x1380, 0x138f, -- 0x13a0, 0x13f4, -- 0x1401, 0x166c, -- 0x166f, 0x167f, -- 0x1681, 0x169a, -- 0x16a0, 0x16ea, -- 0x16ee, 0x16f0, -- 0x1700, 0x170c, -- 0x170e, 0x1714, -- 0x1720, 0x1734, -- 0x1740, 0x1753, -- 0x1760, 0x176c, -- 0x176e, 0x1770, -- 0x1772, 0x1773, -- 0x1780, 0x17b3, -- 0x17b6, 0x17d3, -- 0x17d7, 0x17d7, -- 0x17dc, 0x17dd, -- 0x17e0, 0x17e9, -- 0x180b, 0x180d, -- 0x1810, 0x1819, -- 0x1820, 0x1877, -- 0x1880, 0x18aa, -- 0x18b0, 0x18f5, -- 0x1900, 0x191c, -- 0x1920, 0x192b, -- 0x1930, 0x193b, -- 0x1946, 0x196d, -- 0x1970, 0x1974, -- 0x1980, 0x19ab, -- 0x19b0, 0x19c9, -- 0x19d0, 0x19d9, -- 0x1a00, 0x1a1b, -- 0x1a20, 0x1a5e, -- 0x1a60, 0x1a7c, -- 0x1a7f, 0x1a89, -- 0x1a90, 0x1a99, -- 0x1aa7, 0x1aa7, -- 0x1b00, 0x1b4b, -- 0x1b50, 0x1b59, -- 0x1b6b, 0x1b73, -- 0x1b80, 0x1baa, -- 0x1bae, 0x1bb9, -- 0x1bc0, 0x1bf3, -- 0x1c00, 0x1c37, -- 0x1c40, 0x1c49, -- 0x1c4d, 0x1c7d, -- 0x1cd0, 0x1cd2, -- 0x1cd4, 0x1cf2, -- 0x1d00, 0x1de6, -- 0x1dfc, 0x1f15, -- 0x1f18, 0x1f1d, -- 0x1f20, 0x1f45, -- 0x1f48, 0x1f4d, -- 0x1f50, 0x1f57, -- 0x1f59, 0x1f59, -- 0x1f5b, 0x1f5b, -- 0x1f5d, 0x1f5d, -- 0x1f5f, 0x1f7d, -- 0x1f80, 0x1fb4, -- 0x1fb6, 0x1fbc, -- 0x1fbe, 0x1fbe, -- 0x1fc2, 0x1fc4, -- 0x1fc6, 0x1fcc, -- 0x1fd0, 0x1fd3, -- 0x1fd6, 0x1fdb, -- 0x1fe0, 0x1fec, -- 0x1ff2, 0x1ff4, -- 0x1ff6, 0x1ffc, -- 0x203f, 0x2040, -- 0x2054, 0x2054, -- 0x2071, 0x2071, -- 0x207f, 0x207f, -- 0x2090, 0x209c, -- 0x20d0, 0x20f0, -- 0x2102, 0x2102, -- 0x2107, 0x2107, -- 0x210a, 0x2113, -- 0x2115, 0x2115, -- 0x2119, 0x211d, -- 0x2124, 0x2124, -- 0x2126, 0x2126, -- 0x2128, 0x2128, -- 0x212a, 0x212d, -- 0x212f, 0x2139, -- 0x213c, 0x213f, -- 0x2145, 0x2149, -- 0x214e, 0x214e, -- 0x2160, 0x2188, -- 0x24b6, 0x24e9, -- 0x2c00, 0x2c2e, -- 0x2c30, 0x2c5e, -- 0x2c60, 0x2ce4, -- 0x2ceb, 0x2cf1, -- 0x2d00, 0x2d25, -- 0x2d30, 0x2d65, -- 0x2d6f, 0x2d6f, -- 0x2d7f, 0x2d96, -- 0x2da0, 0x2da6, -- 0x2da8, 0x2dae, -- 0x2db0, 0x2db6, -- 0x2db8, 0x2dbe, -- 0x2dc0, 0x2dc6, -- 0x2dc8, 0x2dce, -- 0x2dd0, 0x2dd6, -- 0x2dd8, 0x2dde, -- 0x2de0, 0x2dff, -- 0x2e2f, 0x2e2f, -- 0x3005, 0x3007, -- 0x3021, 0x302f, -- 0x3031, 0x3035, -- 0x3038, 0x303c, -- 0x3041, 0x3096, -- 0x3099, 0x309a, -- 0x309d, 0x309f, -- 0x30a1, 0x30fa, -- 0x30fc, 0x30ff, -- 0x3105, 0x312d, -- 0x3131, 0x318e, -- 0x31a0, 0x31ba, -- 0x31f0, 0x31ff, -- 0x3400, 0x4db5, -- 0x4e00, 0x9fcb, -- 0xa000, 0xa48c, -- 0xa4d0, 0xa4fd, -- 0xa500, 0xa60c, -- 0xa610, 0xa62b, -- 0xa640, 0xa672, -- 0xa67c, 0xa67d, -- 0xa67f, 0xa697, -- 0xa6a0, 0xa6f1, -- 0xa717, 0xa71f, -- 0xa722, 0xa788, -- 0xa78b, 0xa78e, -- 0xa790, 0xa791, -- 0xa7a0, 0xa7a9, -- 0xa7fa, 0xa827, -- 0xa840, 0xa873, -- 0xa880, 0xa8c4, -- 0xa8d0, 0xa8d9, -- 0xa8e0, 0xa8f7, -- 0xa8fb, 0xa8fb, -- 0xa900, 0xa92d, -- 0xa930, 0xa953, -- 0xa960, 0xa97c, -- 0xa980, 0xa9c0, -- 0xa9cf, 0xa9d9, -- 0xaa00, 0xaa36, -- 0xaa40, 0xaa4d, -- 0xaa50, 0xaa59, -- 0xaa60, 0xaa76, -- 0xaa7a, 0xaa7b, -- 0xaa80, 0xaac2, -- 0xaadb, 0xaadd, -- 0xab01, 0xab06, -- 0xab09, 0xab0e, -- 0xab11, 0xab16, -- 0xab20, 0xab26, -- 0xab28, 0xab2e, -- 0xabc0, 0xabea, -- 0xabec, 0xabed, -- 0xabf0, 0xabf9, -- 0xac00, 0xd7a3, -- 0xd7b0, 0xd7c6, -- 0xd7cb, 0xd7fb, -- 0xf900, 0xfa2d, -- 0xfa30, 0xfa6d, -- 0xfa70, 0xfad9, -- 0xfb00, 0xfb06, -- 0xfb13, 0xfb17, -- 0xfb1d, 0xfb28, -- 0xfb2a, 0xfb36, -- 0xfb38, 0xfb3c, -- 0xfb3e, 0xfb3e, -- 0xfb40, 0xfb41, -- 0xfb43, 0xfb44, -- 0xfb46, 0xfbb1, -- 0xfbd3, 0xfd3d, -- 0xfd50, 0xfd8f, -- 0xfd92, 0xfdc7, -- 0xfdf0, 0xfdfb, -- 0xfe00, 0xfe0f, -- 0xfe20, 0xfe26, -- 0xfe33, 0xfe34, -- 0xfe4d, 0xfe4f, -- 0xfe70, 0xfe74, -- 0xfe76, 0xfefc, -- 0xff10, 0xff19, -- 0xff21, 0xff3a, -- 0xff3f, 0xff3f, -- 0xff41, 0xff5a, -- 0xff66, 0xffbe, -- 0xffc2, 0xffc7, -- 0xffca, 0xffcf, -- 0xffd2, 0xffd7, -- 0xffda, 0xffdc, -- 0x10000, 0x1000b, -- 0x1000d, 0x10026, -- 0x10028, 0x1003a, -- 0x1003c, 0x1003d, -- 0x1003f, 0x1004d, -- 0x10050, 0x1005d, -- 0x10080, 0x100fa, -- 0x10140, 0x10174, -- 0x101fd, 0x101fd, -- 0x10280, 0x1029c, -- 0x102a0, 0x102d0, -- 0x10300, 0x1031e, -- 0x10330, 0x1034a, -- 0x10380, 0x1039d, -- 0x103a0, 0x103c3, -- 0x103c8, 0x103cf, -- 0x103d1, 0x103d5, -- 0x10400, 0x1049d, -- 0x104a0, 0x104a9, -- 0x10800, 0x10805, -- 0x10808, 0x10808, -- 0x1080a, 0x10835, -- 0x10837, 0x10838, -- 0x1083c, 0x1083c, -- 0x1083f, 0x10855, -- 0x10900, 0x10915, -- 0x10920, 0x10939, -- 0x10a00, 0x10a03, -- 0x10a05, 0x10a06, -- 0x10a0c, 0x10a13, -- 0x10a15, 0x10a17, -- 0x10a19, 0x10a33, -- 0x10a38, 0x10a3a, -- 0x10a3f, 0x10a3f, -- 0x10a60, 0x10a7c, -- 0x10b00, 0x10b35, -- 0x10b40, 0x10b55, -- 0x10b60, 0x10b72, -- 0x10c00, 0x10c48, -- 0x11000, 0x11046, -- 0x11066, 0x1106f, -- 0x11080, 0x110ba, -- 0x12000, 0x1236e, -- 0x12400, 0x12462, -- 0x13000, 0x1342e, -- 0x16800, 0x16a38, -- 0x1b000, 0x1b001, -- 0x1d165, 0x1d169, -- 0x1d16d, 0x1d172, -- 0x1d17b, 0x1d182, -- 0x1d185, 0x1d18b, -- 0x1d1aa, 0x1d1ad, -- 0x1d242, 0x1d244, -- 0x1d400, 0x1d454, -- 0x1d456, 0x1d49c, -- 0x1d49e, 0x1d49f, -- 0x1d4a2, 0x1d4a2, -- 0x1d4a5, 0x1d4a6, -- 0x1d4a9, 0x1d4ac, -- 0x1d4ae, 0x1d4b9, -- 0x1d4bb, 0x1d4bb, -- 0x1d4bd, 0x1d4c3, -- 0x1d4c5, 0x1d505, -- 0x1d507, 0x1d50a, -- 0x1d50d, 0x1d514, -- 0x1d516, 0x1d51c, -- 0x1d51e, 0x1d539, -- 0x1d53b, 0x1d53e, -- 0x1d540, 0x1d544, -- 0x1d546, 0x1d546, -- 0x1d54a, 0x1d550, -- 0x1d552, 0x1d6a5, -- 0x1d6a8, 0x1d6c0, -- 0x1d6c2, 0x1d6da, -- 0x1d6dc, 0x1d6fa, -- 0x1d6fc, 0x1d714, -- 0x1d716, 0x1d734, -- 0x1d736, 0x1d74e, -- 0x1d750, 0x1d76e, -- 0x1d770, 0x1d788, -- 0x1d78a, 0x1d7a8, -- 0x1d7aa, 0x1d7c2, -- 0x1d7c4, 0x1d7cb, -- 0x1d7ce, 0x1d7ff, -- 0x20000, 0x2a6d6, -- 0x2a700, 0x2b734, -- 0x2b740, 0x2b81d, -- 0x2f800, 0x2fa1d, -- 0xe0100, 0xe01ef, --}; /* CR_Word */ -- --/* 'Alnum': [[:Alnum:]] */ --static const OnigCodePoint CR_Alnum[] = { -- 509, -- 0x0030, 0x0039, -- 0x0041, 0x005a, -- 0x0061, 0x007a, -- 0x00aa, 0x00aa, -- 0x00b5, 0x00b5, -- 0x00ba, 0x00ba, -- 0x00c0, 0x00d6, -- 0x00d8, 0x00f6, -- 0x00f8, 0x02c1, -- 0x02c6, 0x02d1, -- 0x02e0, 0x02e4, -- 0x02ec, 0x02ec, -- 0x02ee, 0x02ee, -- 0x0345, 0x0345, -- 0x0370, 0x0374, -- 0x0376, 0x0377, -- 0x037a, 0x037d, -- 0x0386, 0x0386, -- 0x0388, 0x038a, -- 0x038c, 0x038c, -- 0x038e, 0x03a1, -- 0x03a3, 0x03f5, -- 0x03f7, 0x0481, -- 0x048a, 0x0527, -- 0x0531, 0x0556, -- 0x0559, 0x0559, -- 0x0561, 0x0587, -- 0x05b0, 0x05bd, -- 0x05bf, 0x05bf, -- 0x05c1, 0x05c2, -- 0x05c4, 0x05c5, -- 0x05c7, 0x05c7, -- 0x05d0, 0x05ea, -- 0x05f0, 0x05f2, -- 0x0610, 0x061a, -- 0x0620, 0x0657, -- 0x0659, 0x0669, -- 0x066e, 0x06d3, -- 0x06d5, 0x06dc, -- 0x06e1, 0x06e8, -- 0x06ed, 0x06fc, -- 0x06ff, 0x06ff, -- 0x0710, 0x073f, -- 0x074d, 0x07b1, -- 0x07c0, 0x07ea, -- 0x07f4, 0x07f5, -- 0x07fa, 0x07fa, -- 0x0800, 0x0817, -- 0x081a, 0x082c, -- 0x0840, 0x0858, -- 0x0900, 0x093b, -- 0x093d, 0x094c, -- 0x094e, 0x0950, -- 0x0955, 0x0963, -- 0x0966, 0x096f, -- 0x0971, 0x0977, -- 0x0979, 0x097f, -- 0x0981, 0x0983, -- 0x0985, 0x098c, -- 0x098f, 0x0990, -- 0x0993, 0x09a8, -- 0x09aa, 0x09b0, -- 0x09b2, 0x09b2, -- 0x09b6, 0x09b9, -- 0x09bd, 0x09c4, -- 0x09c7, 0x09c8, -- 0x09cb, 0x09cc, -- 0x09ce, 0x09ce, -- 0x09d7, 0x09d7, -- 0x09dc, 0x09dd, -- 0x09df, 0x09e3, -- 0x09e6, 0x09f1, -- 0x0a01, 0x0a03, -- 0x0a05, 0x0a0a, -- 0x0a0f, 0x0a10, -- 0x0a13, 0x0a28, -- 0x0a2a, 0x0a30, -- 0x0a32, 0x0a33, -- 0x0a35, 0x0a36, -- 0x0a38, 0x0a39, -- 0x0a3e, 0x0a42, -- 0x0a47, 0x0a48, -- 0x0a4b, 0x0a4c, -- 0x0a51, 0x0a51, -- 0x0a59, 0x0a5c, -- 0x0a5e, 0x0a5e, -- 0x0a66, 0x0a75, -- 0x0a81, 0x0a83, -- 0x0a85, 0x0a8d, -- 0x0a8f, 0x0a91, -- 0x0a93, 0x0aa8, -- 0x0aaa, 0x0ab0, -- 0x0ab2, 0x0ab3, -- 0x0ab5, 0x0ab9, -- 0x0abd, 0x0ac5, -- 0x0ac7, 0x0ac9, -- 0x0acb, 0x0acc, -- 0x0ad0, 0x0ad0, -- 0x0ae0, 0x0ae3, -- 0x0ae6, 0x0aef, -- 0x0b01, 0x0b03, -- 0x0b05, 0x0b0c, -- 0x0b0f, 0x0b10, -- 0x0b13, 0x0b28, -- 0x0b2a, 0x0b30, -- 0x0b32, 0x0b33, -- 0x0b35, 0x0b39, -- 0x0b3d, 0x0b44, -- 0x0b47, 0x0b48, -- 0x0b4b, 0x0b4c, -- 0x0b56, 0x0b57, -- 0x0b5c, 0x0b5d, -- 0x0b5f, 0x0b63, -- 0x0b66, 0x0b6f, -- 0x0b71, 0x0b71, -- 0x0b82, 0x0b83, -- 0x0b85, 0x0b8a, -- 0x0b8e, 0x0b90, -- 0x0b92, 0x0b95, -- 0x0b99, 0x0b9a, -- 0x0b9c, 0x0b9c, -- 0x0b9e, 0x0b9f, -- 0x0ba3, 0x0ba4, -- 0x0ba8, 0x0baa, -- 0x0bae, 0x0bb9, -- 0x0bbe, 0x0bc2, -- 0x0bc6, 0x0bc8, -- 0x0bca, 0x0bcc, -- 0x0bd0, 0x0bd0, -- 0x0bd7, 0x0bd7, -- 0x0be6, 0x0bef, -- 0x0c01, 0x0c03, -- 0x0c05, 0x0c0c, -- 0x0c0e, 0x0c10, -- 0x0c12, 0x0c28, -- 0x0c2a, 0x0c33, -- 0x0c35, 0x0c39, -- 0x0c3d, 0x0c44, -- 0x0c46, 0x0c48, -- 0x0c4a, 0x0c4c, -- 0x0c55, 0x0c56, -- 0x0c58, 0x0c59, -- 0x0c60, 0x0c63, -- 0x0c66, 0x0c6f, -- 0x0c82, 0x0c83, -- 0x0c85, 0x0c8c, -- 0x0c8e, 0x0c90, -- 0x0c92, 0x0ca8, -- 0x0caa, 0x0cb3, -- 0x0cb5, 0x0cb9, -- 0x0cbd, 0x0cc4, -- 0x0cc6, 0x0cc8, -- 0x0cca, 0x0ccc, -- 0x0cd5, 0x0cd6, -- 0x0cde, 0x0cde, -- 0x0ce0, 0x0ce3, -- 0x0ce6, 0x0cef, -- 0x0cf1, 0x0cf2, -- 0x0d02, 0x0d03, -- 0x0d05, 0x0d0c, -- 0x0d0e, 0x0d10, -- 0x0d12, 0x0d3a, -- 0x0d3d, 0x0d44, -- 0x0d46, 0x0d48, -- 0x0d4a, 0x0d4c, -- 0x0d4e, 0x0d4e, -- 0x0d57, 0x0d57, -- 0x0d60, 0x0d63, -- 0x0d66, 0x0d6f, -- 0x0d7a, 0x0d7f, -- 0x0d82, 0x0d83, -- 0x0d85, 0x0d96, -- 0x0d9a, 0x0db1, -- 0x0db3, 0x0dbb, -- 0x0dbd, 0x0dbd, -- 0x0dc0, 0x0dc6, -- 0x0dcf, 0x0dd4, -- 0x0dd6, 0x0dd6, -- 0x0dd8, 0x0ddf, -- 0x0df2, 0x0df3, -- 0x0e01, 0x0e3a, -- 0x0e40, 0x0e46, -- 0x0e4d, 0x0e4d, -- 0x0e50, 0x0e59, -- 0x0e81, 0x0e82, -- 0x0e84, 0x0e84, -- 0x0e87, 0x0e88, -- 0x0e8a, 0x0e8a, -- 0x0e8d, 0x0e8d, -- 0x0e94, 0x0e97, -- 0x0e99, 0x0e9f, -- 0x0ea1, 0x0ea3, -- 0x0ea5, 0x0ea5, -- 0x0ea7, 0x0ea7, -- 0x0eaa, 0x0eab, -- 0x0ead, 0x0eb9, -- 0x0ebb, 0x0ebd, -- 0x0ec0, 0x0ec4, -- 0x0ec6, 0x0ec6, -- 0x0ecd, 0x0ecd, -- 0x0ed0, 0x0ed9, -- 0x0edc, 0x0edd, -- 0x0f00, 0x0f00, -- 0x0f20, 0x0f29, -- 0x0f40, 0x0f47, -- 0x0f49, 0x0f6c, -- 0x0f71, 0x0f81, -- 0x0f88, 0x0f97, -- 0x0f99, 0x0fbc, -- 0x1000, 0x1036, -- 0x1038, 0x1038, -- 0x103b, 0x1049, -- 0x1050, 0x1062, -- 0x1065, 0x1068, -- 0x106e, 0x1086, -- 0x108e, 0x108e, -- 0x1090, 0x1099, -- 0x109c, 0x109d, -- 0x10a0, 0x10c5, -- 0x10d0, 0x10fa, -- 0x10fc, 0x10fc, -- 0x1100, 0x1248, -- 0x124a, 0x124d, -- 0x1250, 0x1256, -- 0x1258, 0x1258, -- 0x125a, 0x125d, -- 0x1260, 0x1288, -- 0x128a, 0x128d, -- 0x1290, 0x12b0, -- 0x12b2, 0x12b5, -- 0x12b8, 0x12be, -- 0x12c0, 0x12c0, -- 0x12c2, 0x12c5, -- 0x12c8, 0x12d6, -- 0x12d8, 0x1310, -- 0x1312, 0x1315, -- 0x1318, 0x135a, -- 0x135f, 0x135f, -- 0x1380, 0x138f, -- 0x13a0, 0x13f4, -- 0x1401, 0x166c, -- 0x166f, 0x167f, -- 0x1681, 0x169a, -- 0x16a0, 0x16ea, -- 0x16ee, 0x16f0, -- 0x1700, 0x170c, -- 0x170e, 0x1713, -- 0x1720, 0x1733, -- 0x1740, 0x1753, -- 0x1760, 0x176c, -- 0x176e, 0x1770, -- 0x1772, 0x1773, -- 0x1780, 0x17b3, -- 0x17b6, 0x17c8, -- 0x17d7, 0x17d7, -- 0x17dc, 0x17dc, -- 0x17e0, 0x17e9, -- 0x1810, 0x1819, -- 0x1820, 0x1877, -- 0x1880, 0x18aa, -- 0x18b0, 0x18f5, -- 0x1900, 0x191c, -- 0x1920, 0x192b, -- 0x1930, 0x1938, -- 0x1946, 0x196d, -- 0x1970, 0x1974, -- 0x1980, 0x19ab, -- 0x19b0, 0x19c9, -- 0x19d0, 0x19d9, -- 0x1a00, 0x1a1b, -- 0x1a20, 0x1a5e, -- 0x1a61, 0x1a74, -- 0x1a80, 0x1a89, -- 0x1a90, 0x1a99, -- 0x1aa7, 0x1aa7, -- 0x1b00, 0x1b33, -- 0x1b35, 0x1b43, -- 0x1b45, 0x1b4b, -- 0x1b50, 0x1b59, -- 0x1b80, 0x1ba9, -- 0x1bae, 0x1bb9, -- 0x1bc0, 0x1be5, -- 0x1be7, 0x1bf1, -- 0x1c00, 0x1c35, -- 0x1c40, 0x1c49, -- 0x1c4d, 0x1c7d, -- 0x1ce9, 0x1cec, -- 0x1cee, 0x1cf2, -- 0x1d00, 0x1dbf, -- 0x1e00, 0x1f15, -- 0x1f18, 0x1f1d, -- 0x1f20, 0x1f45, -- 0x1f48, 0x1f4d, -- 0x1f50, 0x1f57, -- 0x1f59, 0x1f59, -- 0x1f5b, 0x1f5b, -- 0x1f5d, 0x1f5d, -- 0x1f5f, 0x1f7d, -- 0x1f80, 0x1fb4, -- 0x1fb6, 0x1fbc, -- 0x1fbe, 0x1fbe, -- 0x1fc2, 0x1fc4, -- 0x1fc6, 0x1fcc, -- 0x1fd0, 0x1fd3, -- 0x1fd6, 0x1fdb, -- 0x1fe0, 0x1fec, -- 0x1ff2, 0x1ff4, -- 0x1ff6, 0x1ffc, -- 0x2071, 0x2071, -- 0x207f, 0x207f, -- 0x2090, 0x209c, -- 0x2102, 0x2102, -- 0x2107, 0x2107, -- 0x210a, 0x2113, -- 0x2115, 0x2115, -- 0x2119, 0x211d, -- 0x2124, 0x2124, -- 0x2126, 0x2126, -- 0x2128, 0x2128, -- 0x212a, 0x212d, -- 0x212f, 0x2139, -- 0x213c, 0x213f, -- 0x2145, 0x2149, -- 0x214e, 0x214e, -- 0x2160, 0x2188, -- 0x24b6, 0x24e9, -- 0x2c00, 0x2c2e, -- 0x2c30, 0x2c5e, -- 0x2c60, 0x2ce4, -- 0x2ceb, 0x2cee, -- 0x2d00, 0x2d25, -- 0x2d30, 0x2d65, -- 0x2d6f, 0x2d6f, -- 0x2d80, 0x2d96, -- 0x2da0, 0x2da6, -- 0x2da8, 0x2dae, -- 0x2db0, 0x2db6, -- 0x2db8, 0x2dbe, -- 0x2dc0, 0x2dc6, -- 0x2dc8, 0x2dce, -- 0x2dd0, 0x2dd6, -- 0x2dd8, 0x2dde, -- 0x2de0, 0x2dff, -- 0x2e2f, 0x2e2f, -- 0x3005, 0x3007, -- 0x3021, 0x3029, -- 0x3031, 0x3035, -- 0x3038, 0x303c, -- 0x3041, 0x3096, -- 0x309d, 0x309f, -- 0x30a1, 0x30fa, -- 0x30fc, 0x30ff, -- 0x3105, 0x312d, -- 0x3131, 0x318e, -- 0x31a0, 0x31ba, -- 0x31f0, 0x31ff, -- 0x3400, 0x4db5, -- 0x4e00, 0x9fcb, -- 0xa000, 0xa48c, -- 0xa4d0, 0xa4fd, -- 0xa500, 0xa60c, -- 0xa610, 0xa62b, -- 0xa640, 0xa66e, -- 0xa67f, 0xa697, -- 0xa6a0, 0xa6ef, -- 0xa717, 0xa71f, -- 0xa722, 0xa788, -- 0xa78b, 0xa78e, -- 0xa790, 0xa791, -- 0xa7a0, 0xa7a9, -- 0xa7fa, 0xa801, -- 0xa803, 0xa805, -- 0xa807, 0xa80a, -- 0xa80c, 0xa827, -- 0xa840, 0xa873, -- 0xa880, 0xa8c3, -- 0xa8d0, 0xa8d9, -- 0xa8f2, 0xa8f7, -- 0xa8fb, 0xa8fb, -- 0xa900, 0xa92a, -- 0xa930, 0xa952, -- 0xa960, 0xa97c, -- 0xa980, 0xa9b2, -- 0xa9b4, 0xa9bf, -- 0xa9cf, 0xa9d9, -- 0xaa00, 0xaa36, -- 0xaa40, 0xaa4d, -- 0xaa50, 0xaa59, -- 0xaa60, 0xaa76, -- 0xaa7a, 0xaa7a, -- 0xaa80, 0xaabe, -- 0xaac0, 0xaac0, -- 0xaac2, 0xaac2, -- 0xaadb, 0xaadd, -- 0xab01, 0xab06, -- 0xab09, 0xab0e, -- 0xab11, 0xab16, -- 0xab20, 0xab26, -- 0xab28, 0xab2e, -- 0xabc0, 0xabea, -- 0xabf0, 0xabf9, -- 0xac00, 0xd7a3, -- 0xd7b0, 0xd7c6, -- 0xd7cb, 0xd7fb, -- 0xf900, 0xfa2d, -- 0xfa30, 0xfa6d, -- 0xfa70, 0xfad9, -- 0xfb00, 0xfb06, -- 0xfb13, 0xfb17, -- 0xfb1d, 0xfb28, -- 0xfb2a, 0xfb36, -- 0xfb38, 0xfb3c, -- 0xfb3e, 0xfb3e, -- 0xfb40, 0xfb41, -- 0xfb43, 0xfb44, -- 0xfb46, 0xfbb1, -- 0xfbd3, 0xfd3d, -- 0xfd50, 0xfd8f, -- 0xfd92, 0xfdc7, -- 0xfdf0, 0xfdfb, -- 0xfe70, 0xfe74, -- 0xfe76, 0xfefc, -- 0xff10, 0xff19, -- 0xff21, 0xff3a, -- 0xff41, 0xff5a, -- 0xff66, 0xffbe, -- 0xffc2, 0xffc7, -- 0xffca, 0xffcf, -- 0xffd2, 0xffd7, -- 0xffda, 0xffdc, -- 0x10000, 0x1000b, -- 0x1000d, 0x10026, -- 0x10028, 0x1003a, -- 0x1003c, 0x1003d, -- 0x1003f, 0x1004d, -- 0x10050, 0x1005d, -- 0x10080, 0x100fa, -- 0x10140, 0x10174, -- 0x10280, 0x1029c, -- 0x102a0, 0x102d0, -- 0x10300, 0x1031e, -- 0x10330, 0x1034a, -- 0x10380, 0x1039d, -- 0x103a0, 0x103c3, -- 0x103c8, 0x103cf, -- 0x103d1, 0x103d5, -- 0x10400, 0x1049d, -- 0x104a0, 0x104a9, -- 0x10800, 0x10805, -- 0x10808, 0x10808, -- 0x1080a, 0x10835, -- 0x10837, 0x10838, -- 0x1083c, 0x1083c, -- 0x1083f, 0x10855, -- 0x10900, 0x10915, -- 0x10920, 0x10939, -- 0x10a00, 0x10a03, -- 0x10a05, 0x10a06, -- 0x10a0c, 0x10a13, -- 0x10a15, 0x10a17, -- 0x10a19, 0x10a33, -- 0x10a60, 0x10a7c, -- 0x10b00, 0x10b35, -- 0x10b40, 0x10b55, -- 0x10b60, 0x10b72, -- 0x10c00, 0x10c48, -- 0x11000, 0x11045, -- 0x11066, 0x1106f, -- 0x11082, 0x110b8, -- 0x12000, 0x1236e, -- 0x12400, 0x12462, -- 0x13000, 0x1342e, -- 0x16800, 0x16a38, -- 0x1b000, 0x1b001, -- 0x1d400, 0x1d454, -- 0x1d456, 0x1d49c, -- 0x1d49e, 0x1d49f, -- 0x1d4a2, 0x1d4a2, -- 0x1d4a5, 0x1d4a6, -- 0x1d4a9, 0x1d4ac, -- 0x1d4ae, 0x1d4b9, -- 0x1d4bb, 0x1d4bb, -- 0x1d4bd, 0x1d4c3, -- 0x1d4c5, 0x1d505, -- 0x1d507, 0x1d50a, -- 0x1d50d, 0x1d514, -- 0x1d516, 0x1d51c, -- 0x1d51e, 0x1d539, -- 0x1d53b, 0x1d53e, -- 0x1d540, 0x1d544, -- 0x1d546, 0x1d546, -- 0x1d54a, 0x1d550, -- 0x1d552, 0x1d6a5, -- 0x1d6a8, 0x1d6c0, -- 0x1d6c2, 0x1d6da, -- 0x1d6dc, 0x1d6fa, -- 0x1d6fc, 0x1d714, -- 0x1d716, 0x1d734, -- 0x1d736, 0x1d74e, -- 0x1d750, 0x1d76e, -- 0x1d770, 0x1d788, -- 0x1d78a, 0x1d7a8, -- 0x1d7aa, 0x1d7c2, -- 0x1d7c4, 0x1d7cb, -- 0x1d7ce, 0x1d7ff, -- 0x20000, 0x2a6d6, -- 0x2a700, 0x2b734, -- 0x2b740, 0x2b81d, -- 0x2f800, 0x2fa1d, --}; /* CR_Alnum */ -- --/* 'ASCII': [[:ASCII:]] */ --static const OnigCodePoint CR_ASCII[] = { -- 1, -- 0x0000, 0x007f, --}; /* CR_ASCII */ -- --static const OnigCodePoint* const CodeRanges[] = { -- CR_NEWLINE, -- CR_Alpha, -- CR_Blank, -- CR_Cntrl, -- CR_Digit, -- CR_Graph, -- CR_Lower, -- CR_Print, -- CR_Punct, -- CR_Space, -- CR_Upper, -- CR_XDigit, -- CR_Word, -- CR_Alnum, -- CR_ASCII, --#ifdef USE_UNICODE_PROPERTIES --#ifdef USE_UNICODE_PROPERTIES -- CR_Any, -- CR_Assigned, -- CR_C, -- CR_Cc, -- CR_Cf, -- CR_Cn, -- CR_Co, -- CR_Cs, -- CR_L, -- CR_Ll, -- CR_Lm, -- CR_Lo, -- CR_Lt, -- CR_Lu, -- CR_M, -- CR_Mc, -- CR_Me, -- CR_Mn, -- CR_N, -- CR_Nd, -- CR_Nl, -- CR_No, -- CR_P, -- CR_Pc, -- CR_Pd, -- CR_Pe, -- CR_Pf, -- CR_Pi, -- CR_Po, -- CR_Ps, -- CR_S, -- CR_Sc, -- CR_Sk, -- CR_Sm, -- CR_So, -- CR_Z, -- CR_Zl, -- CR_Zp, -- CR_Zs, -- CR_Math, -- CR_Alphabetic, -- CR_Lowercase, -- CR_Uppercase, -- CR_Cased, -- CR_Case_Ignorable, -- CR_Changes_When_Lowercased, -- CR_Changes_When_Uppercased, -- CR_Changes_When_Titlecased, -- CR_Changes_When_Casefolded, -- CR_Changes_When_Casemapped, -- CR_ID_Start, -- CR_ID_Continue, -- CR_XID_Start, -- CR_XID_Continue, -- CR_Default_Ignorable_Code_Point, -- CR_Grapheme_Extend, -- CR_Grapheme_Base, -- CR_Grapheme_Link, -- CR_Common, -- CR_Latin, -- CR_Greek, -- CR_Cyrillic, -- CR_Armenian, -- CR_Hebrew, -- CR_Arabic, -- CR_Syriac, -- CR_Thaana, -- CR_Devanagari, -- CR_Bengali, -- CR_Gurmukhi, -- CR_Gujarati, -- CR_Oriya, -- CR_Tamil, -- CR_Telugu, -- CR_Kannada, -- CR_Malayalam, -- CR_Sinhala, -- CR_Thai, -- CR_Lao, -- CR_Tibetan, -- CR_Myanmar, -- CR_Georgian, -- CR_Hangul, -- CR_Ethiopic, -- CR_Cherokee, -- CR_Canadian_Aboriginal, -- CR_Ogham, -- CR_Runic, -- CR_Khmer, -- CR_Mongolian, -- CR_Hiragana, -- CR_Katakana, -- CR_Bopomofo, -- CR_Han, -- CR_Yi, -- CR_Old_Italic, -- CR_Gothic, -- CR_Deseret, -- CR_Inherited, -- CR_Tagalog, -- CR_Hanunoo, -- CR_Buhid, -- CR_Tagbanwa, -- CR_Limbu, -- CR_Tai_Le, -- CR_Linear_B, -- CR_Ugaritic, -- CR_Shavian, -- CR_Osmanya, -- CR_Cypriot, -- CR_Braille, -- CR_Buginese, -- CR_Coptic, -- CR_New_Tai_Lue, -- CR_Glagolitic, -- CR_Tifinagh, -- CR_Syloti_Nagri, -- CR_Old_Persian, -- CR_Kharoshthi, -- CR_Balinese, -- CR_Cuneiform, -- CR_Phoenician, -- CR_Phags_Pa, -- CR_Nko, -- CR_Sundanese, -- CR_Lepcha, -- CR_Ol_Chiki, -- CR_Vai, -- CR_Saurashtra, -- CR_Kayah_Li, -- CR_Rejang, -- CR_Lycian, -- CR_Carian, -- CR_Lydian, -- CR_Cham, -- CR_Tai_Tham, -- CR_Tai_Viet, -- CR_Avestan, -- CR_Egyptian_Hieroglyphs, -- CR_Samaritan, -- CR_Lisu, -- CR_Bamum, -- CR_Javanese, -- CR_Meetei_Mayek, -- CR_Imperial_Aramaic, -- CR_Old_South_Arabian, -- CR_Inscriptional_Parthian, -- CR_Inscriptional_Pahlavi, -- CR_Old_Turkic, -- CR_Kaithi, -- CR_Batak, -- CR_Brahmi, -- CR_Mandaic, -- CR_White_Space, -- CR_Bidi_Control, -- CR_Join_Control, -- CR_Dash, -- CR_Hyphen, -- CR_Quotation_Mark, -- CR_Terminal_Punctuation, -- CR_Other_Math, -- CR_Hex_Digit, -- CR_ASCII_Hex_Digit, -- CR_Other_Alphabetic, -- CR_Ideographic, -- CR_Diacritic, -- CR_Extender, -- CR_Other_Lowercase, -- CR_Other_Uppercase, -- CR_Noncharacter_Code_Point, -- CR_Other_Grapheme_Extend, -- CR_IDS_Binary_Operator, -- CR_IDS_Trinary_Operator, -- CR_Radical, -- CR_Unified_Ideograph, -- CR_Other_Default_Ignorable_Code_Point, -- CR_Deprecated, -- CR_Soft_Dotted, -- CR_Logical_Order_Exception, -- CR_Other_ID_Start, -- CR_Other_ID_Continue, -- CR_STerm, -- CR_Variation_Selector, -- CR_Pattern_White_Space, -- CR_Pattern_Syntax, -- CR_Unknown, -- CR_Age_1_1, -- CR_Age_2_0, -- CR_Age_2_1, -- CR_Age_3_0, -- CR_Age_3_1, -- CR_Age_3_2, -- CR_Age_4_0, -- CR_Age_4_1, -- CR_Age_5_0, -- CR_Age_5_1, -- CR_Age_5_2, -- CR_Age_6_0, --#endif /* USE_UNICODE_PROPERTIES */ --#endif /* USE_UNICODE_PROPERTIES */ --}; --struct uniname2ctype_struct { -- int name, ctype; --}; -- --static const struct uniname2ctype_struct *uniname2ctype_p(const char *, unsigned int); -- --#ifndef USE_UNICODE_PROPERTIES --#define TOTAL_KEYWORDS 15 --#define MIN_WORD_LENGTH 4 --#define MAX_WORD_LENGTH 7 --#define MIN_HASH_VALUE 7 --#define MAX_HASH_VALUE 21 --/* maximum key range = 15, duplicates = 0 */ --#else /* USE_UNICODE_PROPERTIES */ --#define TOTAL_KEYWORDS 387 --#define MIN_WORD_LENGTH 1 --#define MAX_WORD_LENGTH 30 --#define MIN_HASH_VALUE 3 --#define MAX_HASH_VALUE 1741 --/* maximum key range = 1739, duplicates = 0 */ --#endif /* USE_UNICODE_PROPERTIES */ -- --#ifdef __GNUC__ --__inline --#else --#ifdef __cplusplus --inline --#endif --#endif --static unsigned int --uniname2ctype_hash (str, len) -- register const char *str; -- register unsigned int len; --{ --#ifndef USE_UNICODE_PROPERTIES -- static const unsigned char asso_values[] = --#else /* USE_UNICODE_PROPERTIES */ -- static const unsigned short asso_values[] = --#endif /* USE_UNICODE_PROPERTIES */ -- { --#ifndef USE_UNICODE_PROPERTIES -- 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, -- 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, -- 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, -- 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, -- 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, -- 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, -- 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, -- 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, -- 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, -- 22, 22, 22, 22, 22, 22, 22, 3, 13, 6, -- 4, 22, 22, 11, 22, 1, 22, 22, 10, 22, -- 2, 22, 1, 22, 10, 8, 4, 7, 22, 3, -- 4, 22, 22, 22, 22, 22, 22, 22 --#else /* USE_UNICODE_PROPERTIES */ -- 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, -- 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, -- 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, -- 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, -- 1742, 1742, 1742, 1742, 1742, 1742, 2, 1742, 9, 1, -- 2, 18, 5, 3, 4, 1742, 1742, 1742, 1742, 1742, -- 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, -- 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, -- 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, 1742, -- 1742, 1742, 1742, 1742, 1742, 1742, 1742, 8, 280, 6, -- 96, 67, 362, 294, 38, 9, 63, 517, 2, 213, -- 1, 4, 192, 3, 10, 57, 31, 316, 1, 549, -- 330, 567, 36, 1742, 1742, 1742, 1742, 1742 --#endif /* USE_UNICODE_PROPERTIES */ -- }; --#ifndef USE_UNICODE_PROPERTIES -- return len + asso_values[(unsigned char)str[2]] + asso_values[(unsigned char)str[0]]; --#else /* USE_UNICODE_PROPERTIES */ -- register int hval = len; -- -- switch (hval) -- { -- default: -- hval += asso_values[(unsigned char)str[15]]; -- /*FALLTHROUGH*/ -- case 15: -- case 14: -- case 13: -- case 12: -- hval += asso_values[(unsigned char)str[11]]; -- /*FALLTHROUGH*/ -- case 11: -- case 10: -- case 9: -- case 8: -- case 7: -- case 6: -- hval += asso_values[(unsigned char)str[5]]; -- /*FALLTHROUGH*/ -- case 5: -- hval += asso_values[(unsigned char)str[4]]; -- /*FALLTHROUGH*/ -- case 4: -- case 3: -- hval += asso_values[(unsigned char)str[2]]; -- /*FALLTHROUGH*/ -- case 2: -- hval += asso_values[(unsigned char)str[1]]; -- /*FALLTHROUGH*/ -- case 1: -- hval += asso_values[(unsigned char)str[0]]; -- break; -- } -- return hval + asso_values[(unsigned char)str[len - 1]]; --#endif /* USE_UNICODE_PROPERTIES */ --} -- --struct uniname2ctype_pool_t -- { --#ifndef USE_UNICODE_PROPERTIES -- char uniname2ctype_pool_str7[sizeof("print")]; -- char uniname2ctype_pool_str8[sizeof("punct")]; -- char uniname2ctype_pool_str9[sizeof("alpha")]; -- char uniname2ctype_pool_str10[sizeof("alnum")]; -- char uniname2ctype_pool_str11[sizeof("xdigit")]; -- char uniname2ctype_pool_str12[sizeof("newline")]; -- char uniname2ctype_pool_str13[sizeof("upper")]; -- char uniname2ctype_pool_str14[sizeof("ascii")]; -- char uniname2ctype_pool_str15[sizeof("cntrl")]; -- char uniname2ctype_pool_str16[sizeof("space")]; -- char uniname2ctype_pool_str17[sizeof("word")]; -- char uniname2ctype_pool_str18[sizeof("lower")]; -- char uniname2ctype_pool_str19[sizeof("graph")]; -- char uniname2ctype_pool_str20[sizeof("digit")]; -- char uniname2ctype_pool_str21[sizeof("blank")]; --#else /* USE_UNICODE_PROPERTIES */ -- char uniname2ctype_pool_str3[sizeof("n")]; -- char uniname2ctype_pool_str5[sizeof("l")]; -- char uniname2ctype_pool_str7[sizeof("nl")]; -- char uniname2ctype_pool_str8[sizeof("ll")]; -- char uniname2ctype_pool_str10[sizeof("cn")]; -- char uniname2ctype_pool_str11[sizeof("no")]; -- char uniname2ctype_pool_str12[sizeof("lo")]; -- char uniname2ctype_pool_str13[sizeof("c")]; -- char uniname2ctype_pool_str16[sizeof("co")]; -- char uniname2ctype_pool_str20[sizeof("cc")]; -- char uniname2ctype_pool_str21[sizeof("lao")]; -- char uniname2ctype_pool_str22[sizeof("laoo")]; -- char uniname2ctype_pool_str23[sizeof("lana")]; -- char uniname2ctype_pool_str26[sizeof("ci")]; -- char uniname2ctype_pool_str29[sizeof("qaac")]; -- char uniname2ctype_pool_str30[sizeof("vai")]; -- char uniname2ctype_pool_str31[sizeof("vaii")]; -- char uniname2ctype_pool_str32[sizeof("qaai")]; -- char uniname2ctype_pool_str34[sizeof("control")]; -- char uniname2ctype_pool_str37[sizeof("cari")]; -- char uniname2ctype_pool_str40[sizeof("carian")]; -- char uniname2ctype_pool_str42[sizeof("zl")]; -- char uniname2ctype_pool_str44[sizeof("oriya")]; -- char uniname2ctype_pool_str46[sizeof("latn")]; -- char uniname2ctype_pool_str47[sizeof("cntrl")]; -- char uniname2ctype_pool_str48[sizeof("latin")]; -- char uniname2ctype_pool_str51[sizeof("han")]; -- char uniname2ctype_pool_str53[sizeof("arabic")]; -- char uniname2ctype_pool_str54[sizeof("ital")]; -- char uniname2ctype_pool_str55[sizeof("hano")]; -- char uniname2ctype_pool_str60[sizeof("hani")]; -- char uniname2ctype_pool_str63[sizeof("hanunoo")]; -- char uniname2ctype_pool_str66[sizeof("lt")]; -- char uniname2ctype_pool_str67[sizeof("so")]; -- char uniname2ctype_pool_str69[sizeof("hira")]; -- char uniname2ctype_pool_str70[sizeof("nchar")]; -- char uniname2ctype_pool_str71[sizeof("sc")]; -- char uniname2ctype_pool_str73[sizeof("z")]; -- char uniname2ctype_pool_str74[sizeof("oalpha")]; -- char uniname2ctype_pool_str75[sizeof("tavt")]; -- char uniname2ctype_pool_str76[sizeof("cans")]; -- char uniname2ctype_pool_str84[sizeof("java")]; -- char uniname2ctype_pool_str88[sizeof("zinh")]; -- char uniname2ctype_pool_str89[sizeof("thaa")]; -- char uniname2ctype_pool_str90[sizeof("thai")]; -- char uniname2ctype_pool_str91[sizeof("variationselector")]; -- char uniname2ctype_pool_str92[sizeof("sinhala")]; -- char uniname2ctype_pool_str93[sizeof("joinc")]; -- char uniname2ctype_pool_str94[sizeof("ascii")]; -- char uniname2ctype_pool_str95[sizeof("initialpunctuation")]; -- char uniname2ctype_pool_str98[sizeof("other")]; -- char uniname2ctype_pool_str99[sizeof("joincontrol")]; -- char uniname2ctype_pool_str100[sizeof("thaana")]; -- char uniname2ctype_pool_str101[sizeof("avst")]; -- char uniname2ctype_pool_str103[sizeof("olower")]; -- char uniname2ctype_pool_str105[sizeof("othernumber")]; -- char uniname2ctype_pool_str106[sizeof("otherletter")]; -- char uniname2ctype_pool_str109[sizeof("sinh")]; -- char uniname2ctype_pool_str112[sizeof("tale")]; -- char uniname2ctype_pool_str114[sizeof("connectorpunctuation")]; -- char uniname2ctype_pool_str115[sizeof("s")]; -- char uniname2ctype_pool_str116[sizeof("di")]; -- char uniname2ctype_pool_str117[sizeof("vs")]; -- char uniname2ctype_pool_str119[sizeof("oidc")]; -- char uniname2ctype_pool_str120[sizeof("idc")]; -- char uniname2ctype_pool_str121[sizeof("odi")]; -- char uniname2ctype_pool_str122[sizeof("cs")]; -- char uniname2ctype_pool_str123[sizeof("avestan")]; -- char uniname2ctype_pool_str124[sizeof("dia")]; -- char uniname2ctype_pool_str125[sizeof("cher")]; -- char uniname2ctype_pool_str126[sizeof("inscriptionalparthian")]; -- char uniname2ctype_pool_str128[sizeof("shavian")]; -- char uniname2ctype_pool_str137[sizeof("radical")]; -- char uniname2ctype_pool_str143[sizeof("loe")]; -- char uniname2ctype_pool_str147[sizeof("diacritic")]; -- char uniname2ctype_pool_str148[sizeof("zzzz")]; -- char uniname2ctype_pool_str149[sizeof("ethi")]; -- char uniname2ctype_pool_str151[sizeof("canadianaboriginal")]; -- char uniname2ctype_pool_str152[sizeof("zs")]; -- char uniname2ctype_pool_str153[sizeof("othersymbol")]; -- char uniname2ctype_pool_str156[sizeof("olditalic")]; -- char uniname2ctype_pool_str161[sizeof("inscriptionalpahlavi")]; -- char uniname2ctype_pool_str162[sizeof("taiviet")]; -- char uniname2ctype_pool_str163[sizeof("lineseparator")]; -- char uniname2ctype_pool_str166[sizeof("otheridstart")]; -- char uniname2ctype_pool_str170[sizeof("oids")]; -- char uniname2ctype_pool_str171[sizeof("asciihexdigit")]; -- char uniname2ctype_pool_str172[sizeof("inherited")]; -- char uniname2ctype_pool_str174[sizeof("otherlowercase")]; -- char uniname2ctype_pool_str175[sizeof("terminalpunctuation")]; -- char uniname2ctype_pool_str176[sizeof("deva")]; -- char uniname2ctype_pool_str179[sizeof("otheralphabetic")]; -- char uniname2ctype_pool_str180[sizeof("ideo")]; -- char uniname2ctype_pool_str181[sizeof("noncharactercodepoint")]; -- char uniname2ctype_pool_str183[sizeof("otheridcontinue")]; -- char uniname2ctype_pool_str187[sizeof("taile")]; -- char uniname2ctype_pool_str190[sizeof("oldpersian")]; -- char uniname2ctype_pool_str192[sizeof("devanagari")]; -- char uniname2ctype_pool_str193[sizeof("letter")]; -- char uniname2ctype_pool_str195[sizeof("nd")]; -- char uniname2ctype_pool_str197[sizeof("idst")]; -- char uniname2ctype_pool_str198[sizeof("dsrt")]; -- char uniname2ctype_pool_str200[sizeof("titlecaseletter")]; -- char uniname2ctype_pool_str202[sizeof("po")]; -- char uniname2ctype_pool_str203[sizeof("dash")]; -- char uniname2ctype_pool_str206[sizeof("pc")]; -- char uniname2ctype_pool_str209[sizeof("letternumber")]; -- char uniname2ctype_pool_str212[sizeof("pi")]; -- char uniname2ctype_pool_str215[sizeof("javanese")]; -- char uniname2ctype_pool_str217[sizeof("mn")]; -- char uniname2ctype_pool_str218[sizeof("idstart")]; -- char uniname2ctype_pool_str220[sizeof("idcontinue")]; -- char uniname2ctype_pool_str222[sizeof("ids")]; -- char uniname2ctype_pool_str223[sizeof("alpha")]; -- char uniname2ctype_pool_str227[sizeof("mc")]; -- char uniname2ctype_pool_str229[sizeof("coptic")]; -- char uniname2ctype_pool_str234[sizeof("mongolian")]; -- char uniname2ctype_pool_str235[sizeof("common")]; -- char uniname2ctype_pool_str236[sizeof("armn")]; -- char uniname2ctype_pool_str237[sizeof("copt")]; -- char uniname2ctype_pool_str243[sizeof("cprt")]; -- char uniname2ctype_pool_str244[sizeof("armi")]; -- char uniname2ctype_pool_str245[sizeof("phli")]; -- char uniname2ctype_pool_str246[sizeof("prti")]; -- char uniname2ctype_pool_str250[sizeof("armenian")]; -- char uniname2ctype_pool_str251[sizeof("sd")]; -- char uniname2ctype_pool_str252[sizeof("mandaic")]; -- char uniname2ctype_pool_str255[sizeof("phoenician")]; -- char uniname2ctype_pool_str258[sizeof("taml")]; -- char uniname2ctype_pool_str261[sizeof("tamil")]; -- char uniname2ctype_pool_str268[sizeof("cased")]; -- char uniname2ctype_pool_str269[sizeof("cham")]; -- char uniname2ctype_pool_str270[sizeof("idsbinaryoperator")]; -- char uniname2ctype_pool_str271[sizeof("lepc")]; -- char uniname2ctype_pool_str275[sizeof("otherdefaultignorablecodepoint")]; -- char uniname2ctype_pool_str278[sizeof("print")]; -- char uniname2ctype_pool_str286[sizeof("osma")]; -- char uniname2ctype_pool_str292[sizeof("samr")]; -- char uniname2ctype_pool_str294[sizeof("math")]; -- char uniname2ctype_pool_str296[sizeof("linb")]; -- char uniname2ctype_pool_str297[sizeof("closepunctuation")]; -- char uniname2ctype_pool_str301[sizeof("otherpunctuation")]; -- char uniname2ctype_pool_str303[sizeof("bali")]; -- char uniname2ctype_pool_str306[sizeof("omath")]; -- char uniname2ctype_pool_str307[sizeof("samaritan")]; -- char uniname2ctype_pool_str308[sizeof("ps")]; -- char uniname2ctype_pool_str310[sizeof("arab")]; -- char uniname2ctype_pool_str311[sizeof("brai")]; -- char uniname2ctype_pool_str314[sizeof("taitham")]; -- char uniname2ctype_pool_str317[sizeof("linearb")]; -- char uniname2ctype_pool_str321[sizeof("lepcha")]; -- char uniname2ctype_pool_str322[sizeof("mand")]; -- char uniname2ctype_pool_str324[sizeof("mtei")]; -- char uniname2ctype_pool_str325[sizeof("term")]; -- char uniname2ctype_pool_str326[sizeof("glagolitic")]; -- char uniname2ctype_pool_str327[sizeof("privateuse")]; -- char uniname2ctype_pool_str328[sizeof("pe")]; -- char uniname2ctype_pool_str335[sizeof("deseret")]; -- char uniname2ctype_pool_str340[sizeof("brah")]; -- char uniname2ctype_pool_str341[sizeof("runr")]; -- char uniname2ctype_pool_str343[sizeof("othermath")]; -- char uniname2ctype_pool_str344[sizeof("runic")]; -- char uniname2ctype_pool_str345[sizeof("hang")]; -- char uniname2ctype_pool_str346[sizeof("ethiopic")]; -- char uniname2ctype_pool_str349[sizeof("me")]; -- char uniname2ctype_pool_str350[sizeof("patws")]; -- char uniname2ctype_pool_str353[sizeof("separator")]; -- char uniname2ctype_pool_str355[sizeof("tibt")]; -- char uniname2ctype_pool_str356[sizeof("gothic")]; -- char uniname2ctype_pool_str358[sizeof("tagbanwa")]; -- char uniname2ctype_pool_str359[sizeof("sarb")]; -- char uniname2ctype_pool_str361[sizeof("talu")]; -- char uniname2ctype_pool_str367[sizeof("tibetan")]; -- char uniname2ctype_pool_str371[sizeof("goth")]; -- char uniname2ctype_pool_str372[sizeof("rjng")]; -- char uniname2ctype_pool_str373[sizeof("hangul")]; -- char uniname2ctype_pool_str374[sizeof("bengali")]; -- char uniname2ctype_pool_str375[sizeof("hiragana")]; -- char uniname2ctype_pool_str376[sizeof("braille")]; -- char uniname2ctype_pool_str379[sizeof("geor")]; -- char uniname2ctype_pool_str380[sizeof("age=1.1")]; -- char uniname2ctype_pool_str381[sizeof("age=2.1")]; -- char uniname2ctype_pool_str382[sizeof("age=5.1")]; -- char uniname2ctype_pool_str383[sizeof("age=5.2")]; -- char uniname2ctype_pool_str384[sizeof("age=4.1")]; -- char uniname2ctype_pool_str385[sizeof("p")]; -- char uniname2ctype_pool_str386[sizeof("pd")]; -- char uniname2ctype_pool_str388[sizeof("lisu")]; -- char uniname2ctype_pool_str389[sizeof("age=2.0")]; -- char uniname2ctype_pool_str390[sizeof("age=5.0")]; -- char uniname2ctype_pool_str391[sizeof("age=6.0")]; -- char uniname2ctype_pool_str392[sizeof("age=4.0")]; -- char uniname2ctype_pool_str393[sizeof("graph")]; -- char uniname2ctype_pool_str395[sizeof("saur")]; -- char uniname2ctype_pool_str396[sizeof("space")]; -- char uniname2ctype_pool_str397[sizeof("age=3.1")]; -- char uniname2ctype_pool_str398[sizeof("age=3.2")]; -- char uniname2ctype_pool_str399[sizeof("hebr")]; -- char uniname2ctype_pool_str402[sizeof("bidic")]; -- char uniname2ctype_pool_str405[sizeof("age=3.0")]; -- char uniname2ctype_pool_str408[sizeof("bidicontrol")]; -- char uniname2ctype_pool_str413[sizeof("logicalorderexception")]; -- char uniname2ctype_pool_str420[sizeof("telu")]; -- char uniname2ctype_pool_str422[sizeof("zp")]; -- char uniname2ctype_pool_str427[sizeof("m")]; -- char uniname2ctype_pool_str430[sizeof("lm")]; -- char uniname2ctype_pool_str432[sizeof("idstrinaryoperator")]; -- char uniname2ctype_pool_str433[sizeof("balinese")]; -- char uniname2ctype_pool_str434[sizeof("uideo")]; -- char uniname2ctype_pool_str436[sizeof("spaceseparator")]; -- char uniname2ctype_pool_str438[sizeof("grext")]; -- char uniname2ctype_pool_str442[sizeof("alnum")]; -- char uniname2ctype_pool_str443[sizeof("oldturkic")]; -- char uniname2ctype_pool_str445[sizeof("xidc")]; -- char uniname2ctype_pool_str446[sizeof("idsb")]; -- char uniname2ctype_pool_str447[sizeof("ahex")]; -- char uniname2ctype_pool_str452[sizeof("format")]; -- char uniname2ctype_pool_str456[sizeof("caseignorable")]; -- char uniname2ctype_pool_str457[sizeof("tifinagh")]; -- char uniname2ctype_pool_str459[sizeof("sundanese")]; -- char uniname2ctype_pool_str462[sizeof("ext")]; -- char uniname2ctype_pool_str464[sizeof("saurashtra")]; -- char uniname2ctype_pool_str465[sizeof("patternwhitespace")]; -- char uniname2ctype_pool_str466[sizeof("digit")]; -- char uniname2ctype_pool_str474[sizeof("sund")]; -- char uniname2ctype_pool_str480[sizeof("decimalnumber")]; -- char uniname2ctype_pool_str484[sizeof("bopo")]; -- char uniname2ctype_pool_str485[sizeof("sm")]; -- char uniname2ctype_pool_str488[sizeof("otheruppercase")]; -- char uniname2ctype_pool_str493[sizeof("ideographic")]; -- char uniname2ctype_pool_str496[sizeof("xids")]; -- char uniname2ctype_pool_str497[sizeof("unassigned")]; -- char uniname2ctype_pool_str502[sizeof("phagspa")]; -- char uniname2ctype_pool_str506[sizeof("alphabetic")]; -- char uniname2ctype_pool_str508[sizeof("limb")]; -- char uniname2ctype_pool_str512[sizeof("xdigit")]; -- char uniname2ctype_pool_str513[sizeof("xidstart")]; -- char uniname2ctype_pool_str516[sizeof("mong")]; -- char uniname2ctype_pool_str518[sizeof("xidcontinue")]; -- char uniname2ctype_pool_str521[sizeof("assigned")]; -- char uniname2ctype_pool_str523[sizeof("ogam")]; -- char uniname2ctype_pool_str529[sizeof("nko")]; -- char uniname2ctype_pool_str530[sizeof("nkoo")]; -- char uniname2ctype_pool_str533[sizeof("olck")]; -- char uniname2ctype_pool_str534[sizeof("deprecated")]; -- char uniname2ctype_pool_str535[sizeof("brahmi")]; -- char uniname2ctype_pool_str536[sizeof("phag")]; -- char uniname2ctype_pool_str538[sizeof("kana")]; -- char uniname2ctype_pool_str540[sizeof("kali")]; -- char uniname2ctype_pool_str542[sizeof("changeswhenlowercased")]; -- char uniname2ctype_pool_str543[sizeof("extender")]; -- char uniname2ctype_pool_str550[sizeof("dep")]; -- char uniname2ctype_pool_str554[sizeof("olchiki")]; -- char uniname2ctype_pool_str562[sizeof("cwl")]; -- char uniname2ctype_pool_str563[sizeof("graphemebase")]; -- char uniname2ctype_pool_str565[sizeof("phnx")]; -- char uniname2ctype_pool_str573[sizeof("orkh")]; -- char uniname2ctype_pool_str576[sizeof("punct")]; -- char uniname2ctype_pool_str577[sizeof("khar")]; -- char uniname2ctype_pool_str580[sizeof("lower")]; -- char uniname2ctype_pool_str586[sizeof("sterm")]; -- char uniname2ctype_pool_str587[sizeof("yi")]; -- char uniname2ctype_pool_str588[sizeof("lyci")]; -- char uniname2ctype_pool_str589[sizeof("cyrl")]; -- char uniname2ctype_pool_str591[sizeof("lycian")]; -- char uniname2ctype_pool_str592[sizeof("finalpunctuation")]; -- char uniname2ctype_pool_str593[sizeof("orya")]; -- char uniname2ctype_pool_str594[sizeof("graphemeextend")]; -- char uniname2ctype_pool_str596[sizeof("kaithi")]; -- char uniname2ctype_pool_str597[sizeof("xpeo")]; -- char uniname2ctype_pool_str598[sizeof("yiii")]; -- char uniname2ctype_pool_str599[sizeof("kthi")]; -- char uniname2ctype_pool_str601[sizeof("cyrillic")]; -- char uniname2ctype_pool_str602[sizeof("glag")]; -- char uniname2ctype_pool_str605[sizeof("oupper")]; -- char uniname2ctype_pool_str617[sizeof("tagb")]; -- char uniname2ctype_pool_str620[sizeof("cwt")]; -- char uniname2ctype_pool_str623[sizeof("number")]; -- char uniname2ctype_pool_str625[sizeof("tglg")]; -- char uniname2ctype_pool_str626[sizeof("knda")]; -- char uniname2ctype_pool_str627[sizeof("lowercaseletter")]; -- char uniname2ctype_pool_str628[sizeof("changeswhentitlecased")]; -- char uniname2ctype_pool_str629[sizeof("softdotted")]; -- char uniname2ctype_pool_str632[sizeof("ugar")]; -- char uniname2ctype_pool_str634[sizeof("sylo")]; -- char uniname2ctype_pool_str636[sizeof("lu")]; -- char uniname2ctype_pool_str640[sizeof("tagalog")]; -- char uniname2ctype_pool_str643[sizeof("kharoshthi")]; -- char uniname2ctype_pool_str644[sizeof("syrc")]; -- char uniname2ctype_pool_str645[sizeof("kannada")]; -- char uniname2ctype_pool_str646[sizeof("beng")]; -- char uniname2ctype_pool_str647[sizeof("lowercase")]; -- char uniname2ctype_pool_str656[sizeof("shaw")]; -- char uniname2ctype_pool_str659[sizeof("patternsyntax")]; -- char uniname2ctype_pool_str660[sizeof("syriac")]; -- char uniname2ctype_pool_str663[sizeof("word")]; -- char uniname2ctype_pool_str667[sizeof("imperialaramaic")]; -- char uniname2ctype_pool_str672[sizeof("ugaritic")]; -- char uniname2ctype_pool_str675[sizeof("enclosingmark")]; -- char uniname2ctype_pool_str677[sizeof("georgian")]; -- char uniname2ctype_pool_str678[sizeof("lydi")]; -- char uniname2ctype_pool_str681[sizeof("lydian")]; -- char uniname2ctype_pool_str686[sizeof("sylotinagri")]; -- char uniname2ctype_pool_str687[sizeof("gujr")]; -- char uniname2ctype_pool_str692[sizeof("tfng")]; -- char uniname2ctype_pool_str696[sizeof("currencysymbol")]; -- char uniname2ctype_pool_str701[sizeof("newline")]; -- char uniname2ctype_pool_str705[sizeof("bopomofo")]; -- char uniname2ctype_pool_str706[sizeof("ogrext")]; -- char uniname2ctype_pool_str707[sizeof("cherokee")]; -- char uniname2ctype_pool_str708[sizeof("gujarati")]; -- char uniname2ctype_pool_str710[sizeof("newtailue")]; -- char uniname2ctype_pool_str716[sizeof("dashpunctuation")]; -- char uniname2ctype_pool_str718[sizeof("oldsoutharabian")]; -- char uniname2ctype_pool_str725[sizeof("upper")]; -- char uniname2ctype_pool_str732[sizeof("cf")]; -- char uniname2ctype_pool_str734[sizeof("buhd")]; -- char uniname2ctype_pool_str735[sizeof("rejang")]; -- char uniname2ctype_pool_str736[sizeof("othergraphemeextend")]; -- char uniname2ctype_pool_str739[sizeof("modifierletter")]; -- char uniname2ctype_pool_str745[sizeof("nonspacingmark")]; -- char uniname2ctype_pool_str749[sizeof("changeswhencasemapped")]; -- char uniname2ctype_pool_str752[sizeof("mark")]; -- char uniname2ctype_pool_str757[sizeof("surrogate")]; -- char uniname2ctype_pool_str765[sizeof("paragraphseparator")]; -- char uniname2ctype_pool_str767[sizeof("ogham")]; -- char uniname2ctype_pool_str768[sizeof("hex")]; -- char uniname2ctype_pool_str772[sizeof("uppercaseletter")]; -- char uniname2ctype_pool_str777[sizeof("hexdigit")]; -- char uniname2ctype_pool_str778[sizeof("cwcm")]; -- char uniname2ctype_pool_str781[sizeof("grbase")]; -- char uniname2ctype_pool_str782[sizeof("khmr")]; -- char uniname2ctype_pool_str788[sizeof("unifiedideograph")]; -- char uniname2ctype_pool_str792[sizeof("uppercase")]; -- char uniname2ctype_pool_str793[sizeof("khmer")]; -- char uniname2ctype_pool_str795[sizeof("spacingmark")]; -- char uniname2ctype_pool_str797[sizeof("whitespace")]; -- char uniname2ctype_pool_str806[sizeof("patsyn")]; -- char uniname2ctype_pool_str816[sizeof("cypriot")]; -- char uniname2ctype_pool_str818[sizeof("openpunctuation")]; -- char uniname2ctype_pool_str821[sizeof("bamu")]; -- char uniname2ctype_pool_str831[sizeof("buhid")]; -- char uniname2ctype_pool_str840[sizeof("batk")]; -- char uniname2ctype_pool_str851[sizeof("symbol")]; -- char uniname2ctype_pool_str856[sizeof("changeswhenuppercased")]; -- char uniname2ctype_pool_str857[sizeof("osmanya")]; -- char uniname2ctype_pool_str861[sizeof("limbu")]; -- char uniname2ctype_pool_str868[sizeof("punctuation")]; -- char uniname2ctype_pool_str872[sizeof("hyphen")]; -- char uniname2ctype_pool_str888[sizeof("mathsymbol")]; -- char uniname2ctype_pool_str892[sizeof("grek")]; -- char uniname2ctype_pool_str898[sizeof("changeswhencasefolded")]; -- char uniname2ctype_pool_str902[sizeof("quotationmark")]; -- char uniname2ctype_pool_str903[sizeof("bugi")]; -- char uniname2ctype_pool_str916[sizeof("cuneiform")]; -- char uniname2ctype_pool_str918[sizeof("pf")]; -- char uniname2ctype_pool_str927[sizeof("cwcf")]; -- char uniname2ctype_pool_str932[sizeof("bamum")]; -- char uniname2ctype_pool_str940[sizeof("guru")]; -- char uniname2ctype_pool_str944[sizeof("wspace")]; -- char uniname2ctype_pool_str951[sizeof("meeteimayek")]; -- char uniname2ctype_pool_str976[sizeof("defaultignorablecodepoint")]; -- char uniname2ctype_pool_str980[sizeof("modifiersymbol")]; -- char uniname2ctype_pool_str999[sizeof("mlym")]; -- char uniname2ctype_pool_str1007[sizeof("mymr")]; -- char uniname2ctype_pool_str1020[sizeof("malayalam")]; -- char uniname2ctype_pool_str1026[sizeof("myanmar")]; -- char uniname2ctype_pool_str1032[sizeof("telugu")]; -- char uniname2ctype_pool_str1033[sizeof("buginese")]; -- char uniname2ctype_pool_str1037[sizeof("xsux")]; -- char uniname2ctype_pool_str1093[sizeof("sk")]; -- char uniname2ctype_pool_str1097[sizeof("katakana")]; -- char uniname2ctype_pool_str1124[sizeof("egyp")]; -- char uniname2ctype_pool_str1146[sizeof("any")]; -- char uniname2ctype_pool_str1148[sizeof("kayahli")]; -- char uniname2ctype_pool_str1190[sizeof("cwu")]; -- char uniname2ctype_pool_str1263[sizeof("qmark")]; -- char uniname2ctype_pool_str1329[sizeof("blank")]; -- char uniname2ctype_pool_str1347[sizeof("grlink")]; -- char uniname2ctype_pool_str1358[sizeof("batak")]; -- char uniname2ctype_pool_str1395[sizeof("unknown")]; -- char uniname2ctype_pool_str1410[sizeof("greek")]; -- char uniname2ctype_pool_str1463[sizeof("graphemelink")]; -- char uniname2ctype_pool_str1470[sizeof("gurmukhi")]; -- char uniname2ctype_pool_str1556[sizeof("hebrew")]; -- char uniname2ctype_pool_str1621[sizeof("egyptianhieroglyphs")]; -- char uniname2ctype_pool_str1741[sizeof("zyyy")]; --#endif /* USE_UNICODE_PROPERTIES */ -- }; --static const struct uniname2ctype_pool_t uniname2ctype_pool_contents = -- { --#ifndef USE_UNICODE_PROPERTIES -- "print", -- "punct", --#else /* USE_UNICODE_PROPERTIES */ -- "n", -- "l", -- "nl", -- "ll", -- "cn", -- "no", -- "lo", -- "c", -- "co", -- "cc", -- "lao", -- "laoo", -- "lana", -- "ci", -- "qaac", -- "vai", -- "vaii", -- "qaai", -- "control", -- "cari", -- "carian", -- "zl", -- "oriya", -- "latn", -- "cntrl", -- "latin", -- "han", -- "arabic", -- "ital", -- "hano", -- "hani", -- "hanunoo", -- "lt", -- "so", -- "hira", -- "nchar", -- "sc", -- "z", -- "oalpha", -- "tavt", -- "cans", -- "java", -- "zinh", -- "thaa", -- "thai", -- "variationselector", -- "sinhala", -- "joinc", -- "ascii", -- "initialpunctuation", -- "other", -- "joincontrol", -- "thaana", -- "avst", -- "olower", -- "othernumber", -- "otherletter", -- "sinh", -- "tale", -- "connectorpunctuation", -- "s", -- "di", -- "vs", -- "oidc", -- "idc", -- "odi", -- "cs", -- "avestan", -- "dia", -- "cher", -- "inscriptionalparthian", -- "shavian", -- "radical", -- "loe", -- "diacritic", -- "zzzz", -- "ethi", -- "canadianaboriginal", -- "zs", -- "othersymbol", -- "olditalic", -- "inscriptionalpahlavi", -- "taiviet", -- "lineseparator", -- "otheridstart", -- "oids", -- "asciihexdigit", -- "inherited", -- "otherlowercase", -- "terminalpunctuation", -- "deva", -- "otheralphabetic", -- "ideo", -- "noncharactercodepoint", -- "otheridcontinue", -- "taile", -- "oldpersian", -- "devanagari", -- "letter", -- "nd", -- "idst", -- "dsrt", -- "titlecaseletter", -- "po", -- "dash", -- "pc", -- "letternumber", -- "pi", -- "javanese", -- "mn", -- "idstart", -- "idcontinue", -- "ids", --#endif /* USE_UNICODE_PROPERTIES */ -- "alpha", --#ifdef USE_UNICODE_PROPERTIES -- "mc", -- "coptic", -- "mongolian", -- "common", -- "armn", -- "copt", -- "cprt", -- "armi", -- "phli", -- "prti", -- "armenian", -- "sd", -- "mandaic", -- "phoenician", -- "taml", -- "tamil", -- "cased", -- "cham", -- "idsbinaryoperator", -- "lepc", -- "otherdefaultignorablecodepoint", -- "print", -- "osma", -- "samr", -- "math", -- "linb", -- "closepunctuation", -- "otherpunctuation", -- "bali", -- "omath", -- "samaritan", -- "ps", -- "arab", -- "brai", -- "taitham", -- "linearb", -- "lepcha", -- "mand", -- "mtei", -- "term", -- "glagolitic", -- "privateuse", -- "pe", -- "deseret", -- "brah", -- "runr", -- "othermath", -- "runic", -- "hang", -- "ethiopic", -- "me", -- "patws", -- "separator", -- "tibt", -- "gothic", -- "tagbanwa", -- "sarb", -- "talu", -- "tibetan", -- "goth", -- "rjng", -- "hangul", -- "bengali", -- "hiragana", -- "braille", -- "geor", -- "age=1.1", -- "age=2.1", -- "age=5.1", -- "age=5.2", -- "age=4.1", -- "p", -- "pd", -- "lisu", -- "age=2.0", -- "age=5.0", -- "age=6.0", -- "age=4.0", -- "graph", -- "saur", -- "space", -- "age=3.1", -- "age=3.2", -- "hebr", -- "bidic", -- "age=3.0", -- "bidicontrol", -- "logicalorderexception", -- "telu", -- "zp", -- "m", -- "lm", -- "idstrinaryoperator", -- "balinese", -- "uideo", -- "spaceseparator", -- "grext", --#endif /* USE_UNICODE_PROPERTIES */ -- "alnum", --#ifdef USE_UNICODE_PROPERTIES -- "oldturkic", -- "xidc", -- "idsb", -- "ahex", -- "format", -- "caseignorable", -- "tifinagh", -- "sundanese", -- "ext", -- "saurashtra", -- "patternwhitespace", -- "digit", -- "sund", -- "decimalnumber", -- "bopo", -- "sm", -- "otheruppercase", -- "ideographic", -- "xids", -- "unassigned", -- "phagspa", -- "alphabetic", -- "limb", --#endif /* USE_UNICODE_PROPERTIES */ -- "xdigit", --#ifdef USE_UNICODE_PROPERTIES -- "xidstart", -- "mong", -- "xidcontinue", -- "assigned", -- "ogam", -- "nko", -- "nkoo", -- "olck", -- "deprecated", -- "brahmi", -- "phag", -- "kana", -- "kali", -- "changeswhenlowercased", -- "extender", -- "dep", -- "olchiki", -- "cwl", -- "graphemebase", -- "phnx", -- "orkh", -- "punct", -- "khar", -- "lower", -- "sterm", -- "yi", -- "lyci", -- "cyrl", -- "lycian", -- "finalpunctuation", -- "orya", -- "graphemeextend", -- "kaithi", -- "xpeo", -- "yiii", -- "kthi", -- "cyrillic", -- "glag", -- "oupper", -- "tagb", -- "cwt", -- "number", -- "tglg", -- "knda", -- "lowercaseletter", -- "changeswhentitlecased", -- "softdotted", -- "ugar", -- "sylo", -- "lu", -- "tagalog", -- "kharoshthi", -- "syrc", -- "kannada", -- "beng", -- "lowercase", -- "shaw", -- "patternsyntax", -- "syriac", -- "word", -- "imperialaramaic", -- "ugaritic", -- "enclosingmark", -- "georgian", -- "lydi", -- "lydian", -- "sylotinagri", -- "gujr", -- "tfng", -- "currencysymbol", --#endif /* USE_UNICODE_PROPERTIES */ -- "newline", --#ifdef USE_UNICODE_PROPERTIES -- "bopomofo", -- "ogrext", -- "cherokee", -- "gujarati", -- "newtailue", -- "dashpunctuation", -- "oldsoutharabian", --#endif /* USE_UNICODE_PROPERTIES */ -- "upper", --#ifndef USE_UNICODE_PROPERTIES -- "ascii", -- "cntrl", -- "space", -- "word", -- "lower", -- "graph", -- "digit", -- "blank" --#else /* USE_UNICODE_PROPERTIES */ -- "cf", -- "buhd", -- "rejang", -- "othergraphemeextend", -- "modifierletter", -- "nonspacingmark", -- "changeswhencasemapped", -- "mark", -- "surrogate", -- "paragraphseparator", -- "ogham", -- "hex", -- "uppercaseletter", -- "hexdigit", -- "cwcm", -- "grbase", -- "khmr", -- "unifiedideograph", -- "uppercase", -- "khmer", -- "spacingmark", -- "whitespace", -- "patsyn", -- "cypriot", -- "openpunctuation", -- "bamu", -- "buhid", -- "batk", -- "symbol", -- "changeswhenuppercased", -- "osmanya", -- "limbu", -- "punctuation", -- "hyphen", -- "mathsymbol", -- "grek", -- "changeswhencasefolded", -- "quotationmark", -- "bugi", -- "cuneiform", -- "pf", -- "cwcf", -- "bamum", -- "guru", -- "wspace", -- "meeteimayek", -- "defaultignorablecodepoint", -- "modifiersymbol", -- "mlym", -- "mymr", -- "malayalam", -- "myanmar", -- "telugu", -- "buginese", -- "xsux", -- "sk", -- "katakana", -- "egyp", -- "any", -- "kayahli", -- "cwu", -- "qmark", -- "blank", -- "grlink", -- "batak", -- "unknown", -- "greek", -- "graphemelink", -- "gurmukhi", -- "hebrew", -- "egyptianhieroglyphs", -- "zyyy" --#endif /* USE_UNICODE_PROPERTIES */ -- }; --#define uniname2ctype_pool ((const char *) &uniname2ctype_pool_contents) --#ifdef __GNUC__ --__inline --#ifdef __GNUC_STDC_INLINE__ --__attribute__ ((__gnu_inline__)) --#endif --#endif --const struct uniname2ctype_struct * --uniname2ctype_p (str, len) -- register const char *str; -- register unsigned int len; --{ -- static const struct uniname2ctype_struct wordlist[] = -- { --#ifdef USE_UNICODE_PROPERTIES -- {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str3, 33}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str5, 23}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str7, 35}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str8, 24}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str10, 20}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str11, 36}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str12, 26}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str13, 17}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str16, 21}, -- {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str20, 18}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str21, 93}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str22, 93}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str23, 150}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str26, 59}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str29, 127}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str30, 142}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str31, 142}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str32, 113}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str34, 18}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str37, 147}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str40, 147}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str42, 51}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str44, 86}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str46, 74}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str47, 3}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str48, 74}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str51, 108}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str53, 79}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str54, 110}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str55, 115}, -- {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str60, 108}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str63, 115}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str66, 27}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str67, 49}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str69, 105}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str70, 184}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str71, 46}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str73, 50}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str74, 178}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str75, 151}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str76, 100}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str84, 157}, -- {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str88, 113}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str89, 81}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str90, 92}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str91, 197}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str92, 91}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str93, 170}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str94, 14}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str95, 42}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str98, 17}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str99, 170}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str100, 81}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str101, 152}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str103, 182}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str105, 36}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str106, 26}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str109, 91}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str112, 119}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str114, 38}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str115, 45}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str116, 69}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str117, 197}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str119, 195}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str120, 66}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str121, 190}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str122, 22}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str123, 152}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str124, 180}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str125, 99}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str126, 161}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str128, 122}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str137, 188}, -- {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str143, 193}, -- {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str147, 180}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str148, 200}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str149, 98}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str151, 100}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str152, 53}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str153, 49}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str156, 110}, -- {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str161, 162}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str162, 151}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str163, 51}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str166, 194}, -- {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str170, 194}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str171, 177}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str172, 113}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str174, 182}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str175, 174}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str176, 82}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str179, 178}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str180, 179}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str181, 184}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str183, 195}, -- {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str187, 119}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str190, 132}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str192, 82}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str193, 23}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str195, 34}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str197, 187}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str198, 112}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str200, 27}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str202, 43}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str203, 171}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str206, 38}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str209, 35}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str212, 42}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str215, 157}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str217, 32}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str218, 65}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str220, 66}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str222, 65}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str223, 1}, -- {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str227, 30}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str229, 127}, -- {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str234, 104}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str235, 73}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str236, 77}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str237, 127}, -- {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str243, 124}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str244, 159}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str245, 162}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str246, 161}, -- {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str250, 77}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str251, 192}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str252, 167}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str255, 136}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str258, 87}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str261, 87}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str268, 58}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str269, 149}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str270, 186}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str271, 140}, -- {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str275, 190}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str278, 7}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str286, 123}, -- {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str292, 154}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str294, 54}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str296, 120}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str297, 40}, -- {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str301, 43}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str303, 134}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str306, 175}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str307, 154}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str308, 44}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str310, 79}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str311, 125}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str314, 150}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str317, 120}, -- {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str321, 140}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str322, 167}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str324, 158}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str325, 174}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str326, 129}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str327, 21}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str328, 40}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str335, 112}, -- {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str340, 166}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str341, 102}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str343, 175}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str344, 102}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str345, 97}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str346, 98}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str349, 31}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str350, 198}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str353, 50}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str355, 94}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str356, 111}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str358, 117}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str359, 160}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str361, 128}, -- {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str367, 94}, -- {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str371, 111}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str372, 145}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str373, 97}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str374, 83}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str375, 105}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str376, 125}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str379, 96}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str380, 201}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str381, 203}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str382, 210}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str383, 211}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str384, 208}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str385, 37}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str386, 39}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str388, 155}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str389, 202}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str390, 209}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str391, 212}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str392, 207}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str393, 5}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str395, 143}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str396, 9}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str397, 205}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str398, 206}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str399, 78}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str402, 169}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str405, 204}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str408, 169}, -- {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str413, 193}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str420, 88}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str422, 52}, -- {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str427, 29}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str430, 25}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str432, 187}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str433, 134}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str434, 189}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str436, 53}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str438, 70}, -- {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str442, 13}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str443, 163}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str445, 68}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str446, 186}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str447, 177}, -- {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str452, 19}, -- {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str456, 59}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str457, 130}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str459, 139}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str462, 181}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str464, 143}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str465, 198}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str466, 4}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str474, 139}, -- {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str480, 34}, -- {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str484, 107}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str485, 48}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str488, 183}, -- {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str493, 179}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str496, 67}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str497, 20}, -- {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str502, 137}, -- {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str506, 55}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str508, 118}, -- {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str512, 11}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str513, 67}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str516, 104}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str518, 68}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str521, 16}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str523, 101}, -- {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str529, 138}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str530, 138}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str533, 141}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str534, 191}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str535, 166}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str536, 137}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str538, 106}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str540, 144}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str542, 60}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str543, 181}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str550, 191}, -- {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str554, 141}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str562, 60}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str563, 71}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str565, 136}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str573, 163}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str576, 8}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str577, 133}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str580, 6}, -- {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str586, 196}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str587, 109}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str588, 146}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str589, 76}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str591, 146}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str592, 41}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str593, 86}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str594, 70}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str596, 164}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str597, 132}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str598, 109}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str599, 164}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str601, 76}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str602, 129}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str605, 183}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str617, 117}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str620, 62}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str623, 33}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str625, 114}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str626, 89}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str627, 24}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str628, 62}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str629, 192}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str632, 121}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str634, 131}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str636, 28}, -- {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str640, 114}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str643, 133}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str644, 80}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str645, 89}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str646, 83}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str647, 56}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str656, 122}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str659, 199}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str660, 80}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str663, 12}, -- {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str667, 159}, -- {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str672, 121}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str675, 31}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str677, 96}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str678, 148}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str681, 148}, -- {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str686, 131}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str687, 85}, -- {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str692, 130}, -- {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str696, 46}, -- {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str701, 0}, -- {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str705, 107}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str706, 185}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str707, 99}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str708, 85}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str710, 128}, -- {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str716, 39}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str718, 160}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str725, 10}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str732, 19}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str734, 116}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str735, 145}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str736, 185}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str739, 25}, -- {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str745, 32}, -- {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str749, 64}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str752, 29}, -- {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str757, 22}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str765, 52}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str767, 101}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str768, 176}, -- {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str772, 28}, -- {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str777, 176}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str778, 64}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str781, 71}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str782, 103}, -- {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str788, 189}, -- {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str792, 57}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str793, 103}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str795, 30}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str797, 168}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str806, 199}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str816, 124}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str818, 44}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str821, 156}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str831, 116}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str840, 165}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str851, 45}, -- {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str856, 61}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str857, 123}, -- {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str861, 118}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str868, 37}, -- {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str872, 172}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str888, 48}, -- {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str892, 75}, -- {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str898, 63}, -- {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str902, 173}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str903, 126}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str916, 135}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str918, 41}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str927, 63}, -- {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str932, 156}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str940, 84}, -- {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str944, 168}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str951, 158}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str976, 69}, -- {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str980, 47}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str999, 90}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1007, 95}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1020, 90}, -- {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1026, 95}, -- {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1032, 88}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1033, 126}, -- {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1037, 135}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1093, 47}, -- {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1097, 106}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1124, 153}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1146, 15}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1148, 144}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1190, 61}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1263, 173}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1329, 2}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1347, 72}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1358, 165}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1395, 200}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1410, 75}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, --#endif /* USE_UNICODE_PROPERTIES */ -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, --#ifndef USE_UNICODE_PROPERTIES -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str7, 7}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str8, 8}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str9, 1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str10, 13}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str11, 11}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str12, 0}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str13, 10}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str14, 14}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str15, 3}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str16, 9}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str17, 12}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str18, 6}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str19, 5}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str20, 4}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str21, 2} --#else /* USE_UNICODE_PROPERTIES */ -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1463, 72}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1470, 84}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1556, 78}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1621, 153}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -- {-1}, {-1}, -- {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1741, 73} --#endif /* USE_UNICODE_PROPERTIES */ -- }; -- -- if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) -- { -- register int key = uniname2ctype_hash (str, len); -- -- if (key <= MAX_HASH_VALUE && key >= 0) -- { -- register int o = wordlist[key].name; -- if (o >= 0) -- { -- register const char *s = o + uniname2ctype_pool; -- -- if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0') -- return &wordlist[key]; -- } -- } -- } -- return 0; --} -- --static int --uniname2ctype(const UChar *name, unsigned int len) --{ -- const struct uniname2ctype_struct *p = uniname2ctype_p((const char *)name, len); -- if (p) return p->ctype; -- return -1; --} -diff --git a/test/ruby/test_array.rb b/test/ruby/test_array.rb -index 28d3e41..bcad2c0 100644 ---- a/test/ruby/test_array.rb -+++ b/test/ruby/test_array.rb -@@ -414,6 +414,18 @@ class TestArray < Test::Unit::TestCase - a = @cls[1, 2, 3] - a[-1, 0] = a - assert_equal([1, 2, 1, 2, 3, 3], a) -+ -+ a = @cls[] -+ a[5,0] = [5] -+ assert_equal([nil, nil, nil, nil, nil, 5], a) -+ -+ a = @cls[1] -+ a[1,0] = [2] -+ assert_equal([1, 2], a) -+ -+ a = @cls[1] -+ a[1,1] = [2] -+ assert_equal([1, 2], a) - end - - def test_assoc diff --git a/patches/ruby/1.9.3/p327/railsexpress/12-falcon-sparse-array.patch b/patches/ruby/1.9.3/p327/railsexpress/12-falcon-sparse-array.patch deleted file mode 100644 index 2ea8b4f00c..0000000000 --- a/patches/ruby/1.9.3/p327/railsexpress/12-falcon-sparse-array.patch +++ /dev/null @@ -1,2588 +0,0 @@ -diff --git a/class.c b/class.c -index df19812..d89bd1b 100644 ---- a/class.c -+++ b/class.c -@@ -31,7 +31,7 @@ - #include "internal.h" - #include - --extern st_table *rb_class_tbl; -+extern sa_table rb_class_tbl; - static ID id_attached; - - /** -@@ -50,14 +50,24 @@ static VALUE - class_alloc(VALUE flags, VALUE klass) - { - rb_classext_t *ext = ALLOC(rb_classext_t); -+ rb_class_cache_t *cache = ALLOC(rb_class_cache_t); - NEWOBJ(obj, struct RClass); - OBJSETUP(obj, klass, flags); - obj->ptr = ext; -- RCLASS_IV_TBL(obj) = 0; -- RCLASS_CONST_TBL(obj) = 0; -- RCLASS_M_TBL(obj) = 0; -- RCLASS_SUPER(obj) = 0; -- RCLASS_IV_INDEX_TBL(obj) = 0; -+ obj->cache = cache; -+ MEMZERO(ext, struct rb_classext_struct, 1); -+ MEMZERO(cache, struct rb_class_cache_struct, 1); -+ return (VALUE)obj; -+} -+ -+static VALUE -+iclass_alloc() -+{ -+ rb_class_cache_t *cache = ALLOC(rb_class_cache_t); -+ NEWOBJ(obj, struct RClass); -+ OBJSETUP(obj, rb_cClass, T_ICLASS); -+ obj->cache = cache; -+ MEMZERO(cache, struct rb_class_cache_struct, 1); - return (VALUE)obj; - } - -@@ -77,7 +87,6 @@ rb_class_boot(VALUE super) - VALUE klass = class_alloc(T_CLASS, rb_cClass); - - RCLASS_SUPER(klass) = super; -- RCLASS_M_TBL(klass) = st_init_numtable(); - - OBJ_INFECT(klass, super); - return (VALUE)klass; -@@ -120,85 +129,59 @@ rb_class_new(VALUE super) - return rb_class_boot(super); - } - --struct clone_method_data { -- st_table *tbl; -- VALUE klass; --}; -- - VALUE rb_iseq_clone(VALUE iseqval, VALUE newcbase); - --static int --clone_method(ID mid, const rb_method_entry_t *me, struct clone_method_data *data) -+static void -+clone_method(ID mid, const rb_method_entry_t *me, VALUE klass) - { - VALUE newiseqval; - if (me->def && me->def->type == VM_METHOD_TYPE_ISEQ) { - rb_iseq_t *iseq; -- newiseqval = rb_iseq_clone(me->def->body.iseq->self, data->klass); -+ newiseqval = rb_iseq_clone(me->def->body.iseq->self, klass); - GetISeqPtr(newiseqval, iseq); -- rb_add_method(data->klass, mid, VM_METHOD_TYPE_ISEQ, iseq, me->flag); -+ rb_add_method(klass, mid, VM_METHOD_TYPE_ISEQ, iseq, me->flag); - RB_GC_GUARD(newiseqval); - } - else { -- rb_method_entry_set(data->klass, mid, me, me->flag); -+ rb_method_entry_set(klass, mid, me, me->flag); - } -- return ST_CONTINUE; - } - --static int --clone_const(ID key, const rb_const_entry_t *ce, st_table *tbl) -+static void -+clone_const(sa_index_t key, st_data_t ce, sa_table *tbl) - { - rb_const_entry_t *nce = ALLOC(rb_const_entry_t); -- *nce = *ce; -- st_insert(tbl, key, (st_data_t)nce); -- return ST_CONTINUE; --} -- --static int --clone_const_i(st_data_t key, st_data_t value, st_data_t data) --{ -- return clone_const((ID)key, (const rb_const_entry_t *)value, (st_table *)data); -+ *nce = *(const rb_const_entry_t*)ce; -+ sa_insert(tbl, (sa_index_t)key, (st_data_t)nce); - } - - /* :nodoc: */ - VALUE - rb_mod_init_copy(VALUE clone, VALUE orig) - { -+ ID id; - rb_obj_init_copy(clone, orig); - if (!FL_TEST(CLASS_OF(clone), FL_SINGLETON)) { - RBASIC(clone)->klass = rb_singleton_class_clone(orig); - rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone); - } - RCLASS_SUPER(clone) = RCLASS_SUPER(orig); -- if (RCLASS_IV_TBL(orig)) { -- st_data_t id; - -- if (RCLASS_IV_TBL(clone)) { -- st_free_table(RCLASS_IV_TBL(clone)); -- } -- RCLASS_IV_TBL(clone) = st_copy(RCLASS_IV_TBL(orig)); -- CONST_ID(id, "__classpath__"); -- st_delete(RCLASS_IV_TBL(clone), &id, 0); -- CONST_ID(id, "__classid__"); -- st_delete(RCLASS_IV_TBL(clone), &id, 0); -- } -- if (RCLASS_CONST_TBL(orig)) { -- if (RCLASS_CONST_TBL(clone)) { -- rb_free_const_table(RCLASS_CONST_TBL(clone)); -- } -- RCLASS_CONST_TBL(clone) = st_init_numtable(); -- st_foreach(RCLASS_CONST_TBL(orig), clone_const_i, (st_data_t)RCLASS_CONST_TBL(clone)); -- } -- if (RCLASS_M_TBL(orig)) { -- struct clone_method_data data; -+ sa_copy_to(RCLASS_IV_TBL(orig), RCLASS_IV_TBL(clone)); -+ CONST_ID(id, "__classpath__"); -+ sa_delete(RCLASS_IV_TBL(clone), (sa_index_t)id, 0); -+ CONST_ID(id, "__classid__"); -+ sa_delete(RCLASS_IV_TBL(clone), (sa_index_t)id, 0); - -- if (RCLASS_M_TBL(clone)) { -- rb_free_m_table(RCLASS_M_TBL(clone)); -- } -- data.tbl = RCLASS_M_TBL(clone) = st_init_numtable(); -- data.klass = clone; -- st_foreach(RCLASS_M_TBL(orig), clone_method, -- (st_data_t)&data); -- } -+ sa_clear(RCLASS_CONST_TBL(clone)); -+ SA_FOREACH_START(RCLASS_CONST_TBL(orig)); -+ clone_const(entry->key, value, RCLASS_CONST_TBL(clone)); -+ SA_FOREACH_END(); -+ -+ rb_free_m_table(RCLASS_M_TBL(clone)); -+ SA_FOREACH_START(RCLASS_M_TBL(orig)); -+ clone_method(entry->key, (const rb_method_entry_t *)value, clone); -+ SA_FOREACH_END(); - - return clone; - } -@@ -227,7 +210,6 @@ rb_singleton_class_clone(VALUE obj) - if (!FL_TEST(klass, FL_SINGLETON)) - return klass; - else { -- struct clone_method_data data; - /* copy singleton(unnamed) class */ - VALUE clone = class_alloc((RBASIC(klass)->flags & ~(FL_MARK)), 0); - -@@ -239,18 +221,16 @@ rb_singleton_class_clone(VALUE obj) - } - - RCLASS_SUPER(clone) = RCLASS_SUPER(klass); -- if (RCLASS_IV_TBL(klass)) { -- RCLASS_IV_TBL(clone) = st_copy(RCLASS_IV_TBL(klass)); -- } -- if (RCLASS_CONST_TBL(klass)) { -- RCLASS_CONST_TBL(clone) = st_init_numtable(); -- st_foreach(RCLASS_CONST_TBL(klass), clone_const_i, (st_data_t)RCLASS_CONST_TBL(clone)); -- } -- RCLASS_M_TBL(clone) = st_init_numtable(); -- data.tbl = RCLASS_M_TBL(clone); -- data.klass = (VALUE)clone; -- st_foreach(RCLASS_M_TBL(klass), clone_method, -- (st_data_t)&data); -+ sa_copy_to(RCLASS_IV_TBL(klass), RCLASS_IV_TBL(clone)); -+ -+ SA_FOREACH_START(RCLASS_CONST_TBL(klass)); -+ clone_const(entry->key, value, RCLASS_CONST_TBL(clone)); -+ SA_FOREACH_END(); -+ -+ SA_FOREACH_START(RCLASS_M_TBL(klass)); -+ clone_method(entry->key, (const rb_method_entry_t*)value, clone); -+ SA_FOREACH_END(); -+ - rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone); - FL_SET(clone, FL_SINGLETON); - return (VALUE)clone; -@@ -265,10 +245,7 @@ void - rb_singleton_class_attached(VALUE klass, VALUE obj) - { - if (FL_TEST(klass, FL_SINGLETON)) { -- if (!RCLASS_IV_TBL(klass)) { -- RCLASS_IV_TBL(klass) = st_init_numtable(); -- } -- st_insert(RCLASS_IV_TBL(klass), id_attached, obj); -+ sa_insert(RCLASS_IV_TBL(klass), (sa_index_t)id_attached, obj); - } - } - -@@ -355,12 +332,12 @@ make_singleton_class(VALUE obj) - static VALUE - boot_defclass(const char *name, VALUE super) - { -- extern st_table *rb_class_tbl; -+ extern sa_table rb_class_tbl; - VALUE obj = rb_class_boot(super); - ID id = rb_intern(name); - - rb_name_class(obj, id); -- st_add_direct(rb_class_tbl, id, obj); -+ sa_insert(&rb_class_tbl, (sa_index_t)id, obj); - rb_const_set((rb_cObject ? rb_cObject : obj), id, obj); - return obj; - } -@@ -484,7 +461,7 @@ rb_define_class(const char *name, VALUE super) - rb_warn("no super class for `%s', Object assumed", name); - } - klass = rb_define_class_id(id, super); -- st_add_direct(rb_class_tbl, id, klass); -+ sa_insert(&rb_class_tbl, (sa_index_t)id, klass); - rb_name_class(klass, id); - rb_const_set(rb_cObject, id, klass); - rb_class_inherited(super, klass); -@@ -565,8 +542,6 @@ rb_module_new(void) - { - VALUE mdl = class_alloc(T_MODULE, rb_cModule); - -- RCLASS_M_TBL(mdl) = st_init_numtable(); -- - return (VALUE)mdl; - } - -@@ -595,7 +570,7 @@ rb_define_module(const char *name) - rb_raise(rb_eTypeError, "%s is not a module", rb_obj_classname(module)); - } - module = rb_define_module_id(id); -- st_add_direct(rb_class_tbl, id, module); -+ sa_insert(&rb_class_tbl, (sa_index_t)id, module); - rb_const_set(rb_cObject, id, module); - - return module; -@@ -630,27 +605,15 @@ rb_define_module_id_under(VALUE outer, ID id) - static VALUE - include_class_new(VALUE module, VALUE super) - { -- VALUE klass = class_alloc(T_ICLASS, rb_cClass); -+ VALUE klass; - - if (BUILTIN_TYPE(module) == T_ICLASS) { - module = RBASIC(module)->klass; - } -- if (!RCLASS_IV_TBL(module)) { -- RCLASS_IV_TBL(module) = st_init_numtable(); -- } -- if (!RCLASS_CONST_TBL(module)) { -- RCLASS_CONST_TBL(module) = st_init_numtable(); -- } -- RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module); -- RCLASS_CONST_TBL(klass) = RCLASS_CONST_TBL(module); -- RCLASS_M_TBL(klass) = RCLASS_M_TBL(module); -+ klass = iclass_alloc(); -+ RBASIC(klass)->klass = module; -+ RCLASS_EXT(klass) = RCLASS_EXT(module); - RCLASS_SUPER(klass) = super; -- if (TYPE(module) == T_ICLASS) { -- RBASIC(klass)->klass = RBASIC(module)->klass; -- } -- else { -- RBASIC(klass)->klass = module; -- } - OBJ_INFECT(klass, module); - OBJ_INFECT(klass, super); - -@@ -677,13 +640,13 @@ rb_include_module(VALUE klass, VALUE module) - while (module) { - int superclass_seen = FALSE; - -- if (RCLASS_M_TBL(klass) == RCLASS_M_TBL(module)) -+ if (RCLASS_EXT(klass) == RCLASS_EXT(module)) - rb_raise(rb_eArgError, "cyclic include detected"); - /* ignore if the module included already in superclasses */ - for (p = RCLASS_SUPER(klass); p; p = RCLASS_SUPER(p)) { - switch (BUILTIN_TYPE(p)) { - case T_ICLASS: -- if (RCLASS_M_TBL(p) == RCLASS_M_TBL(module)) { -+ if (RCLASS_EXT(p) == RCLASS_EXT(module)) { - if (!superclass_seen) { - c = p; /* move insertion point */ - } -@@ -696,7 +659,7 @@ rb_include_module(VALUE klass, VALUE module) - } - } - c = RCLASS_SUPER(c) = include_class_new(module, RCLASS_SUPER(c)); -- if (RMODULE_M_TBL(module) && RMODULE_M_TBL(module)->num_entries) -+ if (RMODULE_M_TBL(module)->num_entries) - changed = 1; - skip: - module = RCLASS_SUPER(module); -@@ -827,58 +790,58 @@ ins_methods_push(ID name, long type, VALUE ary, long visi) - } - - static int --ins_methods_i(st_data_t name, st_data_t type, st_data_t ary) -+ins_methods_i(sa_index_t name, st_data_t type, st_data_t ary) - { - return ins_methods_push((ID)name, (long)type, (VALUE)ary, -1); /* everything but private */ - } - - static int --ins_methods_prot_i(st_data_t name, st_data_t type, st_data_t ary) -+ins_methods_prot_i(sa_index_t name, st_data_t type, st_data_t ary) - { - return ins_methods_push((ID)name, (long)type, (VALUE)ary, NOEX_PROTECTED); - } - - static int --ins_methods_priv_i(st_data_t name, st_data_t type, st_data_t ary) -+ins_methods_priv_i(sa_index_t name, st_data_t type, st_data_t ary) - { - return ins_methods_push((ID)name, (long)type, (VALUE)ary, NOEX_PRIVATE); - } - - static int --ins_methods_pub_i(st_data_t name, st_data_t type, st_data_t ary) -+ins_methods_pub_i(sa_index_t name, st_data_t type, st_data_t ary) - { - return ins_methods_push((ID)name, (long)type, (VALUE)ary, NOEX_PUBLIC); - } - - static int --method_entry_i(st_data_t key, st_data_t value, st_data_t data) -+method_entry_i(sa_index_t key, st_data_t value, st_data_t data) - { - const rb_method_entry_t *me = (const rb_method_entry_t *)value; -- st_table *list = (st_table *)data; -+ sa_table *list = (sa_table *)data; - long type; - - if ((ID)key == ID_ALLOCATOR) { - return ST_CONTINUE; - } - -- if (!st_lookup(list, key, 0)) { -+ if (!sa_lookup(list, key, 0)) { - if (UNDEFINED_METHOD_ENTRY_P(me)) { - type = -1; /* none */ - } - else { - type = VISI(me->flag); - } -- st_add_direct(list, key, type); -+ sa_insert(list, key, type); - } - return ST_CONTINUE; - } - - static VALUE --class_instance_method_list(int argc, VALUE *argv, VALUE mod, int obj, int (*func) (st_data_t, st_data_t, st_data_t)) -+class_instance_method_list(int argc, VALUE *argv, VALUE mod, int obj, int (*func) (sa_index_t, st_data_t, st_data_t)) - { - VALUE ary; - int recur; -- st_table *list; -+ sa_table list = SA_EMPTY_TABLE; - - if (argc == 0) { - recur = TRUE; -@@ -889,16 +852,15 @@ class_instance_method_list(int argc, VALUE *argv, VALUE mod, int obj, int (*func - recur = RTEST(r); - } - -- list = st_init_numtable(); - for (; mod; mod = RCLASS_SUPER(mod)) { -- st_foreach(RCLASS_M_TBL(mod), method_entry_i, (st_data_t)list); -+ sa_foreach(RCLASS_M_TBL(mod), method_entry_i, (st_data_t)&list); - if (BUILTIN_TYPE(mod) == T_ICLASS) continue; - if (obj && FL_TEST(mod, FL_SINGLETON)) continue; - if (!recur) break; - } - ary = rb_ary_new(); -- st_foreach(list, func, ary); -- st_free_table(list); -+ sa_foreach(&list, func, ary); -+ sa_clear(&list); - - return ary; - } -@@ -1112,7 +1074,7 @@ VALUE - rb_obj_singleton_methods(int argc, VALUE *argv, VALUE obj) - { - VALUE recur, ary, klass; -- st_table *list; -+ sa_table list = SA_EMPTY_TABLE; - - if (argc == 0) { - recur = Qtrue; -@@ -1121,20 +1083,19 @@ rb_obj_singleton_methods(int argc, VALUE *argv, VALUE obj) - rb_scan_args(argc, argv, "01", &recur); - } - klass = CLASS_OF(obj); -- list = st_init_numtable(); - if (klass && FL_TEST(klass, FL_SINGLETON)) { -- st_foreach(RCLASS_M_TBL(klass), method_entry_i, (st_data_t)list); -+ sa_foreach(RCLASS_M_TBL(klass), method_entry_i, (st_data_t)&list); - klass = RCLASS_SUPER(klass); - } - if (RTEST(recur)) { - while (klass && (FL_TEST(klass, FL_SINGLETON) || TYPE(klass) == T_ICLASS)) { -- st_foreach(RCLASS_M_TBL(klass), method_entry_i, (st_data_t)list); -+ sa_foreach(RCLASS_M_TBL(klass), method_entry_i, (st_data_t)&list); - klass = RCLASS_SUPER(klass); - } - } - ary = rb_ary_new(); -- st_foreach(list, ins_methods_i, ary); -- st_free_table(list); -+ sa_foreach(&list, ins_methods_i, ary); -+ sa_clear(&list); - - return ary; - } -diff --git a/common.mk b/common.mk -index 56e52b6..3ccfa47 100644 ---- a/common.mk -+++ b/common.mk -@@ -79,6 +79,7 @@ COMMONOBJS = array.$(OBJEXT) \ - safe.$(OBJEXT) \ - signal.$(OBJEXT) \ - sprintf.$(OBJEXT) \ -+ sp_ar.$(OBJEXT) \ - st.$(OBJEXT) \ - strftime.$(OBJEXT) \ - string.$(OBJEXT) \ -@@ -703,6 +704,7 @@ signal.$(OBJEXT): {$(VPATH)}signal.c $(RUBY_H_INCLUDES) \ - $(VM_CORE_H_INCLUDES) {$(VPATH)}debug.h - sprintf.$(OBJEXT): {$(VPATH)}sprintf.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \ - {$(VPATH)}regex.h {$(VPATH)}vsnprintf.c $(ENCODING_H_INCLUDES) -+sp_ar.$(OBJEXT): {$(VPATH)}sp_ar.c $(RUBY_H_INCLUDES) - st.$(OBJEXT): {$(VPATH)}st.c $(RUBY_H_INCLUDES) {$(VPATH)}pool_alloc.h - strftime.$(OBJEXT): {$(VPATH)}strftime.c $(RUBY_H_INCLUDES) \ - {$(VPATH)}timev.h -diff --git a/constant.h b/constant.h -index 8232910..9106847 100644 ---- a/constant.h -+++ b/constant.h -@@ -23,7 +23,7 @@ typedef struct rb_const_entry_struct { - - VALUE rb_mod_private_constant(int argc, VALUE *argv, VALUE obj); - VALUE rb_mod_public_constant(int argc, VALUE *argv, VALUE obj); --void rb_free_const_table(st_table *tbl); -+void rb_free_const_table(sa_table *tbl); - VALUE rb_public_const_get(VALUE klass, ID id); - VALUE rb_public_const_get_at(VALUE klass, ID id); - VALUE rb_public_const_get_from(VALUE klass, ID id); -diff --git a/ext/objspace/objspace.c b/ext/objspace/objspace.c -index 66e33a3..4b31f92 100644 ---- a/ext/objspace/objspace.c -+++ b/ext/objspace/objspace.c -@@ -60,20 +60,10 @@ memsize_of(VALUE obj) - break; - case T_MODULE: - case T_CLASS: -- size += st_memsize(RCLASS_M_TBL(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); -+ size += sa_memsize(RCLASS_M_TBL(obj)); -+ size += sa_memsize(RCLASS_IV_TBL(obj)); -+ size += sa_memsize(RCLASS_IV_INDEX_TBL(obj)); -+ size += sa_memsize(RCLASS_CONST_TBL(obj)); - break; - case T_STRING: - size += rb_str_memsize(obj); -diff --git a/gc.c b/gc.c -index 13dd821..81c867d 100644 ---- a/gc.c -+++ b/gc.c -@@ -666,7 +666,7 @@ rb_objspace_free(rb_objspace_t *objspace) - - #define HEAP_OBJ_LIMIT (unsigned int)(HEAP_SIZE / sizeof(struct RVALUE)) - --extern st_table *rb_class_tbl; -+extern sa_table rb_class_tbl; - - int ruby_disable_gc_stress = 0; - -@@ -2235,6 +2235,15 @@ mark_tbl(rb_objspace_t *objspace, st_table *tbl, int lev) - st_foreach(tbl, mark_entry, (st_data_t)&arg); - } - -+static void -+mark_sa_tbl(rb_objspace_t *objspace, sa_table *tbl, int lev) -+{ -+ if (!tbl) return; -+ SA_FOREACH_START(tbl); -+ gc_mark(objspace, (VALUE)value, lev); -+ SA_FOREACH_END(); -+} -+ - static int - mark_key(VALUE key, VALUE value, st_data_t data) - { -@@ -2313,74 +2322,52 @@ rb_mark_method_entry(const rb_method_entry_t *me) - mark_method_entry(&rb_objspace, me, 0); - } - --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; -- mark_method_entry(arg->objspace, me, arg->lev); -- return ST_CONTINUE; --} -- - static void --mark_m_tbl(rb_objspace_t *objspace, st_table *tbl, int lev) -+mark_m_tbl(rb_objspace_t *objspace, sa_table *tbl, int lev) - { -- struct mark_tbl_arg arg; -- if (!tbl) return; -- arg.objspace = objspace; -- arg.lev = lev; -- st_foreach(tbl, mark_method_entry_i, (st_data_t)&arg); --} -- --static int --free_method_entry_i(ID key, rb_method_entry_t *me, st_data_t data) --{ -- rb_free_method_entry(me); -- return ST_CONTINUE; -+ SA_FOREACH_START(tbl); -+ mark_method_entry(objspace, (const rb_method_entry_t*)value, lev); -+ SA_FOREACH_END(); - } - - void --rb_free_m_table(st_table *tbl) -+rb_free_m_table(sa_table *tbl) - { -- st_foreach(tbl, free_method_entry_i, 0); -- st_free_table(tbl); --} -- --static int --mark_const_entry_i(ID key, const rb_const_entry_t *ce, st_data_t data) --{ -- struct mark_tbl_arg *arg = (void*)data; -- gc_mark(arg->objspace, ce->value, arg->lev); -- return ST_CONTINUE; -+ SA_FOREACH_START(tbl); -+ if (!((rb_method_entry_t*)value)->mark) { -+ rb_free_method_entry((rb_method_entry_t*)value); -+ } -+ SA_FOREACH_END(); -+ sa_clear(tbl); - } - - static void --mark_const_tbl(rb_objspace_t *objspace, st_table *tbl, int lev) -+mark_const_tbl(rb_objspace_t *objspace, sa_table *tbl, int lev) - { -- struct mark_tbl_arg arg; -- if (!tbl) return; -- arg.objspace = objspace; -- arg.lev = lev; -- st_foreach(tbl, mark_const_entry_i, (st_data_t)&arg); -+ SA_FOREACH_START(tbl); -+ gc_mark(objspace, ((const rb_const_entry_t*)value)->value, lev); -+ SA_FOREACH_END(); - } - --static int --free_const_entry_i(ID key, rb_const_entry_t *ce, st_data_t data) -+void -+rb_free_const_table(sa_table *tbl) - { -- xfree(ce); -- return ST_CONTINUE; -+ SA_FOREACH_START(tbl); -+ xfree((rb_const_entry_t*)value); -+ SA_FOREACH_END(); -+ sa_clear(tbl); - } - - void --rb_free_const_table(st_table *tbl) -+rb_mark_tbl(st_table *tbl) - { -- st_foreach(tbl, free_const_entry_i, 0); -- st_free_table(tbl); -+ mark_tbl(&rb_objspace, tbl, 0); - } - - void --rb_mark_tbl(st_table *tbl) -+rb_mark_sa_tbl(sa_table *tbl) - { -- mark_tbl(&rb_objspace, tbl, 0); -+ mark_sa_tbl(&rb_objspace, tbl, 0); - } - - void -@@ -2600,7 +2587,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev) - case T_CLASS: - case T_MODULE: - mark_m_tbl(objspace, RCLASS_M_TBL(obj), lev); -- mark_tbl(objspace, RCLASS_IV_TBL(obj), lev); -+ mark_sa_tbl(objspace, RCLASS_IV_TBL(obj), lev); - mark_const_tbl(objspace, RCLASS_CONST_TBL(obj), lev); - ptr = RCLASS_SUPER(obj); - goto again; -@@ -3175,15 +3162,11 @@ obj_free(rb_objspace_t *objspace, VALUE obj) - case T_CLASS: - rb_clear_cache_by_class((VALUE)obj); - rb_free_m_table(RCLASS_M_TBL(obj)); -- 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)); -- } -+ sa_clear(RCLASS_IV_TBL(obj)); -+ rb_free_const_table(RCLASS_CONST_TBL(obj)); -+ sa_clear(RCLASS_IV_INDEX_TBL(obj)); -+ sa_clear(&RCLASS(obj)->cache->m_cache_tbl); -+ xfree(RCLASS(obj)->cache); - xfree(RANY(obj)->as.klass.ptr); - break; - case T_STRING: -@@ -3235,8 +3218,9 @@ obj_free(rb_objspace_t *objspace, VALUE obj) - case T_COMPLEX: - break; - case T_ICLASS: -+ sa_clear(&RCLASS(obj)->cache->m_cache_tbl); -+ xfree(RCLASS(obj)->cache); - /* iClass shares table with the module */ -- xfree(RANY(obj)->as.klass.ptr); - break; - - case T_FLOAT: -@@ -3353,7 +3337,7 @@ gc_marks(rb_objspace_t *objspace) - rb_mark_end_proc(); - rb_gc_mark_global_tbl(); - -- mark_tbl(objspace, rb_class_tbl, 0); -+ mark_sa_tbl(objspace, &rb_class_tbl, 0); - - /* mark generic instance variables for special constants */ - rb_mark_generic_ivar_tbl(); -diff --git a/include/ruby/intern.h b/include/ruby/intern.h -index b82252a..27ed7d8 100644 ---- a/include/ruby/intern.h -+++ b/include/ruby/intern.h -@@ -414,6 +414,7 @@ size_t ruby_stack_length(VALUE**); - int rb_during_gc(void); - void rb_gc_mark_locations(VALUE*, VALUE*); - void rb_mark_tbl(struct st_table*); -+void rb_mark_sa_tbl(sa_table*); - void rb_mark_set(struct st_table*); - void rb_mark_hash(struct st_table*); - void rb_gc_mark_maybe(VALUE); -@@ -847,7 +848,7 @@ VALUE rb_f_trace_var(int, VALUE*); - VALUE rb_f_untrace_var(int, VALUE*); - VALUE rb_f_global_variables(void); - void rb_alias_variable(ID, ID); --struct st_table* rb_generic_ivar_table(VALUE); -+sa_table* rb_generic_ivar_table(VALUE); - void rb_copy_generic_ivar(VALUE,VALUE); - void rb_mark_generic_ivar(VALUE); - void rb_mark_generic_ivar_tbl(void); -diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h -index 2f97b33..1c84e14 100644 ---- a/include/ruby/ruby.h -+++ b/include/ruby/ruby.h -@@ -605,7 +605,7 @@ struct RObject { - struct { - long numiv; - VALUE *ivptr; -- struct st_table *iv_index_tbl; /* shortcut for RCLASS_IV_INDEX_TBL(rb_obj_class(obj)) */ -+ struct sa_table *iv_index_tbl; /* shortcut for RCLASS_IV_INDEX_TBL(rb_obj_class(obj)) */ - } heap; - VALUE ary[ROBJECT_EMBED_LEN_MAX]; - } as; -@@ -626,12 +626,13 @@ struct RObject { - - /** @internal */ - typedef struct rb_classext_struct rb_classext_t; -+typedef struct rb_class_cache_struct rb_class_cache_t; - - struct RClass { - struct RBasic basic; -+ VALUE super; - rb_classext_t *ptr; -- struct st_table *m_tbl; -- struct st_table *iv_index_tbl; -+ rb_class_cache_t *cache; - }; - #define RCLASS_SUPER(c) rb_class_get_superclass(c) - #define RMODULE_IV_TBL(m) RCLASS_IV_TBL(m) -diff --git a/include/ruby/st.h b/include/ruby/st.h -index 119dfde..aff94fc 100644 ---- a/include/ruby/st.h -+++ b/include/ruby/st.h -@@ -151,6 +151,51 @@ st_index_t st_hash_start(st_index_t h); - #pragma GCC visibility pop - #endif - -+typedef unsigned int sa_index_t; -+#define SA_STOP ST_STOP -+#define SA_CONTINUE ST_CONTINUE -+ -+#define SA_EMPTY 0 -+ -+typedef struct sa_entry { -+ sa_index_t next; -+ sa_index_t key; -+ st_data_t value; -+} sa_entry; -+ -+typedef struct sa_table { -+ sa_index_t num_bins; -+ sa_index_t num_entries; -+ sa_index_t free_pos; -+ sa_entry *entries; -+} sa_table; -+ -+#define SA_EMPTY_TABLE {0, 0, 0, 0}; -+void sa_init_table(sa_table *, sa_index_t); -+sa_table *sa_new_table(); -+int sa_insert(sa_table *, sa_index_t, st_data_t); -+int sa_lookup(sa_table *, sa_index_t, st_data_t *); -+int sa_delete(sa_table *, sa_index_t, st_data_t *); -+void sa_clear(sa_table *); -+void sa_clear_no_free(sa_table *); -+void sa_free_table(sa_table *); -+int sa_foreach(sa_table *, int (*)(ANYARGS), st_data_t); -+size_t sa_memsize(const sa_table *); -+sa_table *sa_copy(sa_table*); -+void sa_copy_to(sa_table*, sa_table*); -+typedef int (*sa_iter_func)(sa_index_t key, st_data_t val, st_data_t arg); -+ -+#define SA_FOREACH_START_I(table, entry) do { \ -+ sa_table *T##entry = (table); \ -+ sa_index_t K##entry; \ -+ for(K##entry = 0; K##entry < T##entry->num_bins; K##entry++) { \ -+ sa_entry *entry = T##entry->entries + K##entry; \ -+ if (entry->next != SA_EMPTY) { \ -+ st_data_t value = entry->value -+#define SA_FOREACH_END() } } } while(0) -+ -+#define SA_FOREACH_START(table) SA_FOREACH_START_I(table, entry) -+ - #if defined(__cplusplus) - #if 0 - { /* satisfy cc-mode */ -diff --git a/internal.h b/internal.h -index f5af903..4af90b6 100644 ---- a/internal.h -+++ b/internal.h -@@ -24,18 +24,24 @@ struct rb_deprecated_classext_struct { - }; - - struct rb_classext_struct { -- VALUE super; -- struct st_table *iv_tbl; -- struct st_table *const_tbl; -+ sa_table m_tbl; -+ sa_table iv_tbl; -+ sa_table const_tbl; -+ sa_table iv_index_tbl; -+}; -+ -+struct rb_class_cache_struct { -+ VALUE method_cache_version; -+ sa_table m_cache_tbl; - }; - - #undef RCLASS_SUPER - #define RCLASS_EXT(c) (RCLASS(c)->ptr) --#define RCLASS_SUPER(c) (RCLASS_EXT(c)->super) --#define RCLASS_IV_TBL(c) (RCLASS_EXT(c)->iv_tbl) --#define RCLASS_CONST_TBL(c) (RCLASS_EXT(c)->const_tbl) --#define RCLASS_M_TBL(c) (RCLASS(c)->m_tbl) --#define RCLASS_IV_INDEX_TBL(c) (RCLASS(c)->iv_index_tbl) -+#define RCLASS_SUPER(c) (RCLASS(c)->super) -+#define RCLASS_IV_TBL(c) (&RCLASS_EXT(c)->iv_tbl) -+#define RCLASS_CONST_TBL(c) (&RCLASS_EXT(c)->const_tbl) -+#define RCLASS_M_TBL(c) (&RCLASS_EXT(c)->m_tbl) -+#define RCLASS_IV_INDEX_TBL(c) (&RCLASS_EXT(c)->iv_index_tbl) - - struct vtm; /* defined by timev.h */ - -diff --git a/marshal.c b/marshal.c -index 9a43cdb..a4a3551 100644 ---- a/marshal.c -+++ b/marshal.c -@@ -506,7 +506,7 @@ w_uclass(VALUE obj, VALUE super, struct dump_arg *arg) - } - - static int --w_obj_each(ID id, VALUE value, struct dump_call_arg *arg) -+w_obj_each(sa_index_t id, VALUE value, struct dump_call_arg *arg) - { - if (id == rb_id_encoding()) return ST_CONTINUE; - if (id == rb_intern("E")) return ST_CONTINUE; -@@ -553,13 +553,13 @@ w_encoding(VALUE obj, long num, struct dump_call_arg *arg) - } - - static void --w_ivar(VALUE obj, st_table *tbl, struct dump_call_arg *arg) -+w_ivar(VALUE obj, sa_table *tbl, struct dump_call_arg *arg) - { - long num = tbl ? tbl->num_entries : 0; - - w_encoding(obj, num, arg); - if (tbl) { -- st_foreach_safe(tbl, w_obj_each, (st_data_t)arg); -+ sa_foreach(tbl, w_obj_each, (st_data_t)arg); - } - } - -@@ -586,7 +586,7 @@ static void - w_object(VALUE obj, struct dump_arg *arg, int limit) - { - struct dump_call_arg c_arg; -- st_table *ivtbl = 0; -+ sa_table *ivtbl = 0; - st_data_t num; - int hasiv = 0; - #define has_ivars(obj, ivtbl) (((ivtbl) = rb_generic_ivar_table(obj)) != 0 || \ -@@ -651,7 +651,7 @@ w_object(VALUE obj, struct dump_arg *arg, int limit) - } - if (rb_respond_to(obj, s_dump)) { - VALUE v; -- st_table *ivtbl2 = 0; -+ sa_table *ivtbl2 = 0; - int hasiv2; - - v = rb_funcall(obj, s_dump, 1, INT2NUM(limit)); -diff --git a/method.h b/method.h -index 9229896..2fecd57 100644 ---- a/method.h -+++ b/method.h -@@ -100,6 +100,6 @@ int rb_method_entry_eq(const rb_method_entry_t *m1, const rb_method_entry_t *m2) - void rb_mark_method_entry(const rb_method_entry_t *me); - void rb_free_method_entry(rb_method_entry_t *me); - void rb_sweep_method_entry(void *vm); --void rb_free_m_table(st_table *tbl); -+void rb_free_m_table(sa_table *tbl); - - #endif /* METHOD_H */ -diff --git a/object.c b/object.c -index f45e013..1352d01 100644 ---- a/object.c -+++ b/object.c -@@ -229,17 +229,8 @@ init_copy(VALUE dest, VALUE obj) - break; - case T_CLASS: - case T_MODULE: -- if (RCLASS_IV_TBL(dest)) { -- st_free_table(RCLASS_IV_TBL(dest)); -- RCLASS_IV_TBL(dest) = 0; -- } -- if (RCLASS_CONST_TBL(dest)) { -- rb_free_const_table(RCLASS_CONST_TBL(dest)); -- RCLASS_CONST_TBL(dest) = 0; -- } -- if (RCLASS_IV_TBL(obj)) { -- RCLASS_IV_TBL(dest) = st_copy(RCLASS_IV_TBL(obj)); -- } -+ rb_free_const_table(RCLASS_CONST_TBL(dest)); -+ sa_copy_to(RCLASS_IV_TBL(obj), RCLASS_IV_TBL(dest)); - break; - } - } -@@ -530,7 +521,7 @@ rb_obj_is_kind_of(VALUE obj, VALUE c) - } - - while (cl) { -- if (cl == c || RCLASS_M_TBL(cl) == RCLASS_M_TBL(c)) -+ if (cl == c || RCLASS_EXT(cl) == RCLASS_EXT(c)) - return Qtrue; - cl = RCLASS_SUPER(cl); - } -@@ -1355,13 +1346,13 @@ rb_class_inherited_p(VALUE mod, VALUE arg) - rb_raise(rb_eTypeError, "compared with non class/module"); - } - while (mod) { -- if (RCLASS_M_TBL(mod) == RCLASS_M_TBL(arg)) -+ if (RCLASS_EXT(mod) == RCLASS_EXT(arg)) - return Qtrue; - mod = RCLASS_SUPER(mod); - } - /* not mod < arg; check if mod > arg */ - while (arg) { -- if (RCLASS_M_TBL(arg) == RCLASS_M_TBL(start)) -+ if (RCLASS_EXT(arg) == RCLASS_EXT(start)) - return Qfalse; - arg = RCLASS_SUPER(arg); - } -diff --git a/sp_ar.c b/sp_ar.c -new file mode 100644 -index 0000000..2ed69bf ---- /dev/null -+++ b/sp_ar.c -@@ -0,0 +1,374 @@ -+/* -+ * sparse array lib -+ * inspired by Lua table -+ * written by Sokolov Yura aka funny_falcon -+ */ -+#ifdef NOT_RUBY -+#include "regint.h" -+#include "st.h" -+#else -+#include "ruby/ruby.h" -+#endif -+ -+#include -+#ifdef HAVE_STDLIB_H -+#include -+#endif -+#include -+ -+#ifdef RUBY -+#define malloc xmalloc -+#define calloc xcalloc -+#define realloc xrealloc -+#define free xfree -+#endif -+ -+#define sa_table_alloc() (sa_table*)malloc(sizeof(sa_table)) -+#define sa_table_xalloc() (sa_table*)calloc(1, sizeof(sa_table)) -+#define sa_table_dealloc(table) free(table) -+#define sa_entry_alloc(n) (sa_entry*)calloc((n), sizeof(sa_entry)) -+#define sa_entry_dealloc(entries) free(entries) -+ -+#define SA_LAST 1 -+#define SA_OFFSET 2 -+ -+#define SA_MIN_SIZE 4 -+ -+void -+sa_init_table(register sa_table *table, sa_index_t num_bins) -+{ -+ if (num_bins) { -+ table->num_entries = 0; -+ table->entries = sa_entry_alloc(num_bins); -+ table->num_bins = num_bins; -+ table->free_pos = num_bins; -+ } -+ else { -+ memset(table, 0, sizeof(sa_table)); -+ } -+} -+ -+sa_table* -+sa_new_table() -+{ -+ sa_table* table = sa_table_alloc(); -+ sa_init_table(table, 0); -+ return table; -+} -+ -+static inline sa_index_t -+calc_pos(register sa_table* table, sa_index_t key) -+{ -+ /* this formula is empirical */ -+ /* it has no good avalance, but works well in our case */ -+ key ^= key >> 16; -+ key *= 0x445229; -+ return (key + (key >> 16)) % table->num_bins; -+} -+ -+static void -+fix_empty(register sa_table* table) -+{ -+ while(--table->free_pos && -+ table->entries[table->free_pos-1].next != SA_EMPTY); -+} -+ -+#define FLOOR_TO_4 ((~((sa_index_t)0)) << 2) -+static sa_index_t -+find_empty(register sa_table* table, register sa_index_t pos) -+{ -+ sa_index_t new_pos = table->free_pos-1; -+ sa_entry *entry; -+ pos &= FLOOR_TO_4; -+ entry = table->entries+pos; -+ -+ if (entry->next == SA_EMPTY) { new_pos = pos; goto check; } -+ pos++; entry++; -+ if (entry->next == SA_EMPTY) { new_pos = pos; goto check; } -+ pos++; entry++; -+ if (entry->next == SA_EMPTY) { new_pos = pos; goto check; } -+ pos++; entry++; -+ if (entry->next == SA_EMPTY) { new_pos = pos; goto check; } -+ -+check: -+ if (new_pos+1 == table->free_pos) fix_empty(table); -+ return new_pos; -+} -+ -+static void resize(register sa_table* table); -+static int insert_into_chain(register sa_table*, register sa_index_t, st_data_t, sa_index_t pos); -+static int insert_into_main(register sa_table*, sa_index_t, st_data_t, sa_index_t pos, sa_index_t prev_pos); -+ -+int -+sa_insert(register sa_table* table, register sa_index_t key, st_data_t value) -+{ -+ sa_index_t pos, main_pos; -+ register sa_entry *entry; -+ -+ if (table->num_bins == 0) { -+ sa_init_table(table, SA_MIN_SIZE); -+ } -+ -+ pos = calc_pos(table, key); -+ entry = table->entries + pos; -+ -+ if (entry->next == SA_EMPTY) { -+ entry->next = SA_LAST; -+ entry->key = key; -+ entry->value = value; -+ table->num_entries++; -+ if (pos+1 == table->free_pos) fix_empty(table); -+ return 0; -+ } -+ -+ if (entry->key == key) { -+ entry->value = value; -+ return 1; -+ } -+ -+ if (table->num_entries + (table->num_entries >> 2) > table->num_bins) { -+ resize(table); -+ return sa_insert(table, key, value); -+ } -+ -+ main_pos = calc_pos(table, entry->key); -+ if (main_pos == pos) { -+ return insert_into_chain(table, key, value, pos); -+ } -+ else { -+ if (!table->free_pos) { -+ resize(table); -+ return sa_insert(table, key, value); -+ } -+ return insert_into_main(table, key, value, pos, main_pos); -+ } -+} -+ -+static int -+insert_into_chain(register sa_table* table, register sa_index_t key, st_data_t value, sa_index_t pos) -+{ -+ sa_entry *entry = table->entries + pos, *new_entry; -+ sa_index_t new_pos; -+ -+ while (entry->next != SA_LAST) { -+ pos = entry->next - SA_OFFSET; -+ entry = table->entries + pos; -+ if (entry->key == key) { -+ entry->value = value; -+ return 1; -+ } -+ } -+ -+ if (!table->free_pos) { -+ resize(table); -+ return sa_insert(table, key, value); -+ } -+ -+ new_pos = find_empty(table, pos); -+ new_entry = table->entries + new_pos; -+ entry->next = new_pos + SA_OFFSET; -+ -+ new_entry->next = SA_LAST; -+ new_entry->key = key; -+ new_entry->value = value; -+ table->num_entries++; -+ return 0; -+} -+ -+static int -+insert_into_main(register sa_table* table, sa_index_t key, st_data_t value, sa_index_t pos, sa_index_t prev_pos) -+{ -+ sa_entry *entry = table->entries + pos; -+ sa_index_t new_pos = find_empty(table, pos); -+ sa_entry *new_entry = table->entries + new_pos; -+ sa_index_t npos; -+ -+ *new_entry = *entry; -+ -+ while((npos = table->entries[prev_pos].next - SA_OFFSET) != pos) { -+ prev_pos = npos; -+ } -+ table->entries[prev_pos].next = new_pos + SA_OFFSET; -+ -+ entry->next = SA_LAST; -+ entry->key = key; -+ entry->value = value; -+ table->num_entries++; -+ return 0; -+} -+ -+static sa_index_t -+new_size(sa_index_t num_entries) -+{ -+ sa_index_t msb = num_entries; -+ msb |= msb >> 1; -+ msb |= msb >> 2; -+ msb |= msb >> 4; -+ msb |= msb >> 8; -+ msb |= msb >> 16; -+ msb = ((msb >> 4) + 1) << 3; -+ return (num_entries & (msb | (msb >> 1))) + (msb >> 1); -+} -+ -+static void -+resize(register sa_table *table) -+{ -+ sa_table tmp_table; -+ sa_entry *entry; -+ sa_index_t i; -+ -+ if (table->num_entries == 0) { -+ sa_entry_dealloc(table->entries); -+ memset(table, 0, sizeof(sa_table)); -+ return; -+ } -+ -+ sa_init_table(&tmp_table, new_size(table->num_entries + (table->num_entries >> 2))); -+ entry = table->entries; -+ -+ for(i = 0; i < table->num_bins; i++, entry++) { -+ if (entry->next != SA_EMPTY) { -+ sa_insert(&tmp_table, entry->key, entry->value); -+ } -+ } -+ sa_entry_dealloc(table->entries); -+ *table = tmp_table; -+} -+ -+int -+sa_lookup(register sa_table *table, register sa_index_t key, st_data_t *value) -+{ -+ register sa_entry *entry; -+ -+ if (table->num_entries == 0) return 0; -+ -+ entry = table->entries + calc_pos(table, key); -+ if (entry->next == SA_EMPTY) return 0; -+ -+ if (entry->key == key) goto found; -+ if (entry->next == SA_LAST) return 0; -+ -+ entry = table->entries + (entry->next - SA_OFFSET); -+ if (entry->key == key) goto found; -+ -+ while(entry->next != SA_LAST) { -+ entry = table->entries + (entry->next - SA_OFFSET); -+ if (entry->key == key) goto found; -+ } -+ return 0; -+found: -+ if (value) *value = entry->value; -+ return 1; -+} -+ -+void -+sa_clear(sa_table *table) -+{ -+ sa_entry_dealloc(table->entries); -+ memset(table, 0, sizeof(sa_table)); -+} -+ -+void -+sa_clear_no_free(sa_table *table) -+{ -+ memset(table->entries, 0, sizeof(sa_entry) * table->num_bins); -+ table->num_entries = 0; -+ table->free_pos = table->num_bins; -+} -+ -+void -+sa_free_table(sa_table *table) -+{ -+ sa_entry_dealloc(table->entries); -+ sa_table_dealloc(table); -+} -+ -+int -+sa_delete(sa_table *table, sa_index_t key, st_data_t *value) -+{ -+ sa_index_t pos, prev_pos = ~0; -+ sa_entry *entry; -+ -+ if (table->num_entries == 0) goto not_found; -+ -+ pos = calc_pos(table, key); -+ entry = table->entries + pos; -+ -+ if (entry->next == SA_EMPTY) goto not_found; -+ -+ do { -+ if (entry->key == key) { -+ if (value) *value = entry->value; -+ if (entry->next != SA_LAST) { -+ sa_index_t npos = entry->next - SA_OFFSET; -+ *entry = table->entries[npos]; -+ memset(table->entries + npos, 0, sizeof(sa_entry)); -+ } -+ else { -+ memset(table->entries + pos, 0, sizeof(sa_entry)); -+ if (~prev_pos) { -+ table->entries[prev_pos].next = SA_LAST; -+ } -+ } -+ table->num_entries--; -+ if (table->num_entries < table->num_bins / 4) { -+ resize(table); -+ } -+ return 1; -+ } -+ if (entry->next == SA_LAST) break; -+ prev_pos = pos; -+ pos = entry->next - SA_OFFSET; -+ entry = table->entries + pos; -+ } while(1); -+ -+not_found: -+ if (value) *value = 0; -+ return 0; -+} -+ -+int -+sa_foreach(register sa_table *table, int (*func)(), st_data_t arg) -+{ -+ sa_index_t i; -+ if (table->num_bins == 0) { -+ return 0; -+ } -+ for(i = 0; i < table->num_bins ; i++) { -+ if (table->entries[i].next != SA_EMPTY) { -+ sa_index_t key = table->entries[i].key; -+ st_data_t val = table->entries[i].value; -+ if ((*func)(key, val, arg) == SA_STOP) break; -+ } -+ } -+ return 0; -+} -+ -+size_t -+sa_memsize(const sa_table *table) -+{ -+ return sizeof(sa_table) + table->num_bins * sizeof(sa_entry); -+} -+ -+sa_table* -+sa_copy(sa_table *table) -+{ -+ sa_table *new_table = sa_table_alloc(); -+ *new_table = *table; -+ if (table->num_bins) { -+ new_table->entries = sa_entry_alloc(table->num_bins); -+ memcpy(new_table->entries, table->entries, table->num_bins*sizeof(sa_entry)); -+ } -+ return new_table; -+} -+ -+void -+sa_copy_to(sa_table *from, sa_table *to) -+{ -+ sa_entry_dealloc(to->entries); -+ *to = *from; -+ if (to->num_bins) { -+ to->entries = sa_entry_alloc(to->num_bins); -+ memcpy(to->entries, from->entries, from->num_bins*sizeof(sa_entry)); -+ } -+} -diff --git a/test/ruby/test_marshal.rb b/test/ruby/test_marshal.rb -index 7ec6959..f5774cd 100644 ---- a/test/ruby/test_marshal.rb -+++ b/test/ruby/test_marshal.rb -@@ -312,7 +312,7 @@ class TestMarshal < Test::Unit::TestCase - assert_equal(a.instance_variable_get(i), b.instance_variable_get(i), bug1932) - end - end -- a.__send__(a.methods(true).grep(/=\z/)[0], a) -+ a.__send__(a.methods(true).grep(/\Ar.+=\z/)[0], a) - assert_nothing_raised(bug1932) do - b = Marshal.load(Marshal.dump(a)) - assert_equal(ClassISO8859_1, b.class, bug1932) -diff --git a/test/ruby/test_method.rb b/test/ruby/test_method.rb -index 2cc0de5..b1bf33e 100644 ---- a/test/ruby/test_method.rb -+++ b/test/ruby/test_method.rb -@@ -406,7 +406,7 @@ class TestMethod < Test::Unit::TestCase - obj = a.new - assert_equal([:a], obj.public_methods(false), bug) - obj.extend(m) -- assert_equal([:m1, :a], obj.public_methods(false), bug) -+ assert_equal([:a, :m1], obj.public_methods(false).sort, bug) - end - - def test_visibility -diff --git a/test/ruby/test_module.rb b/test/ruby/test_module.rb -index 6176f48..a67d845 100644 ---- a/test/ruby/test_module.rb -+++ b/test/ruby/test_module.rb -@@ -870,7 +870,7 @@ class TestModule < Test::Unit::TestCase - (class << self ; self ; end).class_eval do - define_method :method_added do |sym| - memo << sym -- memo << mod.instance_methods(false) -+ memo << mod.instance_methods(false).sort - memo << (mod.instance_method(sym) rescue nil) - end - end -@@ -887,10 +887,10 @@ class TestModule < Test::Unit::TestCase - assert_equal [:f, :g], memo.shift - assert_equal mod.instance_method(:f), memo.shift - assert_equal :a, memo.shift -- assert_equal [:f, :g, :a], memo.shift -+ assert_equal [:a, :f, :g], memo.shift - assert_equal mod.instance_method(:a), memo.shift - assert_equal :a=, memo.shift -- assert_equal [:f, :g, :a, :a=], memo.shift -+ assert_equal [:a, :a=, :f, :g], memo.shift - assert_equal mod.instance_method(:a=), memo.shift - end - -diff --git a/time.c b/time.c -index 755812f..83edc83 100644 ---- a/time.c -+++ b/time.c -@@ -4712,16 +4712,14 @@ time_mload(VALUE time, VALUE str) - long nsec; - VALUE submicro, nano_num, nano_den, offset; - wideval_t timew; -- st_data_t data; - - time_modify(time); - - #define get_attr(attr, iffound) \ - attr = rb_attr_get(str, id_##attr); \ - if (!NIL_P(attr)) { \ -- data = id_##attr; \ - iffound; \ -- st_delete(rb_generic_ivar_table(str), &data, 0); \ -+ sa_delete(rb_generic_ivar_table(str), (sa_index_t)id_##attr, 0); \ - } - - get_attr(nano_num, {}); -diff --git a/variable.c b/variable.c -index 3da500e..4a61453 100644 ---- a/variable.c -+++ b/variable.c -@@ -19,15 +19,15 @@ - #include "constant.h" - #include "internal.h" - --st_table *rb_global_tbl; --st_table *rb_class_tbl; -+sa_table rb_global_tbl; -+sa_table rb_class_tbl; - static ID autoload, classpath, tmp_classpath, classid; - - void - Init_var_tables(void) - { -- rb_global_tbl = st_init_numtable(); -- rb_class_tbl = st_init_numtable(); -+ sa_init_table(&rb_global_tbl, 0); -+ sa_init_table(&rb_class_tbl, 0); - CONST_ID(autoload, "__autoload__"); - CONST_ID(classpath, "__classpath__"); - CONST_ID(tmp_classpath, "__tmp_classpath__"); -@@ -43,7 +43,7 @@ struct fc_result { - }; - - static VALUE --fc_path(struct fc_result *fc, ID name) -+fc_path(struct fc_result *fc, sa_index_t name) - { - VALUE path, tmp; - -@@ -51,8 +51,7 @@ fc_path(struct fc_result *fc, ID name) - while (fc) { - st_data_t n; - if (fc->track == rb_cObject) break; -- if (RCLASS_IV_TBL(fc->track) && -- st_lookup(RCLASS_IV_TBL(fc->track), (st_data_t)classpath, &n)) { -+ if (sa_lookup(RCLASS_IV_TBL(fc->track), (sa_index_t)classpath, &n)) { - tmp = rb_str_dup((VALUE)n); - rb_str_cat2(tmp, "::"); - rb_str_append(tmp, path); -@@ -70,7 +69,7 @@ fc_path(struct fc_result *fc, ID name) - } - - static int --fc_i(ID key, rb_const_entry_t *ce, struct fc_result *res) -+fc_i(sa_index_t key, rb_const_entry_t *ce, struct fc_result *res) - { - VALUE value = ce->value; - if (!rb_is_const_id(key)) return ST_CONTINUE; -@@ -98,7 +97,7 @@ fc_i(ID key, rb_const_entry_t *ce, struct fc_result *res) - arg.klass = res->klass; - arg.track = value; - arg.prev = res; -- st_foreach(RCLASS_CONST_TBL(value), fc_i, (st_data_t)&arg); -+ sa_foreach(RCLASS_CONST_TBL(value), fc_i, (st_data_t)&arg); - if (arg.path) { - res->path = arg.path; - return ST_STOP; -@@ -123,18 +122,14 @@ find_class_path(VALUE klass) - arg.track = rb_cObject; - arg.prev = 0; - if (RCLASS_CONST_TBL(rb_cObject)) { -- st_foreach_safe(RCLASS_CONST_TBL(rb_cObject), fc_i, (st_data_t)&arg); -+ sa_foreach(RCLASS_CONST_TBL(rb_cObject), fc_i, (st_data_t)&arg); - } - if (arg.path == 0) { -- st_foreach_safe(rb_class_tbl, fc_i, (st_data_t)&arg); -+ sa_foreach(&rb_class_tbl, fc_i, (st_data_t)&arg); - } - if (arg.path) { -- st_data_t tmp = tmp_classpath; -- if (!RCLASS_IV_TBL(klass)) { -- RCLASS_IV_TBL(klass) = st_init_numtable(); -- } -- st_insert(RCLASS_IV_TBL(klass), (st_data_t)classpath, arg.path); -- st_delete(RCLASS_IV_TBL(klass), &tmp, 0); -+ sa_insert(RCLASS_IV_TBL(klass), (sa_index_t)classpath, arg.path); -+ sa_delete(RCLASS_IV_TBL(klass), (sa_index_t)tmp_classpath, 0); - return arg.path; - } - return Qnil; -@@ -147,16 +142,15 @@ classname(VALUE klass) - st_data_t n; - - if (!klass) klass = rb_cObject; -- if (RCLASS_IV_TBL(klass)) { -- if (!st_lookup(RCLASS_IV_TBL(klass), (st_data_t)classpath, &n)) { -- if (!st_lookup(RCLASS_IV_TBL(klass), (st_data_t)classid, &n)) { -+ if (RCLASS_IV_TBL(klass)->num_entries) { -+ if (!sa_lookup(RCLASS_IV_TBL(klass), (sa_index_t)classpath, &n)) { -+ if (!sa_lookup(RCLASS_IV_TBL(klass), (sa_index_t)classid, &n)) { - return find_class_path(klass); - } - path = rb_str_dup(rb_id2str(SYM2ID((VALUE)n))); - OBJ_FREEZE(path); -- st_insert(RCLASS_IV_TBL(klass), (st_data_t)classpath, (st_data_t)path); -- n = classid; -- st_delete(RCLASS_IV_TBL(klass), &n, 0); -+ sa_insert(RCLASS_IV_TBL(klass), (sa_index_t)classpath, (st_data_t)path); -+ sa_delete(RCLASS_IV_TBL(klass), (sa_index_t)classid, 0); - } - else { - path = (VALUE)n; -@@ -192,8 +186,7 @@ rb_class_path(VALUE klass) - st_data_t n = (st_data_t)path; - - if (!NIL_P(path)) return path; -- if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass), -- (st_data_t)tmp_classpath, &n)) { -+ if (sa_lookup(RCLASS_IV_TBL(klass), (sa_index_t)tmp_classpath, &n)) { - return (VALUE)n; - } - else { -@@ -364,7 +357,7 @@ rb_global_entry(ID id) - struct global_entry *entry; - st_data_t data; - -- if (!st_lookup(rb_global_tbl, (st_data_t)id, &data)) { -+ if (!sa_lookup(&rb_global_tbl, (sa_index_t)id, &data)) { - struct global_variable *var; - entry = ALLOC(struct global_entry); - var = ALLOC(struct global_variable); -@@ -378,7 +371,7 @@ rb_global_entry(ID id) - - var->block_trace = 0; - var->trace = 0; -- st_add_direct(rb_global_tbl, id, (st_data_t)entry); -+ sa_insert(&rb_global_tbl, (sa_index_t)id, (st_data_t)entry); - } - else { - entry = (struct global_entry *)data; -@@ -454,8 +447,8 @@ readonly_setter(VALUE val, ID id, void *data, struct global_variable *gvar) - rb_name_error(id, "%s is a read-only variable", rb_id2name(id)); - } - --static int --mark_global_entry(ID key, struct global_entry *entry) -+static void -+mark_global_entry(struct global_entry *entry) - { - struct trace_var *trace; - struct global_variable *var = entry->var; -@@ -466,14 +459,14 @@ mark_global_entry(ID key, struct global_entry *entry) - if (trace->data) rb_gc_mark_maybe(trace->data); - trace = trace->next; - } -- return ST_CONTINUE; - } - - void - rb_gc_mark_global_tbl(void) - { -- if (rb_global_tbl) -- st_foreach_safe(rb_global_tbl, mark_global_entry, 0); -+ SA_FOREACH_START(&rb_global_tbl); -+ mark_global_entry((struct global_entry*) value); -+ SA_FOREACH_END(); - } - - static ID -@@ -635,7 +628,7 @@ rb_f_untrace_var(int argc, VALUE *argv) - rb_secure(4); - rb_scan_args(argc, argv, "11", &var, &cmd); - id = rb_to_id(var); -- if (!st_lookup(rb_global_tbl, (st_data_t)id, &data)) { -+ if (!sa_lookup(&rb_global_tbl, (sa_index_t)id, &data)) { - rb_name_error(id, "undefined global variable %s", rb_id2name(id)); - } - -@@ -742,13 +735,6 @@ rb_gvar_defined(struct global_entry *entry) - return Qtrue; - } - --static int --gvar_i(ID key, struct global_entry *entry, VALUE ary) --{ -- rb_ary_push(ary, ID2SYM(key)); -- return ST_CONTINUE; --} -- - /* - * call-seq: - * global_variables -> array -@@ -765,7 +751,9 @@ rb_f_global_variables(void) - char buf[2]; - int i; - -- st_foreach_safe(rb_global_tbl, gvar_i, ary); -+ SA_FOREACH_START(&rb_global_tbl); -+ rb_ary_push(ary, ID2SYM(entry->key)); -+ SA_FOREACH_END(); - buf[0] = '$'; - for (i = 1; i <= 9; ++i) { - buf[1] = (char)(i + '0'); -@@ -784,10 +772,10 @@ rb_alias_variable(ID name1, ID name2) - rb_raise(rb_eSecurityError, "Insecure: can't alias global variable"); - - entry2 = rb_global_entry(name2); -- if (!st_lookup(rb_global_tbl, (st_data_t)name1, &data1)) { -+ if (!sa_lookup(&rb_global_tbl, (sa_index_t)name1, &data1)) { - entry1 = ALLOC(struct global_entry); - entry1->id = name1; -- st_add_direct(rb_global_tbl, name1, (st_data_t)entry1); -+ sa_insert(&rb_global_tbl, (sa_index_t)name1, (st_data_t)entry1); - } - else if ((entry1 = (struct global_entry *)data1)->var != entry2->var) { - struct global_variable *var = entry1->var; -@@ -815,7 +803,7 @@ rb_alias_variable(ID name1, ID name2) - static int special_generic_ivar = 0; - static st_table *generic_iv_tbl; - --st_table* -+sa_table* - rb_generic_ivar_table(VALUE obj) - { - st_data_t tbl; -@@ -823,7 +811,7 @@ rb_generic_ivar_table(VALUE obj) - if (!FL_TEST(obj, FL_EXIVAR)) return 0; - if (!generic_iv_tbl) return 0; - if (!st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) return 0; -- return (st_table *)tbl; -+ return (sa_table *)tbl; - } - - static VALUE -@@ -833,7 +821,7 @@ generic_ivar_get(VALUE obj, ID id, int warn) - - if (generic_iv_tbl) { - if (st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) { -- if (st_lookup((st_table *)tbl, (st_data_t)id, &val)) { -+ if (sa_lookup((sa_table *)tbl, (sa_index_t)id, &val)) { - return (VALUE)val; - } - } -@@ -847,7 +835,6 @@ generic_ivar_get(VALUE obj, ID id, int warn) - static void - generic_ivar_set(VALUE obj, ID id, VALUE val) - { -- st_table *tbl; - st_data_t data; - - if (rb_special_const_p(obj)) { -@@ -859,24 +846,22 @@ generic_ivar_set(VALUE obj, ID id, VALUE val) - } - if (!st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) { - FL_SET(obj, FL_EXIVAR); -- tbl = st_init_numtable(); -- st_add_direct(generic_iv_tbl, (st_data_t)obj, (st_data_t)tbl); -- st_add_direct(tbl, (st_data_t)id, (st_data_t)val); -- return; -+ data = (st_data_t)sa_new_table(); -+ st_add_direct(generic_iv_tbl, (st_data_t)obj, data); - } -- st_insert((st_table *)data, (st_data_t)id, (st_data_t)val); -+ sa_insert((sa_table *)data, (sa_index_t)id, (st_data_t)val); - } - - static VALUE - generic_ivar_defined(VALUE obj, ID id) - { -- st_table *tbl; -+ sa_table *tbl; - st_data_t data; - - if (!generic_iv_tbl) return Qfalse; - if (!st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) return Qfalse; -- tbl = (st_table *)data; -- if (st_lookup(tbl, (st_data_t)id, &data)) { -+ tbl = (sa_table *)data; -+ if (sa_lookup(tbl, (sa_index_t)id, &data)) { - return Qtrue; - } - return Qfalse; -@@ -885,18 +870,18 @@ generic_ivar_defined(VALUE obj, ID id) - static int - generic_ivar_remove(VALUE obj, ID id, st_data_t *valp) - { -- st_table *tbl; -+ sa_table *tbl; - st_data_t data, key = (st_data_t)id; - int status; - - if (!generic_iv_tbl) return 0; - if (!st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) return 0; -- tbl = (st_table *)data; -- status = st_delete(tbl, &key, valp); -+ tbl = (sa_table *)data; -+ status = sa_delete(tbl, (sa_index_t)id, valp); - if (tbl->num_entries == 0) { - key = (st_data_t)obj; - st_delete(generic_iv_tbl, &key, &data); -- st_free_table((st_table *)data); -+ sa_free_table(tbl); - } - return status; - } -@@ -908,22 +893,17 @@ rb_mark_generic_ivar(VALUE obj) - - if (!generic_iv_tbl) return; - if (st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) { -- rb_mark_tbl((st_table *)tbl); -+ rb_mark_sa_tbl((sa_table *)tbl); - } - } - - static int --givar_mark_i(ID key, VALUE value) --{ -- rb_gc_mark(value); -- return ST_CONTINUE; --} -- --static int --givar_i(VALUE obj, st_table *tbl) -+givar_i(VALUE obj, sa_table *tbl) - { - if (rb_special_const_p(obj)) { -- st_foreach_safe(tbl, givar_mark_i, 0); -+ SA_FOREACH_START(tbl); -+ rb_gc_mark((VALUE)value); -+ SA_FOREACH_END(); - } - return ST_CONTINUE; - } -@@ -943,7 +923,7 @@ rb_free_generic_ivar(VALUE obj) - - if (!generic_iv_tbl) return; - if (st_delete(generic_iv_tbl, &key, &tbl)) -- st_free_table((st_table *)tbl); -+ sa_free_table((sa_table *)tbl); - } - - RUBY_FUNC_EXPORTED size_t -@@ -951,7 +931,7 @@ rb_generic_ivar_memsize(VALUE obj) - { - st_data_t tbl; - if (st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) -- return st_memsize((st_table *)tbl); -+ return sa_memsize((sa_table *)tbl); - return 0; - } - -@@ -970,17 +950,17 @@ rb_copy_generic_ivar(VALUE clone, VALUE obj) - return; - } - if (st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) { -- st_table *tbl = (st_table *)data; -+ sa_table *tbl = (sa_table *)data; - - if (tbl->num_entries == 0) - goto clear; - - if (st_lookup(generic_iv_tbl, (st_data_t)clone, &data)) { -- st_free_table((st_table *)data); -- st_insert(generic_iv_tbl, (st_data_t)clone, (st_data_t)st_copy(tbl)); -+ sa_free_table((sa_table *)data); -+ st_insert(generic_iv_tbl, (st_data_t)clone, (st_data_t)sa_copy(tbl)); - } - else { -- st_add_direct(generic_iv_tbl, (st_data_t)clone, (st_data_t)st_copy(tbl)); -+ st_add_direct(generic_iv_tbl, (st_data_t)clone, (st_data_t)sa_copy(tbl)); - FL_SET(clone, FL_EXIVAR); - } - } -@@ -990,7 +970,7 @@ static VALUE - ivar_get(VALUE obj, ID id, int warn) - { - VALUE val, *ptr; -- struct st_table *iv_index_tbl; -+ sa_table *iv_index_tbl; - long len; - st_data_t index; - -@@ -1000,7 +980,7 @@ ivar_get(VALUE obj, ID id, int warn) - ptr = ROBJECT_IVPTR(obj); - iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); - if (!iv_index_tbl) break; -- if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break; -+ if (!sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) break; - if (len <= (long)index) break; - val = ptr[index]; - if (val != Qundef) -@@ -1008,7 +988,7 @@ ivar_get(VALUE obj, ID id, int warn) - break; - case T_CLASS: - case T_MODULE: -- if (RCLASS_IV_TBL(obj) && st_lookup(RCLASS_IV_TBL(obj), (st_data_t)id, &index)) -+ if (sa_lookup(RCLASS_IV_TBL(obj), (sa_index_t)id, &index)) - return (VALUE)index; - break; - default: -@@ -1037,7 +1017,7 @@ rb_attr_get(VALUE obj, ID id) - VALUE - rb_ivar_set(VALUE obj, ID id, VALUE val) - { -- struct st_table *iv_index_tbl; -+ struct sa_table *iv_index_tbl; - st_data_t index; - long i, len; - int ivar_extended; -@@ -1051,14 +1031,11 @@ rb_ivar_set(VALUE obj, ID id, VALUE val) - if (!iv_index_tbl) { - VALUE klass = rb_obj_class(obj); - iv_index_tbl = RCLASS_IV_INDEX_TBL(klass); -- if (!iv_index_tbl) { -- iv_index_tbl = RCLASS_IV_INDEX_TBL(klass) = st_init_numtable(); -- } - } - ivar_extended = 0; -- if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) { -+ if (!sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) { - index = iv_index_tbl->num_entries; -- st_add_direct(iv_index_tbl, (st_data_t)id, index); -+ sa_insert(iv_index_tbl, (sa_index_t)id, index); - ivar_extended = 1; - } - len = ROBJECT_NUMIV(obj); -@@ -1098,8 +1075,7 @@ rb_ivar_set(VALUE obj, ID id, VALUE val) - break; - case T_CLASS: - case T_MODULE: -- if (!RCLASS_IV_TBL(obj)) RCLASS_IV_TBL(obj) = st_init_numtable(); -- st_insert(RCLASS_IV_TBL(obj), (st_data_t)id, val); -+ sa_insert(RCLASS_IV_TBL(obj), (sa_index_t)id, val); - break; - default: - generic_ivar_set(obj, id, val); -@@ -1112,13 +1088,13 @@ VALUE - rb_ivar_defined(VALUE obj, ID id) - { - VALUE val; -- struct st_table *iv_index_tbl; -+ struct sa_table *iv_index_tbl; - st_data_t index; - switch (TYPE(obj)) { - case T_OBJECT: - iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); - if (!iv_index_tbl) break; -- if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break; -+ if (!sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) break; - if (ROBJECT_NUMIV(obj) <= (long)index) break; - val = ROBJECT_IVPTR(obj)[index]; - if (val != Qundef) -@@ -1126,7 +1102,7 @@ rb_ivar_defined(VALUE obj, ID id) - break; - case T_CLASS: - case T_MODULE: -- if (RCLASS_IV_TBL(obj) && st_lookup(RCLASS_IV_TBL(obj), (st_data_t)id, 0)) -+ if (sa_lookup(RCLASS_IV_TBL(obj), (sa_index_t)id, 0)) - return Qtrue; - break; - default: -@@ -1137,40 +1113,26 @@ rb_ivar_defined(VALUE obj, ID id) - return Qfalse; - } - --struct obj_ivar_tag { -- VALUE obj; -- int (*func)(ID key, VALUE val, st_data_t arg); -- st_data_t arg; --}; -- --static int --obj_ivar_i(st_data_t key, st_data_t index, st_data_t arg) --{ -- struct obj_ivar_tag *data = (struct obj_ivar_tag *)arg; -- if ((long)index < ROBJECT_NUMIV(data->obj)) { -- VALUE val = ROBJECT_IVPTR(data->obj)[(long)index]; -- if (val != Qundef) { -- return (data->func)((ID)key, val, data->arg); -- } -- } -- return ST_CONTINUE; --} -- - static void - obj_ivar_each(VALUE obj, int (*func)(ANYARGS), st_data_t arg) - { -- st_table *tbl; -- struct obj_ivar_tag data; -+ sa_table *tbl; -+ long numiv = ROBJECT_NUMIV(obj); -+ VALUE *vars = ROBJECT_IVPTR(obj); - - tbl = ROBJECT_IV_INDEX_TBL(obj); -- if (!tbl) -+ if (!tbl || !numiv) - return; - -- data.obj = obj; -- data.func = (int (*)(ID key, VALUE val, st_data_t arg))func; -- data.arg = arg; -- -- st_foreach_safe(tbl, obj_ivar_i, (st_data_t)&data); -+ SA_FOREACH_START(tbl); -+ if ((long)value < numiv) { -+ VALUE val = vars[value]; -+ if (val != Qundef) { -+ if (((sa_iter_func)func)(entry->key, val, arg) == SA_STOP) -+ break; -+ } -+ } -+ SA_FOREACH_END(); - } - - void -@@ -1182,9 +1144,7 @@ rb_ivar_foreach(VALUE obj, int (*func)(ANYARGS), st_data_t arg) - break; - case T_CLASS: - case T_MODULE: -- if (RCLASS_IV_TBL(obj)) { -- st_foreach_safe(RCLASS_IV_TBL(obj), func, arg); -- } -+ sa_foreach(RCLASS_IV_TBL(obj), func, arg); - break; - default: - if (!generic_iv_tbl) break; -@@ -1192,7 +1152,7 @@ rb_ivar_foreach(VALUE obj, int (*func)(ANYARGS), st_data_t arg) - st_data_t tbl; - - if (st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) { -- st_foreach_safe((st_table *)tbl, func, arg); -+ sa_foreach((sa_table *)tbl, func, arg); - } - } - break; -@@ -1202,11 +1162,11 @@ rb_ivar_foreach(VALUE obj, int (*func)(ANYARGS), st_data_t arg) - st_index_t - rb_ivar_count(VALUE obj) - { -- st_table *tbl; -+ sa_table *tbl; - switch (TYPE(obj)) { - case T_OBJECT: - if ((tbl = ROBJECT_IV_INDEX_TBL(obj)) != 0) { -- st_index_t i, count, num = tbl->num_entries; -+ sa_index_t i, count, num = tbl->num_entries; - const VALUE *const ivptr = ROBJECT_IVPTR(obj); - for (i = count = 0; i < num; ++i) { - if (ivptr[i] != Qundef) { -@@ -1228,7 +1188,7 @@ rb_ivar_count(VALUE obj) - st_data_t data; - - if (st_lookup(generic_iv_tbl, (st_data_t)obj, &data) && -- (tbl = (st_table *)data) != 0) { -+ (tbl = (sa_table *)data) != 0) { - return tbl->num_entries; - } - } -@@ -1238,7 +1198,7 @@ rb_ivar_count(VALUE obj) - } - - static int --ivar_i(ID key, VALUE val, VALUE ary) -+ivar_i(sa_index_t key, VALUE val, VALUE ary) - { - if (rb_is_instance_id(key)) { - rb_ary_push(ary, ID2SYM(key)); -@@ -1301,7 +1261,7 @@ rb_obj_remove_instance_variable(VALUE obj, VALUE name) - VALUE val = Qnil; - const ID id = rb_to_id(name); - st_data_t n, v; -- struct st_table *iv_index_tbl; -+ struct sa_table *iv_index_tbl; - st_data_t index; - - if (!OBJ_UNTRUSTED(obj) && rb_safe_level() >= 4) -@@ -1315,7 +1275,7 @@ rb_obj_remove_instance_variable(VALUE obj, VALUE name) - case T_OBJECT: - iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); - if (!iv_index_tbl) break; -- if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break; -+ if (!sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) break; - if (ROBJECT_NUMIV(obj) <= (long)index) break; - val = ROBJECT_IVPTR(obj)[index]; - if (val != Qundef) { -@@ -1326,14 +1286,14 @@ rb_obj_remove_instance_variable(VALUE obj, VALUE name) - case T_CLASS: - case T_MODULE: - n = id; -- if (RCLASS_IV_TBL(obj) && st_delete(RCLASS_IV_TBL(obj), &n, &v)) { -+ if (sa_delete(RCLASS_IV_TBL(obj), (sa_index_t)id, &v)) { - return (VALUE)v; - } - break; - default: - if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) { - v = val; -- if (generic_ivar_remove(obj, (st_data_t)id, &v)) { -+ if (generic_ivar_remove(obj, id, &v)) { - return (VALUE)v; - } - } -@@ -1410,20 +1370,20 @@ rb_mod_const_missing(VALUE klass, VALUE name) - static void - autoload_mark(void *ptr) - { -- rb_mark_tbl((st_table *)ptr); -+ rb_mark_sa_tbl((sa_table *)ptr); - } - - static void - autoload_free(void *ptr) - { -- st_free_table((st_table *)ptr); -+ sa_free_table((sa_table *)ptr); - } - - static size_t - autoload_memsize(const void *ptr) - { -- const st_table *tbl = ptr; -- return st_memsize(tbl); -+ const sa_table *tbl = ptr; -+ return sa_memsize(tbl); - } - - static const rb_data_type_t autoload_data_type = { -@@ -1432,14 +1392,14 @@ static const rb_data_type_t autoload_data_type = { - }; - - #define check_autoload_table(av) \ -- (struct st_table *)rb_check_typeddata((av), &autoload_data_type) -+ (struct sa_table *)rb_check_typeddata((av), &autoload_data_type) - - void - rb_autoload(VALUE mod, ID id, const char *file) - { - st_data_t av; - VALUE fn; -- struct st_table *tbl; -+ struct sa_table *tbl; - - if (!rb_is_const_id(id)) { - rb_raise(rb_eNameError, "autoload must be constant name: %s", rb_id2name(id)); -@@ -1448,43 +1408,41 @@ rb_autoload(VALUE mod, ID id, const char *file) - rb_raise(rb_eArgError, "empty file name"); - } - -- if ((tbl = RCLASS_CONST_TBL(mod)) && st_lookup(tbl, (st_data_t)id, &av) && ((rb_const_entry_t*)av)->value != Qundef) -+ if (sa_lookup(RCLASS_CONST_TBL(mod), (sa_index_t)id, &av) && ((rb_const_entry_t*)av)->value != Qundef) - return; - - rb_const_set(mod, id, Qundef); - tbl = RCLASS_IV_TBL(mod); -- if (tbl && st_lookup(tbl, (st_data_t)autoload, &av)) { -+ if (sa_lookup(tbl, (sa_index_t)autoload, &av)) { - tbl = check_autoload_table((VALUE)av); - } - else { -- if (!tbl) tbl = RCLASS_IV_TBL(mod) = st_init_numtable(); - av = (st_data_t)TypedData_Wrap_Struct(0, &autoload_data_type, 0); -- st_add_direct(tbl, (st_data_t)autoload, av); -- DATA_PTR(av) = tbl = st_init_numtable(); -+ sa_insert(tbl, (sa_index_t)autoload, av); -+ DATA_PTR(av) = tbl = sa_new_table(); - } - fn = rb_str_new2(file); - FL_UNSET(fn, FL_TAINT); - OBJ_FREEZE(fn); -- st_insert(tbl, (st_data_t)id, (st_data_t)rb_node_newnode(NODE_MEMO, fn, rb_safe_level(), 0)); -+ sa_insert(tbl, (sa_index_t)id, (st_data_t)rb_node_newnode(NODE_MEMO, fn, rb_safe_level(), 0)); - } - - static NODE* - autoload_delete(VALUE mod, ID id) - { -- st_data_t val, load = 0, n = id; -+ st_data_t val, load = 0; - rb_const_entry_t *ce; - -- st_delete(RCLASS_CONST_TBL(mod), &n, &val); -+ sa_delete(RCLASS_CONST_TBL(mod), (sa_index_t)id, &val); - ce = (rb_const_entry_t*)val; - if (ce) xfree(ce); -- if (st_lookup(RCLASS_IV_TBL(mod), (st_data_t)autoload, &val)) { -- struct st_table *tbl = check_autoload_table((VALUE)val); -+ if (sa_lookup(RCLASS_IV_TBL(mod), (sa_index_t)autoload, &val)) { -+ struct sa_table *tbl = check_autoload_table((VALUE)val); - -- st_delete(tbl, &n, &load); -+ sa_delete(tbl, (sa_index_t)id, &load); - - if (tbl->num_entries == 0) { -- n = autoload; -- st_delete(RCLASS_IV_TBL(mod), &n, &val); -+ sa_delete(RCLASS_IV_TBL(mod), (sa_index_t)autoload, &val); - } - } - -@@ -1509,14 +1467,14 @@ static NODE * - autoload_node(VALUE mod, ID id, const char **loadingpath) - { - VALUE file; -- struct st_table *tbl; -+ struct sa_table *tbl; - st_data_t val; - NODE *load; - const char *loading; - int safe; - -- if (!st_lookup(RCLASS_IV_TBL(mod), autoload, &val) || -- !(tbl = check_autoload_table((VALUE)val)) || !st_lookup(tbl, (st_data_t)id, &val)) { -+ if (!sa_lookup(RCLASS_IV_TBL(mod), (sa_index_t)autoload, &val) || -+ !(tbl = check_autoload_table((VALUE)val)) || !sa_lookup(tbl, (sa_index_t)id, &val)) { - return 0; - } - load = (NODE *)val; -@@ -1541,10 +1499,10 @@ autoload_node(VALUE mod, ID id, const char **loadingpath) - static int - autoload_node_id(VALUE mod, ID id) - { -- struct st_table *tbl = RCLASS_CONST_TBL(mod); -+ struct sa_table *tbl = RCLASS_CONST_TBL(mod); - st_data_t val; - -- if (!tbl || !st_lookup(tbl, (st_data_t)id, &val) || ((rb_const_entry_t*)val)->value != Qundef) { -+ if (!tbl || !sa_lookup(tbl, (sa_index_t)id, &val) || ((rb_const_entry_t*)val)->value != Qundef) { - return 0; - } - return 1; -@@ -1593,7 +1551,7 @@ rb_const_get_0(VALUE klass, ID id, int exclude, int recurse, int visibility) - while (RTEST(tmp)) { - VALUE am = 0; - st_data_t data; -- while (RCLASS_CONST_TBL(tmp) && st_lookup(RCLASS_CONST_TBL(tmp), (st_data_t)id, &data)) { -+ while (sa_lookup(RCLASS_CONST_TBL(tmp), (sa_index_t)id, &data)) { - rb_const_entry_t *ce = (rb_const_entry_t *)data; - if (visibility && ce->flag == CONST_PRIVATE) { - rb_name_error(id, "private constant %s::%s referenced", rb_class2name(klass), rb_id2name(id)); -@@ -1686,12 +1644,12 @@ VALUE - rb_const_remove(VALUE mod, ID id) - { - VALUE val; -- st_data_t v, n = id; -+ st_data_t v; - - if (!OBJ_UNTRUSTED(mod) && rb_safe_level() >= 4) - rb_raise(rb_eSecurityError, "Insecure: can't remove constant"); - rb_check_frozen(mod); -- if (!RCLASS_CONST_TBL(mod) || !st_delete(RCLASS_CONST_TBL(mod), &n, &v)) { -+ if (!sa_delete(RCLASS_CONST_TBL(mod), (sa_index_t)id, &v)) { - if (rb_const_defined_at(mod, id)) { - rb_name_error(id, "cannot remove %s::%s", - rb_class2name(mod), rb_id2name(id)); -@@ -1711,27 +1669,20 @@ rb_const_remove(VALUE mod, ID id) - return val; - } - --static int --sv_i(ID key, rb_const_entry_t *ce, st_table *tbl) --{ -- if (rb_is_const_id(key)) { -- if (!st_lookup(tbl, (st_data_t)key, 0)) { -- st_insert(tbl, (st_data_t)key, (st_data_t)ce); -- } -- } -- return ST_CONTINUE; --} -- - void* - rb_mod_const_at(VALUE mod, void *data) - { -- st_table *tbl = data; -+ sa_table *tbl = data; - if (!tbl) { -- tbl = st_init_numtable(); -+ tbl = sa_new_table(); - } -- if (RCLASS_CONST_TBL(mod)) { -- st_foreach_safe(RCLASS_CONST_TBL(mod), sv_i, (st_data_t)tbl); -+ SA_FOREACH_START(RCLASS_CONST_TBL(mod)); -+ if (rb_is_const_id(entry->key)) { -+ if (!sa_lookup(tbl, entry->key, 0)) { -+ sa_insert(tbl, entry->key, value); -+ } - } -+ SA_FOREACH_END(); - return tbl; - } - -@@ -1748,25 +1699,21 @@ rb_mod_const_of(VALUE mod, void *data) - return data; - } - --static int --list_i(st_data_t key, st_data_t value, VALUE ary) --{ -- ID sym = (ID)key; -- rb_const_entry_t *ce = (rb_const_entry_t *)value; -- if (ce->flag != CONST_PRIVATE) rb_ary_push(ary, ID2SYM(sym)); -- return ST_CONTINUE; --} -- - VALUE - rb_const_list(void *data) - { -- st_table *tbl = data; -+ sa_table *tbl = data; - VALUE ary; - - if (!tbl) return rb_ary_new2(0); - ary = rb_ary_new2(tbl->num_entries); -- st_foreach_safe(tbl, list_i, ary); -- st_free_table(tbl); -+ -+ SA_FOREACH_START(tbl); -+ rb_const_entry_t *ce = (rb_const_entry_t *)value; -+ if (ce->flag != CONST_PRIVATE) rb_ary_push(ary, ID2SYM(entry->key)); -+ SA_FOREACH_END(); -+ -+ sa_free_table(tbl); - - return ary; - } -@@ -1790,7 +1737,7 @@ VALUE - rb_mod_constants(int argc, VALUE *argv, VALUE mod) - { - VALUE inherit; -- st_table *tbl; -+ sa_table *tbl; - - if (argc == 0) { - inherit = Qtrue; -@@ -1817,7 +1764,7 @@ rb_const_defined_0(VALUE klass, ID id, int exclude, int recurse, int visibility) - tmp = klass; - retry: - while (tmp) { -- if (RCLASS_CONST_TBL(tmp) && st_lookup(RCLASS_CONST_TBL(tmp), (st_data_t)id, &value)) { -+ if (sa_lookup(RCLASS_CONST_TBL(tmp), (sa_index_t)id, &value)) { - rb_const_entry_t *ce = (rb_const_entry_t *)value; - if (visibility && ce->flag == CONST_PRIVATE) { - return (int)Qfalse; -@@ -1885,6 +1832,7 @@ void - rb_const_set(VALUE klass, ID id, VALUE val) - { - rb_const_entry_t *ce; -+ st_data_t value; - VALUE visibility = CONST_PUBLIC; - - if (NIL_P(klass)) { -@@ -1893,21 +1841,14 @@ rb_const_set(VALUE klass, ID id, VALUE val) - } - - check_before_mod_set(klass, id, val, "constant"); -- if (!RCLASS_CONST_TBL(klass)) { -- RCLASS_CONST_TBL(klass) = st_init_numtable(); -- } -- else { -- st_data_t value; -- -- if (st_lookup(RCLASS_CONST_TBL(klass), (st_data_t)id, &value)) { -- rb_const_entry_t *ce = (rb_const_entry_t*)value; -- if (ce->value == Qundef) -- autoload_delete(klass, id); -- else { -- visibility = ce->flag; -- rb_warn("already initialized constant %s", rb_id2name(id)); -- } -- } -+ if (sa_lookup(RCLASS_CONST_TBL(klass), (sa_index_t)id, &value)) { -+ rb_const_entry_t *ce = (rb_const_entry_t*)value; -+ if (ce->value == Qundef) -+ autoload_delete(klass, id); -+ else { -+ visibility = ce->flag; -+ rb_warn("already initialized constant %s", rb_id2name(id)); -+ } - } - - rb_vm_change_state(); -@@ -1916,7 +1857,7 @@ rb_const_set(VALUE klass, ID id, VALUE val) - ce->flag = (rb_const_flag_t)visibility; - ce->value = val; - -- st_insert(RCLASS_CONST_TBL(klass), (st_data_t)id, (st_data_t)ce); -+ sa_insert(RCLASS_CONST_TBL(klass), (sa_index_t)id, (st_data_t)ce); - } - - void -@@ -1958,8 +1899,7 @@ set_const_visibility(VALUE mod, int argc, VALUE *argv, rb_const_flag_t flag) - for (i = 0; i < argc; i++) { - VALUE val = argv[i]; - id = rb_to_id(val); -- if (RCLASS_CONST_TBL(mod) && -- st_lookup(RCLASS_CONST_TBL(mod), (st_data_t)id, &v)) { -+ if (sa_lookup(RCLASS_CONST_TBL(mod), (sa_index_t)id, &v)) { - ((rb_const_entry_t*)v)->flag = flag; - } - else { -@@ -2008,7 +1948,7 @@ original_module(VALUE c) - } - - #define CVAR_LOOKUP(v,r) do {\ -- if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass),(st_data_t)id,(v))) {\ -+ if (sa_lookup(RCLASS_IV_TBL(klass),(sa_index_t)id,(v))) {\ - r;\ - }\ - if (FL_TEST(klass, FL_SINGLETON) ) {\ -@@ -2027,7 +1967,7 @@ original_module(VALUE c) - klass = RCLASS_SUPER(klass);\ - }\ - while (klass) {\ -- if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass),(st_data_t)id,(v))) {\ -+ if (sa_lookup(RCLASS_IV_TBL(klass),(sa_index_t)id,(v))) {\ - r;\ - }\ - klass = RCLASS_SUPER(klass);\ -@@ -2043,15 +1983,13 @@ rb_cvar_set(VALUE klass, ID id, VALUE val) - CVAR_LOOKUP(0, {if (!front) front = klass; target = klass;}); - if (target) { - if (front && target != front) { -- st_data_t did = id; -- - if (RTEST(ruby_verbose)) { - rb_warning("class variable %s of %s is overtaken by %s", - rb_id2name(id), rb_class2name(original_module(front)), - rb_class2name(original_module(target))); - } - if (BUILTIN_TYPE(front) == T_CLASS) { -- st_delete(RCLASS_IV_TBL(front),&did,0); -+ sa_delete(RCLASS_IV_TBL(front),(sa_index_t)id,0); - } - } - } -@@ -2060,11 +1998,7 @@ rb_cvar_set(VALUE klass, ID id, VALUE val) - } - - check_before_mod_set(target, id, val, "class variable"); -- if (!RCLASS_IV_TBL(target)) { -- RCLASS_IV_TBL(target) = st_init_numtable(); -- } -- -- st_insert(RCLASS_IV_TBL(target), (st_data_t)id, (st_data_t)val); -+ sa_insert(RCLASS_IV_TBL(target), (sa_index_t)id, (st_data_t)val); - } - - VALUE -@@ -2080,15 +2014,13 @@ rb_cvar_get(VALUE klass, ID id) - rb_id2name(id), rb_class2name(tmp)); - } - if (front && target != front) { -- st_data_t did = id; -- - if (RTEST(ruby_verbose)) { - rb_warning("class variable %s of %s is overtaken by %s", - rb_id2name(id), rb_class2name(original_module(front)), - rb_class2name(original_module(target))); - } - if (BUILTIN_TYPE(front) == T_CLASS) { -- st_delete(RCLASS_IV_TBL(front),&did,0); -+ sa_delete(RCLASS_IV_TBL(front),(sa_index_t)id,0); - } - } - return (VALUE)value; -@@ -2134,7 +2066,7 @@ rb_define_class_variable(VALUE klass, const char *name, VALUE val) - } - - static int --cv_i(ID key, VALUE value, VALUE ary) -+cv_i(sa_index_t key, VALUE value, VALUE ary) - { - if (rb_is_class_id(key)) { - VALUE kval = ID2SYM(key); -@@ -2167,7 +2099,7 @@ rb_mod_class_variables(VALUE obj) - VALUE ary = rb_ary_new(); - - if (RCLASS_IV_TBL(obj)) { -- st_foreach_safe(RCLASS_IV_TBL(obj), cv_i, ary); -+ sa_foreach(RCLASS_IV_TBL(obj), cv_i, ary); - } - return ary; - } -@@ -2196,7 +2128,7 @@ VALUE - rb_mod_remove_cvar(VALUE mod, VALUE name) - { - const ID id = rb_to_id(name); -- st_data_t val, n = id; -+ st_data_t val; - - if (!rb_is_class_id(id)) { - rb_name_error(id, "wrong class variable name %s", rb_id2name(id)); -@@ -2204,7 +2136,7 @@ rb_mod_remove_cvar(VALUE mod, VALUE name) - if (!OBJ_UNTRUSTED(mod) && rb_safe_level() >= 4) - rb_raise(rb_eSecurityError, "Insecure: can't remove class variable"); - rb_check_frozen(mod); -- if (RCLASS_IV_TBL(mod) && st_delete(RCLASS_IV_TBL(mod), &n, &val)) { -+ if (RCLASS_IV_TBL(mod) && sa_delete(RCLASS_IV_TBL(mod), (sa_index_t)id, &val)) { - return (VALUE)val; - } - if (rb_cvar_defined(mod, id)) { -diff --git a/vm.c b/vm.c -index 3436898..ca1d858 100644 ---- a/vm.c -+++ b/vm.c -@@ -1042,7 +1042,7 @@ static void - add_opt_method(VALUE klass, ID mid, VALUE bop) - { - rb_method_entry_t *me; -- if (st_lookup(RCLASS_M_TBL(klass), mid, (void *)&me) && me->def && -+ if (sa_lookup(RCLASS_M_TBL(klass), (sa_index_t)mid, (void *)&me) && me->def && - me->def->type == VM_METHOD_TYPE_CFUNC) { - st_insert(vm_opt_method_table, (st_data_t)me, (st_data_t)bop); - } -diff --git a/vm_insnhelper.c b/vm_insnhelper.c -index 55152df..deeed9b 100644 ---- a/vm_insnhelper.c -+++ b/vm_insnhelper.c -@@ -1187,7 +1187,7 @@ vm_get_ev_const(rb_thread_t *th, const rb_iseq_t *iseq, - st_data_t data; - search_continue: - if (RCLASS_CONST_TBL(klass) && -- st_lookup(RCLASS_CONST_TBL(klass), id, &data)) { -+ sa_lookup(RCLASS_CONST_TBL(klass), (sa_index_t)id, &data)) { - val = ((rb_const_entry_t*)data)->value; - if (val == Qundef) { - if (am == klass) break; -@@ -1297,10 +1297,10 @@ vm_getivar(VALUE obj, ID id, IC ic) - st_data_t index; - long len = ROBJECT_NUMIV(obj); - VALUE *ptr = ROBJECT_IVPTR(obj); -- struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); -+ struct sa_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); - - if (iv_index_tbl) { -- if (st_lookup(iv_index_tbl, id, &index)) { -+ if (sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) { - if ((long)index < len) { - val = ptr[index]; - } -@@ -1350,9 +1350,9 @@ vm_setivar(VALUE obj, ID id, VALUE val, IC ic) - } - } - else { -- struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); -+ struct sa_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); - -- if (iv_index_tbl && st_lookup(iv_index_tbl, (st_data_t)id, &index)) { -+ if (iv_index_tbl && sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) { - ic->ic_class = klass; - ic->ic_value.index = index; - ic->ic_vmstat = GET_VM_STATE_VERSION(); -diff --git a/vm_method.c b/vm_method.c -index 6e33603..6567440 100644 ---- a/vm_method.c -+++ b/vm_method.c -@@ -2,38 +2,33 @@ - * This file is included by vm.c - */ - --#define CACHE_SIZE 0x800 --#define CACHE_MASK 0x7ff --#define EXPR1(c,m) ((((c)>>3)^(m))&CACHE_MASK) -- - static void rb_vm_check_redefinition_opt_method(const rb_method_entry_t *me); - - static ID object_id, respond_to_missing; - static ID removed, singleton_removed, undefined, singleton_undefined; - static ID added, singleton_added, attached; - --struct cache_entry { /* method hash table. */ -- VALUE filled_version; /* filled state version */ -- ID mid; /* method's id */ -- VALUE klass; /* receiver's class */ -- rb_method_entry_t *me; --}; -- --static struct cache_entry cache[CACHE_SIZE]; - #define ruby_running (GET_VM()->running) - /* int ruby_running = 0; */ - -+static int -+methods_cache_clear_callback(void *vstart, void *vend, size_t stride, void *data) -+{ -+ VALUE v = (VALUE)vstart; -+ for (; v != (VALUE)vend; v += stride) { -+ switch(BUILTIN_TYPE(v)) { -+ case T_CLASS: -+ case T_MODULE: -+ case T_ICLASS: -+ RCLASS(v)->cache->method_cache_version = 0; -+ } -+ } -+ return 0; -+} - static void - vm_clear_global_method_cache(void) - { -- struct cache_entry *ent, *end; -- -- ent = cache; -- end = ent + CACHE_SIZE; -- while (ent < end) { -- ent->filled_version = 0; -- ent++; -- } -+ rb_objspace_each_objects(methods_cache_clear_callback, NULL); - } - - void -@@ -162,7 +157,7 @@ rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type, - rb_method_definition_t *def, rb_method_flag_t noex) - { - rb_method_entry_t *me; -- st_table *mtbl; -+ sa_table *mtbl; - st_data_t data; - - if (NIL_P(klass)) { -@@ -190,7 +185,7 @@ rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type, - mtbl = RCLASS_M_TBL(klass); - - /* check re-definition */ -- if (st_lookup(mtbl, mid, &data)) { -+ if (sa_lookup(mtbl, (sa_index_t)mid, &data)) { - rb_method_entry_t *old_me = (rb_method_entry_t *)data; - rb_method_definition_t *old_def = old_me->def; - -@@ -248,7 +243,7 @@ rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type, - } - } - -- st_insert(mtbl, mid, (st_data_t) me); -+ sa_insert(mtbl, (sa_index_t)mid, (st_data_t) me); - - return me; - } -@@ -371,7 +366,7 @@ search_method(VALUE klass, ID id) - return 0; - } - -- while (!st_lookup(RCLASS_M_TBL(klass), id, &body)) { -+ while (!sa_lookup(RCLASS_M_TBL(klass), (sa_index_t)id, &body)) { - klass = RCLASS_SUPER(klass); - if (!klass) { - return 0; -@@ -393,20 +388,10 @@ rb_method_entry_get_without_cache(VALUE klass, ID id) - rb_method_entry_t *me = search_method(klass, id); - - if (ruby_running) { -- struct cache_entry *ent; -- ent = cache + EXPR1(klass, id); -- ent->filled_version = GET_VM_STATE_VERSION(); -- ent->klass = klass; -- - if (UNDEFINED_METHOD_ENTRY_P(me)) { -- ent->mid = id; -- ent->me = 0; -- me = 0; -- } -- else { -- ent->mid = id; -- ent->me = me; -+ me = 0; - } -+ sa_insert(&RCLASS(klass)->cache->m_cache_tbl, (sa_index_t)id, (st_data_t)me); - } - - return me; -@@ -415,21 +400,23 @@ rb_method_entry_get_without_cache(VALUE klass, ID id) - rb_method_entry_t * - rb_method_entry(VALUE klass, ID id) - { -- struct cache_entry *ent; -+ rb_class_cache_t *cache = RCLASS(klass)->cache; -+ rb_method_entry_t *me; - -- ent = cache + EXPR1(klass, id); -- if (ent->filled_version == GET_VM_STATE_VERSION() && -- ent->mid == id && ent->klass == klass) { -- return ent->me; -+ if (cache->method_cache_version != GET_VM_STATE_VERSION()) { -+ sa_clear_no_free(&cache->m_cache_tbl); -+ cache->method_cache_version = GET_VM_STATE_VERSION(); -+ } -+ else if (sa_lookup(&cache->m_cache_tbl, (sa_index_t)id, (st_data_t*)&me)) { -+ return me; - } -- - return rb_method_entry_get_without_cache(klass, id); - } - - static void - remove_method(VALUE klass, ID mid) - { -- st_data_t key, data; -+ st_data_t data; - rb_method_entry_t *me = 0; - - if (klass == rb_cObject) { -@@ -443,14 +430,13 @@ remove_method(VALUE klass, ID mid) - rb_warn("removing `%s' may cause serious problems", rb_id2name(mid)); - } - -- if (!st_lookup(RCLASS_M_TBL(klass), mid, &data) || -+ if (!sa_lookup(RCLASS_M_TBL(klass), (sa_index_t)mid, &data) || - !(me = (rb_method_entry_t *)data) || - (!me->def || me->def->type == VM_METHOD_TYPE_UNDEF)) { - rb_name_error(mid, "method `%s' not defined in %s", - rb_id2name(mid), rb_class2name(klass)); - } -- key = (st_data_t)mid; -- st_delete(RCLASS_M_TBL(klass), &key, &data); -+ sa_delete(RCLASS_M_TBL(klass), (sa_index_t)mid, &data); - - rb_vm_check_redefinition_opt_method(me); - rb_clear_cache_for_undef(klass, mid); diff --git a/patches/ruby/1.9.3/p362/railsexpress/01-fix-make-clean.patch b/patches/ruby/1.9.3/p362/railsexpress/01-fix-make-clean.patch deleted file mode 100644 index c76a89922d..0000000000 --- a/patches/ruby/1.9.3/p362/railsexpress/01-fix-make-clean.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/lib/mkmf.rb b/lib/mkmf.rb -index 08053a9..361fd08 100644 ---- a/lib/mkmf.rb -+++ b/lib/mkmf.rb -@@ -2191,7 +2191,7 @@ def init_mkmf(config = CONFIG, rbconfig = RbConfig::CONFIG) - $LOCAL_LIBS = "" - - $cleanfiles = config_string('CLEANFILES') {|s| Shellwords.shellwords(s)} || [] -- $cleanfiles << "mkmf.log" -+ $cleanfiles << "mkmf.log .*.time" - $distcleanfiles = config_string('DISTCLEANFILES') {|s| Shellwords.shellwords(s)} || [] - $distcleandirs = config_string('DISTCLEANDIRS') {|s| Shellwords.shellwords(s)} || [] - diff --git a/patches/ruby/1.9.3/p362/railsexpress/02-railsbench-gc.patch b/patches/ruby/1.9.3/p362/railsexpress/02-railsbench-gc.patch deleted file mode 100644 index 1994a12c61..0000000000 --- a/patches/ruby/1.9.3/p362/railsexpress/02-railsbench-gc.patch +++ /dev/null @@ -1,1235 +0,0 @@ -diff --git a/configure.in b/configure.in -index c64d981..6099a92 100644 ---- a/configure.in -+++ b/configure.in -@@ -2416,6 +2416,10 @@ if test "$EXEEXT" = .exe; then - AC_SUBST(EXECUTABLE_EXTS) - fi - -+dnl enable gc debugging -+AC_ARG_ENABLE(gcdebug, -+ AS_HELP_STRING([--enable-gcdebug], [build garbage collector with debugging enabled]), -+ [AC_DEFINE(GC_DEBUG,1)]) - dnl } - dnl build section { - -diff --git a/gc.c b/gc.c -index e38930d..c728587 100644 ---- a/gc.c -+++ b/gc.c -@@ -97,6 +97,15 @@ ruby_gc_params_t initial_params = { - #endif - }; - -+#ifndef HAVE_LONG_LONG -+#define LONG_LONG long -+#endif -+ -+static int heap_min_slots = 10000; -+static int heap_slots_increment = 10000; -+static int initial_heap_slots_increment = 10000; -+static double heap_slots_growth_factor = 1.8; -+ - #define nomem_error GET_VM()->special_exceptions[ruby_error_nomemory] - - #if SIZEOF_LONG == SIZEOF_VOIDP -@@ -301,7 +310,7 @@ typedef struct RVALUE { - struct RComplex complex; - } as; - #ifdef GC_DEBUG -- const char *file; -+ VALUE file; - int line; - #endif - } RVALUE; -@@ -371,11 +380,25 @@ typedef struct rb_objspace { - size_t free_min; - size_t final_num; - size_t do_heap_free; -+ unsigned long max_blocks_to_free; -+ unsigned long freed_blocks; - } heap; - struct { -+ unsigned long processed; -+ unsigned long freed_objects; -+ unsigned long freelist_size; -+ unsigned long zombies; -+ unsigned long free_counts[T_MASK+1]; -+ unsigned long live_counts[T_MASK+1]; -+ unsigned long gc_time_accumulator_before_gc; -+ unsigned long live_after_last_mark_phase; -+ } stats; -+ struct { - int dont_gc; - int dont_lazy_sweep; - int during_gc; -+ int gc_statistics; -+ int verbose_gc_stats; - } flags; - struct { - st_table *table; -@@ -392,6 +415,14 @@ typedef struct rb_objspace { - struct gc_list *global_list; - size_t count; - int gc_stress; -+ long heap_size; -+ unsigned LONG_LONG gc_time_accumulator; -+ FILE* gc_data_file; -+ long gc_collections; -+ unsigned LONG_LONG gc_allocated_size; -+ unsigned LONG_LONG gc_num_allocations; -+ unsigned long live_objects; -+ unsigned LONG_LONG allocated_objects; - } rb_objspace_t; - - #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE -@@ -414,6 +445,16 @@ int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress; - #define heaps_freed objspace->heap.freed - #define dont_gc objspace->flags.dont_gc - #define during_gc objspace->flags.during_gc -+#define gc_statistics objspace->flags.gc_statistics -+#define verbose_gc_stats objspace->flags.verbose_gc_stats -+#define heap_size objspace->heap_size -+#define gc_time_accumulator objspace->gc_time_accumulator -+#define gc_data_file objspace->gc_data_file -+#define gc_collections objspace->gc_collections -+#define gc_allocated_size objspace->gc_allocated_size -+#define gc_num_allocations objspace->gc_num_allocations -+#define live_objects objspace->live_objects -+#define allocated_objects objspace->allocated_objects - #define finalizer_table objspace->final.table - #define deferred_final_list objspace->final.deferred - #define global_List objspace->global_list -@@ -421,6 +462,14 @@ int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress; - #define initial_malloc_limit initial_params.initial_malloc_limit - #define initial_heap_min_slots initial_params.initial_heap_min_slots - #define initial_free_min initial_params.initial_free_min -+#define free_counts objspace->stats.free_counts -+#define live_counts objspace->stats.live_counts -+#define processed objspace->stats.processed -+#define zombies objspace->stats.zombies -+#define freelist_size objspace->stats.freelist_size -+#define freed_objects objspace->stats.freed_objects -+#define gc_time_accumulator_before_gc objspace->stats.gc_time_accumulator_before_gc -+#define live_after_last_mark_phase objspace->stats.live_after_last_mark_phase - - static void rb_objspace_call_finalizer(rb_objspace_t *objspace); - -@@ -443,24 +492,59 @@ static void init_mark_stack(mark_stack_t *stack); - void - rb_gc_set_params(void) - { -- char *malloc_limit_ptr, *heap_min_slots_ptr, *free_min_ptr; -+ char *envp; -+ -+ rb_objspace_t *objspace = &rb_objspace; -+ -+ gc_data_file = stderr; - - if (rb_safe_level() > 0) return; - -- malloc_limit_ptr = getenv("RUBY_GC_MALLOC_LIMIT"); -- if (malloc_limit_ptr != NULL) { -- int malloc_limit_i = atoi(malloc_limit_ptr); -+ envp = getenv("RUBY_GC_STATS"); -+ if (envp != NULL) { -+ int i = atoi(envp); -+ if (i > 0) { -+ verbose_gc_stats = 1; -+ fprintf(stderr, "RUBY_GC_STATS=%d\n", verbose_gc_stats); -+ } -+ /* child processes should not inherit RUBY_GC_STATS */ -+ ruby_unsetenv("RUBY_GC_STATS"); -+ } -+ -+ envp = getenv("RUBY_GC_DATA_FILE"); -+ if (envp != NULL) { -+ FILE* data_file = fopen(envp, "w"); -+ if (data_file != NULL) { -+ gc_data_file = data_file; -+ } -+ else { -+ fprintf(stderr, "can't open gc log file %s for writing, using default\n", envp); -+ } -+ /* child processes should not inherit RUBY_GC_DATA_FILE to avoid clobbering */ -+ ruby_unsetenv("RUBY_GC_DATA_FILE"); -+ } -+ -+ envp = getenv("RUBY_GC_MALLOC_LIMIT"); -+ if (envp != NULL) { -+ int malloc_limit_i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_GC_MALLOC_LIMIT=%s\n", envp); -+ } - if (RTEST(ruby_verbose)) - fprintf(stderr, "malloc_limit=%d (%d)\n", - malloc_limit_i, initial_malloc_limit); - if (malloc_limit_i > 0) { - initial_malloc_limit = malloc_limit_i; -+ // malloc_limit = initial_malloc_limit; - } - } - -- heap_min_slots_ptr = getenv("RUBY_HEAP_MIN_SLOTS"); -- if (heap_min_slots_ptr != NULL) { -- int heap_min_slots_i = atoi(heap_min_slots_ptr); -+ envp = getenv("RUBY_HEAP_MIN_SLOTS"); -+ if (envp != NULL) { -+ int heap_min_slots_i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_MIN_SLOTS=%s\n", envp); -+ } - if (RTEST(ruby_verbose)) - fprintf(stderr, "heap_min_slots=%d (%d)\n", - heap_min_slots_i, initial_heap_min_slots); -@@ -470,15 +554,42 @@ rb_gc_set_params(void) - } - } - -- free_min_ptr = getenv("RUBY_FREE_MIN"); -- if (free_min_ptr != NULL) { -- int free_min_i = atoi(free_min_ptr); -+ if (!(envp = getenv("RUBY_FREE_MIN"))) -+ envp = getenv("RUBY_HEAP_FREE_MIN"); -+ if (envp != NULL) { -+ int free_min_i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_FREE_MIN=%s\n", envp); -+ } - if (RTEST(ruby_verbose)) - fprintf(stderr, "free_min=%d (%d)\n", free_min_i, initial_free_min); - if (free_min_i > 0) { - initial_free_min = free_min_i; - } - } -+ -+ envp = getenv("RUBY_HEAP_SLOTS_INCREMENT"); -+ if (envp != NULL) { -+ int i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_INCREMENT=%s\n", envp); -+ } -+ heap_slots_increment = i; -+ initial_heap_slots_increment = heap_slots_increment; -+ } -+ -+ envp = getenv("RUBY_HEAP_SLOTS_GROWTH_FACTOR"); -+ if (envp != NULL) { -+ double d = atof(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_GROWTH_FACTOR=%s\n", envp); -+ } -+ if (d > 0) { -+ heap_slots_growth_factor = d; -+ } -+ } -+ -+ fflush(gc_data_file); - } - - #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE -@@ -775,6 +886,11 @@ vm_malloc_fixup(rb_objspace_t *objspace, void *mem, size_t size) - mem = (size_t *)mem + 1; - #endif - -+ if (gc_statistics) { -+ gc_allocated_size += size; -+ gc_num_allocations += 1; -+ } -+ - return mem; - } - -@@ -835,6 +951,13 @@ vm_xrealloc(rb_objspace_t *objspace, void *ptr, size_t size) - mem = (size_t *)mem + 1; - #endif - -+ /* TODO: we can't count correctly unless we store old size on heap -+ if (gc_statistics) { -+ gc_allocated_size += size; -+ gc_num_allocations += 1; -+ } -+ */ -+ - return mem; - } - -@@ -916,7 +1039,6 @@ ruby_xfree(void *x) - vm_xfree(&rb_objspace, x); - } - -- - /* - * call-seq: - * GC.enable -> true or false -@@ -962,6 +1084,455 @@ rb_gc_disable(void) - return old ? Qtrue : Qfalse; - } - -+/* -+ * call-seq: -+ * GC.enable_stats => true or false -+ * -+ * Enables garbage collection statistics, returning true if garbage -+ * collection statistics was already enabled. -+ * -+ * GC.enable_stats #=> false or true -+ * GC.enable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = gc_statistics; -+ gc_statistics = 1; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_stats => true or false -+ * -+ * Disables garbage collection statistics, returning true if garbage -+ * collection statistics was already disabled. -+ * -+ * GC.disable_stats #=> false or true -+ * GC.disable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = gc_statistics; -+ gc_statistics = 0; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.stats_enabled? => true or false -+ * -+ * Check whether GC stats have been enabled. -+ * -+ * GC.stats_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_stats_enabled() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return gc_statistics ? Qtrue : Qfalse; -+} -+ -+ -+/* -+ * call-seq: -+ * GC.clear_stats => nil -+ * -+ * Clears garbage collection statistics, returning nil. This resets the number -+ * of collections (GC.collections) and the time used (GC.time) to 0. -+ * -+ * GC.clear_stats #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_clear_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ gc_collections = 0; -+ gc_time_accumulator = 0; -+ gc_time_accumulator_before_gc = 0; -+ gc_allocated_size = 0; -+ gc_num_allocations = 0; -+ return Qnil; -+} -+ -+/* -+ * call-seq: -+ * GC.allocated_size => Integer -+ * -+ * Returns the size of memory (in bytes) allocated since GC statistics collection -+ * was enabled. -+ * -+ * GC.allocated_size #=> 35 -+ * -+ */ -+ -+VALUE -+rb_gc_allocated_size() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_allocated_size); -+#else -+ return ULONG2NUM(gc_allocated_size); -+#endif -+} -+ -+/* -+ * call-seq: -+ * GC.num_allocations => Integer -+ * -+ * Returns the number of memory allocations since GC statistics collection -+ * was enabled. -+ * -+ * GC.num_allocations #=> 150 -+ * -+ */ -+VALUE -+rb_gc_num_allocations() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_num_allocations); -+#else -+ return ULONG2NUM(gc_num_allocations); -+#endif -+} -+ -+/* -+ * call-seq: -+ * GC.enable_trace => true or false -+ * -+ * Enables garbage collection tracing, returning true if garbage -+ * collection tracing was already enabled. -+ * -+ * GC.enable_trace #=> false or true -+ * GC.enable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_trace() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = verbose_gc_stats; -+ verbose_gc_stats = 1; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_trace => true or false -+ * -+ * Disables garbage collection tracing, returning true if garbage -+ * collection tracing was already disabled. -+ * -+ * GC.disable_trace #=> false or true -+ * GC.disable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_trace() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = verbose_gc_stats; -+ verbose_gc_stats = 0; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.trace_enabled? => true or false -+ * -+ * Check whether GC tracing has been enabled. -+ * -+ * GC.trace_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_trace_enabled() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return verbose_gc_stats ? Qtrue : Qfalse; -+} -+ -+ -+const char* GC_LOGFILE_IVAR = "@gc_logfile_name"; -+ -+/* -+ * call-seq: -+ * GC.log_file(filename=nil, mode="w") => boolean -+ * -+ * Changes the GC data log file. Closes the currently open logfile. -+ * Returns true if the file was successfully opened for -+ * writing. Returns false if the file could not be opened for -+ * writing. Returns the name of the current logfile (or nil) if no -+ * parameter is given. Restores logging to stderr when given nil as -+ * an argument. -+ * -+ * GC.log_file #=> nil -+ * GC.log_file "/tmp/gc.log" #=> true -+ * GC.log_file #=> "/tmp/gc.log" -+ * GC.log_file nil #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_log_file(int argc, VALUE *argv, VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ VALUE filename = Qnil; -+ VALUE mode_str = Qnil; -+ FILE* f = NULL; -+ const char* mode = "w"; -+ -+ VALUE current_logfile_name = rb_iv_get(rb_mGC, GC_LOGFILE_IVAR); -+ -+ if (argc==0) -+ return current_logfile_name; -+ -+ rb_scan_args(argc, argv, "02", &filename, &mode_str); -+ -+ if (filename == Qnil) { -+ /* close current logfile and reset logfile to stderr */ -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+ } -+ return Qtrue; -+ } -+ -+ /* we have a real logfile name */ -+ filename = StringValue(filename); -+ -+ if (rb_equal(current_logfile_name, filename) == Qtrue) { -+ /* do nothing if we get the file name we're already logging to */ -+ return Qtrue; -+ } -+ -+ /* get mode for file opening */ -+ if (mode_str != Qnil) -+ { -+ mode = RSTRING_PTR(StringValue(mode_str)); -+ } -+ -+ /* try to open file in given mode */ -+ if (f = fopen(RSTRING_PTR(filename), mode)) { -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ } -+ gc_data_file = f; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, filename); -+ } else { -+ return Qfalse; -+ } -+ return Qtrue; -+} -+ -+/* -+ * call-seq: -+ * GC.log String => String -+ * -+ * Logs string to the GC data file and returns it. -+ * -+ * GC.log "manual GC call" #=> "manual GC call" -+ * -+ */ -+ -+VALUE -+rb_gc_log(self, original_str) -+ VALUE self, original_str; -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ if (original_str == Qnil) { -+ fprintf(gc_data_file, "\n"); -+ } -+ else { -+ VALUE str = StringValue(original_str); -+ char *p = RSTRING_PTR(str); -+ fprintf(gc_data_file, "%s\n", p); -+ } -+ return original_str; -+} -+ -+/* -+ * call-seq: -+ * GC.dump => nil -+ * -+ * dumps information about the current GC data structures to the GC log file -+ * -+ * GC.dump #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_dump() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ size_t i; -+ -+ for (i = 0; i < heaps_used; i++) { -+ size_t limit = objspace->heap.sorted[i].slot->limit; -+ fprintf(gc_data_file, "HEAP[%2lu]: size=%7lu\n", (unsigned long)i, (unsigned long)limit); -+ } -+ -+ return Qnil; -+} -+ -+static const char* obj_type(VALUE tp); -+ -+#ifdef GC_DEBUG -+/* -+ * call-seq: -+ * GC.dump_file_and_line_info(String, boolean) => nil -+ * -+ * dumps information on which currently allocated object was created by which file and on which line -+ * -+ * GC.dump_file_and_line_info(String, boolean) #=> nil -+ * -+ * The second parameter specifies whether class names should be included in the dump. -+ * Note that including class names will allocate additional string objects on the heap. -+ * -+ */ -+ -+VALUE -+rb_gc_dump_file_and_line_info(int argc, VALUE *argv) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ VALUE filename, str, include_classnames = Qnil; -+ char *fname = NULL; -+ char *klass = NULL; -+ FILE* f = NULL; -+ size_t i = 0; -+ -+ rb_scan_args(argc, argv, "11", &filename, &include_classnames); -+ -+ str = StringValue(filename); -+ fname = RSTRING_PTR(str); -+ f = fopen(fname, "w"); -+ -+ for (i = 0; i < heaps_used; i++) { -+ RVALUE *p, *pend; -+ -+ p = objspace->heap.sorted[i].start; pend = objspace->heap.sorted[i].end; -+ for (;p < pend; p++) { -+ if (p->as.basic.flags) { -+ const char *src_filename = (p->file && p->file != Qnil )? RSTRING_PTR(p->file) : ""; -+ fprintf(f, "%s:%s:%d", obj_type(p->as.basic.flags & T_MASK), src_filename, (int)p->line); -+ // rb_obj_classname will create objects on the heap, we need a better solution -+ if (include_classnames == Qtrue) { -+ /* write the class */ -+ fprintf(f, ":"); -+ switch (BUILTIN_TYPE(p)) { -+ case T_NONE: -+ fprintf(f, "__none__"); -+ break; -+ case T_UNDEF: -+ fprintf(f, "__undef__"); -+ break; -+ case T_NODE: -+ fprintf(f, "__node__"); -+ break; -+ default: -+ if (!p->as.basic.klass) { -+ fprintf(f, "__unknown__"); -+ } else { -+ fprintf(f, "%s", rb_obj_classname((VALUE)p)); -+ } -+ } -+ /* print object size for some known object types */ -+ switch (BUILTIN_TYPE(p)) { -+ case T_STRING: -+ fprintf(f, ":%lu", RSTRING_LEN(p)); -+ break; -+ case T_ARRAY: -+ fprintf(f, ":%lu", RARRAY_LEN(p)); -+ break; -+ case T_HASH: -+ fprintf(f, ":%lu", (long unsigned int)RHASH_SIZE(p)); -+ break; -+ } -+ } -+ fprintf(f, "\n"); -+ } -+ } -+ } -+ fclose(f); -+ return Qnil; -+} -+#endif -+ -+/* -+ * call-seq: -+ * GC.heap_slots => Integer -+ * -+ * Returns the number of heap slots available for object allocations. -+ * -+ * GC.heap_slots #=> 10000 -+ * -+ */ -+VALUE -+rb_gc_heap_slots() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return LONG2NUM(heap_size); -+} -+ -+ -+/* -+ * call-seq: -+ * GC.collections => Integer -+ * -+ * Returns the number of garbage collections performed while GC statistics collection -+ * was enabled. -+ * -+ * GC.collections #=> 35 -+ * -+ */ -+ -+VALUE -+rb_gc_collections() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return LONG2NUM(gc_collections); -+} -+ -+/* -+ * call-seq: -+ * GC.time => Integer -+ * -+ * Returns the time spent during garbage collection while GC statistics collection -+ * was enabled (in micro seconds). -+ * -+ * GC.time #=> 20000 -+ * -+ */ -+ -+VALUE -+rb_gc_time() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return LL2NUM(gc_time_accumulator); -+#else -+ return LONG2NUM(gc_time_accumulator); -+#endif -+} -+ - VALUE rb_mGC; - - void -@@ -1033,6 +1604,12 @@ allocate_sorted_heaps(rb_objspace_t *objspace, size_t next_heaps_length) - static void - assign_heap_slot(rb_objspace_t *objspace) - { -+ /* -+ if (gc_statistics & verbose_gc_stats) { -+ fprintf(gc_data_file, "assigning heap slot\n"); -+ } -+ */ -+ - RVALUE *p, *pend, *membase; - struct heaps_slot *slot; - size_t hi, lo, mid; -@@ -1094,6 +1671,7 @@ assign_heap_slot(rb_objspace_t *objspace) - if (lomem == 0 || lomem > p) lomem = p; - if (himem < pend) himem = pend; - heaps_used++; -+ heap_size += objs; - - while (p < pend) { - p->as.free.flags = 0; -@@ -1150,7 +1728,7 @@ initial_expand_heap(rb_objspace_t *objspace) - static void - set_heaps_increment(rb_objspace_t *objspace) - { -- size_t next_heaps_length = (size_t)(heaps_used * 1.8); -+ size_t next_heaps_length = (size_t)(heaps_used * heap_slots_growth_factor); - - if (next_heaps_length == heaps_used) { - next_heaps_length++; -@@ -1183,6 +1761,22 @@ rb_during_gc(void) - - #define RANY(o) ((RVALUE*)(o)) - -+#ifdef GC_DEBUG -+static VALUE -+_rb_sourcefile(void) -+{ -+ rb_thread_t *th = GET_THREAD(); -+ rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp); -+ -+ if (cfp) { -+ return cfp->iseq->filename; -+ } -+ else { -+ return Qnil; -+ } -+} -+#endif -+ - VALUE - rb_newobj(void) - { -@@ -1214,9 +1808,11 @@ rb_newobj(void) - - MEMZERO((void*)obj, RVALUE, 1); - #ifdef GC_DEBUG -- RANY(obj)->file = rb_sourcefile(); -+ RANY(obj)->file = _rb_sourcefile(); - RANY(obj)->line = rb_sourceline(); - #endif -+ live_objects++; -+ allocated_objects++; - GC_PROF_INC_LIVE_NUM; - - return obj; -@@ -1768,6 +2364,12 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr) - { - register RVALUE *obj = RANY(ptr); - -+#ifdef GC_DEBUG -+ if (obj->file && obj->file != Qnil && is_pointer_to_heap(objspace, (void*)obj->file)) { -+ gc_mark(objspace, obj->file, lev); -+ } -+#endif -+ - goto marking; /* skip */ - - again: -@@ -1778,6 +2380,12 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr) - obj->as.basic.flags |= FL_MARK; - objspace->heap.live_num++; - -+#ifdef GC_DEBUG -+ if (obj->file && obj->file != Qnil && is_pointer_to_heap(objspace, (void*)obj->file)) { -+ gc_mark(objspace, obj->file, lev); -+ } -+#endif -+ - marking: - if (FL_TEST(obj, FL_EXIVAR)) { - rb_mark_generic_ivar(ptr); -@@ -2120,6 +2728,25 @@ free_unused_heaps(rb_objspace_t *objspace) - } - } - -+static inline unsigned long -+elapsed_musecs(struct timeval since) -+{ -+ struct timeval now; -+ struct timeval temp; -+ -+ gettimeofday(&now, NULL); -+ -+ if ((now.tv_usec-since.tv_usec)<0) { -+ temp.tv_sec = now.tv_sec-since.tv_sec-1; -+ temp.tv_usec = 1000000+now.tv_usec-since.tv_usec; -+ } else { -+ temp.tv_sec = now.tv_sec-since.tv_sec; -+ temp.tv_usec = now.tv_usec-since.tv_usec; -+ } -+ -+ return temp.tv_sec*1000000 + temp.tv_usec; -+} -+ - static void - slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - { -@@ -2127,14 +2754,23 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - RVALUE *p, *pend; - RVALUE *free = freelist, *final = deferred_final_list; - int deferred; -+ int do_gc_stats = gc_statistics & verbose_gc_stats; -+ -+ struct timeval tv1; -+ if (gc_statistics) gettimeofday(&tv1, NULL); - - p = sweep_slot->slot; pend = p + sweep_slot->limit; - while (p < pend) { - if (!(p->as.basic.flags & FL_MARK)) { -+ if (do_gc_stats && !p->as.basic.flags) { -+ /* slot was free before GC */ -+ freelist_size++; -+ } - if (p->as.basic.flags && - ((deferred = obj_free(objspace, (VALUE)p)) || - (FL_TEST(p, FL_FINALIZE)))) { - if (!deferred) { -+ if (do_gc_stats) zombies++; - p->as.free.flags = T_ZOMBIE; - RDATA(p)->dfree = 0; - } -@@ -2144,6 +2780,10 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - final_num++; - } - else { -+ if (do_gc_stats) { -+ VALUE obt = p->as.basic.flags & T_MASK; -+ if (obt) free_counts[obt]++; -+ } - add_freelist(objspace, p); - free_num++; - } -@@ -2151,13 +2791,22 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - else if (BUILTIN_TYPE(p) == T_ZOMBIE) { - /* objects to be finalized */ - /* do nothing remain marked */ -+ if (do_gc_stats) zombies++; - } - else { - RBASIC(p)->flags &= ~FL_MARK; -+ if (do_gc_stats) { -+ live_counts[p->as.basic.flags & T_MASK]++; -+ } - } - p++; -+ processed++; - } -- if (final_num + free_num == sweep_slot->limit && -+ -+ freed_objects += free_num; -+ -+ if (objspace->heap.freed_blocks < objspace->heap.max_blocks_to_free && -+ final_num + free_num == sweep_slot->limit && - objspace->heap.free_num > objspace->heap.do_heap_free) { - RVALUE *pp; - -@@ -2168,6 +2817,8 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - sweep_slot->limit = final_num; - freelist = free; /* cancel this page from freelist */ - unlink_heap_slot(objspace, sweep_slot); -+ objspace->heap.freed_blocks += 1; -+ heap_size -= final_num + free_num; - } - else { - objspace->heap.free_num += free_num; -@@ -2180,6 +2831,10 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - RUBY_VM_SET_FINALIZER_INTERRUPT(th); - } - } -+ -+ if (gc_statistics) { -+ gc_time_accumulator += elapsed_musecs(tv1); -+ } - } - - static int -@@ -2200,6 +2855,21 @@ ready_to_gc(rb_objspace_t *objspace) - static void - before_gc_sweep(rb_objspace_t *objspace) - { -+ if (gc_statistics & verbose_gc_stats) { -+ /* -+ fprintf(gc_data_file, "Sweep started\n"); -+ */ -+ freed_objects = 0; -+ processed = 0; -+ zombies = 0; -+ freelist_size = 0; -+ MEMZERO((void*)free_counts, unsigned long, T_MASK+1); -+ MEMZERO((void*)live_counts, unsigned long, T_MASK+1); -+ } -+ -+ objspace->heap.max_blocks_to_free = heaps_used - (heap_min_slots / HEAP_OBJ_LIMIT); -+ objspace->heap.freed_blocks = 0; -+ - freelist = 0; - objspace->heap.do_heap_free = (size_t)((heaps_used * HEAP_OBJ_LIMIT) * 0.65); - objspace->heap.free_min = (size_t)((heaps_used * HEAP_OBJ_LIMIT) * 0.2); -@@ -2219,8 +2889,13 @@ before_gc_sweep(rb_objspace_t *objspace) - static void - after_gc_sweep(rb_objspace_t *objspace) - { -+ int i; -+ struct timeval tv1; -+ - GC_PROF_SET_MALLOC_INFO; - -+ if (gc_statistics) gettimeofday(&tv1, NULL); -+ - if (objspace->heap.free_num < objspace->heap.free_min) { - set_heaps_increment(objspace); - heaps_increment(objspace); -@@ -2233,6 +2908,29 @@ after_gc_sweep(rb_objspace_t *objspace) - malloc_increase = 0; - - free_unused_heaps(objspace); -+ -+ if (gc_statistics) { -+ gc_time_accumulator += elapsed_musecs(tv1); -+ -+ if (verbose_gc_stats) { -+ /* log gc stats if requested */ -+ fprintf(gc_data_file, "GC time: %lu musec\n", (unsigned long)(gc_time_accumulator-gc_time_accumulator_before_gc)); -+ fprintf(gc_data_file, "objects processed: %7lu\n", (unsigned long)processed); -+ fprintf(gc_data_file, "live objects : %7lu\n", (unsigned long)live_after_last_mark_phase); -+ fprintf(gc_data_file, "freelist objects : %7lu\n", (unsigned long)freelist_size); -+ fprintf(gc_data_file, "freed objects : %7lu\n", (unsigned long)freed_objects); -+ fprintf(gc_data_file, "zombies : %7lu\n", (unsigned long)zombies); -+ for(i=0; i0 || live_counts[i]>0) { -+ fprintf(gc_data_file, -+ "kept %7lu / freed %7lu objects of type %s\n", -+ (unsigned long)live_counts[i], (unsigned long)free_counts[i], obj_type((int)i)); -+ } -+ } -+ rb_gc_dump(); -+ fflush(gc_data_file); -+ } -+ } - } - - static int -@@ -2266,9 +2964,11 @@ rest_sweep(rb_objspace_t *objspace) - - static void gc_marks(rb_objspace_t *objspace); - -+/* only called from rb_new_obj */ - static int - gc_lazy_sweep(rb_objspace_t *objspace) - { -+ struct timeval gctv1; - int res; - INIT_GC_PROF_PARAMS; - -@@ -2290,7 +2990,6 @@ gc_lazy_sweep(rb_objspace_t *objspace) - GC_PROF_TIMER_STOP(Qfalse); - return res; - } -- after_gc_sweep(objspace); - } - else { - if (heaps_increment(objspace)) { -@@ -2298,6 +2997,18 @@ gc_lazy_sweep(rb_objspace_t *objspace) - return TRUE; - } - } -+ after_gc_sweep(objspace); -+ -+ if (gc_statistics) { -+ gc_time_accumulator_before_gc = gc_time_accumulator; -+ gc_collections++; -+ gettimeofday(&gctv1, NULL); -+ /* -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "Garbage collection started (gc_lazy_sweep)\n"); -+ } -+ */ -+ } - - gc_marks(objspace); - -@@ -2306,6 +3017,10 @@ gc_lazy_sweep(rb_objspace_t *objspace) - set_heaps_increment(objspace); - } - -+ if (gc_statistics) { -+ gc_time_accumulator += elapsed_musecs(gctv1); -+ } -+ - GC_PROF_SWEEP_TIMER_START; - if(!(res = lazy_sweep(objspace))) { - after_gc_sweep(objspace); -@@ -2317,6 +3032,7 @@ gc_lazy_sweep(rb_objspace_t *objspace) - GC_PROF_SWEEP_TIMER_STOP; - - GC_PROF_TIMER_STOP(Qtrue); -+ - return res; - } - -@@ -2543,9 +3259,15 @@ gc_marks(rb_objspace_t *objspace) - rb_thread_t *th = GET_THREAD(); - GC_PROF_MARK_TIMER_START; - -+ /* -+ if (gc_statistics & verbose_gc_stats) { -+ fprintf(gc_data_file, "Marking objects\n"); -+ } -+ */ -+ - objspace->heap.live_num = 0; - objspace->count++; -- -+ live_objects = 0; - - SET_STACK_END; - -@@ -2577,11 +3299,15 @@ gc_marks(rb_objspace_t *objspace) - gc_mark_stacked_objects(objspace); - - GC_PROF_MARK_TIMER_STOP; -+ -+ live_after_last_mark_phase = objspace->heap.live_num; - } - - static int - garbage_collect(rb_objspace_t *objspace) - { -+ struct timeval gctv1; -+ - INIT_GC_PROF_PARAMS; - - if (GC_NOTIFY) printf("start garbage_collect()\n"); -@@ -2597,15 +3323,31 @@ garbage_collect(rb_objspace_t *objspace) - - rest_sweep(objspace); - -+ if (gc_statistics) { -+ gc_time_accumulator_before_gc = gc_time_accumulator; -+ gc_collections++; -+ gettimeofday(&gctv1, NULL); -+ /* -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "Garbage collection started (garbage_collect)\n"); -+ } -+ */ -+ } -+ - during_gc++; - gc_marks(objspace); - -+ if (gc_statistics) { -+ gc_time_accumulator += elapsed_musecs(gctv1); -+ } -+ - GC_PROF_SWEEP_TIMER_START; - gc_sweep(objspace); - GC_PROF_SWEEP_TIMER_STOP; - - GC_PROF_TIMER_STOP(Qtrue); - if (GC_NOTIFY) printf("end garbage_collect()\n"); -+ - return TRUE; - } - -@@ -3094,6 +3836,39 @@ rb_gc_call_finalizer_at_exit(void) - rb_objspace_call_finalizer(&rb_objspace); - } - -+static const char* obj_type(VALUE type) -+{ -+ switch (type) { -+ case T_NIL : return "NIL"; -+ case T_OBJECT : return "OBJECT"; -+ case T_CLASS : return "CLASS"; -+ case T_ICLASS : return "ICLASS"; -+ case T_MODULE : return "MODULE"; -+ case T_FLOAT : return "FLOAT"; -+ case T_COMPLEX: return "COMPLEX"; -+ case T_RATIONAL: return "RATIONAL"; -+ case T_STRING : return "STRING"; -+ case T_REGEXP : return "REGEXP"; -+ case T_ARRAY : return "ARRAY"; -+ case T_FIXNUM : return "FIXNUM"; -+ case T_HASH : return "HASH"; -+ case T_STRUCT : return "STRUCT"; -+ case T_BIGNUM : return "BIGNUM"; -+ case T_FILE : return "FILE"; -+ -+ case T_TRUE : return "TRUE"; -+ case T_FALSE : return "FALSE"; -+ case T_DATA : return "DATA"; -+ case T_MATCH : return "MATCH"; -+ case T_SYMBOL : return "SYMBOL"; -+ case T_ZOMBIE : return "ZOMBIE"; -+ -+ case T_UNDEF : return "UNDEF"; -+ case T_NODE : return "NODE"; -+ default: return "____"; -+ } -+} -+ - static void - rb_objspace_call_finalizer(rb_objspace_t *objspace) - { -@@ -3408,6 +4183,49 @@ count_objects(int argc, VALUE *argv, VALUE os) - return hash; - } - -+/* call-seq: -+ * ObjectSpace.live_objects => number -+ * -+ * Returns the count of objects currently allocated in the system. This goes -+ * down after the garbage collector runs. -+ */ -+static -+VALUE os_live_objects(VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return ULONG2NUM(live_objects); -+} -+ -+unsigned long rb_os_live_objects() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return live_objects; -+} -+ -+/* call-seq: -+ * ObjectSpace.allocated_objects => number -+ * -+ * Returns the count of objects allocated since the Ruby interpreter has -+ * started. This number can only increase. To know how many objects are -+ * currently allocated, use ObjectSpace::live_objects -+ */ -+static -+VALUE os_allocated_objects(VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if defined(HAVE_LONG_LONG) -+ return ULL2NUM(allocated_objects); -+#else -+ return ULONG2NUM(allocated_objects); -+#endif -+} -+ -+unsigned LONG_LONG rb_os_allocated_objects() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return allocated_objects; -+} -+ - /* - * call-seq: - * GC.count -> Integer -@@ -3700,6 +4518,28 @@ Init_GC(void) - rb_define_singleton_method(rb_mGC, "stat", gc_stat, -1); - rb_define_method(rb_mGC, "garbage_collect", rb_gc_start, 0); - -+ rb_define_singleton_method(rb_mGC, "enable_stats", rb_gc_enable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "disable_stats", rb_gc_disable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "stats_enabled?", rb_gc_stats_enabled, 0); -+ rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0); -+ rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); -+ rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); -+ -+ rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); -+ rb_define_singleton_method(rb_mGC, "log_file", rb_gc_log_file, -1); -+ rb_define_singleton_method(rb_mGC, "enable_trace", rb_gc_enable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "disable_trace", rb_gc_disable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "trace_enabled?", rb_gc_trace_enabled, 0); -+ -+ rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); -+ rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); -+ rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); -+#ifdef GC_DEBUG -+ rb_define_singleton_method(rb_mGC, "dump_file_and_line_info", rb_gc_dump_file_and_line_info, -1); -+#endif -+ - 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); -@@ -3713,6 +4553,9 @@ Init_GC(void) - rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1); - rb_define_module_function(rb_mObSpace, "garbage_collect", rb_gc_start, 0); - -+ rb_define_module_function(rb_mObSpace, "live_objects", os_live_objects, 0); -+ rb_define_module_function(rb_mObSpace, "allocated_objects", os_allocated_objects, 0); -+ - rb_define_module_function(rb_mObSpace, "define_finalizer", define_final, -1); - rb_define_module_function(rb_mObSpace, "undefine_finalizer", undefine_final, 1); - diff --git a/patches/ruby/1.9.3/p362/railsexpress/03-display-more-detailed-stack-trace.patch b/patches/ruby/1.9.3/p362/railsexpress/03-display-more-detailed-stack-trace.patch deleted file mode 100644 index 5c7ad30352..0000000000 --- a/patches/ruby/1.9.3/p362/railsexpress/03-display-more-detailed-stack-trace.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/eval_error.c b/eval_error.c -index fd06adf..69c3b48 100644 ---- a/eval_error.c -+++ b/eval_error.c -@@ -164,8 +164,8 @@ error_print(void) - int skip = eclass == rb_eSysStackError; - - #define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5) --#define TRACE_HEAD 8 --#define TRACE_TAIL 5 -+#define TRACE_HEAD 100 -+#define TRACE_TAIL 100 - - for (i = 1; i < len; i++) { - if (TYPE(ptr[i]) == T_STRING) { diff --git a/patches/ruby/1.9.3/p362/railsexpress/04-fork-support-for-gc-logging.patch b/patches/ruby/1.9.3/p362/railsexpress/04-fork-support-for-gc-logging.patch deleted file mode 100644 index 54dd71de14..0000000000 --- a/patches/ruby/1.9.3/p362/railsexpress/04-fork-support-for-gc-logging.patch +++ /dev/null @@ -1,68 +0,0 @@ -diff --git a/gc.c b/gc.c -index c728587..6b6c9f0 100644 ---- a/gc.c -+++ b/gc.c -@@ -1344,6 +1344,34 @@ rb_gc_log_file(int argc, VALUE *argv, VALUE self) - } - - /* -+ * Called from process.c before a fork. Flushes the gc log file to -+ * avoid writing the buffered output twice (once in the parent, and -+ * once in the child). -+ */ -+void -+rb_gc_before_fork() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ fflush(gc_data_file); -+} -+ -+/* -+ * Called from process.c after a fork in the child process. Turns off -+ * logging, disables GC stats and resets all gc counters and timing -+ * information. -+ */ -+void -+rb_gc_after_fork() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ rb_gc_disable_stats(); -+ rb_gc_clear_stats(); -+ rb_gc_disable_trace(); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+} -+ -+/* - * call-seq: - * GC.log String => String - * -diff --git a/include/ruby/intern.h b/include/ruby/intern.h -index 9745afd..7c3d970 100644 ---- a/include/ruby/intern.h -+++ b/include/ruby/intern.h -@@ -426,6 +426,8 @@ void rb_gc_call_finalizer_at_exit(void); - VALUE rb_gc_enable(void); - VALUE rb_gc_disable(void); - VALUE rb_gc_start(void); -+void rb_gc_before_fork _((void)); -+void rb_gc_after_fork _((void)); - #define Init_stack(addr) ruby_init_stack(addr) - void rb_gc_set_params(void); - /* hash.c */ -diff --git a/process.c b/process.c -index 99cfc69..8bee602 100644 ---- a/process.c -+++ b/process.c -@@ -2804,9 +2804,11 @@ rb_f_fork(VALUE obj) - rb_pid_t pid; - - rb_secure(2); -+ rb_gc_before_fork(); - - switch (pid = rb_fork(0, 0, 0, Qnil)) { - case 0: -+ rb_gc_after_fork(); - rb_thread_atfork(); - if (rb_block_given_p()) { - int status; diff --git a/patches/ruby/1.9.3/p362/railsexpress/05-track-live-dataset-size.patch b/patches/ruby/1.9.3/p362/railsexpress/05-track-live-dataset-size.patch deleted file mode 100644 index fba80b55d9..0000000000 --- a/patches/ruby/1.9.3/p362/railsexpress/05-track-live-dataset-size.patch +++ /dev/null @@ -1,45 +0,0 @@ -diff --git a/gc.c b/gc.c -index 6b6c9f0..c995568 100644 ---- a/gc.c -+++ b/gc.c -@@ -280,7 +280,6 @@ getrusage_time(void) - #define GC_PROF_DEC_LIVE_NUM - #endif - -- - #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__) - #pragma pack(push, 1) /* magic for reducing sizeof(RVALUE): 24 -> 20 */ - #endif -@@ -1561,6 +1560,24 @@ rb_gc_time() - #endif - } - -+/* -+ * call-seq: -+ * GC.heap_slots_live_after_last_gc => Integer -+ * -+ * Returns the number of heap slots which were live after the last garbage collection. -+ * -+ * GC.heap_slots_live_after_last_gc #=> 231223 -+ * -+ */ -+VALUE -+rb_gc_heap_slots_live_after_last_gc() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return ULONG2NUM(live_after_last_mark_phase); -+} -+ -+ -+ - VALUE rb_mGC; - - void -@@ -4553,6 +4570,7 @@ Init_GC(void) - rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); - rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); - rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots_live_after_last_gc", rb_gc_heap_slots_live_after_last_gc, 0); - rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); - - rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); diff --git a/patches/ruby/1.9.3/p362/railsexpress/06-webrick_204_304_keep_alive_fix.patch b/patches/ruby/1.9.3/p362/railsexpress/06-webrick_204_304_keep_alive_fix.patch deleted file mode 100644 index 34d9b78133..0000000000 --- a/patches/ruby/1.9.3/p362/railsexpress/06-webrick_204_304_keep_alive_fix.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/lib/webrick/httpresponse.rb b/lib/webrick/httpresponse.rb -index 0d36c07..ce72b3f 100644 ---- a/lib/webrick/httpresponse.rb -+++ b/lib/webrick/httpresponse.rb -@@ -202,7 +202,7 @@ module WEBrick - if @header['connection'] == "close" - @keep_alive = false - elsif keep_alive? -- if chunked? || @header['content-length'] -+ if chunked? || @header['content-length'] || @status == 304 || @status == 204 - @header['connection'] = "Keep-Alive" - else - msg = "Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true" diff --git a/patches/ruby/1.9.3/p362/railsexpress/07-export-a-few-more-symbols-for-ruby-prof.patch b/patches/ruby/1.9.3/p362/railsexpress/07-export-a-few-more-symbols-for-ruby-prof.patch deleted file mode 100644 index 163ae056cb..0000000000 --- a/patches/ruby/1.9.3/p362/railsexpress/07-export-a-few-more-symbols-for-ruby-prof.patch +++ /dev/null @@ -1,84 +0,0 @@ -diff --git a/gc.c b/gc.c -index c995568..52b2c56 100644 ---- a/gc.c -+++ b/gc.c -@@ -1051,6 +1051,7 @@ ruby_xfree(void *x) - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_enable(void) - { -@@ -1073,6 +1074,7 @@ rb_gc_enable(void) - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_disable(void) - { -@@ -1095,6 +1097,7 @@ rb_gc_disable(void) - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_enable_stats() - { -@@ -1116,6 +1119,7 @@ rb_gc_enable_stats() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_disable_stats() - { -@@ -1135,6 +1139,7 @@ rb_gc_disable_stats() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_stats_enabled() - { -@@ -1154,6 +1159,7 @@ rb_gc_stats_enabled() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_clear_stats() - { -@@ -1221,6 +1227,7 @@ rb_gc_num_allocations() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_enable_trace() - { -@@ -1242,6 +1249,7 @@ rb_gc_enable_trace() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_disable_trace() - { -@@ -1261,6 +1269,7 @@ rb_gc_disable_trace() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_trace_enabled() - { -@@ -1289,6 +1298,7 @@ const char* GC_LOGFILE_IVAR = "@gc_logfile_name"; - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_log_file(int argc, VALUE *argv, VALUE self) - { diff --git a/patches/ruby/1.9.3/p362/railsexpress/08-thread-variables.patch b/patches/ruby/1.9.3/p362/railsexpress/08-thread-variables.patch deleted file mode 100644 index 94b8505eb8..0000000000 --- a/patches/ruby/1.9.3/p362/railsexpress/08-thread-variables.patch +++ /dev/null @@ -1,319 +0,0 @@ -diff --git a/NEWS b/NEWS -index 30fec33..9f6c172 100644 ---- a/NEWS -+++ b/NEWS -@@ -103,6 +103,16 @@ with all sufficient information, see the ChangeLog file. - * String#prepend - * String#byteslice - -+ * Thread -+ * added method: -+ * added Thread#thread_variable_get for getting thread local variables -+ (these are different than Fiber local variables). -+ * added Thread#thread_variable_set for setting thread local variables. -+ * added Thread#thread_variables for getting a list of the thread local -+ variable keys. -+ * added Thread#thread_variable? for testing to see if a particular thread -+ variable has been set. -+ - * Time - * extended method: - * Time#strftime supports %:z and %::z. -diff --git a/test/ruby/test_thread.rb b/test/ruby/test_thread.rb -index e8cb3b1..9ff491d 100644 ---- a/test/ruby/test_thread.rb -+++ b/test/ruby/test_thread.rb -@@ -27,6 +27,79 @@ class TestThread < Test::Unit::TestCase - end - end - -+ def test_main_thread_variable_in_enumerator -+ assert_equal Thread.main, Thread.current -+ -+ Thread.current.thread_variable_set :foo, "bar" -+ -+ thread, value = Fiber.new { -+ Fiber.yield [Thread.current, Thread.current.thread_variable_get(:foo)] -+ }.resume -+ -+ assert_equal Thread.current, thread -+ assert_equal Thread.current.thread_variable_get(:foo), value -+ end -+ -+ def test_thread_variable_in_enumerator -+ Thread.new { -+ Thread.current.thread_variable_set :foo, "bar" -+ -+ thread, value = Fiber.new { -+ Fiber.yield [Thread.current, Thread.current.thread_variable_get(:foo)] -+ }.resume -+ -+ assert_equal Thread.current, thread -+ assert_equal Thread.current.thread_variable_get(:foo), value -+ }.join -+ end -+ -+ def test_thread_variables -+ assert_equal [], Thread.new { Thread.current.thread_variables }.join.value -+ -+ t = Thread.new { -+ Thread.current.thread_variable_set(:foo, "bar") -+ Thread.current.thread_variables -+ } -+ assert_equal [:foo], t.join.value -+ end -+ -+ def test_thread_variable? -+ refute Thread.new { Thread.current.thread_variable?("foo") }.join.value -+ t = Thread.new { -+ Thread.current.thread_variable_set("foo", "bar") -+ }.join -+ -+ assert t.thread_variable?("foo") -+ assert t.thread_variable?(:foo) -+ refute t.thread_variable?(:bar) -+ end -+ -+ def test_thread_variable_strings_and_symbols_are_the_same_key -+ t = Thread.new {}.join -+ t.thread_variable_set("foo", "bar") -+ assert_equal "bar", t.thread_variable_get(:foo) -+ end -+ -+ def test_thread_variable_frozen -+ t = Thread.new { }.join -+ t.freeze -+ assert_raises(RuntimeError) do -+ t.thread_variable_set(:foo, "bar") -+ end -+ end -+ -+ def test_thread_variable_security -+ t = Thread.new { sleep } -+ -+ assert_raises(SecurityError) do -+ Thread.new { $SAFE = 4; t.thread_variable_get(:foo) }.join -+ end -+ -+ assert_raises(SecurityError) do -+ Thread.new { $SAFE = 4; t.thread_variable_set(:foo, :baz) }.join -+ end -+ end -+ - def test_mutex_synchronize - m = Mutex.new - r = 0 -diff --git a/thread.c b/thread.c -index 5393e4b..6a915d6 100644 ---- a/thread.c -+++ b/thread.c -@@ -2112,7 +2112,9 @@ rb_thread_local_aset(VALUE thread, ID id, VALUE val) - * thr[sym] = obj -> obj - * - * Attribute Assignment---Sets or creates the value of a thread-local variable, -- * using either a symbol or a string. See also Thread#[]. -+ * using either a symbol or a string. See also Thread#[]. For -+ * thread-local variables, please see Thread#thread_variable_set -+ * and Thread#thread_variable_get. - */ - - static VALUE -@@ -2123,6 +2125,80 @@ rb_thread_aset(VALUE self, VALUE id, VALUE val) - - /* - * call-seq: -+ * thr.thread_variable_get(key) -> obj or nil -+ * -+ * Returns the value of a thread local variable that has been set. Note that -+ * these are different than fiber local values. For fiber local values, -+ * please see Thread#[] and Thread#[]=. -+ * -+ * Thread local values are carried along with threads, and do not respect -+ * fibers. For example: -+ * -+ * Thread.new { -+ * Thread.current.thread_variable_set("foo", "bar") # set a thread local -+ * Thread.current["foo"] = "bar" # set a fiber local -+ * -+ * Fiber.new { -+ * Fiber.yield [ -+ * Thread.current.thread_variable_get("foo"), # get the thread local -+ * Thread.current["foo"], # get the fiber local -+ * ] -+ * }.resume -+ * }.join.value # => ['bar', nil] -+ * -+ * The value "bar" is returned for the thread local, where nil is returned -+ * for the fiber local. The fiber is executed in the same thread, so the -+ * thread local values are available. -+ * -+ * See also Thread#[] -+ */ -+ -+static VALUE -+rb_thread_variable_get(VALUE thread, VALUE id) -+{ -+ VALUE locals; -+ rb_thread_t *th; -+ -+ GetThreadPtr(thread, th); -+ -+ if (rb_safe_level() >= 4 && th != GET_THREAD()) { -+ rb_raise(rb_eSecurityError, "Insecure: can't access thread locals"); -+ } -+ -+ locals = rb_iv_get(thread, "locals"); -+ return rb_hash_aref(locals, ID2SYM(rb_to_id(id))); -+} -+ -+/* -+ * call-seq: -+ * thr.thread_variable_set(key, value) -+ * -+ * Sets a thread local with +key+ to +value+. Note that these are local to -+ * threads, and not to fibers. Please see Thread#thread_variable_get and -+ * Thread#[] for more information. -+ */ -+ -+static VALUE -+rb_thread_variable_set(VALUE thread, VALUE id, VALUE val) -+{ -+ VALUE locals; -+ rb_thread_t *th; -+ -+ GetThreadPtr(thread, th); -+ -+ if (rb_safe_level() >= 4 && th != GET_THREAD()) { -+ rb_raise(rb_eSecurityError, "Insecure: can't modify thread locals"); -+ } -+ if (OBJ_FROZEN(thread)) { -+ rb_error_frozen("thread locals"); -+ } -+ -+ locals = rb_iv_get(thread, "locals"); -+ return rb_hash_aset(locals, ID2SYM(rb_to_id(id)), val); -+} -+ -+/* -+ * call-seq: - * thr.key?(sym) -> true or false - * - * Returns true if the given string (or symbol) exists as a -@@ -2993,6 +3069,9 @@ rb_gc_save_machine_context(rb_thread_t *th) - - /* - * -+ * For thread-local variables, please see Thread#thread_local_get -+ * and Thread#thread_local_set. -+ * - */ - - void -@@ -3195,6 +3274,76 @@ thgroup_list_i(st_data_t key, st_data_t val, st_data_t data) - return ST_CONTINUE; - } - -+static int -+keys_i(VALUE key, VALUE value, VALUE ary) -+{ -+ rb_ary_push(ary, key); -+ return ST_CONTINUE; -+} -+ -+/* -+ * call-seq: -+ * thr.thread_variables -> array -+ * -+ * Returns an an array of the names of the thread-local variables (as Symbols). -+ * -+ * thr = Thread.new do -+ * Thread.current.thread_variable_set(:cat, 'meow') -+ * Thread.current.thread_variable_set("dog", 'woof') -+ * end -+ * thr.join #=> # -+ * thr.thread_variables #=> [:dog, :cat] -+ * -+ * Note that these are not fiber local variables. Please see Thread#[] and -+ * Thread#thread_variable_get for more details. -+ */ -+ -+static VALUE -+rb_thread_variables(VALUE thread) -+{ -+ VALUE locals; -+ VALUE ary; -+ -+ locals = rb_iv_get(thread, "locals"); -+ ary = rb_ary_new(); -+ rb_hash_foreach(locals, keys_i, ary); -+ -+ return ary; -+} -+ -+/* -+ * call-seq: -+ * thr.thread_variable?(key) -> true or false -+ * -+ * Returns true if the given string (or symbol) exists as a -+ * thread-local variable. -+ * -+ * me = Thread.current -+ * me.thread_variable_set(:oliver, "a") -+ * me.thread_variable?(:oliver) #=> true -+ * me.thread_variable?(:stanley) #=> false -+ * -+ * Note that these are not fiber local variables. Please see Thread#[] and -+ * Thread#thread_variable_get for more details. -+ */ -+ -+static VALUE -+rb_thread_variable_p(VALUE thread, VALUE key) -+{ -+ VALUE locals; -+ -+ locals = rb_iv_get(thread, "locals"); -+ -+ if (!RHASH(locals)->ntbl) -+ return Qfalse; -+ -+ if (st_lookup(RHASH(locals)->ntbl, ID2SYM(rb_to_id(key)), 0)) { -+ return Qtrue; -+ } -+ -+ return Qfalse; -+} -+ - /* - * call-seq: - * thgrp.list -> array -@@ -4686,6 +4835,10 @@ Init_Thread(void) - rb_define_method(rb_cThread, "priority", rb_thread_priority, 0); - rb_define_method(rb_cThread, "priority=", rb_thread_priority_set, 1); - rb_define_method(rb_cThread, "status", rb_thread_status, 0); -+ rb_define_method(rb_cThread, "thread_variable_get", rb_thread_variable_get, 1); -+ rb_define_method(rb_cThread, "thread_variable_set", rb_thread_variable_set, 2); -+ rb_define_method(rb_cThread, "thread_variables", rb_thread_variables, 0); -+ rb_define_method(rb_cThread, "thread_variable?", rb_thread_variable_p, 1); - rb_define_method(rb_cThread, "alive?", rb_thread_alive_p, 0); - rb_define_method(rb_cThread, "stop?", rb_thread_stop_p, 0); - rb_define_method(rb_cThread, "abort_on_exception", rb_thread_abort_exc, 0); -diff --git a/vm.c b/vm.c -index 4dd242f..f00b193 100644 ---- a/vm.c -+++ b/vm.c -@@ -1900,6 +1900,7 @@ ruby_thread_init(VALUE self) - GetThreadPtr(self, th); - - th_init(th, self); -+ rb_iv_set(self, "locals", rb_hash_new()); - th->vm = vm; - - th->top_wrapper = 0; -@@ -2168,6 +2169,7 @@ Init_VM(void) - - /* create main thread */ - th_self = th->self = TypedData_Wrap_Struct(rb_cThread, &thread_data_type, th); -+ rb_iv_set(th_self, "locals", rb_hash_new()); - vm->main_thread = th; - vm->running_thread = th; - th->vm = vm; diff --git a/patches/ruby/1.9.3/p362/railsexpress/09-faster-loading.patch b/patches/ruby/1.9.3/p362/railsexpress/09-faster-loading.patch deleted file mode 100644 index d5d0fc0e95..0000000000 --- a/patches/ruby/1.9.3/p362/railsexpress/09-faster-loading.patch +++ /dev/null @@ -1,747 +0,0 @@ -diff --git a/array.c b/array.c -index e427cb3..c33d106 100644 ---- a/array.c -+++ b/array.c -@@ -295,6 +295,22 @@ rb_ary_frozen_p(VALUE ary) - return Qfalse; - } - -+/* This can be used to take a snapshot of an array (with -+ e.g. rb_ary_replace) and check later whether the array has been -+ modified from the snapshot. The snapshot is cheap, though if -+ something does modify the array it will pay the cost of copying -+ it. */ -+VALUE -+rb_ary_shared_with_p(VALUE ary1, VALUE ary2) -+{ -+ if (!ARY_EMBED_P(ary1) && ARY_SHARED_P(ary1) -+ && !ARY_EMBED_P(ary2) && ARY_SHARED_P(ary2) -+ && RARRAY(ary1)->as.heap.aux.shared == RARRAY(ary2)->as.heap.aux.shared) { -+ return Qtrue; -+ } -+ return Qfalse; -+} -+ - static VALUE - ary_alloc(VALUE klass) - { -diff --git a/file.c b/file.c -index 50fa5c7..e991866 100644 ---- a/file.c -+++ b/file.c -@@ -149,23 +149,32 @@ file_path_convert(VALUE name) - return name; - } - --static VALUE --rb_get_path_check(VALUE obj, int level) -+VALUE -+rb_get_path_check_to_string(VALUE obj, int level) - { - VALUE tmp; - ID to_path; -- rb_encoding *enc; - - if (insecure_obj_p(obj, level)) { - rb_insecure_operation(); - } - -+ if (RB_TYPE_P(obj, T_STRING)) { -+ return obj; -+ } - CONST_ID(to_path, "to_path"); - tmp = rb_check_funcall(obj, to_path, 0, 0); - if (tmp == Qundef) { - tmp = obj; - } - StringValue(tmp); -+ return tmp; -+} -+ -+VALUE -+rb_get_path_check_convert(VALUE obj, VALUE tmp, int level) -+{ -+ rb_encoding *enc; - - tmp = file_path_convert(tmp); - if (obj != tmp && insecure_obj_p(tmp, level)) { -@@ -183,6 +192,13 @@ rb_get_path_check(VALUE obj, int level) - return rb_str_new4(tmp); - } - -+static VALUE -+rb_get_path_check(VALUE obj, int level) -+{ -+ VALUE tmp = rb_get_path_check_to_string(obj, level); -+ return rb_get_path_check_convert(obj, tmp, level); -+} -+ - VALUE - rb_get_path_no_checksafe(VALUE obj) - { -@@ -3250,7 +3266,6 @@ rb_file_expand_path(VALUE fname, VALUE dname) - VALUE - rb_file_expand_path_fast(VALUE fname, VALUE dname) - { -- check_expand_path_args(fname, dname); - return rb_file_expand_path_internal(fname, dname, 0, 0, EXPAND_PATH_BUFFER()); - } - -@@ -5238,7 +5253,7 @@ rb_find_file_ext_safe(VALUE *filep, const char *const *ext, int safe_level) - rb_raise(rb_eSecurityError, "loading from non-absolute path %s", f); - } - -- RB_GC_GUARD(load_path) = rb_get_load_path(); -+ RB_GC_GUARD(load_path) = rb_get_expanded_load_path(); - if (!load_path) return 0; - - fname = rb_str_dup(*filep); -@@ -5303,7 +5318,7 @@ rb_find_file_safe(VALUE path, int safe_level) - rb_raise(rb_eSecurityError, "loading from non-absolute path %s", f); - } - -- RB_GC_GUARD(load_path) = rb_get_load_path(); -+ RB_GC_GUARD(load_path) = rb_get_expanded_load_path(); - if (load_path) { - long i; - -diff --git a/hash.c b/hash.c -index fbd8237..8423558 100644 ---- a/hash.c -+++ b/hash.c -@@ -1087,7 +1087,7 @@ clear_i(VALUE key, VALUE value, VALUE dummy) - * - */ - --static VALUE -+VALUE - rb_hash_clear(VALUE hash) - { - rb_hash_modify_check(hash); -diff --git a/include/ruby/intern.h b/include/ruby/intern.h -index 7c3d970..ab1cc94 100644 ---- a/include/ruby/intern.h -+++ b/include/ruby/intern.h -@@ -56,6 +56,7 @@ VALUE rb_ary_tmp_new(long); - void rb_ary_free(VALUE); - void rb_ary_modify(VALUE); - VALUE rb_ary_freeze(VALUE); -+VALUE rb_ary_shared_with_p(VALUE, VALUE); - VALUE rb_ary_aref(int, VALUE*, VALUE); - VALUE rb_ary_subseq(VALUE, long, long); - void rb_ary_store(VALUE, long, VALUE); -@@ -443,6 +444,7 @@ VALUE rb_hash_lookup(VALUE, VALUE); - VALUE rb_hash_lookup2(VALUE, VALUE, VALUE); - VALUE rb_hash_fetch(VALUE, VALUE); - VALUE rb_hash_aset(VALUE, VALUE, VALUE); -+VALUE rb_hash_clear(VALUE); - VALUE rb_hash_delete_if(VALUE); - VALUE rb_hash_delete(VALUE,VALUE); - typedef VALUE rb_hash_update_func(VALUE newkey, VALUE oldkey, VALUE value); -diff --git a/internal.h b/internal.h -index 59c9284..f5af903 100644 ---- a/internal.h -+++ b/internal.h -@@ -94,6 +94,8 @@ VALUE rb_home_dir(const char *user, VALUE result); - VALUE rb_realpath_internal(VALUE basedir, VALUE path, int strict); - VALUE rb_file_expand_path_fast(VALUE, VALUE); - VALUE rb_file_expand_path_internal(VALUE, VALUE, int, int, VALUE); -+VALUE rb_get_path_check_to_string(VALUE, int); -+VALUE rb_get_path_check_convert(VALUE, VALUE, int); - void Init_File(void); - - #ifdef _WIN32 -@@ -119,6 +121,7 @@ VALUE rb_iseq_clone(VALUE iseqval, VALUE newcbase); - - /* load.c */ - VALUE rb_get_load_path(void); -+VALUE rb_get_expanded_load_path(void); - - /* math.c */ - VALUE rb_math_atan2(VALUE, VALUE); -diff --git a/load.c b/load.c -index 163ec4c..e766880 100644 ---- a/load.c -+++ b/load.c -@@ -18,7 +18,6 @@ VALUE ruby_dln_librefs; - #define IS_DLEXT(e) (strcmp((e), DLEXT) == 0) - #endif - -- - static const char *const loadable_ext[] = { - ".rb", DLEXT, - #ifdef DLEXT2 -@@ -34,21 +33,120 @@ rb_get_load_path(void) - return load_path; - } - --VALUE --rb_get_expanded_load_path(void) -+enum expand_type { -+ EXPAND_ALL, -+ EXPAND_RELATIVE, -+ EXPAND_HOME, -+ EXPAND_NON_CACHE -+}; -+ -+/* Construct expanded load path and store it to cache. -+ We rebuild load path partially if the cache is invalid. -+ We don't cache non string object and expand it every times. We ensure that -+ string objects in $LOAD_PATH are frozen. -+ */ -+static void -+rb_construct_expanded_load_path(int type, int *has_relative, int *has_non_cache) - { -- VALUE load_path = rb_get_load_path(); -+ rb_vm_t *vm = GET_VM(); -+ VALUE load_path = vm->load_path; -+ VALUE expanded_load_path = vm->expanded_load_path; - VALUE ary; - long i; -+ int level = rb_safe_level(); - - ary = rb_ary_new2(RARRAY_LEN(load_path)); - for (i = 0; i < RARRAY_LEN(load_path); ++i) { -- VALUE path = rb_file_expand_path_fast(RARRAY_PTR(load_path)[i], Qnil); -- rb_str_freeze(path); -- rb_ary_push(ary, path); -+ VALUE path, as_str, expanded_path; -+ int is_string, non_cache; -+ char *as_cstr; -+ as_str = path = RARRAY_PTR(load_path)[i]; -+ is_string = RB_TYPE_P(path, T_STRING) ? 1 : 0; -+ non_cache = !is_string ? 1 : 0; -+ as_str = rb_get_path_check_to_string(path, level); -+ as_cstr = RSTRING_PTR(as_str); -+ -+ if (!non_cache) { -+ if ((type == EXPAND_RELATIVE && -+ rb_is_absolute_path(as_cstr)) || -+ (type == EXPAND_HOME && -+ (!as_cstr[0] || as_cstr[0] != '~')) || -+ (type == EXPAND_NON_CACHE)) { -+ /* Use cached expanded path. */ -+ rb_ary_push(ary, RARRAY_PTR(expanded_load_path)[i]); -+ continue; -+ } -+ } -+ if (!*has_relative && !rb_is_absolute_path(as_cstr)) -+ *has_relative = 1; -+ if (!*has_non_cache && non_cache) -+ *has_non_cache = 1; -+ /* Freeze only string object. We expand other objects every times. */ -+ if (is_string) -+ rb_str_freeze(path); -+ as_str = rb_get_path_check_convert(path, as_str, level); -+ expanded_path = rb_file_expand_path_fast(as_str, Qnil); -+ rb_str_freeze(expanded_path); -+ rb_ary_push(ary, expanded_path); - } - rb_obj_freeze(ary); -- return ary; -+ vm->expanded_load_path = ary; -+ rb_ary_replace(vm->load_path_snapshot, vm->load_path); -+} -+ -+static VALUE -+load_path_getcwd(void) -+{ -+ char *cwd = my_getcwd(); -+ VALUE cwd_str = rb_filesystem_str_new_cstr(cwd); -+ xfree(cwd); -+ return cwd_str; -+} -+ -+VALUE -+rb_get_expanded_load_path(void) -+{ -+ rb_vm_t *vm = GET_VM(); -+ const VALUE non_cache = Qtrue; -+ -+ if (!rb_ary_shared_with_p(vm->load_path_snapshot, vm->load_path)) { -+ /* The load path was modified. Rebuild the expanded load path. */ -+ int has_relative = 0, has_non_cache = 0; -+ rb_construct_expanded_load_path(EXPAND_ALL, &has_relative, &has_non_cache); -+ if (has_relative) { -+ vm->load_path_check_cache = load_path_getcwd(); -+ } -+ else if (has_non_cache) { -+ /* Non string object. */ -+ vm->load_path_check_cache = non_cache; -+ } -+ else { -+ vm->load_path_check_cache = 0; -+ } -+ } -+ else if (vm->load_path_check_cache == non_cache) { -+ int has_relative = 1, has_non_cache = 1; -+ /* Expand only non-cacheable objects. */ -+ rb_construct_expanded_load_path(EXPAND_NON_CACHE, -+ &has_relative, &has_non_cache); -+ } -+ else if (vm->load_path_check_cache) { -+ int has_relative = 1, has_non_cache = 1; -+ VALUE cwd = load_path_getcwd(); -+ if (!rb_str_equal(vm->load_path_check_cache, cwd)) { -+ /* Current working directory or filesystem encoding was changed. -+ Expand relative load path and non-cacheable objects again. */ -+ vm->load_path_check_cache = cwd; -+ rb_construct_expanded_load_path(EXPAND_RELATIVE, -+ &has_relative, &has_non_cache); -+ } -+ else { -+ /* Expand only tilde (User HOME) and non-cacheable objects. */ -+ rb_construct_expanded_load_path(EXPAND_HOME, -+ &has_relative, &has_non_cache); -+ } -+ } -+ return vm->expanded_load_path; - } - - static VALUE -@@ -63,12 +161,121 @@ get_loaded_features(void) - return GET_VM()->loaded_features; - } - -+static void -+reset_loaded_features_snapshot(void) -+{ -+ rb_vm_t *vm = GET_VM(); -+ rb_ary_replace(vm->loaded_features_snapshot, vm->loaded_features); -+} -+ -+static VALUE -+get_loaded_features_index_raw(void) -+{ -+ return GET_VM()->loaded_features_index; -+} -+ - static st_table * - get_loading_table(void) - { - return GET_VM()->loading_table; - } - -+static void -+features_index_add_single(VALUE short_feature, VALUE offset) -+{ -+ VALUE features_index, this_feature_index; -+ features_index = get_loaded_features_index_raw(); -+ if ((this_feature_index = rb_hash_lookup(features_index, short_feature)) == Qnil) { -+ this_feature_index = rb_ary_new(); -+ rb_hash_aset(features_index, short_feature, this_feature_index); -+ } -+ rb_ary_push(this_feature_index, offset); -+} -+ -+/* Add to the loaded-features index all the required entries for -+ `feature`, located at `offset` in $LOADED_FEATURES. We add an -+ index entry at each string `short_feature` for which -+ feature == "#{prefix}#{short_feature}#{e}" -+ where `e` is empty or matches %r{^\.[^./]*$}, and `prefix` is empty -+ or ends in '/'. This maintains the invariant that `rb_feature_p()` -+ relies on for its fast lookup. -+*/ -+static void -+features_index_add(VALUE feature, VALUE offset) -+{ -+ VALUE short_feature; -+ const char *feature_str, *feature_end, *ext, *p; -+ -+ feature_str = StringValuePtr(feature); -+ feature_end = feature_str + RSTRING_LEN(feature); -+ -+ for (ext = feature_end; ext > feature_str; ext--) -+ if (*ext == '.' || *ext == '/') -+ break; -+ if (*ext != '.') -+ ext = NULL; -+ /* Now `ext` points to the only string matching %r{^\.[^./]*$} that is -+ at the end of `feature`, or is NULL if there is no such string. */ -+ -+ p = ext ? ext : feature_end; -+ while (1) { -+ p--; -+ while (p >= feature_str && *p != '/') -+ p--; -+ if (p < feature_str) -+ break; -+ /* Now *p == '/'. We reach this point for every '/' in `feature`. */ -+ short_feature = rb_str_substr(feature, p + 1 - feature_str, feature_end - p - 1); -+ features_index_add_single(short_feature, offset); -+ if (ext) { -+ short_feature = rb_str_substr(feature, p + 1 - feature_str, ext - p - 1); -+ features_index_add_single(short_feature, offset); -+ } -+ } -+ features_index_add_single(feature, offset); -+ if (ext) { -+ short_feature = rb_str_substr(feature, 0, ext - feature_str); -+ features_index_add_single(short_feature, offset); -+ } -+} -+ -+static VALUE -+get_loaded_features_index(void) -+{ -+ VALUE features; -+ int i; -+ rb_vm_t *vm = GET_VM(); -+ -+ if (!rb_ary_shared_with_p(vm->loaded_features_snapshot, vm->loaded_features)) { -+ /* The sharing was broken; something (other than us in rb_provide_feature()) -+ modified loaded_features. Rebuild the index. */ -+ rb_hash_clear(vm->loaded_features_index); -+ features = vm->loaded_features; -+ for (i = 0; i < RARRAY_LEN(features); i++) { -+ VALUE entry, as_str; -+ as_str = entry = rb_ary_entry(features, i); -+ StringValue(as_str); -+ if (as_str != entry) -+ rb_ary_store(features, i, as_str); -+ rb_str_freeze(as_str); -+ features_index_add(as_str, INT2FIX(i)); -+ } -+ reset_loaded_features_snapshot(); -+ } -+ return vm->loaded_features_index; -+} -+ -+/* This searches `load_path` for a value such that -+ name == "#{load_path[i]}/#{feature}" -+ if `feature` is a suffix of `name`, or otherwise -+ name == "#{load_path[i]}/#{feature}#{ext}" -+ for an acceptable string `ext`. It returns -+ `load_path[i].to_str` if found, else 0. -+ -+ If type is 's', then `ext` is acceptable only if IS_DLEXT(ext); -+ if 'r', then only if IS_RBEXT(ext); otherwise `ext` may be absent -+ or have any value matching `%r{^\.[^./]*$}`. -+*/ - static VALUE - loaded_feature_path(const char *name, long vlen, const char *feature, long len, - int type, VALUE load_path) -@@ -77,7 +284,7 @@ loaded_feature_path(const char *name, long vlen, const char *feature, long len, - long plen; - const char *e; - -- if(vlen < len) return 0; -+ if (vlen < len+1) return 0; - if (!strncmp(name+(vlen-len),feature,len)){ - plen = vlen - len - 1; - } else { -@@ -88,23 +295,22 @@ loaded_feature_path(const char *name, long vlen, const char *feature, long len, - return 0; - plen = e - name - len - 1; - } -+ if (type == 's' && !IS_DLEXT(&name[plen+len+1]) -+ || type == 'r' && !IS_RBEXT(&name[plen+len+1]) -+ || name[plen] != '/') { -+ return 0; -+ } -+ /* Now name == "#{prefix}/#{feature}#{ext}" where ext is acceptable -+ (possibly empty) and prefix is some string of length plen. */ -+ - for (i = 0; i < RARRAY_LEN(load_path); ++i) { - VALUE p = RARRAY_PTR(load_path)[i]; - const char *s = StringValuePtr(p); - long n = RSTRING_LEN(p); - - if (n != plen ) continue; -- if (n && (strncmp(name, s, n) || name[n] != '/')) continue; -- switch (type) { -- case 's': -- if (IS_DLEXT(&name[n+len+1])) return p; -- break; -- case 'r': -- if (IS_RBEXT(&name[n+len+1])) return p; -- break; -- default: -- return p; -- } -+ if (n && strncmp(name, s, n)) continue; -+ return p; - } - return 0; - } -@@ -132,7 +338,7 @@ loaded_feature_path_i(st_data_t v, st_data_t b, st_data_t f) - static int - rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const char **fn) - { -- VALUE v, features, p, load_path = 0; -+ VALUE features, features_index, feature_val, this_feature_index, v, p, load_path = 0; - const char *f, *e; - long i, len, elen, n; - st_table *loading_tbl; -@@ -151,8 +357,39 @@ rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const c - type = 0; - } - features = get_loaded_features(); -- for (i = 0; i < RARRAY_LEN(features); ++i) { -- v = RARRAY_PTR(features)[i]; -+ features_index = get_loaded_features_index(); -+ -+ feature_val = rb_str_new(feature, len); -+ this_feature_index = rb_hash_lookup(features_index, feature_val); -+ /* We search `features` for an entry such that either -+ "#{features[i]}" == "#{load_path[j]}/#{feature}#{e}" -+ for some j, or -+ "#{features[i]}" == "#{feature}#{e}" -+ Here `e` is an "allowed" extension -- either empty or one -+ of the extensions accepted by IS_RBEXT, IS_SOEXT, or -+ IS_DLEXT. Further, if `ext && rb` then `IS_RBEXT(e)`, -+ and if `ext && !rb` then `IS_SOEXT(e) || IS_DLEXT(e)`. -+ -+ If `expanded`, then only the latter form (without load_path[j]) -+ is accepted. Otherwise either form is accepted, *unless* `ext` -+ is false and an otherwise-matching entry of the first form is -+ preceded by an entry of the form -+ "#{features[i2]}" == "#{load_path[j2]}/#{feature}#{e2}" -+ where `e2` matches %r{^\.[^./]*$} but is not an allowed extension. -+ After a "distractor" entry of this form, only entries of the -+ form "#{feature}#{e}" are accepted. -+ -+ In `rb_provide_feature()` and `get_loaded_features_index()` we -+ maintain an invariant that the array `this_feature_index` will -+ point to every entry in `features` which has the form -+ "#{prefix}#{feature}#{e}" -+ where `e` is empty or matches %r{^\.[^./]*$}, and `prefix` is empty -+ or ends in '/'. This includes both match forms above, as well -+ as any distractors, so we may ignore all other entries in `features`. -+ */ -+ for (i = 0; this_feature_index != Qnil && i < RARRAY_LEN(this_feature_index); i++) { -+ long index = FIX2LONG(rb_ary_entry(this_feature_index, i)); -+ v = RARRAY_PTR(features)[index]; - f = StringValuePtr(v); - if ((n = RSTRING_LEN(v)) < len) continue; - if (strncmp(f, feature, len) != 0) { -@@ -175,6 +412,7 @@ rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const c - return 'r'; - } - } -+ - loading_tbl = get_loading_table(); - if (loading_tbl) { - f = 0; -@@ -183,7 +421,7 @@ rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const c - fs.name = feature; - fs.len = len; - fs.type = type; -- fs.load_path = load_path ? load_path : rb_get_load_path(); -+ fs.load_path = load_path ? load_path : rb_get_expanded_load_path(); - fs.result = 0; - st_foreach(loading_tbl, loaded_feature_path_i, (st_data_t)&fs); - if ((f = fs.result) != 0) { -@@ -233,7 +471,7 @@ rb_feature_provided(const char *feature, const char **loading) - - if (*feature == '.' && - (feature[1] == '/' || strncmp(feature+1, "./", 2) == 0)) { -- fullpath = rb_file_expand_path_fast(rb_str_new2(feature), Qnil); -+ fullpath = rb_file_expand_path_fast(rb_get_path(rb_str_new2(feature)), Qnil); - feature = RSTRING_PTR(fullpath); - } - if (ext && !strchr(ext, '/')) { -@@ -254,11 +492,18 @@ rb_feature_provided(const char *feature, const char **loading) - static void - rb_provide_feature(VALUE feature) - { -- if (OBJ_FROZEN(get_loaded_features())) { -+ VALUE features; -+ -+ features = get_loaded_features(); -+ if (OBJ_FROZEN(features)) { - rb_raise(rb_eRuntimeError, - "$LOADED_FEATURES is frozen; cannot append feature"); - } -- rb_ary_push(get_loaded_features(), feature); -+ rb_str_freeze(feature); -+ -+ rb_ary_push(features, feature); -+ features_index_add(feature, INT2FIX(RARRAY_LEN(features)-1)); -+ reset_loaded_features_snapshot(); - } - - void -@@ -774,10 +1019,15 @@ Init_load() - rb_alias_variable(rb_intern("$-I"), id_load_path); - rb_alias_variable(rb_intern("$LOAD_PATH"), id_load_path); - vm->load_path = rb_ary_new(); -+ vm->expanded_load_path = rb_ary_new(); -+ vm->load_path_snapshot = rb_ary_new(); -+ vm->load_path_check_cache = 0; - - rb_define_virtual_variable("$\"", get_loaded_features, 0); - rb_define_virtual_variable("$LOADED_FEATURES", get_loaded_features, 0); - vm->loaded_features = rb_ary_new(); -+ vm->loaded_features_snapshot = rb_ary_new(); -+ vm->loaded_features_index = rb_hash_new(); - - rb_define_global_function("load", rb_f_load, -1); - rb_define_global_function("require", rb_f_require, 1); -diff --git a/ruby.c b/ruby.c -index 3ddd96c..7ffc78e 100644 ---- a/ruby.c -+++ b/ruby.c -@@ -1366,7 +1366,8 @@ process_options(int argc, char **argv, struct cmdline_options *opt) - long i; - VALUE load_path = GET_VM()->load_path; - for (i = 0; i < RARRAY_LEN(load_path); ++i) { -- rb_enc_associate(RARRAY_PTR(load_path)[i], lenc); -+ RARRAY_PTR(load_path)[i] = -+ rb_enc_associate(rb_str_dup(RARRAY_PTR(load_path)[i]), lenc); - } - } - if (!(opt->disable & DISABLE_BIT(gems))) { -diff --git a/test/ruby/test_require.rb b/test/ruby/test_require.rb -index 58a9ee2..ec75096 100644 ---- a/test/ruby/test_require.rb -+++ b/test/ruby/test_require.rb -@@ -356,4 +356,114 @@ class TestRequire < Test::Unit::TestCase - $:.replace(loadpath) - $".replace(features) - end -+ -+ def test_require_changed_current_dir -+ bug7158 = '[ruby-core:47970]' -+ Dir.mktmpdir {|tmp| -+ Dir.chdir(tmp) { -+ Dir.mkdir("a") -+ Dir.mkdir("b") -+ open(File.join("a", "foo.rb"), "w") {} -+ open(File.join("b", "bar.rb"), "w") {|f| -+ f.puts "p :ok" -+ } -+ assert_in_out_err([], <<-INPUT, %w(:ok), [], bug7158) -+ $: << "." -+ Dir.chdir("a") -+ require "foo" -+ Dir.chdir("../b") -+ p :ng unless require "bar" -+ Dir.chdir("..") -+ p :ng if require "b/bar" -+ INPUT -+ } -+ } -+ end -+ -+ def test_require_not_modified_load_path -+ bug7158 = '[ruby-core:47970]' -+ Dir.mktmpdir {|tmp| -+ Dir.chdir(tmp) { -+ open("foo.rb", "w") {} -+ assert_in_out_err([], <<-INPUT, %w(:ok), [], bug7158) -+ a = Object.new -+ def a.to_str -+ "#{tmp}" -+ end -+ $: << a -+ require "foo" -+ last_path = $:.pop -+ p :ok if last_path == a && last_path.class == Object -+ INPUT -+ } -+ } -+ end -+ -+ def test_require_changed_home -+ bug7158 = '[ruby-core:47970]' -+ Dir.mktmpdir {|tmp| -+ Dir.chdir(tmp) { -+ open("foo.rb", "w") {} -+ Dir.mkdir("a") -+ open(File.join("a", "bar.rb"), "w") {} -+ assert_in_out_err([], <<-INPUT, %w(:ok), [], bug7158) -+ $: << '~' -+ ENV['HOME'] = "#{tmp}" -+ require "foo" -+ ENV['HOME'] = "#{tmp}/a" -+ p :ok if require "bar" -+ INPUT -+ } -+ } -+ end -+ -+ def test_require_to_path_redefined_in_load_path -+ bug7158 = '[ruby-core:47970]' -+ Dir.mktmpdir {|tmp| -+ Dir.chdir(tmp) { -+ open("foo.rb", "w") {} -+ assert_in_out_err(["RUBYOPT"=>nil], <<-INPUT, %w(:ok), [], bug7158) -+ a = Object.new -+ def a.to_path -+ "bar" -+ end -+ $: << a -+ begin -+ require "foo" -+ p :ng -+ rescue LoadError -+ end -+ def a.to_path -+ "#{tmp}" -+ end -+ p :ok if require "foo" -+ INPUT -+ } -+ } -+ end -+ -+ def test_require_to_str_redefined_in_load_path -+ bug7158 = '[ruby-core:47970]' -+ Dir.mktmpdir {|tmp| -+ Dir.chdir(tmp) { -+ open("foo.rb", "w") {} -+ assert_in_out_err(["RUBYOPT"=>nil], <<-INPUT, %w(:ok), [], bug7158) -+ a = Object.new -+ def a.to_str -+ "foo" -+ end -+ $: << a -+ begin -+ require "foo" -+ p :ng -+ rescue LoadError -+ end -+ def a.to_str -+ "#{tmp}" -+ end -+ p :ok if require "foo" -+ INPUT -+ } -+ } -+ end - end -diff --git a/vm.c b/vm.c -index f00b193..4a97fba 100644 ---- a/vm.c -+++ b/vm.c -@@ -1582,7 +1582,12 @@ rb_vm_mark(void *ptr) - RUBY_MARK_UNLESS_NULL(vm->thgroup_default); - RUBY_MARK_UNLESS_NULL(vm->mark_object_ary); - RUBY_MARK_UNLESS_NULL(vm->load_path); -+ RUBY_MARK_UNLESS_NULL(vm->load_path_snapshot); -+ RUBY_MARK_UNLESS_NULL(vm->load_path_check_cache); -+ RUBY_MARK_UNLESS_NULL(vm->expanded_load_path); - RUBY_MARK_UNLESS_NULL(vm->loaded_features); -+ RUBY_MARK_UNLESS_NULL(vm->loaded_features_snapshot); -+ RUBY_MARK_UNLESS_NULL(vm->loaded_features_index); - RUBY_MARK_UNLESS_NULL(vm->top_self); - RUBY_MARK_UNLESS_NULL(vm->coverages); - rb_gc_mark_locations(vm->special_exceptions, vm->special_exceptions + ruby_special_error_count); -diff --git a/vm_core.h b/vm_core.h -index 1a10162..c6829a3 100644 ---- a/vm_core.h -+++ b/vm_core.h -@@ -298,7 +298,12 @@ typedef struct rb_vm_struct { - /* load */ - VALUE top_self; - VALUE load_path; -+ VALUE load_path_snapshot; -+ VALUE load_path_check_cache; -+ VALUE expanded_load_path; - VALUE loaded_features; -+ VALUE loaded_features_snapshot; -+ VALUE loaded_features_index; - struct st_table *loading_table; - - /* signal */ diff --git a/patches/ruby/1.9.3/p362/railsexpress/10-falcon-st-opt.patch b/patches/ruby/1.9.3/p362/railsexpress/10-falcon-st-opt.patch deleted file mode 100644 index b2d8bced8a..0000000000 --- a/patches/ruby/1.9.3/p362/railsexpress/10-falcon-st-opt.patch +++ /dev/null @@ -1,2308 +0,0 @@ -diff --git a/common.mk b/common.mk -index ccc9647..1d8e442 100644 ---- a/common.mk -+++ b/common.mk -@@ -638,7 +638,8 @@ file.$(OBJEXT): {$(VPATH)}file.c $(RUBY_H_INCLUDES) {$(VPATH)}io.h \ - gc.$(OBJEXT): {$(VPATH)}gc.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \ - {$(VPATH)}regex.h $(ENCODING_H_INCLUDES) $(VM_CORE_H_INCLUDES) \ - {$(VPATH)}gc.h {$(VPATH)}io.h {$(VPATH)}eval_intern.h {$(VPATH)}util.h \ -- {$(VPATH)}debug.h {$(VPATH)}internal.h {$(VPATH)}constant.h -+ {$(VPATH)}debug.h {$(VPATH)}internal.h {$(VPATH)}constant.h \ -+ {$(VPATH)}pool_alloc.inc.h {$(VPATH)}pool_alloc.h - hash.$(OBJEXT): {$(VPATH)}hash.c $(RUBY_H_INCLUDES) {$(VPATH)}util.h \ - $(ENCODING_H_INCLUDES) - inits.$(OBJEXT): {$(VPATH)}inits.c $(RUBY_H_INCLUDES) \ -@@ -702,7 +703,7 @@ signal.$(OBJEXT): {$(VPATH)}signal.c $(RUBY_H_INCLUDES) \ - $(VM_CORE_H_INCLUDES) {$(VPATH)}debug.h - sprintf.$(OBJEXT): {$(VPATH)}sprintf.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \ - {$(VPATH)}regex.h {$(VPATH)}vsnprintf.c $(ENCODING_H_INCLUDES) --st.$(OBJEXT): {$(VPATH)}st.c $(RUBY_H_INCLUDES) -+st.$(OBJEXT): {$(VPATH)}st.c $(RUBY_H_INCLUDES) {$(VPATH)}pool_alloc.h - strftime.$(OBJEXT): {$(VPATH)}strftime.c $(RUBY_H_INCLUDES) \ - {$(VPATH)}timev.h - string.$(OBJEXT): {$(VPATH)}string.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \ -diff --git a/configure.in b/configure.in -index 6099a92..ee6012e 100644 ---- a/configure.in -+++ b/configure.in -@@ -1367,7 +1367,8 @@ AC_CHECK_FUNCS(fmod killpg wait4 waitpid fork spawnv syscall __syscall chroot ge - setsid telldir seekdir fchmod cosh sinh tanh log2 round\ - setuid setgid daemon select_large_fdset setenv unsetenv\ - mktime timegm gmtime_r clock_gettime gettimeofday poll ppoll\ -- pread sendfile shutdown sigaltstack dl_iterate_phdr) -+ pread sendfile shutdown sigaltstack dl_iterate_phdr\ -+ dup3 pipe2 posix_memalign memalign) - - AC_CACHE_CHECK(for unsetenv returns a value, rb_cv_unsetenv_return_value, - [AC_TRY_COMPILE([ -diff --git a/ext/-test-/st/numhash/numhash.c b/ext/-test-/st/numhash/numhash.c -index e186cd4..53d9e1b 100644 ---- a/ext/-test-/st/numhash/numhash.c -+++ b/ext/-test-/st/numhash/numhash.c -@@ -54,7 +54,7 @@ numhash_i(st_data_t key, st_data_t value, st_data_t arg, int error) - static VALUE - numhash_each(VALUE self) - { -- return st_foreach((st_table *)DATA_PTR(self), numhash_i, self) ? Qtrue : Qfalse; -+ return st_foreach_check((st_table *)DATA_PTR(self), numhash_i, self, 0) ? Qtrue : Qfalse; - } - - void -diff --git a/gc.c b/gc.c -index 52b2c56..7f78316 100644 ---- a/gc.c -+++ b/gc.c -@@ -20,11 +20,13 @@ - #include "vm_core.h" - #include "internal.h" - #include "gc.h" -+#include "pool_alloc.h" - #include "constant.h" - #include "ruby_atomic.h" - #include - #include - #include -+#include - - #ifdef HAVE_SYS_TIME_H - #include -@@ -36,7 +38,12 @@ - - #if defined _WIN32 || defined __CYGWIN__ - #include -+#elif defined(HAVE_POSIX_MEMALIGN) -+#elif defined(HAVE_MEMALIGN) -+#include - #endif -+static void aligned_free(void *); -+static void *aligned_malloc(size_t alignment, size_t size); - - #ifdef HAVE_VALGRIND_MEMCHECK_H - # include -@@ -355,6 +362,24 @@ typedef struct mark_stack { - - #define CALC_EXACT_MALLOC_SIZE 0 - -+#ifdef POOL_ALLOC_API -+/* POOL ALLOC API */ -+#define POOL_ALLOC_PART 1 -+#include "pool_alloc.inc.h" -+#undef POOL_ALLOC_PART -+ -+typedef struct pool_layout_t pool_layout_t; -+struct pool_layout_t { -+ pool_header -+ p6, /* st_table && st_table_entry */ -+ p11; /* st_table.bins init size */ -+} pool_layout = { -+ INIT_POOL(void*[6]), -+ INIT_POOL(void*[11]) -+}; -+static void pool_finalize_header(pool_header *header); -+#endif -+ - typedef struct rb_objspace { - struct { - size_t limit; -@@ -364,6 +389,9 @@ typedef struct rb_objspace { - size_t allocations; - #endif - } malloc_params; -+#ifdef POOL_ALLOC_API -+ pool_layout_t *pool_headers; -+#endif - struct { - size_t increment; - struct heaps_slot *ptr; -@@ -429,7 +457,11 @@ typedef struct rb_objspace { - #define ruby_initial_gc_stress initial_params.gc_stress - int *ruby_initial_gc_stress_ptr = &ruby_initial_gc_stress; - #else -+# ifdef POOL_ALLOC_API -+static rb_objspace_t rb_objspace = {{GC_MALLOC_LIMIT}, &pool_layout, {HEAP_MIN_SLOTS}}; -+# else - static rb_objspace_t rb_objspace = {{GC_MALLOC_LIMIT}, {HEAP_MIN_SLOTS}}; -+# endif - int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress; - #endif - #define malloc_limit objspace->malloc_params.limit -@@ -480,6 +512,10 @@ rb_objspace_alloc(void) - memset(objspace, 0, sizeof(*objspace)); - malloc_limit = initial_malloc_limit; - ruby_gc_stress = ruby_initial_gc_stress; -+#ifdef POOL_ALLOC_API -+ objspace->pool_headers = (pool_layout_t*) malloc(sizeof(pool_layout)); -+ memcpy(objspace->pool_headers, &pool_layout, sizeof(pool_layout)); -+#endif - - return objspace; - } -@@ -623,6 +659,13 @@ rb_objspace_free(rb_objspace_t *objspace) - heaps = 0; - } - free_stack_chunks(&objspace->mark_stack); -+#ifdef POOL_ALLOC_API -+ if (objspace->pool_headers) { -+ pool_finalize_header(&objspace->pool_headers->p6); -+ pool_finalize_header(&objspace->pool_headers->p11); -+ free(objspace->pool_headers); -+ } -+#endif - free(objspace); - } - #endif -@@ -1147,6 +1190,27 @@ rb_gc_stats_enabled() - return gc_statistics ? Qtrue : Qfalse; - } - -+#ifdef POOL_ALLOC_API -+/* POOL ALLOC API */ -+#define POOL_ALLOC_PART 2 -+#include "pool_alloc.inc.h" -+#undef POOL_ALLOC_PART -+ -+void -+ruby_xpool_free(void *ptr) -+{ -+ pool_free_entry((void**)ptr); -+} -+ -+#define CONCRET_POOL_MALLOC(pnts) \ -+void * ruby_xpool_malloc_##pnts##p () { \ -+ return pool_alloc_entry(&rb_objspace.pool_headers->p##pnts ); \ -+} -+CONCRET_POOL_MALLOC(6) -+CONCRET_POOL_MALLOC(11) -+#undef CONCRET_POOL_MALLOC -+ -+#endif - - /* - * call-seq: -@@ -1656,6 +1720,55 @@ allocate_sorted_heaps(rb_objspace_t *objspace, size_t next_heaps_length) - heaps_length = next_heaps_length; - } - -+static void * -+aligned_malloc(size_t alignment, size_t size) -+{ -+ void *res; -+ -+#if defined __MINGW32__ -+ res = __mingw_aligned_malloc(size, alignment); -+#elif defined _WIN32 && !defined __CYGWIN__ -+ 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 -+ -+#if defined(_DEBUG) || defined(GC_DEBUG) -+ /* alignment must be a power of 2 */ -+ assert((alignment - 1) & alignment == 0); -+ assert(alignment % sizeof(void*) == 0); -+#endif -+ return res; -+} -+ -+static void -+aligned_free(void *ptr) -+{ -+#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 -+} -+ - static void - assign_heap_slot(rb_objspace_t *objspace) - { -diff --git a/hash.c b/hash.c -index 8423558..4cb2e2d 100644 ---- a/hash.c -+++ b/hash.c -@@ -44,7 +44,7 @@ rb_any_cmp(VALUE a, VALUE b) - if (FIXNUM_P(a) && FIXNUM_P(b)) { - return a != b; - } -- if (TYPE(a) == T_STRING && RBASIC(a)->klass == rb_cString && -+ if (RB_TYPE_P(a, T_STRING) && RBASIC(a)->klass == rb_cString && - TYPE(b) == T_STRING && RBASIC(b)->klass == rb_cString) { - return rb_str_hash_cmp(a, b); - } -@@ -80,20 +80,14 @@ rb_any_hash(VALUE a) - VALUE hval; - st_index_t hnum; - -- switch (TYPE(a)) { -- case T_FIXNUM: -- case T_SYMBOL: -- case T_NIL: -- case T_FALSE: -- case T_TRUE: -- hnum = rb_hash_end(rb_hash_start((unsigned int)a)); -- break; -- -- case T_STRING: -+ if (SPECIAL_CONST_P(a)) { -+ if (a == Qundef) return 0; -+ hnum = rb_hash_end(rb_hash_start((st_index_t)a)); -+ } -+ else if (BUILTIN_TYPE(a) == T_STRING) { - hnum = rb_str_hash(a); -- break; -- -- default: -+ } -+ else { - hval = rb_hash(a); - hnum = FIX2LONG(hval); - } -@@ -106,10 +100,8 @@ static const struct st_hash_type objhash = { - rb_any_hash, - }; - --static const struct st_hash_type identhash = { -- st_numcmp, -- st_numhash, --}; -+extern const struct st_hash_type st_hashtype_num; -+#define identhash st_hashtype_num - - typedef int st_foreach_func(st_data_t, st_data_t, st_data_t); - -@@ -124,7 +116,6 @@ foreach_safe_i(st_data_t key, st_data_t value, struct foreach_safe_arg *arg) - { - int status; - -- if (key == Qundef) return ST_CONTINUE; - status = (*arg->func)(key, value, arg->arg); - if (status == ST_CONTINUE) { - return ST_CHECK; -@@ -140,7 +131,7 @@ st_foreach_safe(st_table *table, int (*func)(ANYARGS), st_data_t a) - arg.tbl = table; - arg.func = (st_foreach_func *)func; - arg.arg = a; -- if (st_foreach(table, foreach_safe_i, (st_data_t)&arg)) { -+ if (st_foreach_check(table, foreach_safe_i, (st_data_t)&arg, 0)) { - rb_raise(rb_eRuntimeError, "hash modified during iteration"); - } - } -@@ -154,21 +145,21 @@ struct hash_foreach_arg { - }; - - static int --hash_foreach_iter(st_data_t key, st_data_t value, struct hash_foreach_arg *arg) -+hash_foreach_iter(st_data_t key, st_data_t value, st_data_t argp) - { -+ struct hash_foreach_arg *arg = (struct hash_foreach_arg *)argp; - int status; - st_table *tbl; - - tbl = RHASH(arg->hash)->ntbl; -- if ((VALUE)key == Qundef) return ST_CONTINUE; - status = (*arg->func)((VALUE)key, (VALUE)value, arg->arg); - if (RHASH(arg->hash)->ntbl != tbl) { - rb_raise(rb_eRuntimeError, "rehash occurred during iteration"); - } - switch (status) { - case ST_DELETE: -- st_delete_safe(tbl, &key, 0, Qundef); - FL_SET(arg->hash, HASH_DELETED); -+ return ST_DELETE; - case ST_CONTINUE: - break; - case ST_STOP: -@@ -184,7 +175,7 @@ hash_foreach_ensure(VALUE hash) - - if (RHASH(hash)->iter_lev == 0) { - if (FL_TEST(hash, HASH_DELETED)) { -- st_cleanup_safe(RHASH(hash)->ntbl, Qundef); -+ st_cleanup_safe(RHASH(hash)->ntbl, (st_data_t)Qundef); - FL_UNSET(hash, HASH_DELETED); - } - } -@@ -192,9 +183,10 @@ hash_foreach_ensure(VALUE hash) - } - - static VALUE --hash_foreach_call(struct hash_foreach_arg *arg) -+hash_foreach_call(VALUE arg) - { -- if (st_foreach(RHASH(arg->hash)->ntbl, hash_foreach_iter, (st_data_t)arg)) { -+ VALUE hash = ((struct hash_foreach_arg *)arg)->hash; -+ if (st_foreach_check(RHASH(hash)->ntbl, hash_foreach_iter, (st_data_t)arg, (st_data_t)Qundef)) { - rb_raise(rb_eRuntimeError, "hash modified during iteration"); - } - return Qnil; -@@ -447,7 +439,7 @@ rb_hash_rehash_i(VALUE key, VALUE value, VALUE arg) - { - st_table *tbl = (st_table *)arg; - -- if (key != Qundef) st_insert(tbl, key, value); -+ st_insert(tbl, (st_data_t)key, (st_data_t)value); - return ST_CONTINUE; - } - -@@ -490,6 +482,20 @@ rb_hash_rehash(VALUE hash) - return hash; - } - -+static VALUE -+hash_default_value(VALUE hash, VALUE key) -+{ -+ if (rb_method_basic_definition_p(CLASS_OF(hash), id_default)) { -+ VALUE ifnone = RHASH_IFNONE(hash); -+ if (!FL_TEST(hash, HASH_PROC_DEFAULT)) return ifnone; -+ if (key == Qundef) return Qnil; -+ return rb_funcall(ifnone, id_yield, 2, hash, key); -+ } -+ else { -+ return rb_funcall(hash, id_default, 1, key); -+ } -+} -+ - /* - * call-seq: - * hsh[key] -> value -@@ -510,13 +516,7 @@ rb_hash_aref(VALUE hash, VALUE key) - st_data_t val; - - if (!RHASH(hash)->ntbl || !st_lookup(RHASH(hash)->ntbl, key, &val)) { -- if (!FL_TEST(hash, HASH_PROC_DEFAULT) && -- rb_method_basic_definition_p(CLASS_OF(hash), id_default)) { -- return RHASH_IFNONE(hash); -- } -- else { -- return rb_funcall(hash, id_default, 1, key); -- } -+ return hash_default_value(hash, key); - } - return (VALUE)val; - } -@@ -659,7 +659,7 @@ rb_hash_default(int argc, VALUE *argv, VALUE hash) - static VALUE - rb_hash_set_default(VALUE hash, VALUE ifnone) - { -- rb_hash_modify(hash); -+ rb_hash_modify_check(hash); - RHASH_IFNONE(hash) = ifnone; - FL_UNSET(hash, HASH_PROC_DEFAULT); - return ifnone; -@@ -707,7 +707,7 @@ rb_hash_set_default_proc(VALUE hash, VALUE proc) - { - VALUE b; - -- rb_hash_modify(hash); -+ rb_hash_modify_check(hash); - b = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc"); - if (NIL_P(b) || !rb_obj_is_proc(b)) { - rb_raise(rb_eTypeError, -@@ -776,7 +776,7 @@ rb_hash_delete_key(VALUE hash, VALUE key) - if (!RHASH(hash)->ntbl) - return Qundef; - if (RHASH(hash)->iter_lev > 0) { -- if (st_delete_safe(RHASH(hash)->ntbl, &ktmp, &val, Qundef)) { -+ if (st_delete_safe(RHASH(hash)->ntbl, &ktmp, &val, (st_data_t)Qundef)) { - FL_SET(hash, HASH_DELETED); - return (VALUE)val; - } -@@ -809,7 +809,7 @@ rb_hash_delete(VALUE hash, VALUE key) - { - VALUE val; - -- rb_hash_modify(hash); -+ rb_hash_modify_check(hash); - val = rb_hash_delete_key(hash, key); - if (val != Qundef) return val; - if (rb_block_given_p()) { -@@ -828,7 +828,6 @@ shift_i(VALUE key, VALUE value, VALUE arg) - { - struct shift_var *var = (struct shift_var *)arg; - -- if (key == Qundef) return ST_CONTINUE; - if (var->key != Qundef) return ST_STOP; - var->key = key; - var->val = value; -@@ -840,7 +839,6 @@ shift_i_safe(VALUE key, VALUE value, VALUE arg) - { - struct shift_var *var = (struct shift_var *)arg; - -- if (key == Qundef) return ST_CONTINUE; - var->key = key; - var->val = value; - return ST_STOP; -@@ -864,29 +862,25 @@ rb_hash_shift(VALUE hash) - { - struct shift_var var; - -- rb_hash_modify(hash); -- var.key = Qundef; -- rb_hash_foreach(hash, RHASH(hash)->iter_lev > 0 ? shift_i_safe : shift_i, -- (VALUE)&var); -- -- if (var.key != Qundef) { -- if (RHASH(hash)->iter_lev > 0) { -- rb_hash_delete_key(hash, var.key); -+ rb_hash_modify_check(hash); -+ if (RHASH(hash)->ntbl) { -+ var.key = Qundef; -+ rb_hash_foreach(hash, RHASH(hash)->iter_lev > 0 ? shift_i_safe : shift_i, -+ (VALUE)&var); -+ -+ if (var.key != Qundef) { -+ if (RHASH(hash)->iter_lev > 0) { -+ rb_hash_delete_key(hash, var.key); -+ } -+ return rb_assoc_new(var.key, var.val); - } -- return rb_assoc_new(var.key, var.val); -- } -- else if (FL_TEST(hash, HASH_PROC_DEFAULT)) { -- return rb_funcall(RHASH_IFNONE(hash), id_yield, 2, hash, Qnil); -- } -- else { -- return RHASH_IFNONE(hash); - } -+ return hash_default_value(hash, Qnil); - } - - static int - delete_if_i(VALUE key, VALUE value, VALUE hash) - { -- if (key == Qundef) return ST_CONTINUE; - if (RTEST(rb_yield_values(2, key, value))) { - rb_hash_delete_key(hash, key); - } -@@ -912,8 +906,9 @@ VALUE - rb_hash_delete_if(VALUE hash) - { - RETURN_ENUMERATOR(hash, 0, 0); -- rb_hash_modify(hash); -- rb_hash_foreach(hash, delete_if_i, hash); -+ rb_hash_modify_check(hash); -+ if (RHASH(hash)->ntbl) -+ rb_hash_foreach(hash, delete_if_i, hash); - return hash; - } - -@@ -984,7 +979,6 @@ rb_hash_values_at(int argc, VALUE *argv, VALUE hash) - static int - select_i(VALUE key, VALUE value, VALUE result) - { -- if (key == Qundef) return ST_CONTINUE; - if (RTEST(rb_yield_values(2, key, value))) - rb_hash_aset(result, key, value); - return ST_CONTINUE; -@@ -1018,7 +1012,6 @@ rb_hash_select(VALUE hash) - static int - keep_if_i(VALUE key, VALUE value, VALUE hash) - { -- if (key == Qundef) return ST_CONTINUE; - if (!RTEST(rb_yield_values(2, key, value))) { - return ST_DELETE; - } -@@ -1040,7 +1033,7 @@ rb_hash_select_bang(VALUE hash) - st_index_t n; - - RETURN_ENUMERATOR(hash, 0, 0); -- rb_hash_modify(hash); -+ rb_hash_modify_check(hash); - if (!RHASH(hash)->ntbl) - return Qnil; - n = RHASH(hash)->ntbl->num_entries; -@@ -1065,8 +1058,9 @@ VALUE - rb_hash_keep_if(VALUE hash) - { - RETURN_ENUMERATOR(hash, 0, 0); -- rb_hash_modify(hash); -- rb_hash_foreach(hash, keep_if_i, hash); -+ rb_hash_modify_check(hash); -+ if (RHASH(hash)->ntbl) -+ rb_hash_foreach(hash, keep_if_i, hash); - return hash; - } - -@@ -1144,9 +1138,7 @@ rb_hash_aset(VALUE hash, VALUE key, VALUE val) - static int - replace_i(VALUE key, VALUE val, VALUE hash) - { -- if (key != Qundef) { -- rb_hash_aset(hash, key, val); -- } -+ rb_hash_aset(hash, key, val); - - return ST_CONTINUE; - } -@@ -1227,7 +1219,6 @@ rb_hash_empty_p(VALUE hash) - static int - each_value_i(VALUE key, VALUE value) - { -- if (key == Qundef) return ST_CONTINUE; - rb_yield(value); - return ST_CONTINUE; - } -@@ -1262,7 +1253,6 @@ rb_hash_each_value(VALUE hash) - static int - each_key_i(VALUE key, VALUE value) - { -- if (key == Qundef) return ST_CONTINUE; - rb_yield(key); - return ST_CONTINUE; - } -@@ -1296,7 +1286,6 @@ rb_hash_each_key(VALUE hash) - static int - each_pair_i(VALUE key, VALUE value) - { -- if (key == Qundef) return ST_CONTINUE; - rb_yield(rb_assoc_new(key, value)); - return ST_CONTINUE; - } -@@ -1334,7 +1323,6 @@ rb_hash_each_pair(VALUE hash) - static int - to_a_i(VALUE key, VALUE value, VALUE ary) - { -- if (key == Qundef) return ST_CONTINUE; - rb_ary_push(ary, rb_assoc_new(key, value)); - return ST_CONTINUE; - } -@@ -1367,7 +1355,6 @@ inspect_i(VALUE key, VALUE value, VALUE str) - { - VALUE str2; - -- if (key == Qundef) return ST_CONTINUE; - str2 = rb_inspect(key); - if (RSTRING_LEN(str) > 1) { - rb_str_cat2(str, ", "); -@@ -1434,7 +1421,6 @@ rb_hash_to_hash(VALUE hash) - static int - keys_i(VALUE key, VALUE value, VALUE ary) - { -- if (key == Qundef) return ST_CONTINUE; - rb_ary_push(ary, key); - return ST_CONTINUE; - } -@@ -1465,7 +1451,6 @@ rb_hash_keys(VALUE hash) - static int - values_i(VALUE key, VALUE value, VALUE ary) - { -- if (key == Qundef) return ST_CONTINUE; - rb_ary_push(ary, value); - return ST_CONTINUE; - } -@@ -1524,7 +1509,6 @@ rb_hash_search_value(VALUE key, VALUE value, VALUE arg) - { - VALUE *data = (VALUE *)arg; - -- if (key == Qundef) return ST_CONTINUE; - if (rb_equal(value, data[1])) { - data[0] = Qtrue; - return ST_STOP; -@@ -1568,7 +1552,6 @@ eql_i(VALUE key, VALUE val1, VALUE arg) - struct equal_data *data = (struct equal_data *)arg; - st_data_t val2; - -- if (key == Qundef) return ST_CONTINUE; - if (!st_lookup(data->tbl, key, &val2)) { - data->result = Qfalse; - return ST_STOP; -@@ -1599,7 +1582,7 @@ hash_equal(VALUE hash1, VALUE hash2, int eql) - struct equal_data data; - - if (hash1 == hash2) return Qtrue; -- if (TYPE(hash2) != T_HASH) { -+ if (!RB_TYPE_P(hash2, T_HASH)) { - if (!rb_respond_to(hash2, rb_intern("to_hash"))) { - return Qfalse; - } -@@ -1670,7 +1653,6 @@ hash_i(VALUE key, VALUE val, VALUE arg) - st_index_t *hval = (st_index_t *)arg; - st_index_t hdata[2]; - -- if (key == Qundef) return ST_CONTINUE; - hdata[0] = rb_hash(key); - hdata[1] = rb_hash(val); - *hval ^= st_hash(hdata, sizeof(hdata), 0); -@@ -1711,7 +1693,6 @@ rb_hash_hash(VALUE hash) - static int - rb_hash_invert_i(VALUE key, VALUE value, VALUE hash) - { -- if (key == Qundef) return ST_CONTINUE; - rb_hash_aset(hash, value, key); - return ST_CONTINUE; - } -@@ -1740,7 +1721,6 @@ rb_hash_invert(VALUE hash) - static int - rb_hash_update_i(VALUE key, VALUE value, VALUE hash) - { -- if (key == Qundef) return ST_CONTINUE; - hash_update(hash, key); - st_insert(RHASH(hash)->ntbl, key, value); - return ST_CONTINUE; -@@ -1749,7 +1729,6 @@ rb_hash_update_i(VALUE key, VALUE value, VALUE hash) - static int - rb_hash_update_block_i(VALUE key, VALUE value, VALUE hash) - { -- if (key == Qundef) return ST_CONTINUE; - if (rb_hash_has_key(hash, key)) { - value = rb_yield_values(3, key, rb_hash_aref(hash, key), value); - } -@@ -1806,7 +1785,6 @@ rb_hash_update_func_i(VALUE key, VALUE value, VALUE arg0) - struct update_arg *arg = (struct update_arg *)arg0; - VALUE hash = arg->hash; - -- if (key == Qundef) return ST_CONTINUE; - if (rb_hash_has_key(hash, key)) { - value = (*arg->func)(key, rb_hash_aref(hash, key), value); - } -@@ -1863,7 +1841,6 @@ assoc_i(VALUE key, VALUE val, VALUE arg) - { - VALUE *args = (VALUE *)arg; - -- if (key == Qundef) return ST_CONTINUE; - if (RTEST(rb_equal(args[0], key))) { - args[1] = rb_assoc_new(key, val); - return ST_STOP; -@@ -1901,7 +1878,6 @@ rassoc_i(VALUE key, VALUE val, VALUE arg) - { - VALUE *args = (VALUE *)arg; - -- if (key == Qundef) return ST_CONTINUE; - if (RTEST(rb_equal(args[0], val))) { - args[1] = rb_assoc_new(key, val); - return ST_STOP; -@@ -2198,7 +2174,7 @@ rb_env_path_tainted(void) - } - - #if defined(_WIN32) || (defined(HAVE_SETENV) && defined(HAVE_UNSETENV)) --#elif defined __sun__ -+#elif defined __sun - static int - in_origenv(const char *str) - { -@@ -2286,7 +2262,7 @@ ruby_setenv(const char *name, const char *value) - rb_sys_fail("unsetenv"); - #endif - } --#elif defined __sun__ -+#elif defined __sun - size_t len; - char **env_ptr, *str; - if (strchr(name, '=')) { -@@ -3084,11 +3060,9 @@ env_invert(void) - static int - env_replace_i(VALUE key, VALUE val, VALUE keys) - { -- if (key != Qundef) { -- env_aset(Qnil, key, val); -- if (rb_ary_includes(keys, key)) { -- rb_ary_delete(keys, key); -- } -+ env_aset(Qnil, key, val); -+ if (rb_ary_includes(keys, key)) { -+ rb_ary_delete(keys, key); - } - return ST_CONTINUE; - } -@@ -3120,12 +3094,10 @@ env_replace(VALUE env, VALUE hash) - static int - env_update_i(VALUE key, VALUE val) - { -- if (key != Qundef) { -- if (rb_block_given_p()) { -- val = rb_yield_values(3, key, rb_f_getenv(Qnil, key), val); -- } -- env_aset(Qnil, key, val); -+ if (rb_block_given_p()) { -+ val = rb_yield_values(3, key, rb_f_getenv(Qnil, key), val); - } -+ env_aset(Qnil, key, val); - return ST_CONTINUE; - } - -@@ -3150,15 +3122,116 @@ env_update(VALUE env, VALUE hash) - } - - /* -- * A Hash is a collection of key-value pairs. It is -- * similar to an Array, except that indexing is done via -- * arbitrary keys of any object type, not an integer index. Hashes enumerate -- * their values in the order that the corresponding keys were inserted. -+ * A Hash is a dictionary-like collection of unique keys and their values. -+ * Also called associative arrays, they are similar to Arrays, but where an -+ * Array uses integers as its index, a Hash allows you to use any object -+ * type. -+ * -+ * Hashes enumerate their values in the order that the corresponding keys -+ * were inserted. -+ * -+ * A Hash can be easily created by using its implicit form: -+ * -+ * grades = { "Jane Doe" => 10, "Jim Doe" => 6 } -+ * -+ * Hashes allow an alternate syntax form when your keys are always symbols. -+ * Instead of -+ * -+ * options = { :font_size => 10, :font_family => "Arial" } -+ * -+ * You could write it as: -+ * -+ * options = { font_size: 10, font_family: "Arial" } -+ * -+ * Each named key is a symbol you can access in hash: -+ * -+ * options[:font_size] # => 10 -+ * -+ * A Hash can also be created through its ::new method: -+ * -+ * grades = Hash.new -+ * grades["Dorothy Doe"] = 9 - * - * Hashes have a default value that is returned when accessing -- * keys that do not exist in the hash. By default, that value is -- * nil. -+ * keys that do not exist in the hash. If no default is set +nil+ is used. -+ * You can set the default value by sending it as an argument to Hash.new: -+ * -+ * grades = Hash.new(0) -+ * -+ * Or by using the #default= method: -+ * -+ * grades = {"Timmy Doe" => 8} -+ * grades.default = 0 -+ * -+ * Accessing a value in a Hash requires using its key: -+ * -+ * puts grades["Jane Doe"] # => 10 -+ * -+ * === Common Uses -+ * -+ * Hashes are an easy way to represent data structures, such as -+ * -+ * books = {} -+ * books[:matz] = "The Ruby Language" -+ * books[:black] = "The Well-Grounded Rubyist" -+ * -+ * Hashes are also commonly used as a way to have named parameters in -+ * functions. Note that no brackets are used below. If a hash is the last -+ * argument on a method call, no braces are needed, thus creating a really -+ * clean interface: -+ * -+ * Person.create(name: "John Doe", age: 27) -+ * -+ * def self.create(params) -+ * @name = params[:name] -+ * @age = params[:age] -+ * end -+ * -+ * === Hash Keys -+ * -+ * Two objects refer to the same hash key when their hash value -+ * is identical and the two objects are eql? to each other. -+ * -+ * A user-defined class may be used as a hash key if the hash -+ * and eql? methods are overridden to provide meaningful -+ * behavior. By default, separate instances refer to separate hash keys. -+ * -+ * A typical implementation of hash is based on the -+ * object's data while eql? is usually aliased to the overridden -+ * == method: -+ * -+ * class Book -+ * attr_reader :author, :title -+ * -+ * def initialize(author, title) -+ * @author = author -+ * @title = title -+ * end -+ * -+ * def ==(other) -+ * self.class === other and -+ * other.author == @author and -+ * other.title == @title -+ * end -+ * -+ * alias eql? == -+ * -+ * def hash -+ * @author.hash ^ @title.hash # XOR -+ * end -+ * end -+ * -+ * book1 = Book.new 'matz', 'Ruby in a Nutshell' -+ * book2 = Book.new 'matz', 'Ruby in a Nutshell' -+ * -+ * reviews = {} -+ * -+ * reviews[book1] = 'Great reference!' -+ * reviews[book2] = 'Nice and compact!' -+ * -+ * reviews.length #=> 1 - * -+ * See also Object#hash and Object#eql? - */ - - void -diff --git a/include/ruby/st.h b/include/ruby/st.h -index 50f2a75..119dfde 100644 ---- a/include/ruby/st.h -+++ b/include/ruby/st.h -@@ -36,7 +36,7 @@ typedef unsigned long st_data_t; - #elif SIZEOF_LONG_LONG == SIZEOF_VOIDP - typedef unsigned LONG_LONG st_data_t; - #else --# error ---->> st.c requires sizeof(void*) == sizeof(long) to be compiled. <<---- -+# error ---->> st.c requires sizeof(void*) == sizeof(long) or sizeof(LONG_LONG) to be compiled. <<---- - #endif - #define ST_DATA_T_DEFINED - -@@ -74,6 +74,11 @@ struct st_hash_type { - - #define ST_INDEX_BITS (sizeof(st_index_t) * CHAR_BIT) - -+typedef struct st_packed_entry { -+ st_index_t hash; -+ st_data_t key, val; -+} st_packed_entry; -+ - struct st_table { - const struct st_hash_type *type; - st_index_t num_bins; -@@ -91,8 +96,17 @@ struct st_table { - __extension__ - #endif - st_index_t num_entries : ST_INDEX_BITS - 1; -- struct st_table_entry **bins; -- struct st_table_entry *head, *tail; -+ union { -+ struct { -+ struct st_table_entry **bins; -+ struct st_table_entry *head, *tail; -+ } big; -+ struct { -+ struct st_packed_entry *entries; -+ st_index_t real_entries; -+ } packed; -+ st_packed_entry upacked; -+ } as; - }; - - #define st_is_member(table,key) st_lookup((table),(key),(st_data_t *)0) -@@ -114,6 +128,7 @@ int st_insert2(st_table *, st_data_t, st_data_t, st_data_t (*)(st_data_t)); - int st_lookup(st_table *, st_data_t, st_data_t *); - int st_get_key(st_table *, st_data_t, st_data_t *); - int st_foreach(st_table *, int (*)(ANYARGS), st_data_t); -+int st_foreach_check(st_table *, int (*)(ANYARGS), st_data_t, st_data_t); - int st_reverse_foreach(st_table *, int (*)(ANYARGS), st_data_t); - void st_add_direct(st_table *, st_data_t, st_data_t); - void st_free_table(st_table *); -diff --git a/pool_alloc.h b/pool_alloc.h -new file mode 100644 -index 0000000..957708e ---- /dev/null -+++ b/pool_alloc.h -@@ -0,0 +1,11 @@ -+#ifndef POOL_ALLOC_H -+#define POOL_ALLOC_H -+ -+#define POOL_ALLOC_API -+#ifdef POOL_ALLOC_API -+void ruby_xpool_free(void *ptr); -+void *ruby_xpool_malloc_6p(); -+void *ruby_xpool_malloc_11p(); -+#endif -+ -+#endif -diff --git a/pool_alloc.inc.h b/pool_alloc.inc.h -new file mode 100644 -index 0000000..a7879ab ---- /dev/null -+++ b/pool_alloc.inc.h -@@ -0,0 +1,156 @@ -+/* -+ * this is generic pool allocator -+ * you should define following macroses: -+ * ITEM_NAME - unique identifier, which allows to hold functions in a namespace -+ * ITEM_TYPEDEF(name) - passed to typedef to localize item type -+ * free_entry - desired name of function for free entry -+ * alloc_entry - defired name of function for allocate entry -+ */ -+ -+#if POOL_ALLOC_PART == 1 -+#ifdef HEAP_ALIGN_LOG -+#define DEFAULT_POOL_SIZE (1 << HEAP_ALIGN_LOG) -+#else -+#define DEFAULT_POOL_SIZE (sizeof(void*) * 2048) -+#endif -+typedef unsigned int pool_holder_counter; -+ -+typedef struct pool_entry_list pool_entry_list; -+typedef struct pool_holder pool_holder; -+ -+typedef struct pool_header { -+ pool_holder *first; -+ pool_holder *_black_magick; -+ pool_holder_counter size; // size of entry in sizeof(void*) items -+ pool_holder_counter total; // size of entry in sizeof(void*) items -+} pool_header; -+ -+struct pool_holder { -+ pool_holder_counter free, total; -+ pool_header *header; -+ void *freep; -+ pool_holder *fore, *back; -+ void *data[1]; -+}; -+#define POOL_DATA_SIZE(pool_size) (((pool_size) - sizeof(void*) * 6 - offsetof(pool_holder, data)) / sizeof(void*)) -+#define POOL_ENTRY_SIZE(item_type) ((sizeof(item_type) - 1) / sizeof(void*) + 1) -+#define POOL_HOLDER_COUNT(pool_size, item_type) (POOL_DATA_SIZE(pool_size)/POOL_ENTRY_SIZE(item_type)) -+#define INIT_POOL(item_type) {NULL, NULL, POOL_ENTRY_SIZE(item_type), POOL_HOLDER_COUNT(DEFAULT_POOL_SIZE, item_type)} -+ -+#elif POOL_ALLOC_PART == 2 -+static pool_holder * -+pool_holder_alloc(pool_header *header) -+{ -+ pool_holder *holder; -+ pool_holder_counter i, size, count; -+ register void **ptr; -+ -+ size_t sz = offsetof(pool_holder, data) + -+ header->size * header->total * sizeof(void*); -+#define objspace (&rb_objspace) -+ vm_malloc_prepare(objspace, DEFAULT_POOL_SIZE); -+ if (header->first != NULL) return header->first; -+ TRY_WITH_GC(holder = (pool_holder*) aligned_malloc(DEFAULT_POOL_SIZE, sz)); -+ malloc_increase += DEFAULT_POOL_SIZE; -+#if CALC_EXACT_MALLOC_SIZE -+ objspace->malloc_params.allocated_size += DEFAULT_POOL_SIZE; -+ objspace->malloc_params.allocations++; -+#endif -+#undef objspace -+ -+ size = header->size; -+ count = header->total; -+ holder->free = count; -+ holder->total = count; -+ holder->header = header; -+ holder->fore = NULL; -+ holder->back = NULL; -+ holder->freep = &holder->data; -+ ptr = holder->data; -+ for(i = count - 1; i; i-- ) { -+ ptr = *ptr = ptr + size; -+ } -+ *ptr = NULL; -+ header->first = holder; -+ return holder; -+} -+ -+static inline void -+pool_holder_unchaing(pool_header *header, pool_holder *holder) -+{ -+ register pool_holder *fore = holder->fore, *back = holder->back; -+ holder->fore = NULL; -+ holder->back = NULL; -+ if (fore != NULL) fore->back = back; -+ else header->_black_magick = back; -+ if (back != NULL) back->fore = fore; -+ else header->first = fore; -+} -+ -+static inline pool_holder * -+entry_holder(void **entry) -+{ -+ return (pool_holder*)(((uintptr_t)entry) & ~(DEFAULT_POOL_SIZE - 1)); -+} -+ -+static inline void -+pool_free_entry(void **entry) -+{ -+ pool_holder *holder = entry_holder(entry); -+ pool_header *header = holder->header; -+ -+ if (holder->free++ == 0) { -+ register pool_holder *first = header->first; -+ if (first == NULL) { -+ header->first = holder; -+ } else { -+ holder->back = first; -+ holder->fore = first->fore; -+ first->fore = holder; -+ if (holder->fore) -+ holder->fore->back = holder; -+ else -+ header->_black_magick = holder; -+ } -+ } else if (holder->free == holder->total && header->first != holder ) { -+ pool_holder_unchaing(header, holder); -+ aligned_free(holder); -+#if CALC_EXACT_MALLOC_SIZE -+ rb_objspace.malloc_params.allocated_size -= DEFAULT_POOL_SIZE; -+ rb_objspace.malloc_params.allocations--; -+#endif -+ return; -+ } -+ -+ *entry = holder->freep; -+ holder->freep = entry; -+} -+ -+static inline void* -+pool_alloc_entry(pool_header *header) -+{ -+ pool_holder *holder = header->first; -+ void **result; -+ if (holder == NULL) { -+ holder = pool_holder_alloc(header); -+ } -+ -+ result = holder->freep; -+ holder->freep = *result; -+ -+ if (--holder->free == 0) { -+ pool_holder_unchaing(header, holder); -+ } -+ -+ return result; -+} -+ -+static void -+pool_finalize_header(pool_header *header) -+{ -+ if (header->first) { -+ aligned_free(header->first); -+ header->first = NULL; -+ } -+} -+#endif -diff --git a/st.c b/st.c -index fda5784..0194022 100644 ---- a/st.c -+++ b/st.c -@@ -7,6 +7,7 @@ - #include "st.h" - #else - #include "ruby/ruby.h" -+#include "pool_alloc.h" - #endif - - #include -@@ -25,8 +26,17 @@ struct st_table_entry { - st_table_entry *fore, *back; - }; - --#define ST_DEFAULT_MAX_DENSITY 5 -+#define STATIC_ASSERT(name, expr) typedef int static_assert_##name##_check[(expr) ? 1 : -1]; -+ -+#define ST_DEFAULT_MAX_DENSITY 2 - #define ST_DEFAULT_INIT_TABLE_SIZE 11 -+#define ST_DEFAULT_SECOND_TABLE_SIZE 19 -+#define ST_DEFAULT_PACKED_TABLE_SIZE 19 -+#define PACKED_UNIT (int)(sizeof(st_packed_entry) / sizeof(st_table_entry*)) -+#define MAX_PACKED_HASH (int)(ST_DEFAULT_PACKED_TABLE_SIZE * sizeof(st_table_entry*) / sizeof(st_packed_entry)) -+ -+STATIC_ASSERT(st_packed_entry, sizeof(st_packed_entry) == sizeof(st_table_entry*[PACKED_UNIT])) -+STATIC_ASSERT(st_packed_bins, sizeof(st_packed_entry[MAX_PACKED_HASH]) <= sizeof(st_table_entry*[ST_DEFAULT_PACKED_TABLE_SIZE])) - - /* - * DEFAULT_MAX_DENSITY is the default for the largest we allow the -@@ -38,7 +48,8 @@ struct st_table_entry { - * - */ - --static const struct st_hash_type type_numhash = { -+#define type_numhash st_hashtype_num -+const struct st_hash_type st_hashtype_num = { - st_numcmp, - st_numhash, - }; -@@ -61,20 +72,128 @@ static void rehash(st_table *); - #ifdef RUBY - #define malloc xmalloc - #define calloc xcalloc -+#define realloc xrealloc - #define free(x) xfree(x) - #endif - - #define numberof(array) (int)(sizeof(array) / sizeof((array)[0])) - --#define alloc(type) (type*)malloc((size_t)sizeof(type)) --#define Calloc(n,s) (char*)calloc((n),(s)) -- - #define EQUAL(table,x,y) ((x)==(y) || (*(table)->type->compare)((x),(y)) == 0) - --/* remove cast to unsigned int in the future */ --#define do_hash(key,table) (unsigned int)(st_index_t)(*(table)->type->hash)((key)) -+#define do_hash(key,table) (st_index_t)(*(table)->type->hash)((key)) - #define do_hash_bin(key,table) (do_hash((key), (table))%(table)->num_bins) - -+/* preparation for possible allocation improvements */ -+#ifdef POOL_ALLOC_API -+#define st_alloc_entry() (st_table_entry *)ruby_xpool_malloc_6p() -+#define st_free_entry(entry) ruby_xpool_free(entry) -+#define st_alloc_table() (st_table *)ruby_xpool_malloc_6p() -+#define st_dealloc_table(table) ruby_xpool_free(table) -+static inline st_table_entry ** -+st_alloc_bins(st_index_t size) -+{ -+ st_table_entry **result; -+ if (size == 11) { -+ result = (st_table_entry **) ruby_xpool_malloc_11p(); -+ memset(result, 0, 11 * sizeof(st_table_entry *)); -+ } -+ else -+ result = (st_table_entry **) ruby_xcalloc(size, sizeof(st_table_entry*)); -+ return result; -+} -+static inline void -+st_free_bins(st_table_entry **bins, st_index_t size) -+{ -+ if (size == 11) -+ ruby_xpool_free(bins); -+ else -+ ruby_xfree(bins); -+} -+static inline st_table_entry** -+st_realloc_bins(st_table_entry **bins, st_index_t newsize, st_index_t oldsize) -+{ -+ st_table_entry **new_bins = st_alloc_bins(newsize); -+ st_free_bins(bins, oldsize); -+ return new_bins; -+} -+#else -+#define st_alloc_entry() (st_table_entry *)malloc(sizeof(st_table_entry)) -+#define st_free_entry(entry) free(entry) -+#define st_alloc_table() (st_table *)malloc(sizeof(st_table)) -+#define st_dealloc_table(table) free(table) -+#define st_alloc_bins(size) (st_table_entry **)calloc(size, sizeof(st_table_entry *)) -+#define st_free_bins(bins, size) free(bins) -+static inline st_table_entry** -+st_realloc_bins(st_table_entry **bins, st_index_t newsize, st_index_t oldsize) -+{ -+ bins = (st_table_entry **)realloc(bins, newsize * sizeof(st_table_entry *)); -+ MEMZERO(bins, st_table_entry*, newsize); -+ return bins; -+} -+#endif -+ -+/* Shortage */ -+#define bins as.big.bins -+#define head as.big.head -+#define tail as.big.tail -+#define real_entries as.packed.real_entries -+ -+/* preparation for possible packing improvements */ -+#define PACKED_BINS(table) ((table)->as.packed.entries) -+#define PACKED_ENT(table, i) PACKED_BINS(table)[i] -+#define PKEY(table, i) PACKED_ENT((table), (i)).key -+#define PVAL(table, i) PACKED_ENT((table), (i)).val -+#define PHASH(table, i) PACKED_ENT((table), (i)).hash -+#define PKEY_SET(table, i, v) (PKEY((table), (i)) = (v)) -+#define PVAL_SET(table, i, v) (PVAL((table), (i)) = (v)) -+#define PHASH_SET(table, i, v) (PHASH((table), (i)) = (v)) -+ -+/* this function depends much on packed layout, so that it placed here */ -+static inline void -+remove_packed_entry(st_table *table, st_index_t i) -+{ -+ table->real_entries--; -+ table->num_entries--; -+ if (i < table->real_entries) { -+ MEMMOVE(&PACKED_ENT(table, i), &PACKED_ENT(table, i+1), -+ st_packed_entry, table->real_entries - i); -+ } -+} -+ -+static inline void -+remove_safe_packed_entry(st_table *table, st_index_t i, st_data_t never) -+{ -+ table->num_entries--; -+ PKEY_SET(table, i, never); -+ PVAL_SET(table, i, never); -+ PHASH_SET(table, i, 0); -+} -+ -+/* ultrapacking */ -+#define real_upacked num_bins -+#define MAX_UPACKED_HASH 1 -+#define ULTRAPACKED(table) ((table)->real_upacked <= 1) -+#define UPACKED_ENT(table) ((table)->as.upacked) -+#define UPKEY(table) UPACKED_ENT(table).key -+#define UPVAL(table) UPACKED_ENT(table).val -+#define UPHASH(table) UPACKED_ENT(table).hash -+#define UPKEY_SET(table, v) (UPACKED_ENT(table).key = (v)) -+#define UPVAL_SET(table, v) (UPACKED_ENT(table).val = (v)) -+#define UPHASH_SET(table, v) (UPACKED_ENT(table).hash = (v)) -+static inline void -+remove_upacked_entry(st_table *table) -+{ -+ table->real_upacked = table->num_entries = 0; -+} -+ -+static inline void -+remove_safe_upacked_entry(st_table *table, st_data_t never) -+{ -+ table->num_entries = 0; -+ UPKEY_SET(table, never); -+ UPVAL_SET(table, never); -+ UPHASH_SET(table, 0); -+} - /* - * MINSIZE is the minimum size of a dictionary. - */ -@@ -85,8 +204,8 @@ static void rehash(st_table *); - Table of prime numbers 2^n+a, 2<=n<=30. - */ - static const unsigned int primes[] = { -- 8 + 3, -- 16 + 3, -+ ST_DEFAULT_INIT_TABLE_SIZE, -+ ST_DEFAULT_SECOND_TABLE_SIZE, - 32 + 5, - 64 + 3, - 128 + 3, -@@ -161,8 +280,6 @@ stat_col(void) - } - #endif - --#define MAX_PACKED_NUMHASH (ST_DEFAULT_INIT_TABLE_SIZE/2) -- - st_table* - st_init_table_with_size(const struct st_hash_type *type, st_index_t size) - { -@@ -181,14 +298,19 @@ st_init_table_with_size(const struct st_hash_type *type, st_index_t size) - } - #endif - -- size = new_size(size); /* round up to prime number */ - -- tbl = alloc(st_table); -+ tbl = st_alloc_table(); - tbl->type = type; - tbl->num_entries = 0; -- tbl->entries_packed = type == &type_numhash && size/2 <= MAX_PACKED_NUMHASH; -+ tbl->entries_packed = size <= MAX_PACKED_HASH; -+ if (tbl->entries_packed) { -+ size = size <= MAX_UPACKED_HASH ? 0 : ST_DEFAULT_PACKED_TABLE_SIZE; -+ } -+ else { -+ size = new_size(size); /* round up to prime number */ -+ } - tbl->num_bins = size; -- tbl->bins = (st_table_entry **)Calloc(size, sizeof(st_table_entry*)); -+ tbl->bins = size ? st_alloc_bins(size) : 0; - tbl->head = 0; - tbl->tail = 0; - -@@ -243,17 +365,23 @@ st_clear(st_table *table) - register st_table_entry *ptr, *next; - st_index_t i; - -+ if (ULTRAPACKED(table)) { -+ remove_upacked_entry(table); -+ return; -+ } -+ - if (table->entries_packed) { - table->num_entries = 0; -+ table->real_entries = 0; - return; - } - -- for(i = 0; i < table->num_bins; i++) { -+ for (i = 0; i < table->num_bins; i++) { - ptr = table->bins[i]; - table->bins[i] = 0; - while (ptr != 0) { - next = ptr->next; -- free(ptr); -+ st_free_entry(ptr); - ptr = next; - } - } -@@ -266,14 +394,19 @@ void - st_free_table(st_table *table) - { - st_clear(table); -- free(table->bins); -- free(table); -+ if (!ULTRAPACKED(table)) { -+ st_free_bins(table->bins, table->num_bins); -+ } -+ st_dealloc_table(table); - } - - size_t - st_memsize(const st_table *table) - { -- if (table->entries_packed) { -+ if (ULTRAPACKED(table)) { -+ return sizeof(st_table); -+ } -+ else if (table->entries_packed) { - return table->num_bins * sizeof (void *) + sizeof(st_table); - } - else { -@@ -306,46 +439,77 @@ count_collision(const struct st_hash_type *type) - #define FOUND_ENTRY - #endif - --#define FIND_ENTRY(table, ptr, hash_val, bin_pos) do {\ -- (bin_pos) = (hash_val)%(table)->num_bins;\ -- (ptr) = (table)->bins[(bin_pos)];\ -- FOUND_ENTRY;\ -- if (PTR_NOT_EQUAL((table), (ptr), (hash_val), key)) {\ -- COLLISION;\ -- while (PTR_NOT_EQUAL((table), (ptr)->next, (hash_val), key)) {\ -- (ptr) = (ptr)->next;\ -- }\ -- (ptr) = (ptr)->next;\ -- }\ --} while (0) -+#define FIND_ENTRY(table, ptr, hash_val, bin_pos) \ -+ ((ptr) = find_entry((table), key, (hash_val), ((bin_pos) = (hash_val)%(table)->num_bins))) -+ -+static st_table_entry * -+find_entry(st_table *table, st_data_t key, st_index_t hash_val, st_index_t bin_pos) -+{ -+ register st_table_entry *ptr = table->bins[bin_pos]; -+ FOUND_ENTRY; -+ if (PTR_NOT_EQUAL(table, ptr, hash_val, key)) { -+ COLLISION; -+ while (PTR_NOT_EQUAL(table, ptr->next, hash_val, key)) { -+ ptr = ptr->next; -+ } -+ ptr = ptr->next; -+ } -+ return ptr; -+} -+ -+static inline st_index_t -+find_packed_index(st_table *table, st_index_t hash_val, st_data_t key) -+{ -+ st_index_t i = 0; -+ while (i < table->real_entries && -+ (PHASH(table, i) != hash_val || !EQUAL(table, key, PKEY(table, i)))) { -+ i++; -+ } -+ return i; -+} -+ -+static inline int -+check_upacked(st_table *table, st_index_t hash_val, st_data_t key) -+{ -+ return table->num_entries && -+ UPHASH(table) == hash_val && -+ EQUAL(table, key, UPKEY(table)); -+} - - #define collision_check 0 - - int - st_lookup(st_table *table, register st_data_t key, st_data_t *value) - { -- st_index_t hash_val, bin_pos; -+ st_index_t hash_val; - register st_table_entry *ptr; - -+ hash_val = do_hash(key, table); -+ -+ if (ULTRAPACKED(table)) { -+ if (check_upacked(table, hash_val, key)) { -+ if (value != 0) *value = UPVAL(table); -+ return 1; -+ } -+ return 0; -+ } -+ - if (table->entries_packed) { -- st_index_t i; -- for (i = 0; i < table->num_entries; i++) { -- if ((st_data_t)table->bins[i*2] == key) { -- if (value !=0) *value = (st_data_t)table->bins[i*2+1]; -- return 1; -- } -- } -+ st_index_t i = find_packed_index(table, hash_val, key); -+ if (i < table->real_entries) { -+ if (value != 0) *value = PVAL(table, i); -+ return 1; -+ } - return 0; - } - -- hash_val = do_hash(key, table); -- FIND_ENTRY(table, ptr, hash_val, bin_pos); -+ ptr = find_entry(table, key, hash_val, hash_val % table->num_bins); - - if (ptr == 0) { - return 0; - } - else { -- if (value != 0) *value = ptr->record; -+ if (value != 0) *value = ptr->record; - return 1; - } - } -@@ -353,22 +517,29 @@ st_lookup(st_table *table, register st_data_t key, st_data_t *value) - int - st_get_key(st_table *table, register st_data_t key, st_data_t *result) - { -- st_index_t hash_val, bin_pos; -+ st_index_t hash_val; - register st_table_entry *ptr; - -+ hash_val = do_hash(key, table); -+ -+ if (ULTRAPACKED(table)) { -+ if (check_upacked(table, hash_val, key)) { -+ if (result != 0) *result = UPKEY(table); -+ return 1; -+ } -+ return 0; -+ } -+ - if (table->entries_packed) { -- st_index_t i; -- for (i = 0; i < table->num_entries; i++) { -- if ((st_data_t)table->bins[i*2] == key) { -- if (result !=0) *result = (st_data_t)table->bins[i*2]; -- return 1; -- } -- } -+ st_index_t i = find_packed_index(table, hash_val, key); -+ if (i < table->real_entries) { -+ if (result != 0) *result = PKEY(table, i); -+ return 1; -+ } - return 0; - } - -- hash_val = do_hash(key, table); -- FIND_ENTRY(table, ptr, hash_val, bin_pos); -+ ptr = find_entry(table, key, hash_val, hash_val % table->num_bins); - - if (ptr == 0) { - return 0; -@@ -382,85 +553,151 @@ st_get_key(st_table *table, register st_data_t key, st_data_t *result) - #undef collision_check - #define collision_check 1 - --#define MORE_PACKABLE_P(table) \ -- ((st_index_t)((table)->num_entries+1) * 2 <= (table)->num_bins && \ -- (table)->num_entries+1 <= MAX_PACKED_NUMHASH) -- --#define ADD_DIRECT(table, key, value, hash_val, bin_pos)\ --do {\ -- st_table_entry *entry;\ -- if ((table)->num_entries > ST_DEFAULT_MAX_DENSITY * (table)->num_bins) {\ -- rehash(table);\ -- (bin_pos) = (hash_val) % (table)->num_bins;\ -- }\ -- \ -- entry = alloc(st_table_entry);\ -- \ -- entry->hash = (hash_val);\ -- entry->key = (key);\ -- entry->record = (value);\ -- entry->next = (table)->bins[(bin_pos)];\ -- if ((table)->head != 0) {\ -- entry->fore = 0;\ -- (entry->back = (table)->tail)->fore = entry;\ -- (table)->tail = entry;\ -- }\ -- else {\ -- (table)->head = (table)->tail = entry;\ -- entry->fore = entry->back = 0;\ -- }\ -- (table)->bins[(bin_pos)] = entry;\ -- (table)->num_entries++;\ --} while (0) -+static inline st_table_entry * -+new_entry(st_table * table, st_data_t key, st_data_t value, -+ st_index_t hash_val, register st_index_t bin_pos) -+{ -+ register st_table_entry *entry = st_alloc_entry(); -+ -+ entry->next = table->bins[bin_pos]; -+ table->bins[bin_pos] = entry; -+ entry->hash = hash_val; -+ entry->key = key; -+ entry->record = value; -+ -+ return entry; -+} -+ -+static inline void -+add_direct(st_table *table, st_data_t key, st_data_t value, -+ st_index_t hash_val, register st_index_t bin_pos) -+{ -+ register st_table_entry *entry; -+ if (table->num_entries > ST_DEFAULT_MAX_DENSITY * table->num_bins) { -+ rehash(table); -+ bin_pos = hash_val % table->num_bins; -+ } -+ -+ entry = new_entry(table, key, value, hash_val, bin_pos); -+ -+ if (table->head != 0) { -+ entry->fore = 0; -+ (entry->back = table->tail)->fore = entry; -+ table->tail = entry; -+ } -+ else { -+ table->head = table->tail = entry; -+ entry->fore = entry->back = 0; -+ } -+ table->num_entries++; -+} - - static void - unpack_entries(register st_table *table) - { - st_index_t i; -- struct st_table_entry *packed_bins[MAX_PACKED_NUMHASH*2]; -+ st_packed_entry packed_bins[MAX_PACKED_HASH]; -+ register st_table_entry *entry, *preventry = 0, **chain; - st_table tmp_table = *table; - -- memcpy(packed_bins, table->bins, sizeof(struct st_table_entry *) * table->num_entries*2); -- table->bins = packed_bins; -+ MEMCPY(packed_bins, PACKED_BINS(table), st_packed_entry, MAX_PACKED_HASH); -+ table->as.packed.entries = packed_bins; - tmp_table.entries_packed = 0; -- tmp_table.num_entries = 0; -- memset(tmp_table.bins, 0, sizeof(struct st_table_entry *) * tmp_table.num_bins); -- for (i = 0; i < table->num_entries; i++) { -- st_insert(&tmp_table, (st_data_t)packed_bins[i*2], (st_data_t)packed_bins[i*2+1]); -- } -+#if ST_DEFAULT_INIT_TABLE_SIZE == ST_DEFAULT_PACKED_TABLE_SIZE -+ MEMZERO(tmp_table.bins, st_table_entry*, tmp_table.num_bins); -+#else -+ tmp_table.bins = st_realloc_bins(tmp_table.bins, ST_DEFAULT_INIT_TABLE_SIZE, tmp_table.num_bins); -+ tmp_table.num_bins = ST_DEFAULT_INIT_TABLE_SIZE; -+#endif -+ i = 0; -+ chain = &tmp_table.head; -+ do { -+ st_data_t key = packed_bins[i].key; -+ st_data_t val = packed_bins[i].val; -+ st_index_t hash = packed_bins[i].hash; -+ entry = new_entry(&tmp_table, key, val, hash, -+ hash % ST_DEFAULT_INIT_TABLE_SIZE); -+ *chain = entry; -+ entry->back = preventry; -+ preventry = entry; -+ chain = &entry->fore; -+ } while (++i < MAX_PACKED_HASH); -+ *chain = NULL; -+ tmp_table.tail = entry; - *table = tmp_table; - } - -+static void -+add_packed_direct(st_table *table, st_data_t key, st_data_t value, st_index_t hash_val) -+{ -+ if (table->real_entries < MAX_PACKED_HASH) { -+ st_index_t i = table->real_entries++; -+ PKEY_SET(table, i, key); -+ PVAL_SET(table, i, value); -+ PHASH_SET(table, i, hash_val); -+ table->num_entries++; -+ } -+ else { -+ unpack_entries(table); -+ add_direct(table, key, value, hash_val, hash_val % table->num_bins); -+ } -+} -+ -+static void -+add_upacked_direct(register st_table *table, register st_data_t key, st_data_t value, st_index_t hash_val) -+{ -+ if (table->real_upacked) { -+ st_packed_entry *entries = (st_packed_entry *) st_alloc_bins(ST_DEFAULT_PACKED_TABLE_SIZE); -+ entries[0] = UPACKED_ENT(table); -+ entries[1].hash = hash_val; -+ entries[1].key = key; -+ entries[1].val = value; -+ table->num_bins = ST_DEFAULT_PACKED_TABLE_SIZE; -+ table->real_entries = 2; -+ table->num_entries++; -+ table->as.packed.entries = entries; -+ } -+ else { -+ table->real_upacked = 1; -+ table->num_entries = 1; -+ UPHASH_SET(table, hash_val); -+ UPKEY_SET(table, key); -+ UPVAL_SET(table, value); -+ } -+} -+ - int - st_insert(register st_table *table, register st_data_t key, st_data_t value) - { -- st_index_t hash_val, bin_pos; -+ st_index_t hash_val; -+ register st_index_t bin_pos; - register st_table_entry *ptr; - -+ hash_val = do_hash(key, table); -+ -+ if (ULTRAPACKED(table)) { -+ if (check_upacked(table, hash_val, key)) { -+ UPVAL_SET(table, value); -+ return 1; -+ } -+ add_upacked_direct(table, key, value, hash_val); -+ return 0; -+ } -+ - if (table->entries_packed) { -- st_index_t i; -- for (i = 0; i < table->num_entries; i++) { -- if ((st_data_t)table->bins[i*2] == key) { -- table->bins[i*2+1] = (struct st_table_entry*)value; -- return 1; -- } -- } -- if (MORE_PACKABLE_P(table)) { -- i = table->num_entries++; -- table->bins[i*2] = (struct st_table_entry*)key; -- table->bins[i*2+1] = (struct st_table_entry*)value; -- return 0; -- } -- else { -- unpack_entries(table); -+ st_index_t i = find_packed_index(table, hash_val, key); -+ if (i < table->real_entries) { -+ PVAL_SET(table, i, value); -+ return 1; - } -+ add_packed_direct(table, key, value, hash_val); -+ return 0; - } - -- hash_val = do_hash(key, table); - FIND_ENTRY(table, ptr, hash_val, bin_pos); - - if (ptr == 0) { -- ADD_DIRECT(table, key, value, hash_val, bin_pos); -+ add_direct(table, key, value, hash_val, bin_pos); - return 0; - } - else { -@@ -473,34 +710,38 @@ int - st_insert2(register st_table *table, register st_data_t key, st_data_t value, - st_data_t (*func)(st_data_t)) - { -- st_index_t hash_val, bin_pos; -+ st_index_t hash_val; -+ register st_index_t bin_pos; - register st_table_entry *ptr; - -+ hash_val = do_hash(key, table); -+ -+ if (ULTRAPACKED(table)) { -+ if (check_upacked(table, hash_val, key)) { -+ UPVAL_SET(table, value); -+ return 1; -+ } -+ key = (*func)(key); -+ add_upacked_direct(table, key, value, hash_val); -+ return 0; -+ } -+ - if (table->entries_packed) { -- st_index_t i; -- for (i = 0; i < table->num_entries; i++) { -- if ((st_data_t)table->bins[i*2] == key) { -- table->bins[i*2+1] = (struct st_table_entry*)value; -- return 1; -- } -- } -- if (MORE_PACKABLE_P(table)) { -- i = table->num_entries++; -- table->bins[i*2] = (struct st_table_entry*)key; -- table->bins[i*2+1] = (struct st_table_entry*)value; -- return 0; -- } -- else { -- unpack_entries(table); -- } -+ st_index_t i = find_packed_index(table, hash_val, key); -+ if (i < table->real_entries) { -+ PVAL_SET(table, i, value); -+ return 1; -+ } -+ key = (*func)(key); -+ add_packed_direct(table, key, value, hash_val); -+ return 0; - } - -- hash_val = do_hash(key, table); - FIND_ENTRY(table, ptr, hash_val, bin_pos); - - if (ptr == 0) { - key = (*func)(key); -- ADD_DIRECT(table, key, value, hash_val, bin_pos); -+ add_direct(table, key, value, hash_val, bin_pos); - return 0; - } - else { -@@ -512,36 +753,30 @@ st_insert2(register st_table *table, register st_data_t key, st_data_t value, - void - st_add_direct(st_table *table, st_data_t key, st_data_t value) - { -- st_index_t hash_val, bin_pos; -+ st_index_t hash_val; -+ -+ hash_val = do_hash(key, table); -+ if (ULTRAPACKED(table)) { -+ add_upacked_direct(table, key, value, hash_val); -+ return; -+ } - - if (table->entries_packed) { -- int i; -- if (MORE_PACKABLE_P(table)) { -- i = table->num_entries++; -- table->bins[i*2] = (struct st_table_entry*)key; -- table->bins[i*2+1] = (struct st_table_entry*)value; -- return; -- } -- else { -- unpack_entries(table); -- } -+ add_packed_direct(table, key, value, hash_val); -+ return; - } - -- hash_val = do_hash(key, table); -- bin_pos = hash_val % table->num_bins; -- ADD_DIRECT(table, key, value, hash_val, bin_pos); -+ add_direct(table, key, value, hash_val, hash_val % table->num_bins); - } - - static void - rehash(register st_table *table) - { - register st_table_entry *ptr, **new_bins; -- st_index_t i, new_num_bins, hash_val; -+ st_index_t new_num_bins, hash_val; - - new_num_bins = new_size(table->num_bins+1); -- new_bins = (st_table_entry**) -- xrealloc(table->bins, new_num_bins * sizeof(st_table_entry*)); -- for (i = 0; i < new_num_bins; ++i) new_bins[i] = 0; -+ new_bins = st_realloc_bins(table->bins, new_num_bins, table->num_bins); - table->num_bins = new_num_bins; - table->bins = new_bins; - -@@ -558,34 +793,37 @@ st_table* - st_copy(st_table *old_table) - { - st_table *new_table; -- st_table_entry *ptr, *entry, *prev, **tail; -+ st_table_entry *ptr, *entry, *prev, **tailp; - st_index_t num_bins = old_table->num_bins; - st_index_t hash_val; - -- new_table = alloc(st_table); -+ new_table = st_alloc_table(); - if (new_table == 0) { - return 0; - } - - *new_table = *old_table; -- new_table->bins = (st_table_entry**) -- Calloc((unsigned)num_bins, sizeof(st_table_entry*)); -+ if (ULTRAPACKED(old_table)) { -+ return new_table; -+ } -+ -+ new_table->bins = st_alloc_bins(num_bins); - - if (new_table->bins == 0) { -- free(new_table); -+ st_dealloc_table(new_table); - return 0; - } - - if (old_table->entries_packed) { -- memcpy(new_table->bins, old_table->bins, sizeof(struct st_table_entry *) * old_table->num_bins); -+ MEMCPY(new_table->bins, old_table->bins, st_table_entry*, old_table->num_bins); - return new_table; - } - - if ((ptr = old_table->head) != 0) { - prev = 0; -- tail = &new_table->head; -+ tailp = &new_table->head; - do { -- entry = alloc(st_table_entry); -+ entry = st_alloc_entry(); - if (entry == 0) { - st_free_table(new_table); - return 0; -@@ -595,8 +833,8 @@ st_copy(st_table *old_table) - entry->next = new_table->bins[hash_val]; - new_table->bins[hash_val] = entry; - entry->back = prev; -- *tail = prev = entry; -- tail = &entry->fore; -+ *tailp = prev = entry; -+ tailp = &entry->fore; - } while ((ptr = ptr->fore) != 0); - new_table->tail = prev; - } -@@ -604,21 +842,22 @@ st_copy(st_table *old_table) - return new_table; - } - --#define REMOVE_ENTRY(table, ptr) do \ -- { \ -- if ((ptr)->fore == 0 && (ptr)->back == 0) { \ -- (table)->head = 0; \ -- (table)->tail = 0; \ -- } \ -- else { \ -- st_table_entry *fore = (ptr)->fore, *back = (ptr)->back; \ -- if (fore) fore->back = back; \ -- if (back) back->fore = fore; \ -- if ((ptr) == (table)->head) (table)->head = fore; \ -- if ((ptr) == (table)->tail) (table)->tail = back; \ -- } \ -- (table)->num_entries--; \ -- } while (0) -+static inline void -+remove_entry(st_table *table, st_table_entry *ptr) -+{ -+ if (ptr->fore == 0 && ptr->back == 0) { -+ table->head = 0; -+ table->tail = 0; -+ } -+ else { -+ st_table_entry *fore = ptr->fore, *back = ptr->back; -+ if (fore) fore->back = back; -+ if (back) back->fore = fore; -+ if (ptr == table->head) table->head = fore; -+ if (ptr == table->tail) table->tail = back; -+ } -+ table->num_entries--; -+} - - int - st_delete(register st_table *table, register st_data_t *key, st_data_t *value) -@@ -627,30 +866,38 @@ st_delete(register st_table *table, register st_data_t *key, st_data_t *value) - st_table_entry **prev; - register st_table_entry *ptr; - -+ hash_val = do_hash(*key, table); -+ -+ if (ULTRAPACKED(table)) { -+ if (check_upacked(table, hash_val, *key)) { -+ if (value != 0) *value = UPVAL(table); -+ *key = UPKEY(table); -+ remove_upacked_entry(table); -+ return 1; -+ } -+ return 0; -+ } -+ - if (table->entries_packed) { -- st_index_t i; -- for (i = 0; i < table->num_entries; i++) { -- if ((st_data_t)table->bins[i*2] == *key) { -- if (value != 0) *value = (st_data_t)table->bins[i*2+1]; -- table->num_entries--; -- memmove(&table->bins[i*2], &table->bins[(i+1)*2], -- sizeof(struct st_table_entry*) * 2*(table->num_entries-i)); -- return 1; -- } -+ st_index_t i = find_packed_index(table, hash_val, *key); -+ if (i < table->real_entries) { -+ if (value != 0) *value = PVAL(table, i); -+ *key = PKEY(table, i); -+ remove_packed_entry(table, i); -+ return 1; - } - if (value != 0) *value = 0; - return 0; - } - -- hash_val = do_hash_bin(*key, table); -- -- for (prev = &table->bins[hash_val]; (ptr = *prev) != 0; prev = &ptr->next) { -+ prev = &table->bins[hash_val % table->num_bins]; -+ for (;(ptr = *prev) != 0; prev = &ptr->next) { - if (EQUAL(table, *key, ptr->key)) { - *prev = ptr->next; -- REMOVE_ENTRY(table, ptr); -+ remove_entry(table, ptr); - if (value != 0) *value = ptr->record; - *key = ptr->key; -- free(ptr); -+ st_free_entry(ptr); - return 1; - } - } -@@ -665,25 +912,36 @@ st_delete_safe(register st_table *table, register st_data_t *key, st_data_t *val - st_index_t hash_val; - register st_table_entry *ptr; - -+ hash_val = do_hash(*key, table); -+ -+ if (ULTRAPACKED(table)) { -+ if (check_upacked(table, hash_val, *key)) { -+ if (value != 0) *value = UPVAL(table); -+ *key = UPKEY(table); -+ remove_safe_upacked_entry(table, never); -+ return 1; -+ } -+ if (value != 0) *value = 0; -+ return 0; -+ } -+ - if (table->entries_packed) { -- st_index_t i; -- for (i = 0; i < table->num_entries; i++) { -- if ((st_data_t)table->bins[i*2] == *key) { -- if (value != 0) *value = (st_data_t)table->bins[i*2+1]; -- table->bins[i*2] = (void *)never; -- return 1; -- } -+ st_index_t i = find_packed_index(table, hash_val, *key); -+ if (i < table->real_entries) { -+ if (value != 0) *value = PVAL(table, i); -+ *key = PKEY(table, i); -+ remove_safe_packed_entry(table, i, never); -+ return 1; - } - if (value != 0) *value = 0; - return 0; - } - -- hash_val = do_hash_bin(*key, table); -- ptr = table->bins[hash_val]; -+ ptr = table->bins[hash_val % table->num_bins]; - - for (; ptr != 0; ptr = ptr->next) { - if ((ptr->key != never) && EQUAL(table, ptr->key, *key)) { -- REMOVE_ENTRY(table, ptr); -+ remove_entry(table, ptr); - *key = ptr->key; - if (value != 0) *value = ptr->record; - ptr->key = ptr->record = never; -@@ -701,17 +959,23 @@ st_cleanup_safe(st_table *table, st_data_t never) - st_table_entry *ptr, **last, *tmp; - st_index_t i; - -+ if (ULTRAPACKED(table)) { -+ table->real_upacked = table->num_entries; -+ return; -+ } -+ - if (table->entries_packed) { - st_index_t i = 0, j = 0; -- while ((st_data_t)table->bins[i*2] != never) { -- if (i++ == table->num_entries) return; -+ while (PKEY(table, i) != never) { -+ if (i++ == table->real_entries) return; - } -- for (j = i; ++i < table->num_entries;) { -- if ((st_data_t)table->bins[i*2] == never) continue; -- table->bins[j*2] = table->bins[i*2]; -- table->bins[j*2+1] = table->bins[i*2+1]; -+ for (j = i; ++i < table->real_entries;) { -+ if (PKEY(table, i) == never) continue; -+ PACKED_ENT(table, j) = PACKED_ENT(table, i); - j++; - } -+ table->real_entries = j; -+ /* table->num_entries really should be equal j at this moment, but let set it anyway */ - table->num_entries = j; - return; - } -@@ -722,7 +986,7 @@ st_cleanup_safe(st_table *table, st_data_t never) - if (ptr->key == never) { - tmp = ptr; - *last = ptr = ptr->next; -- free(tmp); -+ st_free_entry(tmp); - } - else { - ptr = *(last = &ptr->next); -@@ -732,50 +996,78 @@ st_cleanup_safe(st_table *table, st_data_t never) - } - - int --st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) -+st_foreach_check(st_table *table, int (*func)(ANYARGS), st_data_t arg, st_data_t never) - { - st_table_entry *ptr, **last, *tmp; - enum st_retval retval; -- st_index_t i; -+ st_data_t key, val; -+ st_index_t hash, i = 0; -+ -+ if (table->num_entries == 0) { -+ return 0; -+ } -+ -+ if (ULTRAPACKED(table)) { -+ key = UPKEY(table); -+ val = UPVAL(table); -+ hash = UPHASH(table); -+ if (key == never) return 0; -+ retval = (*func)(key, val, arg); -+ if (!ULTRAPACKED(table)) { -+ goto packed; -+ } -+ switch(retval) { -+ case ST_CHECK: -+ if (UPHASH(table) == 0 && UPKEY(table) == never) -+ break; -+ if (check_upacked(table, hash, key)) -+ break; -+ goto deleted; -+ case ST_DELETE: -+ remove_safe_upacked_entry(table, never); -+ case ST_CONTINUE: -+ case ST_STOP: -+ break; -+ } -+ return 0; -+ } - - if (table->entries_packed) { -- for (i = 0; i < table->num_entries; i++) { -- st_index_t j; -- st_data_t key, val; -- key = (st_data_t)table->bins[i*2]; -- val = (st_data_t)table->bins[i*2+1]; -- retval = (*func)(key, val, arg); -+ for (i = 0; i < table->real_entries; i++) { -+ key = PKEY(table, i); -+ val = PVAL(table, i); -+ hash = PHASH(table, i); -+ if (key == never) continue; -+ retval = (*func)(key, val, arg); -+ packed: - if (!table->entries_packed) { -- FIND_ENTRY(table, ptr, key, i); -+ FIND_ENTRY(table, ptr, hash, i); - if (retval == ST_CHECK) { - if (!ptr) goto deleted; - goto unpacked_continue; - } - goto unpacked; - } -- switch (retval) { -+ switch (retval) { - case ST_CHECK: /* check if hash is modified during iteration */ -- for (j = 0; j < table->num_entries; j++) { -- if ((st_data_t)table->bins[j*2] == key) -- break; -- } -- if (j == table->num_entries) { -+ if (PHASH(table, i) == 0 && PKEY(table, i) == never) { -+ break; -+ } -+ i = find_packed_index(table, hash, key); -+ if (i == table->real_entries) { - goto deleted; -- } -+ } - /* fall through */ - case ST_CONTINUE: - break; - case ST_STOP: - return 0; - case ST_DELETE: -- table->num_entries--; -- memmove(&table->bins[i*2], &table->bins[(i+1)*2], -- sizeof(struct st_table_entry*) * 2*(table->num_entries-i)); -- i--; -- break; -- } -- } -- return 0; -+ remove_safe_packed_entry(table, i, never); -+ break; -+ } -+ } -+ return 0; - } - else { - ptr = table->head; -@@ -783,6 +1075,8 @@ st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) - - if (ptr != 0) { - do { -+ if (ptr->key == never) -+ goto unpacked_continue; - i = ptr->hash % table->num_bins; - retval = (*func)(ptr->key, ptr->record, arg); - unpacked: -@@ -808,10 +1102,100 @@ st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) - for (; (tmp = *last) != 0; last = &tmp->next) { - if (ptr == tmp) { - tmp = ptr->fore; -+ remove_entry(table, ptr); -+ ptr->key = ptr->record = never; -+ ptr->hash = 0; -+ ptr = tmp; -+ break; -+ } -+ } -+ } -+ } while (ptr && table->head); -+ } -+ return 0; -+} -+ -+int -+st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) -+{ -+ st_table_entry *ptr, **last, *tmp; -+ enum st_retval retval; -+ st_data_t key, val; -+ st_index_t hash, i = 0; -+ -+ if (table->num_entries == 0) { -+ return 0; -+ } -+ -+ if (ULTRAPACKED(table)) { -+ key = UPKEY(table); -+ val = UPVAL(table); -+ hash = UPHASH(table); -+ retval = (*func)(key, val, arg); -+ if (!ULTRAPACKED(table)) { -+ goto packed; -+ } -+ switch (retval) { -+ case ST_DELETE: -+ remove_upacked_entry(table); -+ case ST_CONTINUE: -+ case ST_CHECK: -+ case ST_STOP: -+ break; -+ } -+ return 0; -+ } -+ -+ if (table->entries_packed) { -+ for (i = 0; i < table->real_entries; i++) { -+ key = PKEY(table, i); -+ val = PVAL(table, i); -+ hash = PHASH(table, i); -+ retval = (*func)(key, val, arg); -+ packed: -+ if (!table->entries_packed) { -+ FIND_ENTRY(table, ptr, hash, i); -+ if (!ptr) return 0; -+ goto unpacked; -+ } -+ switch (retval) { -+ case ST_CONTINUE: -+ break; -+ case ST_CHECK: -+ case ST_STOP: -+ return 0; -+ case ST_DELETE: -+ remove_packed_entry(table, i); -+ i--; -+ break; -+ } -+ } -+ return 0; -+ } -+ else { -+ ptr = table->head; -+ } -+ -+ if (ptr != 0) { -+ do { -+ i = ptr->hash % table->num_bins; -+ retval = (*func)(ptr->key, ptr->record, arg); -+ unpacked: -+ switch (retval) { -+ case ST_CONTINUE: -+ ptr = ptr->fore; -+ break; -+ case ST_CHECK: -+ case ST_STOP: -+ return 0; -+ case ST_DELETE: -+ last = &table->bins[ptr->hash % table->num_bins]; -+ for (; (tmp = *last) != 0; last = &tmp->next) { -+ if (ptr == tmp) { -+ tmp = ptr->fore; - *last = ptr->next; -- REMOVE_ENTRY(table, ptr); -- free(ptr); -- if (ptr == tmp) return 0; -+ remove_entry(table, ptr); -+ st_free_entry(ptr); - ptr = tmp; - break; - } -@@ -834,13 +1218,13 @@ st_reverse_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) - for (i = table->num_entries-1; 0 <= i; i--) { - int j; - st_data_t key, val; -- key = (st_data_t)table->bins[i*2]; -- val = (st_data_t)table->bins[i*2+1]; -+ key = PKEY(table, i); -+ val = PVAL(table, i); - retval = (*func)(key, val, arg); - switch (retval) { - case ST_CHECK: /* check if hash is modified during iteration */ - for (j = 0; j < table->num_entries; j++) { -- if ((st_data_t)table->bins[j*2] == key) -+ if (PKEY(table, j) == key) - break; - } - if (j == table->num_entries) { -@@ -854,9 +1238,7 @@ st_reverse_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) - case ST_STOP: - return 0; - case ST_DELETE: -- table->num_entries--; -- memmove(&table->bins[i*2], &table->bins[(i+1)*2], -- sizeof(struct st_table_entry*) * 2*(table->num_entries-i)); -+ remove_packed_entry(table, i); - break; - } - } -@@ -889,8 +1271,8 @@ st_reverse_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) - if (ptr == tmp) { - tmp = ptr->back; - *last = ptr->next; -- REMOVE_ENTRY(table, ptr); -- free(ptr); -+ remove_entry(table, ptr); -+ st_free_entry(ptr); - ptr = tmp; - break; - } diff --git a/patches/ruby/1.9.3/p362/railsexpress/11-falcon-sparse-array.patch b/patches/ruby/1.9.3/p362/railsexpress/11-falcon-sparse-array.patch deleted file mode 100644 index 3bb018ad13..0000000000 --- a/patches/ruby/1.9.3/p362/railsexpress/11-falcon-sparse-array.patch +++ /dev/null @@ -1,2590 +0,0 @@ -diff --git a/class.c b/class.c -index 4fbdf18..50e23e4 100644 ---- a/class.c -+++ b/class.c -@@ -31,7 +31,7 @@ - #include "internal.h" - #include - --extern st_table *rb_class_tbl; -+extern sa_table rb_class_tbl; - static ID id_attached; - - /** -@@ -50,14 +50,24 @@ static VALUE - class_alloc(VALUE flags, VALUE klass) - { - rb_classext_t *ext = ALLOC(rb_classext_t); -+ rb_class_cache_t *cache = ALLOC(rb_class_cache_t); - NEWOBJ(obj, struct RClass); - OBJSETUP(obj, klass, flags); - obj->ptr = ext; -- RCLASS_IV_TBL(obj) = 0; -- RCLASS_CONST_TBL(obj) = 0; -- RCLASS_M_TBL(obj) = 0; -- RCLASS_SUPER(obj) = 0; -- RCLASS_IV_INDEX_TBL(obj) = 0; -+ obj->cache = cache; -+ MEMZERO(ext, struct rb_classext_struct, 1); -+ MEMZERO(cache, struct rb_class_cache_struct, 1); -+ return (VALUE)obj; -+} -+ -+static VALUE -+iclass_alloc() -+{ -+ rb_class_cache_t *cache = ALLOC(rb_class_cache_t); -+ NEWOBJ(obj, struct RClass); -+ OBJSETUP(obj, rb_cClass, T_ICLASS); -+ obj->cache = cache; -+ MEMZERO(cache, struct rb_class_cache_struct, 1); - return (VALUE)obj; - } - -@@ -77,7 +87,6 @@ rb_class_boot(VALUE super) - VALUE klass = class_alloc(T_CLASS, rb_cClass); - - RCLASS_SUPER(klass) = super; -- RCLASS_M_TBL(klass) = st_init_numtable(); - - OBJ_INFECT(klass, super); - return (VALUE)klass; -@@ -120,43 +129,30 @@ rb_class_new(VALUE super) - return rb_class_boot(super); - } - --struct clone_method_data { -- st_table *tbl; -- VALUE klass; --}; -- - VALUE rb_iseq_clone(VALUE iseqval, VALUE newcbase); - --static int --clone_method(ID mid, const rb_method_entry_t *me, struct clone_method_data *data) -+static void -+clone_method(ID mid, const rb_method_entry_t *me, VALUE klass) - { - VALUE newiseqval; - if (me->def && me->def->type == VM_METHOD_TYPE_ISEQ) { - rb_iseq_t *iseq; -- newiseqval = rb_iseq_clone(me->def->body.iseq->self, data->klass); -+ newiseqval = rb_iseq_clone(me->def->body.iseq->self, klass); - GetISeqPtr(newiseqval, iseq); -- rb_add_method(data->klass, mid, VM_METHOD_TYPE_ISEQ, iseq, me->flag); -+ rb_add_method(klass, mid, VM_METHOD_TYPE_ISEQ, iseq, me->flag); - RB_GC_GUARD(newiseqval); - } - else { -- rb_method_entry_set(data->klass, mid, me, me->flag); -+ rb_method_entry_set(klass, mid, me, me->flag); - } -- return ST_CONTINUE; - } - --static int --clone_const(ID key, const rb_const_entry_t *ce, st_table *tbl) -+static void -+clone_const(sa_index_t key, st_data_t ce, sa_table *tbl) - { - rb_const_entry_t *nce = ALLOC(rb_const_entry_t); -- *nce = *ce; -- st_insert(tbl, key, (st_data_t)nce); -- return ST_CONTINUE; --} -- --static int --clone_const_i(st_data_t key, st_data_t value, st_data_t data) --{ -- return clone_const((ID)key, (const rb_const_entry_t *)value, (st_table *)data); -+ *nce = *(const rb_const_entry_t*)ce; -+ sa_insert(tbl, (sa_index_t)key, (st_data_t)nce); - } - - static void -@@ -177,6 +173,7 @@ class_init_copy_check(VALUE clone, VALUE orig) - VALUE - rb_mod_init_copy(VALUE clone, VALUE orig) - { -+ ID id; - if (RB_TYPE_P(clone, T_CLASS)) { - class_init_copy_check(clone, orig); - } -@@ -186,36 +183,22 @@ rb_mod_init_copy(VALUE clone, VALUE orig) - rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone); - } - RCLASS_SUPER(clone) = RCLASS_SUPER(orig); -- if (RCLASS_IV_TBL(orig)) { -- st_data_t id; - -- if (RCLASS_IV_TBL(clone)) { -- st_free_table(RCLASS_IV_TBL(clone)); -- } -- RCLASS_IV_TBL(clone) = st_copy(RCLASS_IV_TBL(orig)); -- CONST_ID(id, "__classpath__"); -- st_delete(RCLASS_IV_TBL(clone), &id, 0); -- CONST_ID(id, "__classid__"); -- st_delete(RCLASS_IV_TBL(clone), &id, 0); -- } -- if (RCLASS_CONST_TBL(orig)) { -- if (RCLASS_CONST_TBL(clone)) { -- rb_free_const_table(RCLASS_CONST_TBL(clone)); -- } -- RCLASS_CONST_TBL(clone) = st_init_numtable(); -- st_foreach(RCLASS_CONST_TBL(orig), clone_const_i, (st_data_t)RCLASS_CONST_TBL(clone)); -- } -- if (RCLASS_M_TBL(orig)) { -- struct clone_method_data data; -+ sa_copy_to(RCLASS_IV_TBL(orig), RCLASS_IV_TBL(clone)); -+ CONST_ID(id, "__classpath__"); -+ sa_delete(RCLASS_IV_TBL(clone), (sa_index_t)id, 0); -+ CONST_ID(id, "__classid__"); -+ sa_delete(RCLASS_IV_TBL(clone), (sa_index_t)id, 0); - -- if (RCLASS_M_TBL(clone)) { -- rb_free_m_table(RCLASS_M_TBL(clone)); -- } -- data.tbl = RCLASS_M_TBL(clone) = st_init_numtable(); -- data.klass = clone; -- st_foreach(RCLASS_M_TBL(orig), clone_method, -- (st_data_t)&data); -- } -+ sa_clear(RCLASS_CONST_TBL(clone)); -+ SA_FOREACH_START(RCLASS_CONST_TBL(orig)); -+ clone_const(entry->key, value, RCLASS_CONST_TBL(clone)); -+ SA_FOREACH_END(); -+ -+ rb_free_m_table(RCLASS_M_TBL(clone)); -+ SA_FOREACH_START(RCLASS_M_TBL(orig)); -+ clone_method(entry->key, (const rb_method_entry_t *)value, clone); -+ SA_FOREACH_END(); - - return clone; - } -@@ -228,7 +211,6 @@ rb_singleton_class_clone(VALUE obj) - if (!FL_TEST(klass, FL_SINGLETON)) - return klass; - else { -- struct clone_method_data data; - /* copy singleton(unnamed) class */ - VALUE clone = class_alloc((RBASIC(klass)->flags & ~(FL_MARK)), 0); - -@@ -240,18 +222,16 @@ rb_singleton_class_clone(VALUE obj) - } - - RCLASS_SUPER(clone) = RCLASS_SUPER(klass); -- if (RCLASS_IV_TBL(klass)) { -- RCLASS_IV_TBL(clone) = st_copy(RCLASS_IV_TBL(klass)); -- } -- if (RCLASS_CONST_TBL(klass)) { -- RCLASS_CONST_TBL(clone) = st_init_numtable(); -- st_foreach(RCLASS_CONST_TBL(klass), clone_const_i, (st_data_t)RCLASS_CONST_TBL(clone)); -- } -- RCLASS_M_TBL(clone) = st_init_numtable(); -- data.tbl = RCLASS_M_TBL(clone); -- data.klass = (VALUE)clone; -- st_foreach(RCLASS_M_TBL(klass), clone_method, -- (st_data_t)&data); -+ sa_copy_to(RCLASS_IV_TBL(klass), RCLASS_IV_TBL(clone)); -+ -+ SA_FOREACH_START(RCLASS_CONST_TBL(klass)); -+ clone_const(entry->key, value, RCLASS_CONST_TBL(clone)); -+ SA_FOREACH_END(); -+ -+ SA_FOREACH_START(RCLASS_M_TBL(klass)); -+ clone_method(entry->key, (const rb_method_entry_t*)value, clone); -+ SA_FOREACH_END(); -+ - rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone); - FL_SET(clone, FL_SINGLETON); - return (VALUE)clone; -@@ -266,10 +246,7 @@ void - rb_singleton_class_attached(VALUE klass, VALUE obj) - { - if (FL_TEST(klass, FL_SINGLETON)) { -- if (!RCLASS_IV_TBL(klass)) { -- RCLASS_IV_TBL(klass) = st_init_numtable(); -- } -- st_insert(RCLASS_IV_TBL(klass), id_attached, obj); -+ sa_insert(RCLASS_IV_TBL(klass), (sa_index_t)id_attached, obj); - } - } - -@@ -356,12 +333,12 @@ make_singleton_class(VALUE obj) - static VALUE - boot_defclass(const char *name, VALUE super) - { -- extern st_table *rb_class_tbl; -+ extern sa_table rb_class_tbl; - VALUE obj = rb_class_boot(super); - ID id = rb_intern(name); - - rb_name_class(obj, id); -- st_add_direct(rb_class_tbl, id, obj); -+ sa_insert(&rb_class_tbl, (sa_index_t)id, obj); - rb_const_set((rb_cObject ? rb_cObject : obj), id, obj); - return obj; - } -@@ -485,7 +462,7 @@ rb_define_class(const char *name, VALUE super) - rb_warn("no super class for `%s', Object assumed", name); - } - klass = rb_define_class_id(id, super); -- st_add_direct(rb_class_tbl, id, klass); -+ sa_insert(&rb_class_tbl, (sa_index_t)id, klass); - rb_name_class(klass, id); - rb_const_set(rb_cObject, id, klass); - rb_class_inherited(super, klass); -@@ -566,8 +543,6 @@ rb_module_new(void) - { - VALUE mdl = class_alloc(T_MODULE, rb_cModule); - -- RCLASS_M_TBL(mdl) = st_init_numtable(); -- - return (VALUE)mdl; - } - -@@ -596,7 +571,7 @@ rb_define_module(const char *name) - rb_raise(rb_eTypeError, "%s is not a module", rb_obj_classname(module)); - } - module = rb_define_module_id(id); -- st_add_direct(rb_class_tbl, id, module); -+ sa_insert(&rb_class_tbl, (sa_index_t)id, module); - rb_const_set(rb_cObject, id, module); - - return module; -@@ -631,27 +606,15 @@ rb_define_module_id_under(VALUE outer, ID id) - static VALUE - include_class_new(VALUE module, VALUE super) - { -- VALUE klass = class_alloc(T_ICLASS, rb_cClass); -+ VALUE klass; - - if (BUILTIN_TYPE(module) == T_ICLASS) { - module = RBASIC(module)->klass; - } -- if (!RCLASS_IV_TBL(module)) { -- RCLASS_IV_TBL(module) = st_init_numtable(); -- } -- if (!RCLASS_CONST_TBL(module)) { -- RCLASS_CONST_TBL(module) = st_init_numtable(); -- } -- RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module); -- RCLASS_CONST_TBL(klass) = RCLASS_CONST_TBL(module); -- RCLASS_M_TBL(klass) = RCLASS_M_TBL(module); -+ klass = iclass_alloc(); -+ RBASIC(klass)->klass = module; -+ RCLASS_EXT(klass) = RCLASS_EXT(module); - RCLASS_SUPER(klass) = super; -- if (TYPE(module) == T_ICLASS) { -- RBASIC(klass)->klass = RBASIC(module)->klass; -- } -- else { -- RBASIC(klass)->klass = module; -- } - OBJ_INFECT(klass, module); - OBJ_INFECT(klass, super); - -@@ -678,13 +641,13 @@ rb_include_module(VALUE klass, VALUE module) - while (module) { - int superclass_seen = FALSE; - -- if (RCLASS_M_TBL(klass) == RCLASS_M_TBL(module)) -+ if (RCLASS_EXT(klass) == RCLASS_EXT(module)) - rb_raise(rb_eArgError, "cyclic include detected"); - /* ignore if the module included already in superclasses */ - for (p = RCLASS_SUPER(klass); p; p = RCLASS_SUPER(p)) { - switch (BUILTIN_TYPE(p)) { - case T_ICLASS: -- if (RCLASS_M_TBL(p) == RCLASS_M_TBL(module)) { -+ if (RCLASS_EXT(p) == RCLASS_EXT(module)) { - if (!superclass_seen) { - c = p; /* move insertion point */ - } -@@ -697,7 +660,7 @@ rb_include_module(VALUE klass, VALUE module) - } - } - c = RCLASS_SUPER(c) = include_class_new(module, RCLASS_SUPER(c)); -- if (RMODULE_M_TBL(module) && RMODULE_M_TBL(module)->num_entries) -+ if (RMODULE_M_TBL(module)->num_entries) - changed = 1; - skip: - module = RCLASS_SUPER(module); -@@ -828,58 +791,58 @@ ins_methods_push(ID name, long type, VALUE ary, long visi) - } - - static int --ins_methods_i(st_data_t name, st_data_t type, st_data_t ary) -+ins_methods_i(sa_index_t name, st_data_t type, st_data_t ary) - { - return ins_methods_push((ID)name, (long)type, (VALUE)ary, -1); /* everything but private */ - } - - static int --ins_methods_prot_i(st_data_t name, st_data_t type, st_data_t ary) -+ins_methods_prot_i(sa_index_t name, st_data_t type, st_data_t ary) - { - return ins_methods_push((ID)name, (long)type, (VALUE)ary, NOEX_PROTECTED); - } - - static int --ins_methods_priv_i(st_data_t name, st_data_t type, st_data_t ary) -+ins_methods_priv_i(sa_index_t name, st_data_t type, st_data_t ary) - { - return ins_methods_push((ID)name, (long)type, (VALUE)ary, NOEX_PRIVATE); - } - - static int --ins_methods_pub_i(st_data_t name, st_data_t type, st_data_t ary) -+ins_methods_pub_i(sa_index_t name, st_data_t type, st_data_t ary) - { - return ins_methods_push((ID)name, (long)type, (VALUE)ary, NOEX_PUBLIC); - } - - static int --method_entry_i(st_data_t key, st_data_t value, st_data_t data) -+method_entry_i(sa_index_t key, st_data_t value, st_data_t data) - { - const rb_method_entry_t *me = (const rb_method_entry_t *)value; -- st_table *list = (st_table *)data; -+ sa_table *list = (sa_table *)data; - long type; - - if ((ID)key == ID_ALLOCATOR) { - return ST_CONTINUE; - } - -- if (!st_lookup(list, key, 0)) { -+ if (!sa_lookup(list, key, 0)) { - if (UNDEFINED_METHOD_ENTRY_P(me)) { - type = -1; /* none */ - } - else { - type = VISI(me->flag); - } -- st_add_direct(list, key, type); -+ sa_insert(list, key, type); - } - return ST_CONTINUE; - } - - static VALUE --class_instance_method_list(int argc, VALUE *argv, VALUE mod, int obj, int (*func) (st_data_t, st_data_t, st_data_t)) -+class_instance_method_list(int argc, VALUE *argv, VALUE mod, int obj, int (*func) (sa_index_t, st_data_t, st_data_t)) - { - VALUE ary; - int recur; -- st_table *list; -+ sa_table list = SA_EMPTY_TABLE; - - if (argc == 0) { - recur = TRUE; -@@ -890,16 +853,15 @@ class_instance_method_list(int argc, VALUE *argv, VALUE mod, int obj, int (*func - recur = RTEST(r); - } - -- list = st_init_numtable(); - for (; mod; mod = RCLASS_SUPER(mod)) { -- st_foreach(RCLASS_M_TBL(mod), method_entry_i, (st_data_t)list); -+ sa_foreach(RCLASS_M_TBL(mod), method_entry_i, (st_data_t)&list); - if (BUILTIN_TYPE(mod) == T_ICLASS) continue; - if (obj && FL_TEST(mod, FL_SINGLETON)) continue; - if (!recur) break; - } - ary = rb_ary_new(); -- st_foreach(list, func, ary); -- st_free_table(list); -+ sa_foreach(&list, func, ary); -+ sa_clear(&list); - - return ary; - } -@@ -1113,7 +1075,7 @@ VALUE - rb_obj_singleton_methods(int argc, VALUE *argv, VALUE obj) - { - VALUE recur, ary, klass; -- st_table *list; -+ sa_table list = SA_EMPTY_TABLE; - - if (argc == 0) { - recur = Qtrue; -@@ -1122,20 +1084,19 @@ rb_obj_singleton_methods(int argc, VALUE *argv, VALUE obj) - rb_scan_args(argc, argv, "01", &recur); - } - klass = CLASS_OF(obj); -- list = st_init_numtable(); - if (klass && FL_TEST(klass, FL_SINGLETON)) { -- st_foreach(RCLASS_M_TBL(klass), method_entry_i, (st_data_t)list); -+ sa_foreach(RCLASS_M_TBL(klass), method_entry_i, (st_data_t)&list); - klass = RCLASS_SUPER(klass); - } - if (RTEST(recur)) { - while (klass && (FL_TEST(klass, FL_SINGLETON) || TYPE(klass) == T_ICLASS)) { -- st_foreach(RCLASS_M_TBL(klass), method_entry_i, (st_data_t)list); -+ sa_foreach(RCLASS_M_TBL(klass), method_entry_i, (st_data_t)&list); - klass = RCLASS_SUPER(klass); - } - } - ary = rb_ary_new(); -- st_foreach(list, ins_methods_i, ary); -- st_free_table(list); -+ sa_foreach(&list, ins_methods_i, ary); -+ sa_clear(&list); - - return ary; - } -diff --git a/common.mk b/common.mk -index 1d8e442..0d767ab 100644 ---- a/common.mk -+++ b/common.mk -@@ -79,6 +79,7 @@ COMMONOBJS = array.$(OBJEXT) \ - safe.$(OBJEXT) \ - signal.$(OBJEXT) \ - sprintf.$(OBJEXT) \ -+ sp_ar.$(OBJEXT) \ - st.$(OBJEXT) \ - strftime.$(OBJEXT) \ - string.$(OBJEXT) \ -@@ -703,6 +704,7 @@ signal.$(OBJEXT): {$(VPATH)}signal.c $(RUBY_H_INCLUDES) \ - $(VM_CORE_H_INCLUDES) {$(VPATH)}debug.h - sprintf.$(OBJEXT): {$(VPATH)}sprintf.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \ - {$(VPATH)}regex.h {$(VPATH)}vsnprintf.c $(ENCODING_H_INCLUDES) -+sp_ar.$(OBJEXT): {$(VPATH)}sp_ar.c $(RUBY_H_INCLUDES) - st.$(OBJEXT): {$(VPATH)}st.c $(RUBY_H_INCLUDES) {$(VPATH)}pool_alloc.h - strftime.$(OBJEXT): {$(VPATH)}strftime.c $(RUBY_H_INCLUDES) \ - {$(VPATH)}timev.h -diff --git a/constant.h b/constant.h -index 8232910..9106847 100644 ---- a/constant.h -+++ b/constant.h -@@ -23,7 +23,7 @@ typedef struct rb_const_entry_struct { - - VALUE rb_mod_private_constant(int argc, VALUE *argv, VALUE obj); - VALUE rb_mod_public_constant(int argc, VALUE *argv, VALUE obj); --void rb_free_const_table(st_table *tbl); -+void rb_free_const_table(sa_table *tbl); - VALUE rb_public_const_get(VALUE klass, ID id); - VALUE rb_public_const_get_at(VALUE klass, ID id); - VALUE rb_public_const_get_from(VALUE klass, ID id); -diff --git a/ext/objspace/objspace.c b/ext/objspace/objspace.c -index 66e33a3..4b31f92 100644 ---- a/ext/objspace/objspace.c -+++ b/ext/objspace/objspace.c -@@ -60,20 +60,10 @@ memsize_of(VALUE obj) - break; - case T_MODULE: - case T_CLASS: -- size += st_memsize(RCLASS_M_TBL(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); -+ size += sa_memsize(RCLASS_M_TBL(obj)); -+ size += sa_memsize(RCLASS_IV_TBL(obj)); -+ size += sa_memsize(RCLASS_IV_INDEX_TBL(obj)); -+ size += sa_memsize(RCLASS_CONST_TBL(obj)); - break; - case T_STRING: - size += rb_str_memsize(obj); -diff --git a/gc.c b/gc.c -index 7f78316..95875da 100644 ---- a/gc.c -+++ b/gc.c -@@ -688,7 +688,7 @@ rb_objspace_free(rb_objspace_t *objspace) - - #define HEAP_OBJ_LIMIT (unsigned int)(HEAP_SIZE / sizeof(struct RVALUE)) - --extern st_table *rb_class_tbl; -+extern sa_table rb_class_tbl; - - int ruby_disable_gc_stress = 0; - -@@ -2352,6 +2352,15 @@ mark_tbl(rb_objspace_t *objspace, st_table *tbl) - st_foreach(tbl, mark_entry, (st_data_t)&arg); - } - -+static void -+mark_sa_tbl(rb_objspace_t *objspace, sa_table *tbl) -+{ -+ if (!tbl) return; -+ SA_FOREACH_START(tbl); -+ gc_mark(objspace, (VALUE)value); -+ SA_FOREACH_END(); -+} -+ - static int - mark_key(VALUE key, VALUE value, st_data_t data) - { -@@ -2428,74 +2437,52 @@ rb_mark_method_entry(const rb_method_entry_t *me) - mark_method_entry(&rb_objspace, me); - } - --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; -- mark_method_entry(arg->objspace, me); -- return ST_CONTINUE; --} -- - static void --mark_m_tbl(rb_objspace_t *objspace, st_table *tbl) --{ -- struct mark_tbl_arg arg; -- if (!tbl) return; -- arg.objspace = objspace; -- st_foreach(tbl, mark_method_entry_i, (st_data_t)&arg); --} -- --static int --free_method_entry_i(ID key, rb_method_entry_t *me, st_data_t data) -+mark_m_tbl(rb_objspace_t *objspace, sa_table *tbl) - { -- if (!me->mark) { -- rb_free_method_entry(me); -- } -- return ST_CONTINUE; -+ SA_FOREACH_START(tbl); -+ mark_method_entry(objspace, (const rb_method_entry_t*)value); -+ SA_FOREACH_END(); - } - - void --rb_free_m_table(st_table *tbl) -+rb_free_m_table(sa_table *tbl) - { -- st_foreach(tbl, free_method_entry_i, 0); -- st_free_table(tbl); --} -- --static int --mark_const_entry_i(ID key, const rb_const_entry_t *ce, st_data_t data) --{ -- struct mark_tbl_arg *arg = (void*)data; -- gc_mark(arg->objspace, ce->value); -- return ST_CONTINUE; -+ SA_FOREACH_START(tbl); -+ if (!((rb_method_entry_t*)value)->mark) { -+ rb_free_method_entry((rb_method_entry_t*)value); -+ } -+ SA_FOREACH_END(); -+ sa_clear(tbl); - } - - static void --mark_const_tbl(rb_objspace_t *objspace, st_table *tbl) -+mark_const_tbl(rb_objspace_t *objspace, sa_table *tbl) - { -- struct mark_tbl_arg arg; -- if (!tbl) return; -- arg.objspace = objspace; -- st_foreach(tbl, mark_const_entry_i, (st_data_t)&arg); -+ SA_FOREACH_START(tbl); -+ gc_mark(objspace, ((const rb_const_entry_t*)value)->value); -+ SA_FOREACH_END(); - } - --static int --free_const_entry_i(ID key, rb_const_entry_t *ce, st_data_t data) -+void -+rb_free_const_table(sa_table *tbl) - { -- xfree(ce); -- return ST_CONTINUE; -+ SA_FOREACH_START(tbl); -+ xfree((rb_const_entry_t*)value); -+ SA_FOREACH_END(); -+ sa_clear(tbl); - } - - void --rb_free_const_table(st_table *tbl) -+rb_mark_tbl(st_table *tbl) - { -- st_foreach(tbl, free_const_entry_i, 0); -- st_free_table(tbl); -+ mark_tbl(&rb_objspace, tbl); - } - - void --rb_mark_tbl(st_table *tbl) -+rb_mark_sa_tbl(sa_table *tbl) - { -- mark_tbl(&rb_objspace, tbl); -+ mark_sa_tbl(&rb_objspace, tbl); - } - - void -@@ -2703,7 +2690,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr) - case T_CLASS: - case T_MODULE: - mark_m_tbl(objspace, RCLASS_M_TBL(obj)); -- mark_tbl(objspace, RCLASS_IV_TBL(obj)); -+ mark_sa_tbl(objspace, RCLASS_IV_TBL(obj)); - mark_const_tbl(objspace, RCLASS_CONST_TBL(obj)); - ptr = RCLASS_SUPER(obj); - goto again; -@@ -3278,15 +3265,11 @@ obj_free(rb_objspace_t *objspace, VALUE obj) - case T_CLASS: - rb_clear_cache_by_class((VALUE)obj); - rb_free_m_table(RCLASS_M_TBL(obj)); -- 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)); -- } -+ sa_clear(RCLASS_IV_TBL(obj)); -+ rb_free_const_table(RCLASS_CONST_TBL(obj)); -+ sa_clear(RCLASS_IV_INDEX_TBL(obj)); -+ sa_clear(&RCLASS(obj)->cache->m_cache_tbl); -+ xfree(RCLASS(obj)->cache); - xfree(RANY(obj)->as.klass.ptr); - break; - case T_STRING: -@@ -3338,8 +3321,9 @@ obj_free(rb_objspace_t *objspace, VALUE obj) - case T_COMPLEX: - break; - case T_ICLASS: -+ sa_clear(&RCLASS(obj)->cache->m_cache_tbl); -+ xfree(RCLASS(obj)->cache); - /* iClass shares table with the module */ -- xfree(RANY(obj)->as.klass.ptr); - break; - - case T_FLOAT: -@@ -3454,7 +3438,7 @@ gc_marks(rb_objspace_t *objspace) - rb_mark_end_proc(); - rb_gc_mark_global_tbl(); - -- mark_tbl(objspace, rb_class_tbl); -+ mark_sa_tbl(objspace, &rb_class_tbl); - - /* mark generic instance variables for special constants */ - rb_mark_generic_ivar_tbl(); -diff --git a/include/ruby/intern.h b/include/ruby/intern.h -index ab1cc94..53ca8b0 100644 ---- a/include/ruby/intern.h -+++ b/include/ruby/intern.h -@@ -415,6 +415,7 @@ size_t ruby_stack_length(VALUE**); - int rb_during_gc(void); - void rb_gc_mark_locations(VALUE*, VALUE*); - void rb_mark_tbl(struct st_table*); -+void rb_mark_sa_tbl(sa_table*); - void rb_mark_set(struct st_table*); - void rb_mark_hash(struct st_table*); - void rb_gc_mark_maybe(VALUE); -@@ -848,7 +849,7 @@ VALUE rb_f_trace_var(int, VALUE*); - VALUE rb_f_untrace_var(int, VALUE*); - VALUE rb_f_global_variables(void); - void rb_alias_variable(ID, ID); --struct st_table* rb_generic_ivar_table(VALUE); -+sa_table* rb_generic_ivar_table(VALUE); - void rb_copy_generic_ivar(VALUE,VALUE); - void rb_mark_generic_ivar(VALUE); - void rb_mark_generic_ivar_tbl(void); -diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h -index 2f97b33..1c84e14 100644 ---- a/include/ruby/ruby.h -+++ b/include/ruby/ruby.h -@@ -605,7 +605,7 @@ struct RObject { - struct { - long numiv; - VALUE *ivptr; -- struct st_table *iv_index_tbl; /* shortcut for RCLASS_IV_INDEX_TBL(rb_obj_class(obj)) */ -+ struct sa_table *iv_index_tbl; /* shortcut for RCLASS_IV_INDEX_TBL(rb_obj_class(obj)) */ - } heap; - VALUE ary[ROBJECT_EMBED_LEN_MAX]; - } as; -@@ -626,12 +626,13 @@ struct RObject { - - /** @internal */ - typedef struct rb_classext_struct rb_classext_t; -+typedef struct rb_class_cache_struct rb_class_cache_t; - - struct RClass { - struct RBasic basic; -+ VALUE super; - rb_classext_t *ptr; -- struct st_table *m_tbl; -- struct st_table *iv_index_tbl; -+ rb_class_cache_t *cache; - }; - #define RCLASS_SUPER(c) rb_class_get_superclass(c) - #define RMODULE_IV_TBL(m) RCLASS_IV_TBL(m) -diff --git a/include/ruby/st.h b/include/ruby/st.h -index 119dfde..aff94fc 100644 ---- a/include/ruby/st.h -+++ b/include/ruby/st.h -@@ -151,6 +151,51 @@ st_index_t st_hash_start(st_index_t h); - #pragma GCC visibility pop - #endif - -+typedef unsigned int sa_index_t; -+#define SA_STOP ST_STOP -+#define SA_CONTINUE ST_CONTINUE -+ -+#define SA_EMPTY 0 -+ -+typedef struct sa_entry { -+ sa_index_t next; -+ sa_index_t key; -+ st_data_t value; -+} sa_entry; -+ -+typedef struct sa_table { -+ sa_index_t num_bins; -+ sa_index_t num_entries; -+ sa_index_t free_pos; -+ sa_entry *entries; -+} sa_table; -+ -+#define SA_EMPTY_TABLE {0, 0, 0, 0}; -+void sa_init_table(sa_table *, sa_index_t); -+sa_table *sa_new_table(); -+int sa_insert(sa_table *, sa_index_t, st_data_t); -+int sa_lookup(sa_table *, sa_index_t, st_data_t *); -+int sa_delete(sa_table *, sa_index_t, st_data_t *); -+void sa_clear(sa_table *); -+void sa_clear_no_free(sa_table *); -+void sa_free_table(sa_table *); -+int sa_foreach(sa_table *, int (*)(ANYARGS), st_data_t); -+size_t sa_memsize(const sa_table *); -+sa_table *sa_copy(sa_table*); -+void sa_copy_to(sa_table*, sa_table*); -+typedef int (*sa_iter_func)(sa_index_t key, st_data_t val, st_data_t arg); -+ -+#define SA_FOREACH_START_I(table, entry) do { \ -+ sa_table *T##entry = (table); \ -+ sa_index_t K##entry; \ -+ for(K##entry = 0; K##entry < T##entry->num_bins; K##entry++) { \ -+ sa_entry *entry = T##entry->entries + K##entry; \ -+ if (entry->next != SA_EMPTY) { \ -+ st_data_t value = entry->value -+#define SA_FOREACH_END() } } } while(0) -+ -+#define SA_FOREACH_START(table) SA_FOREACH_START_I(table, entry) -+ - #if defined(__cplusplus) - #if 0 - { /* satisfy cc-mode */ -diff --git a/internal.h b/internal.h -index f5af903..4af90b6 100644 ---- a/internal.h -+++ b/internal.h -@@ -24,18 +24,24 @@ struct rb_deprecated_classext_struct { - }; - - struct rb_classext_struct { -- VALUE super; -- struct st_table *iv_tbl; -- struct st_table *const_tbl; -+ sa_table m_tbl; -+ sa_table iv_tbl; -+ sa_table const_tbl; -+ sa_table iv_index_tbl; -+}; -+ -+struct rb_class_cache_struct { -+ VALUE method_cache_version; -+ sa_table m_cache_tbl; - }; - - #undef RCLASS_SUPER - #define RCLASS_EXT(c) (RCLASS(c)->ptr) --#define RCLASS_SUPER(c) (RCLASS_EXT(c)->super) --#define RCLASS_IV_TBL(c) (RCLASS_EXT(c)->iv_tbl) --#define RCLASS_CONST_TBL(c) (RCLASS_EXT(c)->const_tbl) --#define RCLASS_M_TBL(c) (RCLASS(c)->m_tbl) --#define RCLASS_IV_INDEX_TBL(c) (RCLASS(c)->iv_index_tbl) -+#define RCLASS_SUPER(c) (RCLASS(c)->super) -+#define RCLASS_IV_TBL(c) (&RCLASS_EXT(c)->iv_tbl) -+#define RCLASS_CONST_TBL(c) (&RCLASS_EXT(c)->const_tbl) -+#define RCLASS_M_TBL(c) (&RCLASS_EXT(c)->m_tbl) -+#define RCLASS_IV_INDEX_TBL(c) (&RCLASS_EXT(c)->iv_index_tbl) - - struct vtm; /* defined by timev.h */ - -diff --git a/marshal.c b/marshal.c -index 6ae3a55..48d9d9b 100644 ---- a/marshal.c -+++ b/marshal.c -@@ -506,7 +506,7 @@ w_uclass(VALUE obj, VALUE super, struct dump_arg *arg) - } - - static int --w_obj_each(ID id, VALUE value, struct dump_call_arg *arg) -+w_obj_each(sa_index_t id, VALUE value, struct dump_call_arg *arg) - { - if (id == rb_id_encoding()) return ST_CONTINUE; - if (id == rb_intern("E")) return ST_CONTINUE; -@@ -553,13 +553,13 @@ w_encoding(VALUE obj, long num, struct dump_call_arg *arg) - } - - static void --w_ivar(VALUE obj, st_table *tbl, struct dump_call_arg *arg) -+w_ivar(VALUE obj, sa_table *tbl, struct dump_call_arg *arg) - { - long num = tbl ? tbl->num_entries : 0; - - w_encoding(obj, num, arg); - if (tbl) { -- st_foreach_safe(tbl, w_obj_each, (st_data_t)arg); -+ sa_foreach(tbl, w_obj_each, (st_data_t)arg); - } - } - -@@ -586,7 +586,7 @@ static void - w_object(VALUE obj, struct dump_arg *arg, int limit) - { - struct dump_call_arg c_arg; -- st_table *ivtbl = 0; -+ sa_table *ivtbl = 0; - st_data_t num; - int hasiv = 0; - #define has_ivars(obj, ivtbl) (((ivtbl) = rb_generic_ivar_table(obj)) != 0 || \ -@@ -651,7 +651,7 @@ w_object(VALUE obj, struct dump_arg *arg, int limit) - } - if (rb_respond_to(obj, s_dump)) { - VALUE v; -- st_table *ivtbl2 = 0; -+ sa_table *ivtbl2 = 0; - int hasiv2; - - v = rb_funcall(obj, s_dump, 1, INT2NUM(limit)); -diff --git a/method.h b/method.h -index 9229896..2fecd57 100644 ---- a/method.h -+++ b/method.h -@@ -100,6 +100,6 @@ int rb_method_entry_eq(const rb_method_entry_t *m1, const rb_method_entry_t *m2) - void rb_mark_method_entry(const rb_method_entry_t *me); - void rb_free_method_entry(rb_method_entry_t *me); - void rb_sweep_method_entry(void *vm); --void rb_free_m_table(st_table *tbl); -+void rb_free_m_table(sa_table *tbl); - - #endif /* METHOD_H */ -diff --git a/object.c b/object.c -index e8cb328..d99323f 100644 ---- a/object.c -+++ b/object.c -@@ -236,17 +236,8 @@ init_copy(VALUE dest, VALUE obj) - break; - case T_CLASS: - case T_MODULE: -- if (RCLASS_IV_TBL(dest)) { -- st_free_table(RCLASS_IV_TBL(dest)); -- RCLASS_IV_TBL(dest) = 0; -- } -- if (RCLASS_CONST_TBL(dest)) { -- rb_free_const_table(RCLASS_CONST_TBL(dest)); -- RCLASS_CONST_TBL(dest) = 0; -- } -- if (RCLASS_IV_TBL(obj)) { -- RCLASS_IV_TBL(dest) = st_copy(RCLASS_IV_TBL(obj)); -- } -+ rb_free_const_table(RCLASS_CONST_TBL(dest)); -+ sa_copy_to(RCLASS_IV_TBL(obj), RCLASS_IV_TBL(dest)); - break; - } - } -@@ -537,7 +528,7 @@ rb_obj_is_kind_of(VALUE obj, VALUE c) - } - - while (cl) { -- if (cl == c || RCLASS_M_TBL(cl) == RCLASS_M_TBL(c)) -+ if (cl == c || RCLASS_EXT(cl) == RCLASS_EXT(c)) - return Qtrue; - cl = RCLASS_SUPER(cl); - } -@@ -1362,13 +1353,13 @@ rb_class_inherited_p(VALUE mod, VALUE arg) - rb_raise(rb_eTypeError, "compared with non class/module"); - } - while (mod) { -- if (RCLASS_M_TBL(mod) == RCLASS_M_TBL(arg)) -+ if (RCLASS_EXT(mod) == RCLASS_EXT(arg)) - return Qtrue; - mod = RCLASS_SUPER(mod); - } - /* not mod < arg; check if mod > arg */ - while (arg) { -- if (RCLASS_M_TBL(arg) == RCLASS_M_TBL(start)) -+ if (RCLASS_EXT(arg) == RCLASS_EXT(start)) - return Qfalse; - arg = RCLASS_SUPER(arg); - } -diff --git a/sp_ar.c b/sp_ar.c -new file mode 100644 -index 0000000..2ed69bf ---- /dev/null -+++ b/sp_ar.c -@@ -0,0 +1,374 @@ -+/* -+ * sparse array lib -+ * inspired by Lua table -+ * written by Sokolov Yura aka funny_falcon -+ */ -+#ifdef NOT_RUBY -+#include "regint.h" -+#include "st.h" -+#else -+#include "ruby/ruby.h" -+#endif -+ -+#include -+#ifdef HAVE_STDLIB_H -+#include -+#endif -+#include -+ -+#ifdef RUBY -+#define malloc xmalloc -+#define calloc xcalloc -+#define realloc xrealloc -+#define free xfree -+#endif -+ -+#define sa_table_alloc() (sa_table*)malloc(sizeof(sa_table)) -+#define sa_table_xalloc() (sa_table*)calloc(1, sizeof(sa_table)) -+#define sa_table_dealloc(table) free(table) -+#define sa_entry_alloc(n) (sa_entry*)calloc((n), sizeof(sa_entry)) -+#define sa_entry_dealloc(entries) free(entries) -+ -+#define SA_LAST 1 -+#define SA_OFFSET 2 -+ -+#define SA_MIN_SIZE 4 -+ -+void -+sa_init_table(register sa_table *table, sa_index_t num_bins) -+{ -+ if (num_bins) { -+ table->num_entries = 0; -+ table->entries = sa_entry_alloc(num_bins); -+ table->num_bins = num_bins; -+ table->free_pos = num_bins; -+ } -+ else { -+ memset(table, 0, sizeof(sa_table)); -+ } -+} -+ -+sa_table* -+sa_new_table() -+{ -+ sa_table* table = sa_table_alloc(); -+ sa_init_table(table, 0); -+ return table; -+} -+ -+static inline sa_index_t -+calc_pos(register sa_table* table, sa_index_t key) -+{ -+ /* this formula is empirical */ -+ /* it has no good avalance, but works well in our case */ -+ key ^= key >> 16; -+ key *= 0x445229; -+ return (key + (key >> 16)) % table->num_bins; -+} -+ -+static void -+fix_empty(register sa_table* table) -+{ -+ while(--table->free_pos && -+ table->entries[table->free_pos-1].next != SA_EMPTY); -+} -+ -+#define FLOOR_TO_4 ((~((sa_index_t)0)) << 2) -+static sa_index_t -+find_empty(register sa_table* table, register sa_index_t pos) -+{ -+ sa_index_t new_pos = table->free_pos-1; -+ sa_entry *entry; -+ pos &= FLOOR_TO_4; -+ entry = table->entries+pos; -+ -+ if (entry->next == SA_EMPTY) { new_pos = pos; goto check; } -+ pos++; entry++; -+ if (entry->next == SA_EMPTY) { new_pos = pos; goto check; } -+ pos++; entry++; -+ if (entry->next == SA_EMPTY) { new_pos = pos; goto check; } -+ pos++; entry++; -+ if (entry->next == SA_EMPTY) { new_pos = pos; goto check; } -+ -+check: -+ if (new_pos+1 == table->free_pos) fix_empty(table); -+ return new_pos; -+} -+ -+static void resize(register sa_table* table); -+static int insert_into_chain(register sa_table*, register sa_index_t, st_data_t, sa_index_t pos); -+static int insert_into_main(register sa_table*, sa_index_t, st_data_t, sa_index_t pos, sa_index_t prev_pos); -+ -+int -+sa_insert(register sa_table* table, register sa_index_t key, st_data_t value) -+{ -+ sa_index_t pos, main_pos; -+ register sa_entry *entry; -+ -+ if (table->num_bins == 0) { -+ sa_init_table(table, SA_MIN_SIZE); -+ } -+ -+ pos = calc_pos(table, key); -+ entry = table->entries + pos; -+ -+ if (entry->next == SA_EMPTY) { -+ entry->next = SA_LAST; -+ entry->key = key; -+ entry->value = value; -+ table->num_entries++; -+ if (pos+1 == table->free_pos) fix_empty(table); -+ return 0; -+ } -+ -+ if (entry->key == key) { -+ entry->value = value; -+ return 1; -+ } -+ -+ if (table->num_entries + (table->num_entries >> 2) > table->num_bins) { -+ resize(table); -+ return sa_insert(table, key, value); -+ } -+ -+ main_pos = calc_pos(table, entry->key); -+ if (main_pos == pos) { -+ return insert_into_chain(table, key, value, pos); -+ } -+ else { -+ if (!table->free_pos) { -+ resize(table); -+ return sa_insert(table, key, value); -+ } -+ return insert_into_main(table, key, value, pos, main_pos); -+ } -+} -+ -+static int -+insert_into_chain(register sa_table* table, register sa_index_t key, st_data_t value, sa_index_t pos) -+{ -+ sa_entry *entry = table->entries + pos, *new_entry; -+ sa_index_t new_pos; -+ -+ while (entry->next != SA_LAST) { -+ pos = entry->next - SA_OFFSET; -+ entry = table->entries + pos; -+ if (entry->key == key) { -+ entry->value = value; -+ return 1; -+ } -+ } -+ -+ if (!table->free_pos) { -+ resize(table); -+ return sa_insert(table, key, value); -+ } -+ -+ new_pos = find_empty(table, pos); -+ new_entry = table->entries + new_pos; -+ entry->next = new_pos + SA_OFFSET; -+ -+ new_entry->next = SA_LAST; -+ new_entry->key = key; -+ new_entry->value = value; -+ table->num_entries++; -+ return 0; -+} -+ -+static int -+insert_into_main(register sa_table* table, sa_index_t key, st_data_t value, sa_index_t pos, sa_index_t prev_pos) -+{ -+ sa_entry *entry = table->entries + pos; -+ sa_index_t new_pos = find_empty(table, pos); -+ sa_entry *new_entry = table->entries + new_pos; -+ sa_index_t npos; -+ -+ *new_entry = *entry; -+ -+ while((npos = table->entries[prev_pos].next - SA_OFFSET) != pos) { -+ prev_pos = npos; -+ } -+ table->entries[prev_pos].next = new_pos + SA_OFFSET; -+ -+ entry->next = SA_LAST; -+ entry->key = key; -+ entry->value = value; -+ table->num_entries++; -+ return 0; -+} -+ -+static sa_index_t -+new_size(sa_index_t num_entries) -+{ -+ sa_index_t msb = num_entries; -+ msb |= msb >> 1; -+ msb |= msb >> 2; -+ msb |= msb >> 4; -+ msb |= msb >> 8; -+ msb |= msb >> 16; -+ msb = ((msb >> 4) + 1) << 3; -+ return (num_entries & (msb | (msb >> 1))) + (msb >> 1); -+} -+ -+static void -+resize(register sa_table *table) -+{ -+ sa_table tmp_table; -+ sa_entry *entry; -+ sa_index_t i; -+ -+ if (table->num_entries == 0) { -+ sa_entry_dealloc(table->entries); -+ memset(table, 0, sizeof(sa_table)); -+ return; -+ } -+ -+ sa_init_table(&tmp_table, new_size(table->num_entries + (table->num_entries >> 2))); -+ entry = table->entries; -+ -+ for(i = 0; i < table->num_bins; i++, entry++) { -+ if (entry->next != SA_EMPTY) { -+ sa_insert(&tmp_table, entry->key, entry->value); -+ } -+ } -+ sa_entry_dealloc(table->entries); -+ *table = tmp_table; -+} -+ -+int -+sa_lookup(register sa_table *table, register sa_index_t key, st_data_t *value) -+{ -+ register sa_entry *entry; -+ -+ if (table->num_entries == 0) return 0; -+ -+ entry = table->entries + calc_pos(table, key); -+ if (entry->next == SA_EMPTY) return 0; -+ -+ if (entry->key == key) goto found; -+ if (entry->next == SA_LAST) return 0; -+ -+ entry = table->entries + (entry->next - SA_OFFSET); -+ if (entry->key == key) goto found; -+ -+ while(entry->next != SA_LAST) { -+ entry = table->entries + (entry->next - SA_OFFSET); -+ if (entry->key == key) goto found; -+ } -+ return 0; -+found: -+ if (value) *value = entry->value; -+ return 1; -+} -+ -+void -+sa_clear(sa_table *table) -+{ -+ sa_entry_dealloc(table->entries); -+ memset(table, 0, sizeof(sa_table)); -+} -+ -+void -+sa_clear_no_free(sa_table *table) -+{ -+ memset(table->entries, 0, sizeof(sa_entry) * table->num_bins); -+ table->num_entries = 0; -+ table->free_pos = table->num_bins; -+} -+ -+void -+sa_free_table(sa_table *table) -+{ -+ sa_entry_dealloc(table->entries); -+ sa_table_dealloc(table); -+} -+ -+int -+sa_delete(sa_table *table, sa_index_t key, st_data_t *value) -+{ -+ sa_index_t pos, prev_pos = ~0; -+ sa_entry *entry; -+ -+ if (table->num_entries == 0) goto not_found; -+ -+ pos = calc_pos(table, key); -+ entry = table->entries + pos; -+ -+ if (entry->next == SA_EMPTY) goto not_found; -+ -+ do { -+ if (entry->key == key) { -+ if (value) *value = entry->value; -+ if (entry->next != SA_LAST) { -+ sa_index_t npos = entry->next - SA_OFFSET; -+ *entry = table->entries[npos]; -+ memset(table->entries + npos, 0, sizeof(sa_entry)); -+ } -+ else { -+ memset(table->entries + pos, 0, sizeof(sa_entry)); -+ if (~prev_pos) { -+ table->entries[prev_pos].next = SA_LAST; -+ } -+ } -+ table->num_entries--; -+ if (table->num_entries < table->num_bins / 4) { -+ resize(table); -+ } -+ return 1; -+ } -+ if (entry->next == SA_LAST) break; -+ prev_pos = pos; -+ pos = entry->next - SA_OFFSET; -+ entry = table->entries + pos; -+ } while(1); -+ -+not_found: -+ if (value) *value = 0; -+ return 0; -+} -+ -+int -+sa_foreach(register sa_table *table, int (*func)(), st_data_t arg) -+{ -+ sa_index_t i; -+ if (table->num_bins == 0) { -+ return 0; -+ } -+ for(i = 0; i < table->num_bins ; i++) { -+ if (table->entries[i].next != SA_EMPTY) { -+ sa_index_t key = table->entries[i].key; -+ st_data_t val = table->entries[i].value; -+ if ((*func)(key, val, arg) == SA_STOP) break; -+ } -+ } -+ return 0; -+} -+ -+size_t -+sa_memsize(const sa_table *table) -+{ -+ return sizeof(sa_table) + table->num_bins * sizeof(sa_entry); -+} -+ -+sa_table* -+sa_copy(sa_table *table) -+{ -+ sa_table *new_table = sa_table_alloc(); -+ *new_table = *table; -+ if (table->num_bins) { -+ new_table->entries = sa_entry_alloc(table->num_bins); -+ memcpy(new_table->entries, table->entries, table->num_bins*sizeof(sa_entry)); -+ } -+ return new_table; -+} -+ -+void -+sa_copy_to(sa_table *from, sa_table *to) -+{ -+ sa_entry_dealloc(to->entries); -+ *to = *from; -+ if (to->num_bins) { -+ to->entries = sa_entry_alloc(to->num_bins); -+ memcpy(to->entries, from->entries, from->num_bins*sizeof(sa_entry)); -+ } -+} -diff --git a/test/ruby/test_marshal.rb b/test/ruby/test_marshal.rb -index 0f3f794..2316c15 100644 ---- a/test/ruby/test_marshal.rb -+++ b/test/ruby/test_marshal.rb -@@ -312,7 +312,7 @@ class TestMarshal < Test::Unit::TestCase - assert_equal(a.instance_variable_get(i), b.instance_variable_get(i), bug1932) - end - end -- a.__send__(a.methods(true).grep(/=\z/)[0], a) -+ a.__send__(a.methods(true).grep(/\Ar.+=\z/)[0], a) - assert_nothing_raised(bug1932) do - b = Marshal.load(Marshal.dump(a)) - assert_equal(ClassISO8859_1, b.class, bug1932) -diff --git a/test/ruby/test_method.rb b/test/ruby/test_method.rb -index ea6c5f2..6ccd37c 100644 ---- a/test/ruby/test_method.rb -+++ b/test/ruby/test_method.rb -@@ -406,7 +406,7 @@ class TestMethod < Test::Unit::TestCase - obj = a.new - assert_equal([:a], obj.public_methods(false), bug) - obj.extend(m) -- assert_equal([:m1, :a], obj.public_methods(false), bug) -+ assert_equal([:a, :m1], obj.public_methods(false).sort, bug) - end - - def test_visibility -diff --git a/test/ruby/test_module.rb b/test/ruby/test_module.rb -index 6176f48..a67d845 100644 ---- a/test/ruby/test_module.rb -+++ b/test/ruby/test_module.rb -@@ -870,7 +870,7 @@ class TestModule < Test::Unit::TestCase - (class << self ; self ; end).class_eval do - define_method :method_added do |sym| - memo << sym -- memo << mod.instance_methods(false) -+ memo << mod.instance_methods(false).sort - memo << (mod.instance_method(sym) rescue nil) - end - end -@@ -887,10 +887,10 @@ class TestModule < Test::Unit::TestCase - assert_equal [:f, :g], memo.shift - assert_equal mod.instance_method(:f), memo.shift - assert_equal :a, memo.shift -- assert_equal [:f, :g, :a], memo.shift -+ assert_equal [:a, :f, :g], memo.shift - assert_equal mod.instance_method(:a), memo.shift - assert_equal :a=, memo.shift -- assert_equal [:f, :g, :a, :a=], memo.shift -+ assert_equal [:a, :a=, :f, :g], memo.shift - assert_equal mod.instance_method(:a=), memo.shift - end - -diff --git a/time.c b/time.c -index 755812f..83edc83 100644 ---- a/time.c -+++ b/time.c -@@ -4712,16 +4712,14 @@ time_mload(VALUE time, VALUE str) - long nsec; - VALUE submicro, nano_num, nano_den, offset; - wideval_t timew; -- st_data_t data; - - time_modify(time); - - #define get_attr(attr, iffound) \ - attr = rb_attr_get(str, id_##attr); \ - if (!NIL_P(attr)) { \ -- data = id_##attr; \ - iffound; \ -- st_delete(rb_generic_ivar_table(str), &data, 0); \ -+ sa_delete(rb_generic_ivar_table(str), (sa_index_t)id_##attr, 0); \ - } - - get_attr(nano_num, {}); -diff --git a/variable.c b/variable.c -index 3da500e..4a61453 100644 ---- a/variable.c -+++ b/variable.c -@@ -19,15 +19,15 @@ - #include "constant.h" - #include "internal.h" - --st_table *rb_global_tbl; --st_table *rb_class_tbl; -+sa_table rb_global_tbl; -+sa_table rb_class_tbl; - static ID autoload, classpath, tmp_classpath, classid; - - void - Init_var_tables(void) - { -- rb_global_tbl = st_init_numtable(); -- rb_class_tbl = st_init_numtable(); -+ sa_init_table(&rb_global_tbl, 0); -+ sa_init_table(&rb_class_tbl, 0); - CONST_ID(autoload, "__autoload__"); - CONST_ID(classpath, "__classpath__"); - CONST_ID(tmp_classpath, "__tmp_classpath__"); -@@ -43,7 +43,7 @@ struct fc_result { - }; - - static VALUE --fc_path(struct fc_result *fc, ID name) -+fc_path(struct fc_result *fc, sa_index_t name) - { - VALUE path, tmp; - -@@ -51,8 +51,7 @@ fc_path(struct fc_result *fc, ID name) - while (fc) { - st_data_t n; - if (fc->track == rb_cObject) break; -- if (RCLASS_IV_TBL(fc->track) && -- st_lookup(RCLASS_IV_TBL(fc->track), (st_data_t)classpath, &n)) { -+ if (sa_lookup(RCLASS_IV_TBL(fc->track), (sa_index_t)classpath, &n)) { - tmp = rb_str_dup((VALUE)n); - rb_str_cat2(tmp, "::"); - rb_str_append(tmp, path); -@@ -70,7 +69,7 @@ fc_path(struct fc_result *fc, ID name) - } - - static int --fc_i(ID key, rb_const_entry_t *ce, struct fc_result *res) -+fc_i(sa_index_t key, rb_const_entry_t *ce, struct fc_result *res) - { - VALUE value = ce->value; - if (!rb_is_const_id(key)) return ST_CONTINUE; -@@ -98,7 +97,7 @@ fc_i(ID key, rb_const_entry_t *ce, struct fc_result *res) - arg.klass = res->klass; - arg.track = value; - arg.prev = res; -- st_foreach(RCLASS_CONST_TBL(value), fc_i, (st_data_t)&arg); -+ sa_foreach(RCLASS_CONST_TBL(value), fc_i, (st_data_t)&arg); - if (arg.path) { - res->path = arg.path; - return ST_STOP; -@@ -123,18 +122,14 @@ find_class_path(VALUE klass) - arg.track = rb_cObject; - arg.prev = 0; - if (RCLASS_CONST_TBL(rb_cObject)) { -- st_foreach_safe(RCLASS_CONST_TBL(rb_cObject), fc_i, (st_data_t)&arg); -+ sa_foreach(RCLASS_CONST_TBL(rb_cObject), fc_i, (st_data_t)&arg); - } - if (arg.path == 0) { -- st_foreach_safe(rb_class_tbl, fc_i, (st_data_t)&arg); -+ sa_foreach(&rb_class_tbl, fc_i, (st_data_t)&arg); - } - if (arg.path) { -- st_data_t tmp = tmp_classpath; -- if (!RCLASS_IV_TBL(klass)) { -- RCLASS_IV_TBL(klass) = st_init_numtable(); -- } -- st_insert(RCLASS_IV_TBL(klass), (st_data_t)classpath, arg.path); -- st_delete(RCLASS_IV_TBL(klass), &tmp, 0); -+ sa_insert(RCLASS_IV_TBL(klass), (sa_index_t)classpath, arg.path); -+ sa_delete(RCLASS_IV_TBL(klass), (sa_index_t)tmp_classpath, 0); - return arg.path; - } - return Qnil; -@@ -147,16 +142,15 @@ classname(VALUE klass) - st_data_t n; - - if (!klass) klass = rb_cObject; -- if (RCLASS_IV_TBL(klass)) { -- if (!st_lookup(RCLASS_IV_TBL(klass), (st_data_t)classpath, &n)) { -- if (!st_lookup(RCLASS_IV_TBL(klass), (st_data_t)classid, &n)) { -+ if (RCLASS_IV_TBL(klass)->num_entries) { -+ if (!sa_lookup(RCLASS_IV_TBL(klass), (sa_index_t)classpath, &n)) { -+ if (!sa_lookup(RCLASS_IV_TBL(klass), (sa_index_t)classid, &n)) { - return find_class_path(klass); - } - path = rb_str_dup(rb_id2str(SYM2ID((VALUE)n))); - OBJ_FREEZE(path); -- st_insert(RCLASS_IV_TBL(klass), (st_data_t)classpath, (st_data_t)path); -- n = classid; -- st_delete(RCLASS_IV_TBL(klass), &n, 0); -+ sa_insert(RCLASS_IV_TBL(klass), (sa_index_t)classpath, (st_data_t)path); -+ sa_delete(RCLASS_IV_TBL(klass), (sa_index_t)classid, 0); - } - else { - path = (VALUE)n; -@@ -192,8 +186,7 @@ rb_class_path(VALUE klass) - st_data_t n = (st_data_t)path; - - if (!NIL_P(path)) return path; -- if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass), -- (st_data_t)tmp_classpath, &n)) { -+ if (sa_lookup(RCLASS_IV_TBL(klass), (sa_index_t)tmp_classpath, &n)) { - return (VALUE)n; - } - else { -@@ -364,7 +357,7 @@ rb_global_entry(ID id) - struct global_entry *entry; - st_data_t data; - -- if (!st_lookup(rb_global_tbl, (st_data_t)id, &data)) { -+ if (!sa_lookup(&rb_global_tbl, (sa_index_t)id, &data)) { - struct global_variable *var; - entry = ALLOC(struct global_entry); - var = ALLOC(struct global_variable); -@@ -378,7 +371,7 @@ rb_global_entry(ID id) - - var->block_trace = 0; - var->trace = 0; -- st_add_direct(rb_global_tbl, id, (st_data_t)entry); -+ sa_insert(&rb_global_tbl, (sa_index_t)id, (st_data_t)entry); - } - else { - entry = (struct global_entry *)data; -@@ -454,8 +447,8 @@ readonly_setter(VALUE val, ID id, void *data, struct global_variable *gvar) - rb_name_error(id, "%s is a read-only variable", rb_id2name(id)); - } - --static int --mark_global_entry(ID key, struct global_entry *entry) -+static void -+mark_global_entry(struct global_entry *entry) - { - struct trace_var *trace; - struct global_variable *var = entry->var; -@@ -466,14 +459,14 @@ mark_global_entry(ID key, struct global_entry *entry) - if (trace->data) rb_gc_mark_maybe(trace->data); - trace = trace->next; - } -- return ST_CONTINUE; - } - - void - rb_gc_mark_global_tbl(void) - { -- if (rb_global_tbl) -- st_foreach_safe(rb_global_tbl, mark_global_entry, 0); -+ SA_FOREACH_START(&rb_global_tbl); -+ mark_global_entry((struct global_entry*) value); -+ SA_FOREACH_END(); - } - - static ID -@@ -635,7 +628,7 @@ rb_f_untrace_var(int argc, VALUE *argv) - rb_secure(4); - rb_scan_args(argc, argv, "11", &var, &cmd); - id = rb_to_id(var); -- if (!st_lookup(rb_global_tbl, (st_data_t)id, &data)) { -+ if (!sa_lookup(&rb_global_tbl, (sa_index_t)id, &data)) { - rb_name_error(id, "undefined global variable %s", rb_id2name(id)); - } - -@@ -742,13 +735,6 @@ rb_gvar_defined(struct global_entry *entry) - return Qtrue; - } - --static int --gvar_i(ID key, struct global_entry *entry, VALUE ary) --{ -- rb_ary_push(ary, ID2SYM(key)); -- return ST_CONTINUE; --} -- - /* - * call-seq: - * global_variables -> array -@@ -765,7 +751,9 @@ rb_f_global_variables(void) - char buf[2]; - int i; - -- st_foreach_safe(rb_global_tbl, gvar_i, ary); -+ SA_FOREACH_START(&rb_global_tbl); -+ rb_ary_push(ary, ID2SYM(entry->key)); -+ SA_FOREACH_END(); - buf[0] = '$'; - for (i = 1; i <= 9; ++i) { - buf[1] = (char)(i + '0'); -@@ -784,10 +772,10 @@ rb_alias_variable(ID name1, ID name2) - rb_raise(rb_eSecurityError, "Insecure: can't alias global variable"); - - entry2 = rb_global_entry(name2); -- if (!st_lookup(rb_global_tbl, (st_data_t)name1, &data1)) { -+ if (!sa_lookup(&rb_global_tbl, (sa_index_t)name1, &data1)) { - entry1 = ALLOC(struct global_entry); - entry1->id = name1; -- st_add_direct(rb_global_tbl, name1, (st_data_t)entry1); -+ sa_insert(&rb_global_tbl, (sa_index_t)name1, (st_data_t)entry1); - } - else if ((entry1 = (struct global_entry *)data1)->var != entry2->var) { - struct global_variable *var = entry1->var; -@@ -815,7 +803,7 @@ rb_alias_variable(ID name1, ID name2) - static int special_generic_ivar = 0; - static st_table *generic_iv_tbl; - --st_table* -+sa_table* - rb_generic_ivar_table(VALUE obj) - { - st_data_t tbl; -@@ -823,7 +811,7 @@ rb_generic_ivar_table(VALUE obj) - if (!FL_TEST(obj, FL_EXIVAR)) return 0; - if (!generic_iv_tbl) return 0; - if (!st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) return 0; -- return (st_table *)tbl; -+ return (sa_table *)tbl; - } - - static VALUE -@@ -833,7 +821,7 @@ generic_ivar_get(VALUE obj, ID id, int warn) - - if (generic_iv_tbl) { - if (st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) { -- if (st_lookup((st_table *)tbl, (st_data_t)id, &val)) { -+ if (sa_lookup((sa_table *)tbl, (sa_index_t)id, &val)) { - return (VALUE)val; - } - } -@@ -847,7 +835,6 @@ generic_ivar_get(VALUE obj, ID id, int warn) - static void - generic_ivar_set(VALUE obj, ID id, VALUE val) - { -- st_table *tbl; - st_data_t data; - - if (rb_special_const_p(obj)) { -@@ -859,24 +846,22 @@ generic_ivar_set(VALUE obj, ID id, VALUE val) - } - if (!st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) { - FL_SET(obj, FL_EXIVAR); -- tbl = st_init_numtable(); -- st_add_direct(generic_iv_tbl, (st_data_t)obj, (st_data_t)tbl); -- st_add_direct(tbl, (st_data_t)id, (st_data_t)val); -- return; -+ data = (st_data_t)sa_new_table(); -+ st_add_direct(generic_iv_tbl, (st_data_t)obj, data); - } -- st_insert((st_table *)data, (st_data_t)id, (st_data_t)val); -+ sa_insert((sa_table *)data, (sa_index_t)id, (st_data_t)val); - } - - static VALUE - generic_ivar_defined(VALUE obj, ID id) - { -- st_table *tbl; -+ sa_table *tbl; - st_data_t data; - - if (!generic_iv_tbl) return Qfalse; - if (!st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) return Qfalse; -- tbl = (st_table *)data; -- if (st_lookup(tbl, (st_data_t)id, &data)) { -+ tbl = (sa_table *)data; -+ if (sa_lookup(tbl, (sa_index_t)id, &data)) { - return Qtrue; - } - return Qfalse; -@@ -885,18 +870,18 @@ generic_ivar_defined(VALUE obj, ID id) - static int - generic_ivar_remove(VALUE obj, ID id, st_data_t *valp) - { -- st_table *tbl; -+ sa_table *tbl; - st_data_t data, key = (st_data_t)id; - int status; - - if (!generic_iv_tbl) return 0; - if (!st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) return 0; -- tbl = (st_table *)data; -- status = st_delete(tbl, &key, valp); -+ tbl = (sa_table *)data; -+ status = sa_delete(tbl, (sa_index_t)id, valp); - if (tbl->num_entries == 0) { - key = (st_data_t)obj; - st_delete(generic_iv_tbl, &key, &data); -- st_free_table((st_table *)data); -+ sa_free_table(tbl); - } - return status; - } -@@ -908,22 +893,17 @@ rb_mark_generic_ivar(VALUE obj) - - if (!generic_iv_tbl) return; - if (st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) { -- rb_mark_tbl((st_table *)tbl); -+ rb_mark_sa_tbl((sa_table *)tbl); - } - } - - static int --givar_mark_i(ID key, VALUE value) --{ -- rb_gc_mark(value); -- return ST_CONTINUE; --} -- --static int --givar_i(VALUE obj, st_table *tbl) -+givar_i(VALUE obj, sa_table *tbl) - { - if (rb_special_const_p(obj)) { -- st_foreach_safe(tbl, givar_mark_i, 0); -+ SA_FOREACH_START(tbl); -+ rb_gc_mark((VALUE)value); -+ SA_FOREACH_END(); - } - return ST_CONTINUE; - } -@@ -943,7 +923,7 @@ rb_free_generic_ivar(VALUE obj) - - if (!generic_iv_tbl) return; - if (st_delete(generic_iv_tbl, &key, &tbl)) -- st_free_table((st_table *)tbl); -+ sa_free_table((sa_table *)tbl); - } - - RUBY_FUNC_EXPORTED size_t -@@ -951,7 +931,7 @@ rb_generic_ivar_memsize(VALUE obj) - { - st_data_t tbl; - if (st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) -- return st_memsize((st_table *)tbl); -+ return sa_memsize((sa_table *)tbl); - return 0; - } - -@@ -970,17 +950,17 @@ rb_copy_generic_ivar(VALUE clone, VALUE obj) - return; - } - if (st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) { -- st_table *tbl = (st_table *)data; -+ sa_table *tbl = (sa_table *)data; - - if (tbl->num_entries == 0) - goto clear; - - if (st_lookup(generic_iv_tbl, (st_data_t)clone, &data)) { -- st_free_table((st_table *)data); -- st_insert(generic_iv_tbl, (st_data_t)clone, (st_data_t)st_copy(tbl)); -+ sa_free_table((sa_table *)data); -+ st_insert(generic_iv_tbl, (st_data_t)clone, (st_data_t)sa_copy(tbl)); - } - else { -- st_add_direct(generic_iv_tbl, (st_data_t)clone, (st_data_t)st_copy(tbl)); -+ st_add_direct(generic_iv_tbl, (st_data_t)clone, (st_data_t)sa_copy(tbl)); - FL_SET(clone, FL_EXIVAR); - } - } -@@ -990,7 +970,7 @@ static VALUE - ivar_get(VALUE obj, ID id, int warn) - { - VALUE val, *ptr; -- struct st_table *iv_index_tbl; -+ sa_table *iv_index_tbl; - long len; - st_data_t index; - -@@ -1000,7 +980,7 @@ ivar_get(VALUE obj, ID id, int warn) - ptr = ROBJECT_IVPTR(obj); - iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); - if (!iv_index_tbl) break; -- if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break; -+ if (!sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) break; - if (len <= (long)index) break; - val = ptr[index]; - if (val != Qundef) -@@ -1008,7 +988,7 @@ ivar_get(VALUE obj, ID id, int warn) - break; - case T_CLASS: - case T_MODULE: -- if (RCLASS_IV_TBL(obj) && st_lookup(RCLASS_IV_TBL(obj), (st_data_t)id, &index)) -+ if (sa_lookup(RCLASS_IV_TBL(obj), (sa_index_t)id, &index)) - return (VALUE)index; - break; - default: -@@ -1037,7 +1017,7 @@ rb_attr_get(VALUE obj, ID id) - VALUE - rb_ivar_set(VALUE obj, ID id, VALUE val) - { -- struct st_table *iv_index_tbl; -+ struct sa_table *iv_index_tbl; - st_data_t index; - long i, len; - int ivar_extended; -@@ -1051,14 +1031,11 @@ rb_ivar_set(VALUE obj, ID id, VALUE val) - if (!iv_index_tbl) { - VALUE klass = rb_obj_class(obj); - iv_index_tbl = RCLASS_IV_INDEX_TBL(klass); -- if (!iv_index_tbl) { -- iv_index_tbl = RCLASS_IV_INDEX_TBL(klass) = st_init_numtable(); -- } - } - ivar_extended = 0; -- if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) { -+ if (!sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) { - index = iv_index_tbl->num_entries; -- st_add_direct(iv_index_tbl, (st_data_t)id, index); -+ sa_insert(iv_index_tbl, (sa_index_t)id, index); - ivar_extended = 1; - } - len = ROBJECT_NUMIV(obj); -@@ -1098,8 +1075,7 @@ rb_ivar_set(VALUE obj, ID id, VALUE val) - break; - case T_CLASS: - case T_MODULE: -- if (!RCLASS_IV_TBL(obj)) RCLASS_IV_TBL(obj) = st_init_numtable(); -- st_insert(RCLASS_IV_TBL(obj), (st_data_t)id, val); -+ sa_insert(RCLASS_IV_TBL(obj), (sa_index_t)id, val); - break; - default: - generic_ivar_set(obj, id, val); -@@ -1112,13 +1088,13 @@ VALUE - rb_ivar_defined(VALUE obj, ID id) - { - VALUE val; -- struct st_table *iv_index_tbl; -+ struct sa_table *iv_index_tbl; - st_data_t index; - switch (TYPE(obj)) { - case T_OBJECT: - iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); - if (!iv_index_tbl) break; -- if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break; -+ if (!sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) break; - if (ROBJECT_NUMIV(obj) <= (long)index) break; - val = ROBJECT_IVPTR(obj)[index]; - if (val != Qundef) -@@ -1126,7 +1102,7 @@ rb_ivar_defined(VALUE obj, ID id) - break; - case T_CLASS: - case T_MODULE: -- if (RCLASS_IV_TBL(obj) && st_lookup(RCLASS_IV_TBL(obj), (st_data_t)id, 0)) -+ if (sa_lookup(RCLASS_IV_TBL(obj), (sa_index_t)id, 0)) - return Qtrue; - break; - default: -@@ -1137,40 +1113,26 @@ rb_ivar_defined(VALUE obj, ID id) - return Qfalse; - } - --struct obj_ivar_tag { -- VALUE obj; -- int (*func)(ID key, VALUE val, st_data_t arg); -- st_data_t arg; --}; -- --static int --obj_ivar_i(st_data_t key, st_data_t index, st_data_t arg) --{ -- struct obj_ivar_tag *data = (struct obj_ivar_tag *)arg; -- if ((long)index < ROBJECT_NUMIV(data->obj)) { -- VALUE val = ROBJECT_IVPTR(data->obj)[(long)index]; -- if (val != Qundef) { -- return (data->func)((ID)key, val, data->arg); -- } -- } -- return ST_CONTINUE; --} -- - static void - obj_ivar_each(VALUE obj, int (*func)(ANYARGS), st_data_t arg) - { -- st_table *tbl; -- struct obj_ivar_tag data; -+ sa_table *tbl; -+ long numiv = ROBJECT_NUMIV(obj); -+ VALUE *vars = ROBJECT_IVPTR(obj); - - tbl = ROBJECT_IV_INDEX_TBL(obj); -- if (!tbl) -+ if (!tbl || !numiv) - return; - -- data.obj = obj; -- data.func = (int (*)(ID key, VALUE val, st_data_t arg))func; -- data.arg = arg; -- -- st_foreach_safe(tbl, obj_ivar_i, (st_data_t)&data); -+ SA_FOREACH_START(tbl); -+ if ((long)value < numiv) { -+ VALUE val = vars[value]; -+ if (val != Qundef) { -+ if (((sa_iter_func)func)(entry->key, val, arg) == SA_STOP) -+ break; -+ } -+ } -+ SA_FOREACH_END(); - } - - void -@@ -1182,9 +1144,7 @@ rb_ivar_foreach(VALUE obj, int (*func)(ANYARGS), st_data_t arg) - break; - case T_CLASS: - case T_MODULE: -- if (RCLASS_IV_TBL(obj)) { -- st_foreach_safe(RCLASS_IV_TBL(obj), func, arg); -- } -+ sa_foreach(RCLASS_IV_TBL(obj), func, arg); - break; - default: - if (!generic_iv_tbl) break; -@@ -1192,7 +1152,7 @@ rb_ivar_foreach(VALUE obj, int (*func)(ANYARGS), st_data_t arg) - st_data_t tbl; - - if (st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) { -- st_foreach_safe((st_table *)tbl, func, arg); -+ sa_foreach((sa_table *)tbl, func, arg); - } - } - break; -@@ -1202,11 +1162,11 @@ rb_ivar_foreach(VALUE obj, int (*func)(ANYARGS), st_data_t arg) - st_index_t - rb_ivar_count(VALUE obj) - { -- st_table *tbl; -+ sa_table *tbl; - switch (TYPE(obj)) { - case T_OBJECT: - if ((tbl = ROBJECT_IV_INDEX_TBL(obj)) != 0) { -- st_index_t i, count, num = tbl->num_entries; -+ sa_index_t i, count, num = tbl->num_entries; - const VALUE *const ivptr = ROBJECT_IVPTR(obj); - for (i = count = 0; i < num; ++i) { - if (ivptr[i] != Qundef) { -@@ -1228,7 +1188,7 @@ rb_ivar_count(VALUE obj) - st_data_t data; - - if (st_lookup(generic_iv_tbl, (st_data_t)obj, &data) && -- (tbl = (st_table *)data) != 0) { -+ (tbl = (sa_table *)data) != 0) { - return tbl->num_entries; - } - } -@@ -1238,7 +1198,7 @@ rb_ivar_count(VALUE obj) - } - - static int --ivar_i(ID key, VALUE val, VALUE ary) -+ivar_i(sa_index_t key, VALUE val, VALUE ary) - { - if (rb_is_instance_id(key)) { - rb_ary_push(ary, ID2SYM(key)); -@@ -1301,7 +1261,7 @@ rb_obj_remove_instance_variable(VALUE obj, VALUE name) - VALUE val = Qnil; - const ID id = rb_to_id(name); - st_data_t n, v; -- struct st_table *iv_index_tbl; -+ struct sa_table *iv_index_tbl; - st_data_t index; - - if (!OBJ_UNTRUSTED(obj) && rb_safe_level() >= 4) -@@ -1315,7 +1275,7 @@ rb_obj_remove_instance_variable(VALUE obj, VALUE name) - case T_OBJECT: - iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); - if (!iv_index_tbl) break; -- if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break; -+ if (!sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) break; - if (ROBJECT_NUMIV(obj) <= (long)index) break; - val = ROBJECT_IVPTR(obj)[index]; - if (val != Qundef) { -@@ -1326,14 +1286,14 @@ rb_obj_remove_instance_variable(VALUE obj, VALUE name) - case T_CLASS: - case T_MODULE: - n = id; -- if (RCLASS_IV_TBL(obj) && st_delete(RCLASS_IV_TBL(obj), &n, &v)) { -+ if (sa_delete(RCLASS_IV_TBL(obj), (sa_index_t)id, &v)) { - return (VALUE)v; - } - break; - default: - if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) { - v = val; -- if (generic_ivar_remove(obj, (st_data_t)id, &v)) { -+ if (generic_ivar_remove(obj, id, &v)) { - return (VALUE)v; - } - } -@@ -1410,20 +1370,20 @@ rb_mod_const_missing(VALUE klass, VALUE name) - static void - autoload_mark(void *ptr) - { -- rb_mark_tbl((st_table *)ptr); -+ rb_mark_sa_tbl((sa_table *)ptr); - } - - static void - autoload_free(void *ptr) - { -- st_free_table((st_table *)ptr); -+ sa_free_table((sa_table *)ptr); - } - - static size_t - autoload_memsize(const void *ptr) - { -- const st_table *tbl = ptr; -- return st_memsize(tbl); -+ const sa_table *tbl = ptr; -+ return sa_memsize(tbl); - } - - static const rb_data_type_t autoload_data_type = { -@@ -1432,14 +1392,14 @@ static const rb_data_type_t autoload_data_type = { - }; - - #define check_autoload_table(av) \ -- (struct st_table *)rb_check_typeddata((av), &autoload_data_type) -+ (struct sa_table *)rb_check_typeddata((av), &autoload_data_type) - - void - rb_autoload(VALUE mod, ID id, const char *file) - { - st_data_t av; - VALUE fn; -- struct st_table *tbl; -+ struct sa_table *tbl; - - if (!rb_is_const_id(id)) { - rb_raise(rb_eNameError, "autoload must be constant name: %s", rb_id2name(id)); -@@ -1448,43 +1408,41 @@ rb_autoload(VALUE mod, ID id, const char *file) - rb_raise(rb_eArgError, "empty file name"); - } - -- if ((tbl = RCLASS_CONST_TBL(mod)) && st_lookup(tbl, (st_data_t)id, &av) && ((rb_const_entry_t*)av)->value != Qundef) -+ if (sa_lookup(RCLASS_CONST_TBL(mod), (sa_index_t)id, &av) && ((rb_const_entry_t*)av)->value != Qundef) - return; - - rb_const_set(mod, id, Qundef); - tbl = RCLASS_IV_TBL(mod); -- if (tbl && st_lookup(tbl, (st_data_t)autoload, &av)) { -+ if (sa_lookup(tbl, (sa_index_t)autoload, &av)) { - tbl = check_autoload_table((VALUE)av); - } - else { -- if (!tbl) tbl = RCLASS_IV_TBL(mod) = st_init_numtable(); - av = (st_data_t)TypedData_Wrap_Struct(0, &autoload_data_type, 0); -- st_add_direct(tbl, (st_data_t)autoload, av); -- DATA_PTR(av) = tbl = st_init_numtable(); -+ sa_insert(tbl, (sa_index_t)autoload, av); -+ DATA_PTR(av) = tbl = sa_new_table(); - } - fn = rb_str_new2(file); - FL_UNSET(fn, FL_TAINT); - OBJ_FREEZE(fn); -- st_insert(tbl, (st_data_t)id, (st_data_t)rb_node_newnode(NODE_MEMO, fn, rb_safe_level(), 0)); -+ sa_insert(tbl, (sa_index_t)id, (st_data_t)rb_node_newnode(NODE_MEMO, fn, rb_safe_level(), 0)); - } - - static NODE* - autoload_delete(VALUE mod, ID id) - { -- st_data_t val, load = 0, n = id; -+ st_data_t val, load = 0; - rb_const_entry_t *ce; - -- st_delete(RCLASS_CONST_TBL(mod), &n, &val); -+ sa_delete(RCLASS_CONST_TBL(mod), (sa_index_t)id, &val); - ce = (rb_const_entry_t*)val; - if (ce) xfree(ce); -- if (st_lookup(RCLASS_IV_TBL(mod), (st_data_t)autoload, &val)) { -- struct st_table *tbl = check_autoload_table((VALUE)val); -+ if (sa_lookup(RCLASS_IV_TBL(mod), (sa_index_t)autoload, &val)) { -+ struct sa_table *tbl = check_autoload_table((VALUE)val); - -- st_delete(tbl, &n, &load); -+ sa_delete(tbl, (sa_index_t)id, &load); - - if (tbl->num_entries == 0) { -- n = autoload; -- st_delete(RCLASS_IV_TBL(mod), &n, &val); -+ sa_delete(RCLASS_IV_TBL(mod), (sa_index_t)autoload, &val); - } - } - -@@ -1509,14 +1467,14 @@ static NODE * - autoload_node(VALUE mod, ID id, const char **loadingpath) - { - VALUE file; -- struct st_table *tbl; -+ struct sa_table *tbl; - st_data_t val; - NODE *load; - const char *loading; - int safe; - -- if (!st_lookup(RCLASS_IV_TBL(mod), autoload, &val) || -- !(tbl = check_autoload_table((VALUE)val)) || !st_lookup(tbl, (st_data_t)id, &val)) { -+ if (!sa_lookup(RCLASS_IV_TBL(mod), (sa_index_t)autoload, &val) || -+ !(tbl = check_autoload_table((VALUE)val)) || !sa_lookup(tbl, (sa_index_t)id, &val)) { - return 0; - } - load = (NODE *)val; -@@ -1541,10 +1499,10 @@ autoload_node(VALUE mod, ID id, const char **loadingpath) - static int - autoload_node_id(VALUE mod, ID id) - { -- struct st_table *tbl = RCLASS_CONST_TBL(mod); -+ struct sa_table *tbl = RCLASS_CONST_TBL(mod); - st_data_t val; - -- if (!tbl || !st_lookup(tbl, (st_data_t)id, &val) || ((rb_const_entry_t*)val)->value != Qundef) { -+ if (!tbl || !sa_lookup(tbl, (sa_index_t)id, &val) || ((rb_const_entry_t*)val)->value != Qundef) { - return 0; - } - return 1; -@@ -1593,7 +1551,7 @@ rb_const_get_0(VALUE klass, ID id, int exclude, int recurse, int visibility) - while (RTEST(tmp)) { - VALUE am = 0; - st_data_t data; -- while (RCLASS_CONST_TBL(tmp) && st_lookup(RCLASS_CONST_TBL(tmp), (st_data_t)id, &data)) { -+ while (sa_lookup(RCLASS_CONST_TBL(tmp), (sa_index_t)id, &data)) { - rb_const_entry_t *ce = (rb_const_entry_t *)data; - if (visibility && ce->flag == CONST_PRIVATE) { - rb_name_error(id, "private constant %s::%s referenced", rb_class2name(klass), rb_id2name(id)); -@@ -1686,12 +1644,12 @@ VALUE - rb_const_remove(VALUE mod, ID id) - { - VALUE val; -- st_data_t v, n = id; -+ st_data_t v; - - if (!OBJ_UNTRUSTED(mod) && rb_safe_level() >= 4) - rb_raise(rb_eSecurityError, "Insecure: can't remove constant"); - rb_check_frozen(mod); -- if (!RCLASS_CONST_TBL(mod) || !st_delete(RCLASS_CONST_TBL(mod), &n, &v)) { -+ if (!sa_delete(RCLASS_CONST_TBL(mod), (sa_index_t)id, &v)) { - if (rb_const_defined_at(mod, id)) { - rb_name_error(id, "cannot remove %s::%s", - rb_class2name(mod), rb_id2name(id)); -@@ -1711,27 +1669,20 @@ rb_const_remove(VALUE mod, ID id) - return val; - } - --static int --sv_i(ID key, rb_const_entry_t *ce, st_table *tbl) --{ -- if (rb_is_const_id(key)) { -- if (!st_lookup(tbl, (st_data_t)key, 0)) { -- st_insert(tbl, (st_data_t)key, (st_data_t)ce); -- } -- } -- return ST_CONTINUE; --} -- - void* - rb_mod_const_at(VALUE mod, void *data) - { -- st_table *tbl = data; -+ sa_table *tbl = data; - if (!tbl) { -- tbl = st_init_numtable(); -+ tbl = sa_new_table(); - } -- if (RCLASS_CONST_TBL(mod)) { -- st_foreach_safe(RCLASS_CONST_TBL(mod), sv_i, (st_data_t)tbl); -+ SA_FOREACH_START(RCLASS_CONST_TBL(mod)); -+ if (rb_is_const_id(entry->key)) { -+ if (!sa_lookup(tbl, entry->key, 0)) { -+ sa_insert(tbl, entry->key, value); -+ } - } -+ SA_FOREACH_END(); - return tbl; - } - -@@ -1748,25 +1699,21 @@ rb_mod_const_of(VALUE mod, void *data) - return data; - } - --static int --list_i(st_data_t key, st_data_t value, VALUE ary) --{ -- ID sym = (ID)key; -- rb_const_entry_t *ce = (rb_const_entry_t *)value; -- if (ce->flag != CONST_PRIVATE) rb_ary_push(ary, ID2SYM(sym)); -- return ST_CONTINUE; --} -- - VALUE - rb_const_list(void *data) - { -- st_table *tbl = data; -+ sa_table *tbl = data; - VALUE ary; - - if (!tbl) return rb_ary_new2(0); - ary = rb_ary_new2(tbl->num_entries); -- st_foreach_safe(tbl, list_i, ary); -- st_free_table(tbl); -+ -+ SA_FOREACH_START(tbl); -+ rb_const_entry_t *ce = (rb_const_entry_t *)value; -+ if (ce->flag != CONST_PRIVATE) rb_ary_push(ary, ID2SYM(entry->key)); -+ SA_FOREACH_END(); -+ -+ sa_free_table(tbl); - - return ary; - } -@@ -1790,7 +1737,7 @@ VALUE - rb_mod_constants(int argc, VALUE *argv, VALUE mod) - { - VALUE inherit; -- st_table *tbl; -+ sa_table *tbl; - - if (argc == 0) { - inherit = Qtrue; -@@ -1817,7 +1764,7 @@ rb_const_defined_0(VALUE klass, ID id, int exclude, int recurse, int visibility) - tmp = klass; - retry: - while (tmp) { -- if (RCLASS_CONST_TBL(tmp) && st_lookup(RCLASS_CONST_TBL(tmp), (st_data_t)id, &value)) { -+ if (sa_lookup(RCLASS_CONST_TBL(tmp), (sa_index_t)id, &value)) { - rb_const_entry_t *ce = (rb_const_entry_t *)value; - if (visibility && ce->flag == CONST_PRIVATE) { - return (int)Qfalse; -@@ -1885,6 +1832,7 @@ void - rb_const_set(VALUE klass, ID id, VALUE val) - { - rb_const_entry_t *ce; -+ st_data_t value; - VALUE visibility = CONST_PUBLIC; - - if (NIL_P(klass)) { -@@ -1893,21 +1841,14 @@ rb_const_set(VALUE klass, ID id, VALUE val) - } - - check_before_mod_set(klass, id, val, "constant"); -- if (!RCLASS_CONST_TBL(klass)) { -- RCLASS_CONST_TBL(klass) = st_init_numtable(); -- } -- else { -- st_data_t value; -- -- if (st_lookup(RCLASS_CONST_TBL(klass), (st_data_t)id, &value)) { -- rb_const_entry_t *ce = (rb_const_entry_t*)value; -- if (ce->value == Qundef) -- autoload_delete(klass, id); -- else { -- visibility = ce->flag; -- rb_warn("already initialized constant %s", rb_id2name(id)); -- } -- } -+ if (sa_lookup(RCLASS_CONST_TBL(klass), (sa_index_t)id, &value)) { -+ rb_const_entry_t *ce = (rb_const_entry_t*)value; -+ if (ce->value == Qundef) -+ autoload_delete(klass, id); -+ else { -+ visibility = ce->flag; -+ rb_warn("already initialized constant %s", rb_id2name(id)); -+ } - } - - rb_vm_change_state(); -@@ -1916,7 +1857,7 @@ rb_const_set(VALUE klass, ID id, VALUE val) - ce->flag = (rb_const_flag_t)visibility; - ce->value = val; - -- st_insert(RCLASS_CONST_TBL(klass), (st_data_t)id, (st_data_t)ce); -+ sa_insert(RCLASS_CONST_TBL(klass), (sa_index_t)id, (st_data_t)ce); - } - - void -@@ -1958,8 +1899,7 @@ set_const_visibility(VALUE mod, int argc, VALUE *argv, rb_const_flag_t flag) - for (i = 0; i < argc; i++) { - VALUE val = argv[i]; - id = rb_to_id(val); -- if (RCLASS_CONST_TBL(mod) && -- st_lookup(RCLASS_CONST_TBL(mod), (st_data_t)id, &v)) { -+ if (sa_lookup(RCLASS_CONST_TBL(mod), (sa_index_t)id, &v)) { - ((rb_const_entry_t*)v)->flag = flag; - } - else { -@@ -2008,7 +1948,7 @@ original_module(VALUE c) - } - - #define CVAR_LOOKUP(v,r) do {\ -- if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass),(st_data_t)id,(v))) {\ -+ if (sa_lookup(RCLASS_IV_TBL(klass),(sa_index_t)id,(v))) {\ - r;\ - }\ - if (FL_TEST(klass, FL_SINGLETON) ) {\ -@@ -2027,7 +1967,7 @@ original_module(VALUE c) - klass = RCLASS_SUPER(klass);\ - }\ - while (klass) {\ -- if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass),(st_data_t)id,(v))) {\ -+ if (sa_lookup(RCLASS_IV_TBL(klass),(sa_index_t)id,(v))) {\ - r;\ - }\ - klass = RCLASS_SUPER(klass);\ -@@ -2043,15 +1983,13 @@ rb_cvar_set(VALUE klass, ID id, VALUE val) - CVAR_LOOKUP(0, {if (!front) front = klass; target = klass;}); - if (target) { - if (front && target != front) { -- st_data_t did = id; -- - if (RTEST(ruby_verbose)) { - rb_warning("class variable %s of %s is overtaken by %s", - rb_id2name(id), rb_class2name(original_module(front)), - rb_class2name(original_module(target))); - } - if (BUILTIN_TYPE(front) == T_CLASS) { -- st_delete(RCLASS_IV_TBL(front),&did,0); -+ sa_delete(RCLASS_IV_TBL(front),(sa_index_t)id,0); - } - } - } -@@ -2060,11 +1998,7 @@ rb_cvar_set(VALUE klass, ID id, VALUE val) - } - - check_before_mod_set(target, id, val, "class variable"); -- if (!RCLASS_IV_TBL(target)) { -- RCLASS_IV_TBL(target) = st_init_numtable(); -- } -- -- st_insert(RCLASS_IV_TBL(target), (st_data_t)id, (st_data_t)val); -+ sa_insert(RCLASS_IV_TBL(target), (sa_index_t)id, (st_data_t)val); - } - - VALUE -@@ -2080,15 +2014,13 @@ rb_cvar_get(VALUE klass, ID id) - rb_id2name(id), rb_class2name(tmp)); - } - if (front && target != front) { -- st_data_t did = id; -- - if (RTEST(ruby_verbose)) { - rb_warning("class variable %s of %s is overtaken by %s", - rb_id2name(id), rb_class2name(original_module(front)), - rb_class2name(original_module(target))); - } - if (BUILTIN_TYPE(front) == T_CLASS) { -- st_delete(RCLASS_IV_TBL(front),&did,0); -+ sa_delete(RCLASS_IV_TBL(front),(sa_index_t)id,0); - } - } - return (VALUE)value; -@@ -2134,7 +2066,7 @@ rb_define_class_variable(VALUE klass, const char *name, VALUE val) - } - - static int --cv_i(ID key, VALUE value, VALUE ary) -+cv_i(sa_index_t key, VALUE value, VALUE ary) - { - if (rb_is_class_id(key)) { - VALUE kval = ID2SYM(key); -@@ -2167,7 +2099,7 @@ rb_mod_class_variables(VALUE obj) - VALUE ary = rb_ary_new(); - - if (RCLASS_IV_TBL(obj)) { -- st_foreach_safe(RCLASS_IV_TBL(obj), cv_i, ary); -+ sa_foreach(RCLASS_IV_TBL(obj), cv_i, ary); - } - return ary; - } -@@ -2196,7 +2128,7 @@ VALUE - rb_mod_remove_cvar(VALUE mod, VALUE name) - { - const ID id = rb_to_id(name); -- st_data_t val, n = id; -+ st_data_t val; - - if (!rb_is_class_id(id)) { - rb_name_error(id, "wrong class variable name %s", rb_id2name(id)); -@@ -2204,7 +2136,7 @@ rb_mod_remove_cvar(VALUE mod, VALUE name) - if (!OBJ_UNTRUSTED(mod) && rb_safe_level() >= 4) - rb_raise(rb_eSecurityError, "Insecure: can't remove class variable"); - rb_check_frozen(mod); -- if (RCLASS_IV_TBL(mod) && st_delete(RCLASS_IV_TBL(mod), &n, &val)) { -+ if (RCLASS_IV_TBL(mod) && sa_delete(RCLASS_IV_TBL(mod), (sa_index_t)id, &val)) { - return (VALUE)val; - } - if (rb_cvar_defined(mod, id)) { -diff --git a/vm.c b/vm.c -index 4a97fba..ecfa90d 100644 ---- a/vm.c -+++ b/vm.c -@@ -1046,7 +1046,7 @@ static void - add_opt_method(VALUE klass, ID mid, VALUE bop) - { - rb_method_entry_t *me; -- if (st_lookup(RCLASS_M_TBL(klass), mid, (void *)&me) && me->def && -+ if (sa_lookup(RCLASS_M_TBL(klass), (sa_index_t)mid, (void *)&me) && me->def && - me->def->type == VM_METHOD_TYPE_CFUNC) { - st_insert(vm_opt_method_table, (st_data_t)me, (st_data_t)bop); - } -diff --git a/vm_insnhelper.c b/vm_insnhelper.c -index 4f709e6..1bfd131 100644 ---- a/vm_insnhelper.c -+++ b/vm_insnhelper.c -@@ -1183,7 +1183,7 @@ vm_get_ev_const(rb_thread_t *th, const rb_iseq_t *iseq, - st_data_t data; - search_continue: - if (RCLASS_CONST_TBL(klass) && -- st_lookup(RCLASS_CONST_TBL(klass), id, &data)) { -+ sa_lookup(RCLASS_CONST_TBL(klass), (sa_index_t)id, &data)) { - val = ((rb_const_entry_t*)data)->value; - if (val == Qundef) { - if (am == klass) break; -@@ -1293,10 +1293,10 @@ vm_getivar(VALUE obj, ID id, IC ic) - st_data_t index; - long len = ROBJECT_NUMIV(obj); - VALUE *ptr = ROBJECT_IVPTR(obj); -- struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); -+ struct sa_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); - - if (iv_index_tbl) { -- if (st_lookup(iv_index_tbl, id, &index)) { -+ if (sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) { - if ((long)index < len) { - val = ptr[index]; - } -@@ -1346,9 +1346,9 @@ vm_setivar(VALUE obj, ID id, VALUE val, IC ic) - } - } - else { -- struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); -+ struct sa_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); - -- if (iv_index_tbl && st_lookup(iv_index_tbl, (st_data_t)id, &index)) { -+ if (iv_index_tbl && sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) { - ic->ic_class = klass; - ic->ic_value.index = index; - ic->ic_vmstat = GET_VM_STATE_VERSION(); -diff --git a/vm_method.c b/vm_method.c -index 6e33603..6567440 100644 ---- a/vm_method.c -+++ b/vm_method.c -@@ -2,38 +2,33 @@ - * This file is included by vm.c - */ - --#define CACHE_SIZE 0x800 --#define CACHE_MASK 0x7ff --#define EXPR1(c,m) ((((c)>>3)^(m))&CACHE_MASK) -- - static void rb_vm_check_redefinition_opt_method(const rb_method_entry_t *me); - - static ID object_id, respond_to_missing; - static ID removed, singleton_removed, undefined, singleton_undefined; - static ID added, singleton_added, attached; - --struct cache_entry { /* method hash table. */ -- VALUE filled_version; /* filled state version */ -- ID mid; /* method's id */ -- VALUE klass; /* receiver's class */ -- rb_method_entry_t *me; --}; -- --static struct cache_entry cache[CACHE_SIZE]; - #define ruby_running (GET_VM()->running) - /* int ruby_running = 0; */ - -+static int -+methods_cache_clear_callback(void *vstart, void *vend, size_t stride, void *data) -+{ -+ VALUE v = (VALUE)vstart; -+ for (; v != (VALUE)vend; v += stride) { -+ switch(BUILTIN_TYPE(v)) { -+ case T_CLASS: -+ case T_MODULE: -+ case T_ICLASS: -+ RCLASS(v)->cache->method_cache_version = 0; -+ } -+ } -+ return 0; -+} - static void - vm_clear_global_method_cache(void) - { -- struct cache_entry *ent, *end; -- -- ent = cache; -- end = ent + CACHE_SIZE; -- while (ent < end) { -- ent->filled_version = 0; -- ent++; -- } -+ rb_objspace_each_objects(methods_cache_clear_callback, NULL); - } - - void -@@ -162,7 +157,7 @@ rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type, - rb_method_definition_t *def, rb_method_flag_t noex) - { - rb_method_entry_t *me; -- st_table *mtbl; -+ sa_table *mtbl; - st_data_t data; - - if (NIL_P(klass)) { -@@ -190,7 +185,7 @@ rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type, - mtbl = RCLASS_M_TBL(klass); - - /* check re-definition */ -- if (st_lookup(mtbl, mid, &data)) { -+ if (sa_lookup(mtbl, (sa_index_t)mid, &data)) { - rb_method_entry_t *old_me = (rb_method_entry_t *)data; - rb_method_definition_t *old_def = old_me->def; - -@@ -248,7 +243,7 @@ rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type, - } - } - -- st_insert(mtbl, mid, (st_data_t) me); -+ sa_insert(mtbl, (sa_index_t)mid, (st_data_t) me); - - return me; - } -@@ -371,7 +366,7 @@ search_method(VALUE klass, ID id) - return 0; - } - -- while (!st_lookup(RCLASS_M_TBL(klass), id, &body)) { -+ while (!sa_lookup(RCLASS_M_TBL(klass), (sa_index_t)id, &body)) { - klass = RCLASS_SUPER(klass); - if (!klass) { - return 0; -@@ -393,20 +388,10 @@ rb_method_entry_get_without_cache(VALUE klass, ID id) - rb_method_entry_t *me = search_method(klass, id); - - if (ruby_running) { -- struct cache_entry *ent; -- ent = cache + EXPR1(klass, id); -- ent->filled_version = GET_VM_STATE_VERSION(); -- ent->klass = klass; -- - if (UNDEFINED_METHOD_ENTRY_P(me)) { -- ent->mid = id; -- ent->me = 0; -- me = 0; -- } -- else { -- ent->mid = id; -- ent->me = me; -+ me = 0; - } -+ sa_insert(&RCLASS(klass)->cache->m_cache_tbl, (sa_index_t)id, (st_data_t)me); - } - - return me; -@@ -415,21 +400,23 @@ rb_method_entry_get_without_cache(VALUE klass, ID id) - rb_method_entry_t * - rb_method_entry(VALUE klass, ID id) - { -- struct cache_entry *ent; -+ rb_class_cache_t *cache = RCLASS(klass)->cache; -+ rb_method_entry_t *me; - -- ent = cache + EXPR1(klass, id); -- if (ent->filled_version == GET_VM_STATE_VERSION() && -- ent->mid == id && ent->klass == klass) { -- return ent->me; -+ if (cache->method_cache_version != GET_VM_STATE_VERSION()) { -+ sa_clear_no_free(&cache->m_cache_tbl); -+ cache->method_cache_version = GET_VM_STATE_VERSION(); -+ } -+ else if (sa_lookup(&cache->m_cache_tbl, (sa_index_t)id, (st_data_t*)&me)) { -+ return me; - } -- - return rb_method_entry_get_without_cache(klass, id); - } - - static void - remove_method(VALUE klass, ID mid) - { -- st_data_t key, data; -+ st_data_t data; - rb_method_entry_t *me = 0; - - if (klass == rb_cObject) { -@@ -443,14 +430,13 @@ remove_method(VALUE klass, ID mid) - rb_warn("removing `%s' may cause serious problems", rb_id2name(mid)); - } - -- if (!st_lookup(RCLASS_M_TBL(klass), mid, &data) || -+ if (!sa_lookup(RCLASS_M_TBL(klass), (sa_index_t)mid, &data) || - !(me = (rb_method_entry_t *)data) || - (!me->def || me->def->type == VM_METHOD_TYPE_UNDEF)) { - rb_name_error(mid, "method `%s' not defined in %s", - rb_id2name(mid), rb_class2name(klass)); - } -- key = (st_data_t)mid; -- st_delete(RCLASS_M_TBL(klass), &key, &data); -+ sa_delete(RCLASS_M_TBL(klass), (sa_index_t)mid, &data); - - rb_vm_check_redefinition_opt_method(me); - rb_clear_cache_for_undef(klass, mid); diff --git a/patches/ruby/1.9.3/p362/railsexpress/12-falcon-array-queue.patch b/patches/ruby/1.9.3/p362/railsexpress/12-falcon-array-queue.patch deleted file mode 100644 index e99cafa1ee..0000000000 --- a/patches/ruby/1.9.3/p362/railsexpress/12-falcon-array-queue.patch +++ /dev/null @@ -1,301 +0,0 @@ -diff --git a/array.c b/array.c -index c33d106..a459a4a 100644 ---- a/array.c -+++ b/array.c -@@ -255,15 +255,24 @@ rb_ary_modify(VALUE ary) - rb_ary_modify_check(ary); - if (ARY_SHARED_P(ary)) { - long len = RARRAY_LEN(ary); -+ VALUE shared = ARY_SHARED(ary); - if (len <= RARRAY_EMBED_LEN_MAX) { - VALUE *ptr = ARY_HEAP_PTR(ary); -- VALUE shared = ARY_SHARED(ary); - FL_UNSET_SHARED(ary); - FL_SET_EMBED(ary); - MEMCPY(ARY_EMBED_PTR(ary), ptr, VALUE, len); - rb_ary_decrement_share(shared); - ARY_SET_EMBED_LEN(ary, len); - } -+ else if (ARY_SHARED_NUM(shared) == 1 && len > RARRAY_LEN(shared)>>1) { -+ long shift = RARRAY_PTR(ary) - RARRAY_PTR(shared); -+ ARY_SET_PTR(ary, RARRAY_PTR(shared)); -+ ARY_SET_CAPA(ary, RARRAY_LEN(shared)); -+ MEMMOVE(RARRAY_PTR(ary), RARRAY_PTR(ary)+shift, VALUE, len); -+ FL_UNSET_SHARED(ary); -+ FL_SET_EMBED(shared); -+ rb_ary_decrement_share(shared); -+ } - else { - VALUE *ptr = ALLOC_N(VALUE, len); - MEMCPY(ptr, RARRAY_PTR(ary), VALUE, len); -@@ -274,6 +283,38 @@ rb_ary_modify(VALUE ary) - } - } - -+static void -+ary_ensure_room_for_push(VALUE ary, long add_len) -+{ -+ long new_len = RARRAY_LEN(ary) + add_len; -+ long capa; -+ -+ if (ARY_SHARED_P(ary)) { -+ if (new_len > RARRAY_EMBED_LEN_MAX) { -+ VALUE shared = ARY_SHARED(ary); -+ if (ARY_SHARED_NUM(shared) == 1) { -+ if (RARRAY_PTR(ary) - RARRAY_PTR(shared) + new_len <= RARRAY_LEN(shared)) { -+ rb_ary_modify_check(ary); -+ } -+ else { -+ /* if array is shared, than it is likely it participate in push/shift pattern */ -+ rb_ary_modify(ary); -+ capa = ARY_CAPA(ary); -+ if (new_len > capa - (capa >> 6)) { -+ ary_double_capa(ary, new_len); -+ } -+ } -+ return; -+ } -+ } -+ } -+ rb_ary_modify(ary); -+ capa = ARY_CAPA(ary); -+ if (new_len > capa) { -+ ary_double_capa(ary, new_len); -+ } -+} -+ - VALUE - rb_ary_freeze(VALUE ary) - { -@@ -446,8 +487,9 @@ ary_make_shared(VALUE ary) - OBJSETUP(shared, 0, T_ARRAY); - FL_UNSET_EMBED(shared); - -- ARY_SET_LEN((VALUE)shared, RARRAY_LEN(ary)); -+ ARY_SET_LEN((VALUE)shared, ARY_CAPA(ary)); - ARY_SET_PTR((VALUE)shared, RARRAY_PTR(ary)); -+ rb_mem_clear(RARRAY_PTR(shared) + RARRAY_LEN(ary), ARY_CAPA(ary) - RARRAY_LEN(ary)); - FL_SET_SHARED_ROOT(shared); - ARY_SET_SHARED_NUM((VALUE)shared, 1); - FL_SET_SHARED(ary); -@@ -737,8 +779,6 @@ ary_take_first_or_last(int argc, VALUE *argv, VALUE ary, enum ary_take_pos_flags - return ary_make_partial(ary, rb_cArray, offset, n); - } - --static VALUE rb_ary_push_1(VALUE ary, VALUE item); -- - /* - * call-seq: - * ary << obj -> ary -@@ -755,8 +795,12 @@ static VALUE rb_ary_push_1(VALUE ary, VALUE item); - VALUE - rb_ary_push(VALUE ary, VALUE item) - { -- rb_ary_modify(ary); -- return rb_ary_push_1(ary, item); -+ long idx = RARRAY_LEN(ary); -+ -+ ary_ensure_room_for_push(ary, 1); -+ RARRAY_PTR(ary)[idx] = item; -+ ARY_SET_LEN(ary, idx + 1); -+ return ary; - } - - static VALUE -@@ -772,6 +816,18 @@ rb_ary_push_1(VALUE ary, VALUE item) - return ary; - } - -+static VALUE -+rb_ary_cat(VALUE ary, const VALUE *ptr, long len) -+{ -+ long oldlen = RARRAY_LEN(ary); -+ -+ ary_ensure_room_for_push(ary, len); -+ -+ MEMCPY(RARRAY_PTR(ary) + oldlen, ptr, VALUE, len); -+ ARY_SET_LEN(ary, oldlen + len); -+ return ary; -+} -+ - /* - * call-seq: - * ary.push(obj, ... ) -> ary -@@ -788,11 +844,7 @@ rb_ary_push_1(VALUE ary, VALUE item) - static VALUE - rb_ary_push_m(int argc, VALUE *argv, VALUE ary) - { -- rb_ary_modify(ary); -- while (argc--) { -- rb_ary_push_1(ary, *argv++); -- } -- return ary; -+ return rb_ary_cat(ary, argv, argc); - } - - VALUE -@@ -920,6 +972,55 @@ rb_ary_shift_m(int argc, VALUE *argv, VALUE ary) - return result; - } - -+static void -+ary_ensure_room_for_unshift(VALUE ary, int argc) -+{ -+ long len = RARRAY_LEN(ary); -+ long new_len = len + argc; -+ long capa; -+ VALUE *head, *sharedp; -+ -+ if (ARY_SHARED_P(ary)) { -+ VALUE shared = ARY_SHARED(ary); -+ capa = RARRAY_LEN(shared); -+ if (ARY_SHARED_NUM(shared) == 1 && capa > new_len) { -+ head = RARRAY_PTR(ary); -+ sharedp = RARRAY_PTR(shared); -+ goto makeroom_if_need; -+ } -+ } -+ -+ rb_ary_modify(ary); -+ capa = ARY_CAPA(ary); -+ if (capa - (capa >> 6) <= new_len) { -+ ary_double_capa(ary, new_len); -+ } -+ -+ /* use shared array for big "queues" */ -+ if (new_len > ARY_DEFAULT_SIZE * 4) { -+ /* make a room for unshifted items */ -+ capa = ARY_CAPA(ary); -+ ary_make_shared(ary); -+ -+ head = sharedp = RARRAY_PTR(ary); -+ goto makeroom; -+makeroom_if_need: -+ if (head - sharedp < argc) { -+ long room; -+makeroom: -+ room = capa - new_len; -+ room -= room >> 4; -+ MEMMOVE(sharedp + argc + room, head, VALUE, len); -+ head = sharedp + argc + room; -+ } -+ ARY_SET_PTR(ary, head - argc); -+ } -+ else { -+ /* sliding items */ -+ MEMMOVE(RARRAY_PTR(ary) + argc, RARRAY_PTR(ary), VALUE, len); -+ } -+} -+ - /* - * call-seq: - * ary.unshift(obj, ...) -> ary -@@ -935,19 +1036,16 @@ rb_ary_shift_m(int argc, VALUE *argv, VALUE ary) - static VALUE - rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary) - { -- long len; -+ long len = RARRAY_LEN(ary); - -- rb_ary_modify(ary); -- if (argc == 0) return ary; -- if (ARY_CAPA(ary) <= (len = RARRAY_LEN(ary)) + argc) { -- ary_double_capa(ary, len + argc); -+ if (argc == 0) { -+ rb_ary_modify_check(ary); -+ return ary; - } - -- /* sliding items */ -- MEMMOVE(RARRAY_PTR(ary) + argc, RARRAY_PTR(ary), VALUE, len); -+ ary_ensure_room_for_unshift(ary, argc); - MEMCPY(RARRAY_PTR(ary), argv, VALUE, argc); -- ARY_INCREASE_LEN(ary, argc); -- -+ ARY_SET_LEN(ary, len + argc); - return ary; - } - -@@ -1309,15 +1407,12 @@ rb_ary_splice(VALUE ary, long beg, long len, VALUE rpl) - rpl = rb_ary_to_ary(rpl); - rlen = RARRAY_LEN(rpl); - } -- rb_ary_modify(ary); - if (beg >= RARRAY_LEN(ary)) { - if (beg > ARY_MAX_SIZE - rlen) { - rb_raise(rb_eIndexError, "index %ld too big", beg); - } -+ ary_ensure_room_for_push(ary, rlen-len); /* len is 0 or negative */ - len = beg + rlen; -- if (len >= ARY_CAPA(ary)) { -- ary_double_capa(ary, len); -- } - rb_mem_clear(RARRAY_PTR(ary) + RARRAY_LEN(ary), beg - RARRAY_LEN(ary)); - if (rlen > 0) { - MEMCPY(RARRAY_PTR(ary) + beg, RARRAY_PTR(rpl), VALUE, rlen); -@@ -1327,6 +1422,7 @@ rb_ary_splice(VALUE ary, long beg, long len, VALUE rpl) - else { - long alen; - -+ rb_ary_modify(ary); - alen = RARRAY_LEN(ary) + rlen - len; - if (alen >= ARY_CAPA(ary)) { - ary_double_capa(ary, alen); -@@ -2116,12 +2212,13 @@ rb_ary_sort_bang(VALUE ary) - if (RARRAY_LEN(ary) > 1) { - VALUE tmp = ary_make_substitution(ary); /* only ary refers tmp */ - struct ary_sort_data data; -+ long len = RARRAY_LEN(ary); - - RBASIC(tmp)->klass = 0; - data.ary = tmp; - data.opt_methods = 0; - data.opt_inited = 0; -- ruby_qsort(RARRAY_PTR(tmp), RARRAY_LEN(tmp), sizeof(VALUE), -+ ruby_qsort(RARRAY_PTR(tmp), len, sizeof(VALUE), - rb_block_given_p()?sort_1:sort_2, &data); - - if (ARY_EMBED_P(tmp)) { -@@ -2138,7 +2235,7 @@ rb_ary_sort_bang(VALUE ary) - if (ARY_HEAP_PTR(ary) == ARY_HEAP_PTR(tmp)) { - assert(!ARY_EMBED_P(ary)); - FL_UNSET_SHARED(ary); -- ARY_SET_CAPA(ary, ARY_CAPA(tmp)); -+ ARY_SET_CAPA(ary, RARRAY_LEN(tmp)); - } - else { - assert(!ARY_SHARED_P(tmp)); -@@ -2153,8 +2250,8 @@ rb_ary_sort_bang(VALUE ary) - xfree(ARY_HEAP_PTR(ary)); - } - ARY_SET_PTR(ary, RARRAY_PTR(tmp)); -- ARY_SET_HEAP_LEN(ary, RARRAY_LEN(tmp)); -- ARY_SET_CAPA(ary, ARY_CAPA(tmp)); -+ ARY_SET_HEAP_LEN(ary, len); -+ ARY_SET_CAPA(ary, RARRAY_LEN(tmp)); - } - /* tmp was lost ownership for the ptr */ - FL_UNSET(tmp, FL_FREEZE); -diff --git a/test/ruby/test_array.rb b/test/ruby/test_array.rb -index 28d3e41..bcad2c0 100644 ---- a/test/ruby/test_array.rb -+++ b/test/ruby/test_array.rb -@@ -414,6 +414,18 @@ class TestArray < Test::Unit::TestCase - a = @cls[1, 2, 3] - a[-1, 0] = a - assert_equal([1, 2, 1, 2, 3, 3], a) -+ -+ a = @cls[] -+ a[5,0] = [5] -+ assert_equal([nil, nil, nil, nil, nil, 5], a) -+ -+ a = @cls[1] -+ a[1,0] = [2] -+ assert_equal([1, 2], a) -+ -+ a = @cls[1] -+ a[1,1] = [2] -+ assert_equal([1, 2], a) - end - - def test_assoc diff --git a/patches/ruby/1.9.3/p374/railsexpress/01-fix-make-clean.patch b/patches/ruby/1.9.3/p374/railsexpress/01-fix-make-clean.patch deleted file mode 100644 index bd3b673664..0000000000 --- a/patches/ruby/1.9.3/p374/railsexpress/01-fix-make-clean.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/lib/mkmf.rb b/lib/mkmf.rb -index 7c706e8..c381a38 100644 ---- a/lib/mkmf.rb -+++ b/lib/mkmf.rb -@@ -2191,7 +2191,7 @@ def init_mkmf(config = CONFIG, rbconfig = RbConfig::CONFIG) - $LOCAL_LIBS = "" - - $cleanfiles = config_string('CLEANFILES') {|s| Shellwords.shellwords(s)} || [] -- $cleanfiles << "mkmf.log" -+ $cleanfiles << "mkmf.log .*.time" - $distcleanfiles = config_string('DISTCLEANFILES') {|s| Shellwords.shellwords(s)} || [] - $distcleandirs = config_string('DISTCLEANDIRS') {|s| Shellwords.shellwords(s)} || [] - diff --git a/patches/ruby/1.9.3/p374/railsexpress/02-railsbench-gc.patch b/patches/ruby/1.9.3/p374/railsexpress/02-railsbench-gc.patch deleted file mode 100644 index a7411ac8d4..0000000000 --- a/patches/ruby/1.9.3/p374/railsexpress/02-railsbench-gc.patch +++ /dev/null @@ -1,1235 +0,0 @@ -diff --git a/configure.in b/configure.in -index c64d981..6099a92 100644 ---- a/configure.in -+++ b/configure.in -@@ -2416,6 +2416,10 @@ if test "$EXEEXT" = .exe; then - AC_SUBST(EXECUTABLE_EXTS) - fi - -+dnl enable gc debugging -+AC_ARG_ENABLE(gcdebug, -+ AS_HELP_STRING([--enable-gcdebug], [build garbage collector with debugging enabled]), -+ [AC_DEFINE(GC_DEBUG,1)]) - dnl } - dnl build section { - -diff --git a/gc.c b/gc.c -index f307ecb..0be1ec9 100644 ---- a/gc.c -+++ b/gc.c -@@ -98,6 +98,15 @@ ruby_gc_params_t initial_params = { - #endif - }; - -+#ifndef HAVE_LONG_LONG -+#define LONG_LONG long -+#endif -+ -+static int heap_min_slots = 10000; -+static int heap_slots_increment = 10000; -+static int initial_heap_slots_increment = 10000; -+static double heap_slots_growth_factor = 1.8; -+ - #define nomem_error GET_VM()->special_exceptions[ruby_error_nomemory] - - #if SIZEOF_LONG == SIZEOF_VOIDP -@@ -302,7 +311,7 @@ typedef struct RVALUE { - struct RComplex complex; - } as; - #ifdef GC_DEBUG -- const char *file; -+ VALUE file; - int line; - #endif - } RVALUE; -@@ -372,11 +381,25 @@ typedef struct rb_objspace { - size_t free_min; - size_t final_num; - size_t do_heap_free; -+ unsigned long max_blocks_to_free; -+ unsigned long freed_blocks; - } heap; - struct { -+ unsigned long processed; -+ unsigned long freed_objects; -+ unsigned long freelist_size; -+ unsigned long zombies; -+ unsigned long free_counts[T_MASK+1]; -+ unsigned long live_counts[T_MASK+1]; -+ unsigned long gc_time_accumulator_before_gc; -+ unsigned long live_after_last_mark_phase; -+ } stats; -+ struct { - int dont_gc; - int dont_lazy_sweep; - int during_gc; -+ int gc_statistics; -+ int verbose_gc_stats; - } flags; - struct { - st_table *table; -@@ -393,6 +416,14 @@ typedef struct rb_objspace { - struct gc_list *global_list; - size_t count; - int gc_stress; -+ long heap_size; -+ unsigned LONG_LONG gc_time_accumulator; -+ FILE* gc_data_file; -+ long gc_collections; -+ unsigned LONG_LONG gc_allocated_size; -+ unsigned LONG_LONG gc_num_allocations; -+ unsigned long live_objects; -+ unsigned LONG_LONG allocated_objects; - } rb_objspace_t; - - #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE -@@ -415,6 +446,16 @@ int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress; - #define heaps_freed objspace->heap.freed - #define dont_gc objspace->flags.dont_gc - #define during_gc objspace->flags.during_gc -+#define gc_statistics objspace->flags.gc_statistics -+#define verbose_gc_stats objspace->flags.verbose_gc_stats -+#define heap_size objspace->heap_size -+#define gc_time_accumulator objspace->gc_time_accumulator -+#define gc_data_file objspace->gc_data_file -+#define gc_collections objspace->gc_collections -+#define gc_allocated_size objspace->gc_allocated_size -+#define gc_num_allocations objspace->gc_num_allocations -+#define live_objects objspace->live_objects -+#define allocated_objects objspace->allocated_objects - #define finalizer_table objspace->final.table - #define deferred_final_list objspace->final.deferred - #define global_List objspace->global_list -@@ -422,6 +463,14 @@ int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress; - #define initial_malloc_limit initial_params.initial_malloc_limit - #define initial_heap_min_slots initial_params.initial_heap_min_slots - #define initial_free_min initial_params.initial_free_min -+#define free_counts objspace->stats.free_counts -+#define live_counts objspace->stats.live_counts -+#define processed objspace->stats.processed -+#define zombies objspace->stats.zombies -+#define freelist_size objspace->stats.freelist_size -+#define freed_objects objspace->stats.freed_objects -+#define gc_time_accumulator_before_gc objspace->stats.gc_time_accumulator_before_gc -+#define live_after_last_mark_phase objspace->stats.live_after_last_mark_phase - - static void rb_objspace_call_finalizer(rb_objspace_t *objspace); - -@@ -444,24 +493,59 @@ static void init_mark_stack(mark_stack_t *stack); - void - rb_gc_set_params(void) - { -- char *malloc_limit_ptr, *heap_min_slots_ptr, *free_min_ptr; -+ char *envp; -+ -+ rb_objspace_t *objspace = &rb_objspace; -+ -+ gc_data_file = stderr; - - if (rb_safe_level() > 0) return; - -- malloc_limit_ptr = getenv("RUBY_GC_MALLOC_LIMIT"); -- if (malloc_limit_ptr != NULL) { -- int malloc_limit_i = atoi(malloc_limit_ptr); -+ envp = getenv("RUBY_GC_STATS"); -+ if (envp != NULL) { -+ int i = atoi(envp); -+ if (i > 0) { -+ verbose_gc_stats = 1; -+ fprintf(stderr, "RUBY_GC_STATS=%d\n", verbose_gc_stats); -+ } -+ /* child processes should not inherit RUBY_GC_STATS */ -+ ruby_unsetenv("RUBY_GC_STATS"); -+ } -+ -+ envp = getenv("RUBY_GC_DATA_FILE"); -+ if (envp != NULL) { -+ FILE* data_file = fopen(envp, "w"); -+ if (data_file != NULL) { -+ gc_data_file = data_file; -+ } -+ else { -+ fprintf(stderr, "can't open gc log file %s for writing, using default\n", envp); -+ } -+ /* child processes should not inherit RUBY_GC_DATA_FILE to avoid clobbering */ -+ ruby_unsetenv("RUBY_GC_DATA_FILE"); -+ } -+ -+ envp = getenv("RUBY_GC_MALLOC_LIMIT"); -+ if (envp != NULL) { -+ int malloc_limit_i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_GC_MALLOC_LIMIT=%s\n", envp); -+ } - if (RTEST(ruby_verbose)) - fprintf(stderr, "malloc_limit=%d (%d)\n", - malloc_limit_i, initial_malloc_limit); - if (malloc_limit_i > 0) { - initial_malloc_limit = malloc_limit_i; -+ // malloc_limit = initial_malloc_limit; - } - } - -- heap_min_slots_ptr = getenv("RUBY_HEAP_MIN_SLOTS"); -- if (heap_min_slots_ptr != NULL) { -- int heap_min_slots_i = atoi(heap_min_slots_ptr); -+ envp = getenv("RUBY_HEAP_MIN_SLOTS"); -+ if (envp != NULL) { -+ int heap_min_slots_i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_MIN_SLOTS=%s\n", envp); -+ } - if (RTEST(ruby_verbose)) - fprintf(stderr, "heap_min_slots=%d (%d)\n", - heap_min_slots_i, initial_heap_min_slots); -@@ -471,15 +555,42 @@ rb_gc_set_params(void) - } - } - -- free_min_ptr = getenv("RUBY_FREE_MIN"); -- if (free_min_ptr != NULL) { -- int free_min_i = atoi(free_min_ptr); -+ if (!(envp = getenv("RUBY_FREE_MIN"))) -+ envp = getenv("RUBY_HEAP_FREE_MIN"); -+ if (envp != NULL) { -+ int free_min_i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_FREE_MIN=%s\n", envp); -+ } - if (RTEST(ruby_verbose)) - fprintf(stderr, "free_min=%d (%d)\n", free_min_i, initial_free_min); - if (free_min_i > 0) { - initial_free_min = free_min_i; - } - } -+ -+ envp = getenv("RUBY_HEAP_SLOTS_INCREMENT"); -+ if (envp != NULL) { -+ int i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_INCREMENT=%s\n", envp); -+ } -+ heap_slots_increment = i; -+ initial_heap_slots_increment = heap_slots_increment; -+ } -+ -+ envp = getenv("RUBY_HEAP_SLOTS_GROWTH_FACTOR"); -+ if (envp != NULL) { -+ double d = atof(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_GROWTH_FACTOR=%s\n", envp); -+ } -+ if (d > 0) { -+ heap_slots_growth_factor = d; -+ } -+ } -+ -+ fflush(gc_data_file); - } - - #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE -@@ -776,6 +887,11 @@ vm_malloc_fixup(rb_objspace_t *objspace, void *mem, size_t size) - mem = (size_t *)mem + 1; - #endif - -+ if (gc_statistics) { -+ gc_allocated_size += size; -+ gc_num_allocations += 1; -+ } -+ - return mem; - } - -@@ -836,6 +952,13 @@ vm_xrealloc(rb_objspace_t *objspace, void *ptr, size_t size) - mem = (size_t *)mem + 1; - #endif - -+ /* TODO: we can't count correctly unless we store old size on heap -+ if (gc_statistics) { -+ gc_allocated_size += size; -+ gc_num_allocations += 1; -+ } -+ */ -+ - return mem; - } - -@@ -917,7 +1040,6 @@ ruby_xfree(void *x) - vm_xfree(&rb_objspace, x); - } - -- - /* - * call-seq: - * GC.enable -> true or false -@@ -963,6 +1085,455 @@ rb_gc_disable(void) - return old ? Qtrue : Qfalse; - } - -+/* -+ * call-seq: -+ * GC.enable_stats => true or false -+ * -+ * Enables garbage collection statistics, returning true if garbage -+ * collection statistics was already enabled. -+ * -+ * GC.enable_stats #=> false or true -+ * GC.enable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = gc_statistics; -+ gc_statistics = 1; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_stats => true or false -+ * -+ * Disables garbage collection statistics, returning true if garbage -+ * collection statistics was already disabled. -+ * -+ * GC.disable_stats #=> false or true -+ * GC.disable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = gc_statistics; -+ gc_statistics = 0; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.stats_enabled? => true or false -+ * -+ * Check whether GC stats have been enabled. -+ * -+ * GC.stats_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_stats_enabled() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return gc_statistics ? Qtrue : Qfalse; -+} -+ -+ -+/* -+ * call-seq: -+ * GC.clear_stats => nil -+ * -+ * Clears garbage collection statistics, returning nil. This resets the number -+ * of collections (GC.collections) and the time used (GC.time) to 0. -+ * -+ * GC.clear_stats #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_clear_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ gc_collections = 0; -+ gc_time_accumulator = 0; -+ gc_time_accumulator_before_gc = 0; -+ gc_allocated_size = 0; -+ gc_num_allocations = 0; -+ return Qnil; -+} -+ -+/* -+ * call-seq: -+ * GC.allocated_size => Integer -+ * -+ * Returns the size of memory (in bytes) allocated since GC statistics collection -+ * was enabled. -+ * -+ * GC.allocated_size #=> 35 -+ * -+ */ -+ -+VALUE -+rb_gc_allocated_size() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_allocated_size); -+#else -+ return ULONG2NUM(gc_allocated_size); -+#endif -+} -+ -+/* -+ * call-seq: -+ * GC.num_allocations => Integer -+ * -+ * Returns the number of memory allocations since GC statistics collection -+ * was enabled. -+ * -+ * GC.num_allocations #=> 150 -+ * -+ */ -+VALUE -+rb_gc_num_allocations() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_num_allocations); -+#else -+ return ULONG2NUM(gc_num_allocations); -+#endif -+} -+ -+/* -+ * call-seq: -+ * GC.enable_trace => true or false -+ * -+ * Enables garbage collection tracing, returning true if garbage -+ * collection tracing was already enabled. -+ * -+ * GC.enable_trace #=> false or true -+ * GC.enable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_trace() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = verbose_gc_stats; -+ verbose_gc_stats = 1; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_trace => true or false -+ * -+ * Disables garbage collection tracing, returning true if garbage -+ * collection tracing was already disabled. -+ * -+ * GC.disable_trace #=> false or true -+ * GC.disable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_trace() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = verbose_gc_stats; -+ verbose_gc_stats = 0; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.trace_enabled? => true or false -+ * -+ * Check whether GC tracing has been enabled. -+ * -+ * GC.trace_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_trace_enabled() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return verbose_gc_stats ? Qtrue : Qfalse; -+} -+ -+ -+const char* GC_LOGFILE_IVAR = "@gc_logfile_name"; -+ -+/* -+ * call-seq: -+ * GC.log_file(filename=nil, mode="w") => boolean -+ * -+ * Changes the GC data log file. Closes the currently open logfile. -+ * Returns true if the file was successfully opened for -+ * writing. Returns false if the file could not be opened for -+ * writing. Returns the name of the current logfile (or nil) if no -+ * parameter is given. Restores logging to stderr when given nil as -+ * an argument. -+ * -+ * GC.log_file #=> nil -+ * GC.log_file "/tmp/gc.log" #=> true -+ * GC.log_file #=> "/tmp/gc.log" -+ * GC.log_file nil #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_log_file(int argc, VALUE *argv, VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ VALUE filename = Qnil; -+ VALUE mode_str = Qnil; -+ FILE* f = NULL; -+ const char* mode = "w"; -+ -+ VALUE current_logfile_name = rb_iv_get(rb_mGC, GC_LOGFILE_IVAR); -+ -+ if (argc==0) -+ return current_logfile_name; -+ -+ rb_scan_args(argc, argv, "02", &filename, &mode_str); -+ -+ if (filename == Qnil) { -+ /* close current logfile and reset logfile to stderr */ -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+ } -+ return Qtrue; -+ } -+ -+ /* we have a real logfile name */ -+ filename = StringValue(filename); -+ -+ if (rb_equal(current_logfile_name, filename) == Qtrue) { -+ /* do nothing if we get the file name we're already logging to */ -+ return Qtrue; -+ } -+ -+ /* get mode for file opening */ -+ if (mode_str != Qnil) -+ { -+ mode = RSTRING_PTR(StringValue(mode_str)); -+ } -+ -+ /* try to open file in given mode */ -+ if (f = fopen(RSTRING_PTR(filename), mode)) { -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ } -+ gc_data_file = f; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, filename); -+ } else { -+ return Qfalse; -+ } -+ return Qtrue; -+} -+ -+/* -+ * call-seq: -+ * GC.log String => String -+ * -+ * Logs string to the GC data file and returns it. -+ * -+ * GC.log "manual GC call" #=> "manual GC call" -+ * -+ */ -+ -+VALUE -+rb_gc_log(self, original_str) -+ VALUE self, original_str; -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ if (original_str == Qnil) { -+ fprintf(gc_data_file, "\n"); -+ } -+ else { -+ VALUE str = StringValue(original_str); -+ char *p = RSTRING_PTR(str); -+ fprintf(gc_data_file, "%s\n", p); -+ } -+ return original_str; -+} -+ -+/* -+ * call-seq: -+ * GC.dump => nil -+ * -+ * dumps information about the current GC data structures to the GC log file -+ * -+ * GC.dump #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_dump() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ size_t i; -+ -+ for (i = 0; i < heaps_used; i++) { -+ size_t limit = objspace->heap.sorted[i].slot->limit; -+ fprintf(gc_data_file, "HEAP[%2lu]: size=%7lu\n", (unsigned long)i, (unsigned long)limit); -+ } -+ -+ return Qnil; -+} -+ -+static const char* obj_type(VALUE tp); -+ -+#ifdef GC_DEBUG -+/* -+ * call-seq: -+ * GC.dump_file_and_line_info(String, boolean) => nil -+ * -+ * dumps information on which currently allocated object was created by which file and on which line -+ * -+ * GC.dump_file_and_line_info(String, boolean) #=> nil -+ * -+ * The second parameter specifies whether class names should be included in the dump. -+ * Note that including class names will allocate additional string objects on the heap. -+ * -+ */ -+ -+VALUE -+rb_gc_dump_file_and_line_info(int argc, VALUE *argv) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ VALUE filename, str, include_classnames = Qnil; -+ char *fname = NULL; -+ char *klass = NULL; -+ FILE* f = NULL; -+ size_t i = 0; -+ -+ rb_scan_args(argc, argv, "11", &filename, &include_classnames); -+ -+ str = StringValue(filename); -+ fname = RSTRING_PTR(str); -+ f = fopen(fname, "w"); -+ -+ for (i = 0; i < heaps_used; i++) { -+ RVALUE *p, *pend; -+ -+ p = objspace->heap.sorted[i].start; pend = objspace->heap.sorted[i].end; -+ for (;p < pend; p++) { -+ if (p->as.basic.flags) { -+ const char *src_filename = (p->file && p->file != Qnil )? RSTRING_PTR(p->file) : ""; -+ fprintf(f, "%s:%s:%d", obj_type(p->as.basic.flags & T_MASK), src_filename, (int)p->line); -+ // rb_obj_classname will create objects on the heap, we need a better solution -+ if (include_classnames == Qtrue) { -+ /* write the class */ -+ fprintf(f, ":"); -+ switch (BUILTIN_TYPE(p)) { -+ case T_NONE: -+ fprintf(f, "__none__"); -+ break; -+ case T_UNDEF: -+ fprintf(f, "__undef__"); -+ break; -+ case T_NODE: -+ fprintf(f, "__node__"); -+ break; -+ default: -+ if (!p->as.basic.klass) { -+ fprintf(f, "__unknown__"); -+ } else { -+ fprintf(f, "%s", rb_obj_classname((VALUE)p)); -+ } -+ } -+ /* print object size for some known object types */ -+ switch (BUILTIN_TYPE(p)) { -+ case T_STRING: -+ fprintf(f, ":%lu", RSTRING_LEN(p)); -+ break; -+ case T_ARRAY: -+ fprintf(f, ":%lu", RARRAY_LEN(p)); -+ break; -+ case T_HASH: -+ fprintf(f, ":%lu", (long unsigned int)RHASH_SIZE(p)); -+ break; -+ } -+ } -+ fprintf(f, "\n"); -+ } -+ } -+ } -+ fclose(f); -+ return Qnil; -+} -+#endif -+ -+/* -+ * call-seq: -+ * GC.heap_slots => Integer -+ * -+ * Returns the number of heap slots available for object allocations. -+ * -+ * GC.heap_slots #=> 10000 -+ * -+ */ -+VALUE -+rb_gc_heap_slots() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return LONG2NUM(heap_size); -+} -+ -+ -+/* -+ * call-seq: -+ * GC.collections => Integer -+ * -+ * Returns the number of garbage collections performed while GC statistics collection -+ * was enabled. -+ * -+ * GC.collections #=> 35 -+ * -+ */ -+ -+VALUE -+rb_gc_collections() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return LONG2NUM(gc_collections); -+} -+ -+/* -+ * call-seq: -+ * GC.time => Integer -+ * -+ * Returns the time spent during garbage collection while GC statistics collection -+ * was enabled (in micro seconds). -+ * -+ * GC.time #=> 20000 -+ * -+ */ -+ -+VALUE -+rb_gc_time() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return LL2NUM(gc_time_accumulator); -+#else -+ return LONG2NUM(gc_time_accumulator); -+#endif -+} -+ - VALUE rb_mGC; - - void -@@ -1034,6 +1605,12 @@ allocate_sorted_heaps(rb_objspace_t *objspace, size_t next_heaps_length) - static void - assign_heap_slot(rb_objspace_t *objspace) - { -+ /* -+ if (gc_statistics & verbose_gc_stats) { -+ fprintf(gc_data_file, "assigning heap slot\n"); -+ } -+ */ -+ - RVALUE *p, *pend, *membase; - struct heaps_slot *slot; - size_t hi, lo, mid; -@@ -1095,6 +1672,7 @@ assign_heap_slot(rb_objspace_t *objspace) - if (lomem == 0 || lomem > p) lomem = p; - if (himem < pend) himem = pend; - heaps_used++; -+ heap_size += objs; - - while (p < pend) { - p->as.free.flags = 0; -@@ -1151,7 +1729,7 @@ initial_expand_heap(rb_objspace_t *objspace) - static void - set_heaps_increment(rb_objspace_t *objspace) - { -- size_t next_heaps_length = (size_t)(heaps_used * 1.8); -+ size_t next_heaps_length = (size_t)(heaps_used * heap_slots_growth_factor); - - if (next_heaps_length == heaps_used) { - next_heaps_length++; -@@ -1184,6 +1762,22 @@ rb_during_gc(void) - - #define RANY(o) ((RVALUE*)(o)) - -+#ifdef GC_DEBUG -+static VALUE -+_rb_sourcefile(void) -+{ -+ rb_thread_t *th = GET_THREAD(); -+ rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp); -+ -+ if (cfp) { -+ return cfp->iseq->filename; -+ } -+ else { -+ return Qnil; -+ } -+} -+#endif -+ - VALUE - rb_newobj(void) - { -@@ -1215,9 +1809,11 @@ rb_newobj(void) - - MEMZERO((void*)obj, RVALUE, 1); - #ifdef GC_DEBUG -- RANY(obj)->file = rb_sourcefile(); -+ RANY(obj)->file = _rb_sourcefile(); - RANY(obj)->line = rb_sourceline(); - #endif -+ live_objects++; -+ allocated_objects++; - GC_PROF_INC_LIVE_NUM; - - return obj; -@@ -1769,6 +2365,12 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr) - { - register RVALUE *obj = RANY(ptr); - -+#ifdef GC_DEBUG -+ if (obj->file && obj->file != Qnil && is_pointer_to_heap(objspace, (void*)obj->file)) { -+ gc_mark(objspace, obj->file, lev); -+ } -+#endif -+ - goto marking; /* skip */ - - again: -@@ -1779,6 +2381,12 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr) - obj->as.basic.flags |= FL_MARK; - objspace->heap.live_num++; - -+#ifdef GC_DEBUG -+ if (obj->file && obj->file != Qnil && is_pointer_to_heap(objspace, (void*)obj->file)) { -+ gc_mark(objspace, obj->file, lev); -+ } -+#endif -+ - marking: - if (FL_TEST(obj, FL_EXIVAR)) { - rb_mark_generic_ivar(ptr); -@@ -2121,6 +2729,25 @@ free_unused_heaps(rb_objspace_t *objspace) - } - } - -+static inline unsigned long -+elapsed_musecs(struct timeval since) -+{ -+ struct timeval now; -+ struct timeval temp; -+ -+ gettimeofday(&now, NULL); -+ -+ if ((now.tv_usec-since.tv_usec)<0) { -+ temp.tv_sec = now.tv_sec-since.tv_sec-1; -+ temp.tv_usec = 1000000+now.tv_usec-since.tv_usec; -+ } else { -+ temp.tv_sec = now.tv_sec-since.tv_sec; -+ temp.tv_usec = now.tv_usec-since.tv_usec; -+ } -+ -+ return temp.tv_sec*1000000 + temp.tv_usec; -+} -+ - static void - slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - { -@@ -2128,14 +2755,23 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - RVALUE *p, *pend; - RVALUE *free = freelist, *final = deferred_final_list; - int deferred; -+ int do_gc_stats = gc_statistics & verbose_gc_stats; -+ -+ struct timeval tv1; -+ if (gc_statistics) gettimeofday(&tv1, NULL); - - p = sweep_slot->slot; pend = p + sweep_slot->limit; - while (p < pend) { - if (!(p->as.basic.flags & FL_MARK)) { -+ if (do_gc_stats && !p->as.basic.flags) { -+ /* slot was free before GC */ -+ freelist_size++; -+ } - if (p->as.basic.flags && - ((deferred = obj_free(objspace, (VALUE)p)) || - (FL_TEST(p, FL_FINALIZE)))) { - if (!deferred) { -+ if (do_gc_stats) zombies++; - p->as.free.flags = T_ZOMBIE; - RDATA(p)->dfree = 0; - } -@@ -2145,6 +2781,10 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - final_num++; - } - else { -+ if (do_gc_stats) { -+ VALUE obt = p->as.basic.flags & T_MASK; -+ if (obt) free_counts[obt]++; -+ } - add_freelist(objspace, p); - free_num++; - } -@@ -2152,13 +2792,22 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - else if (BUILTIN_TYPE(p) == T_ZOMBIE) { - /* objects to be finalized */ - /* do nothing remain marked */ -+ if (do_gc_stats) zombies++; - } - else { - RBASIC(p)->flags &= ~FL_MARK; -+ if (do_gc_stats) { -+ live_counts[p->as.basic.flags & T_MASK]++; -+ } - } - p++; -+ processed++; - } -- if (final_num + free_num == sweep_slot->limit && -+ -+ freed_objects += free_num; -+ -+ if (objspace->heap.freed_blocks < objspace->heap.max_blocks_to_free && -+ final_num + free_num == sweep_slot->limit && - objspace->heap.free_num > objspace->heap.do_heap_free) { - RVALUE *pp; - -@@ -2169,6 +2818,8 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - sweep_slot->limit = final_num; - freelist = free; /* cancel this page from freelist */ - unlink_heap_slot(objspace, sweep_slot); -+ objspace->heap.freed_blocks += 1; -+ heap_size -= final_num + free_num; - } - else { - objspace->heap.free_num += free_num; -@@ -2181,6 +2832,10 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - RUBY_VM_SET_FINALIZER_INTERRUPT(th); - } - } -+ -+ if (gc_statistics) { -+ gc_time_accumulator += elapsed_musecs(tv1); -+ } - } - - static int -@@ -2201,6 +2856,21 @@ ready_to_gc(rb_objspace_t *objspace) - static void - before_gc_sweep(rb_objspace_t *objspace) - { -+ if (gc_statistics & verbose_gc_stats) { -+ /* -+ fprintf(gc_data_file, "Sweep started\n"); -+ */ -+ freed_objects = 0; -+ processed = 0; -+ zombies = 0; -+ freelist_size = 0; -+ MEMZERO((void*)free_counts, unsigned long, T_MASK+1); -+ MEMZERO((void*)live_counts, unsigned long, T_MASK+1); -+ } -+ -+ objspace->heap.max_blocks_to_free = heaps_used - (heap_min_slots / HEAP_OBJ_LIMIT); -+ objspace->heap.freed_blocks = 0; -+ - freelist = 0; - objspace->heap.do_heap_free = (size_t)((heaps_used * HEAP_OBJ_LIMIT) * 0.65); - objspace->heap.free_min = (size_t)((heaps_used * HEAP_OBJ_LIMIT) * 0.2); -@@ -2220,8 +2890,13 @@ before_gc_sweep(rb_objspace_t *objspace) - static void - after_gc_sweep(rb_objspace_t *objspace) - { -+ int i; -+ struct timeval tv1; -+ - GC_PROF_SET_MALLOC_INFO; - -+ if (gc_statistics) gettimeofday(&tv1, NULL); -+ - if (objspace->heap.free_num < objspace->heap.free_min) { - set_heaps_increment(objspace); - heaps_increment(objspace); -@@ -2234,6 +2909,29 @@ after_gc_sweep(rb_objspace_t *objspace) - malloc_increase = 0; - - free_unused_heaps(objspace); -+ -+ if (gc_statistics) { -+ gc_time_accumulator += elapsed_musecs(tv1); -+ -+ if (verbose_gc_stats) { -+ /* log gc stats if requested */ -+ fprintf(gc_data_file, "GC time: %lu musec\n", (unsigned long)(gc_time_accumulator-gc_time_accumulator_before_gc)); -+ fprintf(gc_data_file, "objects processed: %7lu\n", (unsigned long)processed); -+ fprintf(gc_data_file, "live objects : %7lu\n", (unsigned long)live_after_last_mark_phase); -+ fprintf(gc_data_file, "freelist objects : %7lu\n", (unsigned long)freelist_size); -+ fprintf(gc_data_file, "freed objects : %7lu\n", (unsigned long)freed_objects); -+ fprintf(gc_data_file, "zombies : %7lu\n", (unsigned long)zombies); -+ for(i=0; i0 || live_counts[i]>0) { -+ fprintf(gc_data_file, -+ "kept %7lu / freed %7lu objects of type %s\n", -+ (unsigned long)live_counts[i], (unsigned long)free_counts[i], obj_type((int)i)); -+ } -+ } -+ rb_gc_dump(); -+ fflush(gc_data_file); -+ } -+ } - } - - static int -@@ -2267,9 +2965,11 @@ rest_sweep(rb_objspace_t *objspace) - - static void gc_marks(rb_objspace_t *objspace); - -+/* only called from rb_new_obj */ - static int - gc_lazy_sweep(rb_objspace_t *objspace) - { -+ struct timeval gctv1; - int res; - INIT_GC_PROF_PARAMS; - -@@ -2291,7 +2991,6 @@ gc_lazy_sweep(rb_objspace_t *objspace) - GC_PROF_TIMER_STOP(Qfalse); - return res; - } -- after_gc_sweep(objspace); - } - else { - if (heaps_increment(objspace)) { -@@ -2299,6 +2998,18 @@ gc_lazy_sweep(rb_objspace_t *objspace) - return TRUE; - } - } -+ after_gc_sweep(objspace); -+ -+ if (gc_statistics) { -+ gc_time_accumulator_before_gc = gc_time_accumulator; -+ gc_collections++; -+ gettimeofday(&gctv1, NULL); -+ /* -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "Garbage collection started (gc_lazy_sweep)\n"); -+ } -+ */ -+ } - - gc_marks(objspace); - -@@ -2307,6 +3018,10 @@ gc_lazy_sweep(rb_objspace_t *objspace) - set_heaps_increment(objspace); - } - -+ if (gc_statistics) { -+ gc_time_accumulator += elapsed_musecs(gctv1); -+ } -+ - GC_PROF_SWEEP_TIMER_START; - if(!(res = lazy_sweep(objspace))) { - after_gc_sweep(objspace); -@@ -2318,6 +3033,7 @@ gc_lazy_sweep(rb_objspace_t *objspace) - GC_PROF_SWEEP_TIMER_STOP; - - GC_PROF_TIMER_STOP(Qtrue); -+ - return res; - } - -@@ -2544,9 +3260,15 @@ gc_marks(rb_objspace_t *objspace) - rb_thread_t *th = GET_THREAD(); - GC_PROF_MARK_TIMER_START; - -+ /* -+ if (gc_statistics & verbose_gc_stats) { -+ fprintf(gc_data_file, "Marking objects\n"); -+ } -+ */ -+ - objspace->heap.live_num = 0; - objspace->count++; -- -+ live_objects = 0; - - SET_STACK_END; - -@@ -2578,11 +3300,15 @@ gc_marks(rb_objspace_t *objspace) - gc_mark_stacked_objects(objspace); - - GC_PROF_MARK_TIMER_STOP; -+ -+ live_after_last_mark_phase = objspace->heap.live_num; - } - - static int - garbage_collect(rb_objspace_t *objspace) - { -+ struct timeval gctv1; -+ - INIT_GC_PROF_PARAMS; - - if (GC_NOTIFY) printf("start garbage_collect()\n"); -@@ -2598,15 +3324,31 @@ garbage_collect(rb_objspace_t *objspace) - - rest_sweep(objspace); - -+ if (gc_statistics) { -+ gc_time_accumulator_before_gc = gc_time_accumulator; -+ gc_collections++; -+ gettimeofday(&gctv1, NULL); -+ /* -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "Garbage collection started (garbage_collect)\n"); -+ } -+ */ -+ } -+ - during_gc++; - gc_marks(objspace); - -+ if (gc_statistics) { -+ gc_time_accumulator += elapsed_musecs(gctv1); -+ } -+ - GC_PROF_SWEEP_TIMER_START; - gc_sweep(objspace); - GC_PROF_SWEEP_TIMER_STOP; - - GC_PROF_TIMER_STOP(Qtrue); - if (GC_NOTIFY) printf("end garbage_collect()\n"); -+ - return TRUE; - } - -@@ -3095,6 +3837,39 @@ rb_gc_call_finalizer_at_exit(void) - rb_objspace_call_finalizer(&rb_objspace); - } - -+static const char* obj_type(VALUE type) -+{ -+ switch (type) { -+ case T_NIL : return "NIL"; -+ case T_OBJECT : return "OBJECT"; -+ case T_CLASS : return "CLASS"; -+ case T_ICLASS : return "ICLASS"; -+ case T_MODULE : return "MODULE"; -+ case T_FLOAT : return "FLOAT"; -+ case T_COMPLEX: return "COMPLEX"; -+ case T_RATIONAL: return "RATIONAL"; -+ case T_STRING : return "STRING"; -+ case T_REGEXP : return "REGEXP"; -+ case T_ARRAY : return "ARRAY"; -+ case T_FIXNUM : return "FIXNUM"; -+ case T_HASH : return "HASH"; -+ case T_STRUCT : return "STRUCT"; -+ case T_BIGNUM : return "BIGNUM"; -+ case T_FILE : return "FILE"; -+ -+ case T_TRUE : return "TRUE"; -+ case T_FALSE : return "FALSE"; -+ case T_DATA : return "DATA"; -+ case T_MATCH : return "MATCH"; -+ case T_SYMBOL : return "SYMBOL"; -+ case T_ZOMBIE : return "ZOMBIE"; -+ -+ case T_UNDEF : return "UNDEF"; -+ case T_NODE : return "NODE"; -+ default: return "____"; -+ } -+} -+ - static void - rb_objspace_call_finalizer(rb_objspace_t *objspace) - { -@@ -3403,6 +4178,49 @@ count_objects(int argc, VALUE *argv, VALUE os) - return hash; - } - -+/* call-seq: -+ * ObjectSpace.live_objects => number -+ * -+ * Returns the count of objects currently allocated in the system. This goes -+ * down after the garbage collector runs. -+ */ -+static -+VALUE os_live_objects(VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return ULONG2NUM(live_objects); -+} -+ -+unsigned long rb_os_live_objects() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return live_objects; -+} -+ -+/* call-seq: -+ * ObjectSpace.allocated_objects => number -+ * -+ * Returns the count of objects allocated since the Ruby interpreter has -+ * started. This number can only increase. To know how many objects are -+ * currently allocated, use ObjectSpace::live_objects -+ */ -+static -+VALUE os_allocated_objects(VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if defined(HAVE_LONG_LONG) -+ return ULL2NUM(allocated_objects); -+#else -+ return ULONG2NUM(allocated_objects); -+#endif -+} -+ -+unsigned LONG_LONG rb_os_allocated_objects() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return allocated_objects; -+} -+ - /* - * call-seq: - * GC.count -> Integer -@@ -3695,6 +4513,28 @@ Init_GC(void) - rb_define_singleton_method(rb_mGC, "stat", gc_stat, -1); - rb_define_method(rb_mGC, "garbage_collect", rb_gc_start, 0); - -+ rb_define_singleton_method(rb_mGC, "enable_stats", rb_gc_enable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "disable_stats", rb_gc_disable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "stats_enabled?", rb_gc_stats_enabled, 0); -+ rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0); -+ rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); -+ rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); -+ -+ rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); -+ rb_define_singleton_method(rb_mGC, "log_file", rb_gc_log_file, -1); -+ rb_define_singleton_method(rb_mGC, "enable_trace", rb_gc_enable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "disable_trace", rb_gc_disable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "trace_enabled?", rb_gc_trace_enabled, 0); -+ -+ rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); -+ rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); -+ rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); -+#ifdef GC_DEBUG -+ rb_define_singleton_method(rb_mGC, "dump_file_and_line_info", rb_gc_dump_file_and_line_info, -1); -+#endif -+ - 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); -@@ -3708,6 +4548,9 @@ Init_GC(void) - rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1); - rb_define_module_function(rb_mObSpace, "garbage_collect", rb_gc_start, 0); - -+ rb_define_module_function(rb_mObSpace, "live_objects", os_live_objects, 0); -+ rb_define_module_function(rb_mObSpace, "allocated_objects", os_allocated_objects, 0); -+ - rb_define_module_function(rb_mObSpace, "define_finalizer", define_final, -1); - rb_define_module_function(rb_mObSpace, "undefine_finalizer", undefine_final, 1); - diff --git a/patches/ruby/1.9.3/p374/railsexpress/03-display-more-detailed-stack-trace.patch b/patches/ruby/1.9.3/p374/railsexpress/03-display-more-detailed-stack-trace.patch deleted file mode 100644 index 5c7ad30352..0000000000 --- a/patches/ruby/1.9.3/p374/railsexpress/03-display-more-detailed-stack-trace.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/eval_error.c b/eval_error.c -index fd06adf..69c3b48 100644 ---- a/eval_error.c -+++ b/eval_error.c -@@ -164,8 +164,8 @@ error_print(void) - int skip = eclass == rb_eSysStackError; - - #define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5) --#define TRACE_HEAD 8 --#define TRACE_TAIL 5 -+#define TRACE_HEAD 100 -+#define TRACE_TAIL 100 - - for (i = 1; i < len; i++) { - if (TYPE(ptr[i]) == T_STRING) { diff --git a/patches/ruby/1.9.3/p374/railsexpress/04-fork-support-for-gc-logging.patch b/patches/ruby/1.9.3/p374/railsexpress/04-fork-support-for-gc-logging.patch deleted file mode 100644 index bb263566cc..0000000000 --- a/patches/ruby/1.9.3/p374/railsexpress/04-fork-support-for-gc-logging.patch +++ /dev/null @@ -1,68 +0,0 @@ -diff --git a/gc.c b/gc.c -index 0be1ec9..c198770 100644 ---- a/gc.c -+++ b/gc.c -@@ -1345,6 +1345,34 @@ rb_gc_log_file(int argc, VALUE *argv, VALUE self) - } - - /* -+ * Called from process.c before a fork. Flushes the gc log file to -+ * avoid writing the buffered output twice (once in the parent, and -+ * once in the child). -+ */ -+void -+rb_gc_before_fork() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ fflush(gc_data_file); -+} -+ -+/* -+ * Called from process.c after a fork in the child process. Turns off -+ * logging, disables GC stats and resets all gc counters and timing -+ * information. -+ */ -+void -+rb_gc_after_fork() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ rb_gc_disable_stats(); -+ rb_gc_clear_stats(); -+ rb_gc_disable_trace(); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+} -+ -+/* - * call-seq: - * GC.log String => String - * -diff --git a/include/ruby/intern.h b/include/ruby/intern.h -index 9745afd..7c3d970 100644 ---- a/include/ruby/intern.h -+++ b/include/ruby/intern.h -@@ -426,6 +426,8 @@ void rb_gc_call_finalizer_at_exit(void); - VALUE rb_gc_enable(void); - VALUE rb_gc_disable(void); - VALUE rb_gc_start(void); -+void rb_gc_before_fork _((void)); -+void rb_gc_after_fork _((void)); - #define Init_stack(addr) ruby_init_stack(addr) - void rb_gc_set_params(void); - /* hash.c */ -diff --git a/process.c b/process.c -index 99cfc69..8bee602 100644 ---- a/process.c -+++ b/process.c -@@ -2804,9 +2804,11 @@ rb_f_fork(VALUE obj) - rb_pid_t pid; - - rb_secure(2); -+ rb_gc_before_fork(); - - switch (pid = rb_fork(0, 0, 0, Qnil)) { - case 0: -+ rb_gc_after_fork(); - rb_thread_atfork(); - if (rb_block_given_p()) { - int status; diff --git a/patches/ruby/1.9.3/p374/railsexpress/05-track-live-dataset-size.patch b/patches/ruby/1.9.3/p374/railsexpress/05-track-live-dataset-size.patch deleted file mode 100644 index e1775107b6..0000000000 --- a/patches/ruby/1.9.3/p374/railsexpress/05-track-live-dataset-size.patch +++ /dev/null @@ -1,45 +0,0 @@ -diff --git a/gc.c b/gc.c -index c198770..68dd48a 100644 ---- a/gc.c -+++ b/gc.c -@@ -281,7 +281,6 @@ getrusage_time(void) - #define GC_PROF_DEC_LIVE_NUM - #endif - -- - #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__) - #pragma pack(push, 1) /* magic for reducing sizeof(RVALUE): 24 -> 20 */ - #endif -@@ -1562,6 +1561,24 @@ rb_gc_time() - #endif - } - -+/* -+ * call-seq: -+ * GC.heap_slots_live_after_last_gc => Integer -+ * -+ * Returns the number of heap slots which were live after the last garbage collection. -+ * -+ * GC.heap_slots_live_after_last_gc #=> 231223 -+ * -+ */ -+VALUE -+rb_gc_heap_slots_live_after_last_gc() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return ULONG2NUM(live_after_last_mark_phase); -+} -+ -+ -+ - VALUE rb_mGC; - - void -@@ -4548,6 +4565,7 @@ Init_GC(void) - rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); - rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); - rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots_live_after_last_gc", rb_gc_heap_slots_live_after_last_gc, 0); - rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); - - rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); diff --git a/patches/ruby/1.9.3/p374/railsexpress/06-webrick_204_304_keep_alive_fix.patch b/patches/ruby/1.9.3/p374/railsexpress/06-webrick_204_304_keep_alive_fix.patch deleted file mode 100644 index 34d9b78133..0000000000 --- a/patches/ruby/1.9.3/p374/railsexpress/06-webrick_204_304_keep_alive_fix.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/lib/webrick/httpresponse.rb b/lib/webrick/httpresponse.rb -index 0d36c07..ce72b3f 100644 ---- a/lib/webrick/httpresponse.rb -+++ b/lib/webrick/httpresponse.rb -@@ -202,7 +202,7 @@ module WEBrick - if @header['connection'] == "close" - @keep_alive = false - elsif keep_alive? -- if chunked? || @header['content-length'] -+ if chunked? || @header['content-length'] || @status == 304 || @status == 204 - @header['connection'] = "Keep-Alive" - else - msg = "Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true" diff --git a/patches/ruby/1.9.3/p374/railsexpress/07-export-a-few-more-symbols-for-ruby-prof.patch b/patches/ruby/1.9.3/p374/railsexpress/07-export-a-few-more-symbols-for-ruby-prof.patch deleted file mode 100644 index 7145443e98..0000000000 --- a/patches/ruby/1.9.3/p374/railsexpress/07-export-a-few-more-symbols-for-ruby-prof.patch +++ /dev/null @@ -1,124 +0,0 @@ -diff --git a/gc.c b/gc.c -index 68dd48a..80c3e05 100644 ---- a/gc.c -+++ b/gc.c -@@ -1052,6 +1052,7 @@ ruby_xfree(void *x) - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_enable(void) - { -@@ -1074,6 +1075,7 @@ rb_gc_enable(void) - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_disable(void) - { -@@ -1096,6 +1098,7 @@ rb_gc_disable(void) - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_enable_stats() - { -@@ -1117,6 +1120,7 @@ rb_gc_enable_stats() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_disable_stats() - { -@@ -1136,6 +1140,7 @@ rb_gc_disable_stats() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_stats_enabled() - { -@@ -1155,6 +1160,7 @@ rb_gc_stats_enabled() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_clear_stats() - { -@@ -1178,6 +1184,7 @@ rb_gc_clear_stats() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_allocated_size() - { -@@ -1199,6 +1206,7 @@ rb_gc_allocated_size() - * GC.num_allocations #=> 150 - * - */ -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_num_allocations() - { -@@ -1222,6 +1230,7 @@ rb_gc_num_allocations() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_enable_trace() - { -@@ -1243,6 +1252,7 @@ rb_gc_enable_trace() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_disable_trace() - { -@@ -1262,6 +1272,7 @@ rb_gc_disable_trace() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_trace_enabled() - { -@@ -1290,6 +1301,7 @@ const char* GC_LOGFILE_IVAR = "@gc_logfile_name"; - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_log_file(int argc, VALUE *argv, VALUE self) - { -@@ -1532,6 +1544,7 @@ rb_gc_heap_slots() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_collections() - { -@@ -1550,6 +1563,7 @@ rb_gc_collections() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_time() - { -@@ -4260,6 +4274,7 @@ VALUE os_allocated_objects(VALUE self) - #endif - } - -+RUBY_FUNC_EXPORTED - unsigned LONG_LONG rb_os_allocated_objects() - { - rb_objspace_t *objspace = &rb_objspace; diff --git a/patches/ruby/1.9.3/p374/railsexpress/08-thread-variables.patch b/patches/ruby/1.9.3/p374/railsexpress/08-thread-variables.patch deleted file mode 100644 index 303fb18d86..0000000000 --- a/patches/ruby/1.9.3/p374/railsexpress/08-thread-variables.patch +++ /dev/null @@ -1,319 +0,0 @@ -diff --git a/NEWS b/NEWS -index 30fec33..9f6c172 100644 ---- a/NEWS -+++ b/NEWS -@@ -103,6 +103,16 @@ with all sufficient information, see the ChangeLog file. - * String#prepend - * String#byteslice - -+ * Thread -+ * added method: -+ * added Thread#thread_variable_get for getting thread local variables -+ (these are different than Fiber local variables). -+ * added Thread#thread_variable_set for setting thread local variables. -+ * added Thread#thread_variables for getting a list of the thread local -+ variable keys. -+ * added Thread#thread_variable? for testing to see if a particular thread -+ variable has been set. -+ - * Time - * extended method: - * Time#strftime supports %:z and %::z. -diff --git a/test/ruby/test_thread.rb b/test/ruby/test_thread.rb -index e8cb3b1..9ff491d 100644 ---- a/test/ruby/test_thread.rb -+++ b/test/ruby/test_thread.rb -@@ -27,6 +27,79 @@ class TestThread < Test::Unit::TestCase - end - end - -+ def test_main_thread_variable_in_enumerator -+ assert_equal Thread.main, Thread.current -+ -+ Thread.current.thread_variable_set :foo, "bar" -+ -+ thread, value = Fiber.new { -+ Fiber.yield [Thread.current, Thread.current.thread_variable_get(:foo)] -+ }.resume -+ -+ assert_equal Thread.current, thread -+ assert_equal Thread.current.thread_variable_get(:foo), value -+ end -+ -+ def test_thread_variable_in_enumerator -+ Thread.new { -+ Thread.current.thread_variable_set :foo, "bar" -+ -+ thread, value = Fiber.new { -+ Fiber.yield [Thread.current, Thread.current.thread_variable_get(:foo)] -+ }.resume -+ -+ assert_equal Thread.current, thread -+ assert_equal Thread.current.thread_variable_get(:foo), value -+ }.join -+ end -+ -+ def test_thread_variables -+ assert_equal [], Thread.new { Thread.current.thread_variables }.join.value -+ -+ t = Thread.new { -+ Thread.current.thread_variable_set(:foo, "bar") -+ Thread.current.thread_variables -+ } -+ assert_equal [:foo], t.join.value -+ end -+ -+ def test_thread_variable? -+ refute Thread.new { Thread.current.thread_variable?("foo") }.join.value -+ t = Thread.new { -+ Thread.current.thread_variable_set("foo", "bar") -+ }.join -+ -+ assert t.thread_variable?("foo") -+ assert t.thread_variable?(:foo) -+ refute t.thread_variable?(:bar) -+ end -+ -+ def test_thread_variable_strings_and_symbols_are_the_same_key -+ t = Thread.new {}.join -+ t.thread_variable_set("foo", "bar") -+ assert_equal "bar", t.thread_variable_get(:foo) -+ end -+ -+ def test_thread_variable_frozen -+ t = Thread.new { }.join -+ t.freeze -+ assert_raises(RuntimeError) do -+ t.thread_variable_set(:foo, "bar") -+ end -+ end -+ -+ def test_thread_variable_security -+ t = Thread.new { sleep } -+ -+ assert_raises(SecurityError) do -+ Thread.new { $SAFE = 4; t.thread_variable_get(:foo) }.join -+ end -+ -+ assert_raises(SecurityError) do -+ Thread.new { $SAFE = 4; t.thread_variable_set(:foo, :baz) }.join -+ end -+ end -+ - def test_mutex_synchronize - m = Mutex.new - r = 0 -diff --git a/thread.c b/thread.c -index c7da34b..ce1fa3f 100644 ---- a/thread.c -+++ b/thread.c -@@ -2112,7 +2112,9 @@ rb_thread_local_aset(VALUE thread, ID id, VALUE val) - * thr[sym] = obj -> obj - * - * Attribute Assignment---Sets or creates the value of a thread-local variable, -- * using either a symbol or a string. See also Thread#[]. -+ * using either a symbol or a string. See also Thread#[]. For -+ * thread-local variables, please see Thread#thread_variable_set -+ * and Thread#thread_variable_get. - */ - - static VALUE -@@ -2123,6 +2125,80 @@ rb_thread_aset(VALUE self, VALUE id, VALUE val) - - /* - * call-seq: -+ * thr.thread_variable_get(key) -> obj or nil -+ * -+ * Returns the value of a thread local variable that has been set. Note that -+ * these are different than fiber local values. For fiber local values, -+ * please see Thread#[] and Thread#[]=. -+ * -+ * Thread local values are carried along with threads, and do not respect -+ * fibers. For example: -+ * -+ * Thread.new { -+ * Thread.current.thread_variable_set("foo", "bar") # set a thread local -+ * Thread.current["foo"] = "bar" # set a fiber local -+ * -+ * Fiber.new { -+ * Fiber.yield [ -+ * Thread.current.thread_variable_get("foo"), # get the thread local -+ * Thread.current["foo"], # get the fiber local -+ * ] -+ * }.resume -+ * }.join.value # => ['bar', nil] -+ * -+ * The value "bar" is returned for the thread local, where nil is returned -+ * for the fiber local. The fiber is executed in the same thread, so the -+ * thread local values are available. -+ * -+ * See also Thread#[] -+ */ -+ -+static VALUE -+rb_thread_variable_get(VALUE thread, VALUE id) -+{ -+ VALUE locals; -+ rb_thread_t *th; -+ -+ GetThreadPtr(thread, th); -+ -+ if (rb_safe_level() >= 4 && th != GET_THREAD()) { -+ rb_raise(rb_eSecurityError, "Insecure: can't access thread locals"); -+ } -+ -+ locals = rb_iv_get(thread, "locals"); -+ return rb_hash_aref(locals, ID2SYM(rb_to_id(id))); -+} -+ -+/* -+ * call-seq: -+ * thr.thread_variable_set(key, value) -+ * -+ * Sets a thread local with +key+ to +value+. Note that these are local to -+ * threads, and not to fibers. Please see Thread#thread_variable_get and -+ * Thread#[] for more information. -+ */ -+ -+static VALUE -+rb_thread_variable_set(VALUE thread, VALUE id, VALUE val) -+{ -+ VALUE locals; -+ rb_thread_t *th; -+ -+ GetThreadPtr(thread, th); -+ -+ if (rb_safe_level() >= 4 && th != GET_THREAD()) { -+ rb_raise(rb_eSecurityError, "Insecure: can't modify thread locals"); -+ } -+ if (OBJ_FROZEN(thread)) { -+ rb_error_frozen("thread locals"); -+ } -+ -+ locals = rb_iv_get(thread, "locals"); -+ return rb_hash_aset(locals, ID2SYM(rb_to_id(id)), val); -+} -+ -+/* -+ * call-seq: - * thr.key?(sym) -> true or false - * - * Returns true if the given string (or symbol) exists as a -@@ -2993,6 +3069,9 @@ rb_gc_save_machine_context(rb_thread_t *th) - - /* - * -+ * For thread-local variables, please see Thread#thread_local_get -+ * and Thread#thread_local_set. -+ * - */ - - void -@@ -3195,6 +3274,76 @@ thgroup_list_i(st_data_t key, st_data_t val, st_data_t data) - return ST_CONTINUE; - } - -+static int -+keys_i(VALUE key, VALUE value, VALUE ary) -+{ -+ rb_ary_push(ary, key); -+ return ST_CONTINUE; -+} -+ -+/* -+ * call-seq: -+ * thr.thread_variables -> array -+ * -+ * Returns an an array of the names of the thread-local variables (as Symbols). -+ * -+ * thr = Thread.new do -+ * Thread.current.thread_variable_set(:cat, 'meow') -+ * Thread.current.thread_variable_set("dog", 'woof') -+ * end -+ * thr.join #=> # -+ * thr.thread_variables #=> [:dog, :cat] -+ * -+ * Note that these are not fiber local variables. Please see Thread#[] and -+ * Thread#thread_variable_get for more details. -+ */ -+ -+static VALUE -+rb_thread_variables(VALUE thread) -+{ -+ VALUE locals; -+ VALUE ary; -+ -+ locals = rb_iv_get(thread, "locals"); -+ ary = rb_ary_new(); -+ rb_hash_foreach(locals, keys_i, ary); -+ -+ return ary; -+} -+ -+/* -+ * call-seq: -+ * thr.thread_variable?(key) -> true or false -+ * -+ * Returns true if the given string (or symbol) exists as a -+ * thread-local variable. -+ * -+ * me = Thread.current -+ * me.thread_variable_set(:oliver, "a") -+ * me.thread_variable?(:oliver) #=> true -+ * me.thread_variable?(:stanley) #=> false -+ * -+ * Note that these are not fiber local variables. Please see Thread#[] and -+ * Thread#thread_variable_get for more details. -+ */ -+ -+static VALUE -+rb_thread_variable_p(VALUE thread, VALUE key) -+{ -+ VALUE locals; -+ -+ locals = rb_iv_get(thread, "locals"); -+ -+ if (!RHASH(locals)->ntbl) -+ return Qfalse; -+ -+ if (st_lookup(RHASH(locals)->ntbl, ID2SYM(rb_to_id(key)), 0)) { -+ return Qtrue; -+ } -+ -+ return Qfalse; -+} -+ - /* - * call-seq: - * thgrp.list -> array -@@ -4680,6 +4829,10 @@ Init_Thread(void) - rb_define_method(rb_cThread, "priority", rb_thread_priority, 0); - rb_define_method(rb_cThread, "priority=", rb_thread_priority_set, 1); - rb_define_method(rb_cThread, "status", rb_thread_status, 0); -+ rb_define_method(rb_cThread, "thread_variable_get", rb_thread_variable_get, 1); -+ rb_define_method(rb_cThread, "thread_variable_set", rb_thread_variable_set, 2); -+ rb_define_method(rb_cThread, "thread_variables", rb_thread_variables, 0); -+ rb_define_method(rb_cThread, "thread_variable?", rb_thread_variable_p, 1); - rb_define_method(rb_cThread, "alive?", rb_thread_alive_p, 0); - rb_define_method(rb_cThread, "stop?", rb_thread_stop_p, 0); - rb_define_method(rb_cThread, "abort_on_exception", rb_thread_abort_exc, 0); -diff --git a/vm.c b/vm.c -index 4c44aa4..1517e73 100644 ---- a/vm.c -+++ b/vm.c -@@ -1909,6 +1909,7 @@ ruby_thread_init(VALUE self) - GetThreadPtr(self, th); - - th_init(th, self); -+ rb_iv_set(self, "locals", rb_hash_new()); - th->vm = vm; - - th->top_wrapper = 0; -@@ -2177,6 +2178,7 @@ Init_VM(void) - - /* create main thread */ - th_self = th->self = TypedData_Wrap_Struct(rb_cThread, &thread_data_type, th); -+ rb_iv_set(th_self, "locals", rb_hash_new()); - vm->main_thread = th; - vm->running_thread = th; - th->vm = vm; diff --git a/patches/ruby/1.9.3/p374/railsexpress/09-faster-loading.patch b/patches/ruby/1.9.3/p374/railsexpress/09-faster-loading.patch deleted file mode 100644 index 456d87668a..0000000000 --- a/patches/ruby/1.9.3/p374/railsexpress/09-faster-loading.patch +++ /dev/null @@ -1,747 +0,0 @@ -diff --git a/array.c b/array.c -index e427cb3..c33d106 100644 ---- a/array.c -+++ b/array.c -@@ -295,6 +295,22 @@ rb_ary_frozen_p(VALUE ary) - return Qfalse; - } - -+/* This can be used to take a snapshot of an array (with -+ e.g. rb_ary_replace) and check later whether the array has been -+ modified from the snapshot. The snapshot is cheap, though if -+ something does modify the array it will pay the cost of copying -+ it. */ -+VALUE -+rb_ary_shared_with_p(VALUE ary1, VALUE ary2) -+{ -+ if (!ARY_EMBED_P(ary1) && ARY_SHARED_P(ary1) -+ && !ARY_EMBED_P(ary2) && ARY_SHARED_P(ary2) -+ && RARRAY(ary1)->as.heap.aux.shared == RARRAY(ary2)->as.heap.aux.shared) { -+ return Qtrue; -+ } -+ return Qfalse; -+} -+ - static VALUE - ary_alloc(VALUE klass) - { -diff --git a/file.c b/file.c -index 50fa5c7..e991866 100644 ---- a/file.c -+++ b/file.c -@@ -149,23 +149,32 @@ file_path_convert(VALUE name) - return name; - } - --static VALUE --rb_get_path_check(VALUE obj, int level) -+VALUE -+rb_get_path_check_to_string(VALUE obj, int level) - { - VALUE tmp; - ID to_path; -- rb_encoding *enc; - - if (insecure_obj_p(obj, level)) { - rb_insecure_operation(); - } - -+ if (RB_TYPE_P(obj, T_STRING)) { -+ return obj; -+ } - CONST_ID(to_path, "to_path"); - tmp = rb_check_funcall(obj, to_path, 0, 0); - if (tmp == Qundef) { - tmp = obj; - } - StringValue(tmp); -+ return tmp; -+} -+ -+VALUE -+rb_get_path_check_convert(VALUE obj, VALUE tmp, int level) -+{ -+ rb_encoding *enc; - - tmp = file_path_convert(tmp); - if (obj != tmp && insecure_obj_p(tmp, level)) { -@@ -183,6 +192,13 @@ rb_get_path_check(VALUE obj, int level) - return rb_str_new4(tmp); - } - -+static VALUE -+rb_get_path_check(VALUE obj, int level) -+{ -+ VALUE tmp = rb_get_path_check_to_string(obj, level); -+ return rb_get_path_check_convert(obj, tmp, level); -+} -+ - VALUE - rb_get_path_no_checksafe(VALUE obj) - { -@@ -3250,7 +3266,6 @@ rb_file_expand_path(VALUE fname, VALUE dname) - VALUE - rb_file_expand_path_fast(VALUE fname, VALUE dname) - { -- check_expand_path_args(fname, dname); - return rb_file_expand_path_internal(fname, dname, 0, 0, EXPAND_PATH_BUFFER()); - } - -@@ -5238,7 +5253,7 @@ rb_find_file_ext_safe(VALUE *filep, const char *const *ext, int safe_level) - rb_raise(rb_eSecurityError, "loading from non-absolute path %s", f); - } - -- RB_GC_GUARD(load_path) = rb_get_load_path(); -+ RB_GC_GUARD(load_path) = rb_get_expanded_load_path(); - if (!load_path) return 0; - - fname = rb_str_dup(*filep); -@@ -5303,7 +5318,7 @@ rb_find_file_safe(VALUE path, int safe_level) - rb_raise(rb_eSecurityError, "loading from non-absolute path %s", f); - } - -- RB_GC_GUARD(load_path) = rb_get_load_path(); -+ RB_GC_GUARD(load_path) = rb_get_expanded_load_path(); - if (load_path) { - long i; - -diff --git a/hash.c b/hash.c -index fbd8237..8423558 100644 ---- a/hash.c -+++ b/hash.c -@@ -1087,7 +1087,7 @@ clear_i(VALUE key, VALUE value, VALUE dummy) - * - */ - --static VALUE -+VALUE - rb_hash_clear(VALUE hash) - { - rb_hash_modify_check(hash); -diff --git a/include/ruby/intern.h b/include/ruby/intern.h -index 7c3d970..ab1cc94 100644 ---- a/include/ruby/intern.h -+++ b/include/ruby/intern.h -@@ -56,6 +56,7 @@ VALUE rb_ary_tmp_new(long); - void rb_ary_free(VALUE); - void rb_ary_modify(VALUE); - VALUE rb_ary_freeze(VALUE); -+VALUE rb_ary_shared_with_p(VALUE, VALUE); - VALUE rb_ary_aref(int, VALUE*, VALUE); - VALUE rb_ary_subseq(VALUE, long, long); - void rb_ary_store(VALUE, long, VALUE); -@@ -443,6 +444,7 @@ VALUE rb_hash_lookup(VALUE, VALUE); - VALUE rb_hash_lookup2(VALUE, VALUE, VALUE); - VALUE rb_hash_fetch(VALUE, VALUE); - VALUE rb_hash_aset(VALUE, VALUE, VALUE); -+VALUE rb_hash_clear(VALUE); - VALUE rb_hash_delete_if(VALUE); - VALUE rb_hash_delete(VALUE,VALUE); - typedef VALUE rb_hash_update_func(VALUE newkey, VALUE oldkey, VALUE value); -diff --git a/internal.h b/internal.h -index 59c9284..f5af903 100644 ---- a/internal.h -+++ b/internal.h -@@ -94,6 +94,8 @@ VALUE rb_home_dir(const char *user, VALUE result); - VALUE rb_realpath_internal(VALUE basedir, VALUE path, int strict); - VALUE rb_file_expand_path_fast(VALUE, VALUE); - VALUE rb_file_expand_path_internal(VALUE, VALUE, int, int, VALUE); -+VALUE rb_get_path_check_to_string(VALUE, int); -+VALUE rb_get_path_check_convert(VALUE, VALUE, int); - void Init_File(void); - - #ifdef _WIN32 -@@ -119,6 +121,7 @@ VALUE rb_iseq_clone(VALUE iseqval, VALUE newcbase); - - /* load.c */ - VALUE rb_get_load_path(void); -+VALUE rb_get_expanded_load_path(void); - - /* math.c */ - VALUE rb_math_atan2(VALUE, VALUE); -diff --git a/load.c b/load.c -index 163ec4c..e766880 100644 ---- a/load.c -+++ b/load.c -@@ -18,7 +18,6 @@ VALUE ruby_dln_librefs; - #define IS_DLEXT(e) (strcmp((e), DLEXT) == 0) - #endif - -- - static const char *const loadable_ext[] = { - ".rb", DLEXT, - #ifdef DLEXT2 -@@ -34,21 +33,120 @@ rb_get_load_path(void) - return load_path; - } - --VALUE --rb_get_expanded_load_path(void) -+enum expand_type { -+ EXPAND_ALL, -+ EXPAND_RELATIVE, -+ EXPAND_HOME, -+ EXPAND_NON_CACHE -+}; -+ -+/* Construct expanded load path and store it to cache. -+ We rebuild load path partially if the cache is invalid. -+ We don't cache non string object and expand it every times. We ensure that -+ string objects in $LOAD_PATH are frozen. -+ */ -+static void -+rb_construct_expanded_load_path(int type, int *has_relative, int *has_non_cache) - { -- VALUE load_path = rb_get_load_path(); -+ rb_vm_t *vm = GET_VM(); -+ VALUE load_path = vm->load_path; -+ VALUE expanded_load_path = vm->expanded_load_path; - VALUE ary; - long i; -+ int level = rb_safe_level(); - - ary = rb_ary_new2(RARRAY_LEN(load_path)); - for (i = 0; i < RARRAY_LEN(load_path); ++i) { -- VALUE path = rb_file_expand_path_fast(RARRAY_PTR(load_path)[i], Qnil); -- rb_str_freeze(path); -- rb_ary_push(ary, path); -+ VALUE path, as_str, expanded_path; -+ int is_string, non_cache; -+ char *as_cstr; -+ as_str = path = RARRAY_PTR(load_path)[i]; -+ is_string = RB_TYPE_P(path, T_STRING) ? 1 : 0; -+ non_cache = !is_string ? 1 : 0; -+ as_str = rb_get_path_check_to_string(path, level); -+ as_cstr = RSTRING_PTR(as_str); -+ -+ if (!non_cache) { -+ if ((type == EXPAND_RELATIVE && -+ rb_is_absolute_path(as_cstr)) || -+ (type == EXPAND_HOME && -+ (!as_cstr[0] || as_cstr[0] != '~')) || -+ (type == EXPAND_NON_CACHE)) { -+ /* Use cached expanded path. */ -+ rb_ary_push(ary, RARRAY_PTR(expanded_load_path)[i]); -+ continue; -+ } -+ } -+ if (!*has_relative && !rb_is_absolute_path(as_cstr)) -+ *has_relative = 1; -+ if (!*has_non_cache && non_cache) -+ *has_non_cache = 1; -+ /* Freeze only string object. We expand other objects every times. */ -+ if (is_string) -+ rb_str_freeze(path); -+ as_str = rb_get_path_check_convert(path, as_str, level); -+ expanded_path = rb_file_expand_path_fast(as_str, Qnil); -+ rb_str_freeze(expanded_path); -+ rb_ary_push(ary, expanded_path); - } - rb_obj_freeze(ary); -- return ary; -+ vm->expanded_load_path = ary; -+ rb_ary_replace(vm->load_path_snapshot, vm->load_path); -+} -+ -+static VALUE -+load_path_getcwd(void) -+{ -+ char *cwd = my_getcwd(); -+ VALUE cwd_str = rb_filesystem_str_new_cstr(cwd); -+ xfree(cwd); -+ return cwd_str; -+} -+ -+VALUE -+rb_get_expanded_load_path(void) -+{ -+ rb_vm_t *vm = GET_VM(); -+ const VALUE non_cache = Qtrue; -+ -+ if (!rb_ary_shared_with_p(vm->load_path_snapshot, vm->load_path)) { -+ /* The load path was modified. Rebuild the expanded load path. */ -+ int has_relative = 0, has_non_cache = 0; -+ rb_construct_expanded_load_path(EXPAND_ALL, &has_relative, &has_non_cache); -+ if (has_relative) { -+ vm->load_path_check_cache = load_path_getcwd(); -+ } -+ else if (has_non_cache) { -+ /* Non string object. */ -+ vm->load_path_check_cache = non_cache; -+ } -+ else { -+ vm->load_path_check_cache = 0; -+ } -+ } -+ else if (vm->load_path_check_cache == non_cache) { -+ int has_relative = 1, has_non_cache = 1; -+ /* Expand only non-cacheable objects. */ -+ rb_construct_expanded_load_path(EXPAND_NON_CACHE, -+ &has_relative, &has_non_cache); -+ } -+ else if (vm->load_path_check_cache) { -+ int has_relative = 1, has_non_cache = 1; -+ VALUE cwd = load_path_getcwd(); -+ if (!rb_str_equal(vm->load_path_check_cache, cwd)) { -+ /* Current working directory or filesystem encoding was changed. -+ Expand relative load path and non-cacheable objects again. */ -+ vm->load_path_check_cache = cwd; -+ rb_construct_expanded_load_path(EXPAND_RELATIVE, -+ &has_relative, &has_non_cache); -+ } -+ else { -+ /* Expand only tilde (User HOME) and non-cacheable objects. */ -+ rb_construct_expanded_load_path(EXPAND_HOME, -+ &has_relative, &has_non_cache); -+ } -+ } -+ return vm->expanded_load_path; - } - - static VALUE -@@ -63,12 +161,121 @@ get_loaded_features(void) - return GET_VM()->loaded_features; - } - -+static void -+reset_loaded_features_snapshot(void) -+{ -+ rb_vm_t *vm = GET_VM(); -+ rb_ary_replace(vm->loaded_features_snapshot, vm->loaded_features); -+} -+ -+static VALUE -+get_loaded_features_index_raw(void) -+{ -+ return GET_VM()->loaded_features_index; -+} -+ - static st_table * - get_loading_table(void) - { - return GET_VM()->loading_table; - } - -+static void -+features_index_add_single(VALUE short_feature, VALUE offset) -+{ -+ VALUE features_index, this_feature_index; -+ features_index = get_loaded_features_index_raw(); -+ if ((this_feature_index = rb_hash_lookup(features_index, short_feature)) == Qnil) { -+ this_feature_index = rb_ary_new(); -+ rb_hash_aset(features_index, short_feature, this_feature_index); -+ } -+ rb_ary_push(this_feature_index, offset); -+} -+ -+/* Add to the loaded-features index all the required entries for -+ `feature`, located at `offset` in $LOADED_FEATURES. We add an -+ index entry at each string `short_feature` for which -+ feature == "#{prefix}#{short_feature}#{e}" -+ where `e` is empty or matches %r{^\.[^./]*$}, and `prefix` is empty -+ or ends in '/'. This maintains the invariant that `rb_feature_p()` -+ relies on for its fast lookup. -+*/ -+static void -+features_index_add(VALUE feature, VALUE offset) -+{ -+ VALUE short_feature; -+ const char *feature_str, *feature_end, *ext, *p; -+ -+ feature_str = StringValuePtr(feature); -+ feature_end = feature_str + RSTRING_LEN(feature); -+ -+ for (ext = feature_end; ext > feature_str; ext--) -+ if (*ext == '.' || *ext == '/') -+ break; -+ if (*ext != '.') -+ ext = NULL; -+ /* Now `ext` points to the only string matching %r{^\.[^./]*$} that is -+ at the end of `feature`, or is NULL if there is no such string. */ -+ -+ p = ext ? ext : feature_end; -+ while (1) { -+ p--; -+ while (p >= feature_str && *p != '/') -+ p--; -+ if (p < feature_str) -+ break; -+ /* Now *p == '/'. We reach this point for every '/' in `feature`. */ -+ short_feature = rb_str_substr(feature, p + 1 - feature_str, feature_end - p - 1); -+ features_index_add_single(short_feature, offset); -+ if (ext) { -+ short_feature = rb_str_substr(feature, p + 1 - feature_str, ext - p - 1); -+ features_index_add_single(short_feature, offset); -+ } -+ } -+ features_index_add_single(feature, offset); -+ if (ext) { -+ short_feature = rb_str_substr(feature, 0, ext - feature_str); -+ features_index_add_single(short_feature, offset); -+ } -+} -+ -+static VALUE -+get_loaded_features_index(void) -+{ -+ VALUE features; -+ int i; -+ rb_vm_t *vm = GET_VM(); -+ -+ if (!rb_ary_shared_with_p(vm->loaded_features_snapshot, vm->loaded_features)) { -+ /* The sharing was broken; something (other than us in rb_provide_feature()) -+ modified loaded_features. Rebuild the index. */ -+ rb_hash_clear(vm->loaded_features_index); -+ features = vm->loaded_features; -+ for (i = 0; i < RARRAY_LEN(features); i++) { -+ VALUE entry, as_str; -+ as_str = entry = rb_ary_entry(features, i); -+ StringValue(as_str); -+ if (as_str != entry) -+ rb_ary_store(features, i, as_str); -+ rb_str_freeze(as_str); -+ features_index_add(as_str, INT2FIX(i)); -+ } -+ reset_loaded_features_snapshot(); -+ } -+ return vm->loaded_features_index; -+} -+ -+/* This searches `load_path` for a value such that -+ name == "#{load_path[i]}/#{feature}" -+ if `feature` is a suffix of `name`, or otherwise -+ name == "#{load_path[i]}/#{feature}#{ext}" -+ for an acceptable string `ext`. It returns -+ `load_path[i].to_str` if found, else 0. -+ -+ If type is 's', then `ext` is acceptable only if IS_DLEXT(ext); -+ if 'r', then only if IS_RBEXT(ext); otherwise `ext` may be absent -+ or have any value matching `%r{^\.[^./]*$}`. -+*/ - static VALUE - loaded_feature_path(const char *name, long vlen, const char *feature, long len, - int type, VALUE load_path) -@@ -77,7 +284,7 @@ loaded_feature_path(const char *name, long vlen, const char *feature, long len, - long plen; - const char *e; - -- if(vlen < len) return 0; -+ if (vlen < len+1) return 0; - if (!strncmp(name+(vlen-len),feature,len)){ - plen = vlen - len - 1; - } else { -@@ -88,23 +295,22 @@ loaded_feature_path(const char *name, long vlen, const char *feature, long len, - return 0; - plen = e - name - len - 1; - } -+ if (type == 's' && !IS_DLEXT(&name[plen+len+1]) -+ || type == 'r' && !IS_RBEXT(&name[plen+len+1]) -+ || name[plen] != '/') { -+ return 0; -+ } -+ /* Now name == "#{prefix}/#{feature}#{ext}" where ext is acceptable -+ (possibly empty) and prefix is some string of length plen. */ -+ - for (i = 0; i < RARRAY_LEN(load_path); ++i) { - VALUE p = RARRAY_PTR(load_path)[i]; - const char *s = StringValuePtr(p); - long n = RSTRING_LEN(p); - - if (n != plen ) continue; -- if (n && (strncmp(name, s, n) || name[n] != '/')) continue; -- switch (type) { -- case 's': -- if (IS_DLEXT(&name[n+len+1])) return p; -- break; -- case 'r': -- if (IS_RBEXT(&name[n+len+1])) return p; -- break; -- default: -- return p; -- } -+ if (n && strncmp(name, s, n)) continue; -+ return p; - } - return 0; - } -@@ -132,7 +338,7 @@ loaded_feature_path_i(st_data_t v, st_data_t b, st_data_t f) - static int - rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const char **fn) - { -- VALUE v, features, p, load_path = 0; -+ VALUE features, features_index, feature_val, this_feature_index, v, p, load_path = 0; - const char *f, *e; - long i, len, elen, n; - st_table *loading_tbl; -@@ -151,8 +357,39 @@ rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const c - type = 0; - } - features = get_loaded_features(); -- for (i = 0; i < RARRAY_LEN(features); ++i) { -- v = RARRAY_PTR(features)[i]; -+ features_index = get_loaded_features_index(); -+ -+ feature_val = rb_str_new(feature, len); -+ this_feature_index = rb_hash_lookup(features_index, feature_val); -+ /* We search `features` for an entry such that either -+ "#{features[i]}" == "#{load_path[j]}/#{feature}#{e}" -+ for some j, or -+ "#{features[i]}" == "#{feature}#{e}" -+ Here `e` is an "allowed" extension -- either empty or one -+ of the extensions accepted by IS_RBEXT, IS_SOEXT, or -+ IS_DLEXT. Further, if `ext && rb` then `IS_RBEXT(e)`, -+ and if `ext && !rb` then `IS_SOEXT(e) || IS_DLEXT(e)`. -+ -+ If `expanded`, then only the latter form (without load_path[j]) -+ is accepted. Otherwise either form is accepted, *unless* `ext` -+ is false and an otherwise-matching entry of the first form is -+ preceded by an entry of the form -+ "#{features[i2]}" == "#{load_path[j2]}/#{feature}#{e2}" -+ where `e2` matches %r{^\.[^./]*$} but is not an allowed extension. -+ After a "distractor" entry of this form, only entries of the -+ form "#{feature}#{e}" are accepted. -+ -+ In `rb_provide_feature()` and `get_loaded_features_index()` we -+ maintain an invariant that the array `this_feature_index` will -+ point to every entry in `features` which has the form -+ "#{prefix}#{feature}#{e}" -+ where `e` is empty or matches %r{^\.[^./]*$}, and `prefix` is empty -+ or ends in '/'. This includes both match forms above, as well -+ as any distractors, so we may ignore all other entries in `features`. -+ */ -+ for (i = 0; this_feature_index != Qnil && i < RARRAY_LEN(this_feature_index); i++) { -+ long index = FIX2LONG(rb_ary_entry(this_feature_index, i)); -+ v = RARRAY_PTR(features)[index]; - f = StringValuePtr(v); - if ((n = RSTRING_LEN(v)) < len) continue; - if (strncmp(f, feature, len) != 0) { -@@ -175,6 +412,7 @@ rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const c - return 'r'; - } - } -+ - loading_tbl = get_loading_table(); - if (loading_tbl) { - f = 0; -@@ -183,7 +421,7 @@ rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const c - fs.name = feature; - fs.len = len; - fs.type = type; -- fs.load_path = load_path ? load_path : rb_get_load_path(); -+ fs.load_path = load_path ? load_path : rb_get_expanded_load_path(); - fs.result = 0; - st_foreach(loading_tbl, loaded_feature_path_i, (st_data_t)&fs); - if ((f = fs.result) != 0) { -@@ -233,7 +471,7 @@ rb_feature_provided(const char *feature, const char **loading) - - if (*feature == '.' && - (feature[1] == '/' || strncmp(feature+1, "./", 2) == 0)) { -- fullpath = rb_file_expand_path_fast(rb_str_new2(feature), Qnil); -+ fullpath = rb_file_expand_path_fast(rb_get_path(rb_str_new2(feature)), Qnil); - feature = RSTRING_PTR(fullpath); - } - if (ext && !strchr(ext, '/')) { -@@ -254,11 +492,18 @@ rb_feature_provided(const char *feature, const char **loading) - static void - rb_provide_feature(VALUE feature) - { -- if (OBJ_FROZEN(get_loaded_features())) { -+ VALUE features; -+ -+ features = get_loaded_features(); -+ if (OBJ_FROZEN(features)) { - rb_raise(rb_eRuntimeError, - "$LOADED_FEATURES is frozen; cannot append feature"); - } -- rb_ary_push(get_loaded_features(), feature); -+ rb_str_freeze(feature); -+ -+ rb_ary_push(features, feature); -+ features_index_add(feature, INT2FIX(RARRAY_LEN(features)-1)); -+ reset_loaded_features_snapshot(); - } - - void -@@ -774,10 +1019,15 @@ Init_load() - rb_alias_variable(rb_intern("$-I"), id_load_path); - rb_alias_variable(rb_intern("$LOAD_PATH"), id_load_path); - vm->load_path = rb_ary_new(); -+ vm->expanded_load_path = rb_ary_new(); -+ vm->load_path_snapshot = rb_ary_new(); -+ vm->load_path_check_cache = 0; - - rb_define_virtual_variable("$\"", get_loaded_features, 0); - rb_define_virtual_variable("$LOADED_FEATURES", get_loaded_features, 0); - vm->loaded_features = rb_ary_new(); -+ vm->loaded_features_snapshot = rb_ary_new(); -+ vm->loaded_features_index = rb_hash_new(); - - rb_define_global_function("load", rb_f_load, -1); - rb_define_global_function("require", rb_f_require, 1); -diff --git a/ruby.c b/ruby.c -index 3ddd96c..7ffc78e 100644 ---- a/ruby.c -+++ b/ruby.c -@@ -1366,7 +1366,8 @@ process_options(int argc, char **argv, struct cmdline_options *opt) - long i; - VALUE load_path = GET_VM()->load_path; - for (i = 0; i < RARRAY_LEN(load_path); ++i) { -- rb_enc_associate(RARRAY_PTR(load_path)[i], lenc); -+ RARRAY_PTR(load_path)[i] = -+ rb_enc_associate(rb_str_dup(RARRAY_PTR(load_path)[i]), lenc); - } - } - if (!(opt->disable & DISABLE_BIT(gems))) { -diff --git a/test/ruby/test_require.rb b/test/ruby/test_require.rb -index 58a9ee2..ec75096 100644 ---- a/test/ruby/test_require.rb -+++ b/test/ruby/test_require.rb -@@ -356,4 +356,114 @@ class TestRequire < Test::Unit::TestCase - $:.replace(loadpath) - $".replace(features) - end -+ -+ def test_require_changed_current_dir -+ bug7158 = '[ruby-core:47970]' -+ Dir.mktmpdir {|tmp| -+ Dir.chdir(tmp) { -+ Dir.mkdir("a") -+ Dir.mkdir("b") -+ open(File.join("a", "foo.rb"), "w") {} -+ open(File.join("b", "bar.rb"), "w") {|f| -+ f.puts "p :ok" -+ } -+ assert_in_out_err([], <<-INPUT, %w(:ok), [], bug7158) -+ $: << "." -+ Dir.chdir("a") -+ require "foo" -+ Dir.chdir("../b") -+ p :ng unless require "bar" -+ Dir.chdir("..") -+ p :ng if require "b/bar" -+ INPUT -+ } -+ } -+ end -+ -+ def test_require_not_modified_load_path -+ bug7158 = '[ruby-core:47970]' -+ Dir.mktmpdir {|tmp| -+ Dir.chdir(tmp) { -+ open("foo.rb", "w") {} -+ assert_in_out_err([], <<-INPUT, %w(:ok), [], bug7158) -+ a = Object.new -+ def a.to_str -+ "#{tmp}" -+ end -+ $: << a -+ require "foo" -+ last_path = $:.pop -+ p :ok if last_path == a && last_path.class == Object -+ INPUT -+ } -+ } -+ end -+ -+ def test_require_changed_home -+ bug7158 = '[ruby-core:47970]' -+ Dir.mktmpdir {|tmp| -+ Dir.chdir(tmp) { -+ open("foo.rb", "w") {} -+ Dir.mkdir("a") -+ open(File.join("a", "bar.rb"), "w") {} -+ assert_in_out_err([], <<-INPUT, %w(:ok), [], bug7158) -+ $: << '~' -+ ENV['HOME'] = "#{tmp}" -+ require "foo" -+ ENV['HOME'] = "#{tmp}/a" -+ p :ok if require "bar" -+ INPUT -+ } -+ } -+ end -+ -+ def test_require_to_path_redefined_in_load_path -+ bug7158 = '[ruby-core:47970]' -+ Dir.mktmpdir {|tmp| -+ Dir.chdir(tmp) { -+ open("foo.rb", "w") {} -+ assert_in_out_err(["RUBYOPT"=>nil], <<-INPUT, %w(:ok), [], bug7158) -+ a = Object.new -+ def a.to_path -+ "bar" -+ end -+ $: << a -+ begin -+ require "foo" -+ p :ng -+ rescue LoadError -+ end -+ def a.to_path -+ "#{tmp}" -+ end -+ p :ok if require "foo" -+ INPUT -+ } -+ } -+ end -+ -+ def test_require_to_str_redefined_in_load_path -+ bug7158 = '[ruby-core:47970]' -+ Dir.mktmpdir {|tmp| -+ Dir.chdir(tmp) { -+ open("foo.rb", "w") {} -+ assert_in_out_err(["RUBYOPT"=>nil], <<-INPUT, %w(:ok), [], bug7158) -+ a = Object.new -+ def a.to_str -+ "foo" -+ end -+ $: << a -+ begin -+ require "foo" -+ p :ng -+ rescue LoadError -+ end -+ def a.to_str -+ "#{tmp}" -+ end -+ p :ok if require "foo" -+ INPUT -+ } -+ } -+ end - end -diff --git a/vm.c b/vm.c -index 1517e73..04ef956 100644 ---- a/vm.c -+++ b/vm.c -@@ -1591,7 +1591,12 @@ rb_vm_mark(void *ptr) - RUBY_MARK_UNLESS_NULL(vm->thgroup_default); - RUBY_MARK_UNLESS_NULL(vm->mark_object_ary); - RUBY_MARK_UNLESS_NULL(vm->load_path); -+ RUBY_MARK_UNLESS_NULL(vm->load_path_snapshot); -+ RUBY_MARK_UNLESS_NULL(vm->load_path_check_cache); -+ RUBY_MARK_UNLESS_NULL(vm->expanded_load_path); - RUBY_MARK_UNLESS_NULL(vm->loaded_features); -+ RUBY_MARK_UNLESS_NULL(vm->loaded_features_snapshot); -+ RUBY_MARK_UNLESS_NULL(vm->loaded_features_index); - RUBY_MARK_UNLESS_NULL(vm->top_self); - RUBY_MARK_UNLESS_NULL(vm->coverages); - rb_gc_mark_locations(vm->special_exceptions, vm->special_exceptions + ruby_special_error_count); -diff --git a/vm_core.h b/vm_core.h -index dfc0e3c..70c5f5c 100644 ---- a/vm_core.h -+++ b/vm_core.h -@@ -299,7 +299,12 @@ typedef struct rb_vm_struct { - /* load */ - VALUE top_self; - VALUE load_path; -+ VALUE load_path_snapshot; -+ VALUE load_path_check_cache; -+ VALUE expanded_load_path; - VALUE loaded_features; -+ VALUE loaded_features_snapshot; -+ VALUE loaded_features_index; - struct st_table *loading_table; - - /* signal */ diff --git a/patches/ruby/1.9.3/p374/railsexpress/10-falcon-st-opt.patch b/patches/ruby/1.9.3/p374/railsexpress/10-falcon-st-opt.patch deleted file mode 100644 index d7624b8400..0000000000 --- a/patches/ruby/1.9.3/p374/railsexpress/10-falcon-st-opt.patch +++ /dev/null @@ -1,2302 +0,0 @@ -diff --git a/common.mk b/common.mk -index ccc9647..1d8e442 100644 ---- a/common.mk -+++ b/common.mk -@@ -638,7 +638,8 @@ file.$(OBJEXT): {$(VPATH)}file.c $(RUBY_H_INCLUDES) {$(VPATH)}io.h \ - gc.$(OBJEXT): {$(VPATH)}gc.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \ - {$(VPATH)}regex.h $(ENCODING_H_INCLUDES) $(VM_CORE_H_INCLUDES) \ - {$(VPATH)}gc.h {$(VPATH)}io.h {$(VPATH)}eval_intern.h {$(VPATH)}util.h \ -- {$(VPATH)}debug.h {$(VPATH)}internal.h {$(VPATH)}constant.h -+ {$(VPATH)}debug.h {$(VPATH)}internal.h {$(VPATH)}constant.h \ -+ {$(VPATH)}pool_alloc.inc.h {$(VPATH)}pool_alloc.h - hash.$(OBJEXT): {$(VPATH)}hash.c $(RUBY_H_INCLUDES) {$(VPATH)}util.h \ - $(ENCODING_H_INCLUDES) - inits.$(OBJEXT): {$(VPATH)}inits.c $(RUBY_H_INCLUDES) \ -@@ -702,7 +703,7 @@ signal.$(OBJEXT): {$(VPATH)}signal.c $(RUBY_H_INCLUDES) \ - $(VM_CORE_H_INCLUDES) {$(VPATH)}debug.h - sprintf.$(OBJEXT): {$(VPATH)}sprintf.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \ - {$(VPATH)}regex.h {$(VPATH)}vsnprintf.c $(ENCODING_H_INCLUDES) --st.$(OBJEXT): {$(VPATH)}st.c $(RUBY_H_INCLUDES) -+st.$(OBJEXT): {$(VPATH)}st.c $(RUBY_H_INCLUDES) {$(VPATH)}pool_alloc.h - strftime.$(OBJEXT): {$(VPATH)}strftime.c $(RUBY_H_INCLUDES) \ - {$(VPATH)}timev.h - string.$(OBJEXT): {$(VPATH)}string.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \ -diff --git a/configure.in b/configure.in -index 6099a92..ee6012e 100644 ---- a/configure.in -+++ b/configure.in -@@ -1367,7 +1367,8 @@ AC_CHECK_FUNCS(fmod killpg wait4 waitpid fork spawnv syscall __syscall chroot ge - setsid telldir seekdir fchmod cosh sinh tanh log2 round\ - setuid setgid daemon select_large_fdset setenv unsetenv\ - mktime timegm gmtime_r clock_gettime gettimeofday poll ppoll\ -- pread sendfile shutdown sigaltstack dl_iterate_phdr) -+ pread sendfile shutdown sigaltstack dl_iterate_phdr\ -+ dup3 pipe2 posix_memalign memalign) - - AC_CACHE_CHECK(for unsetenv returns a value, rb_cv_unsetenv_return_value, - [AC_TRY_COMPILE([ -diff --git a/ext/-test-/st/numhash/numhash.c b/ext/-test-/st/numhash/numhash.c -index e186cd4..53d9e1b 100644 ---- a/ext/-test-/st/numhash/numhash.c -+++ b/ext/-test-/st/numhash/numhash.c -@@ -54,7 +54,7 @@ numhash_i(st_data_t key, st_data_t value, st_data_t arg, int error) - static VALUE - numhash_each(VALUE self) - { -- return st_foreach((st_table *)DATA_PTR(self), numhash_i, self) ? Qtrue : Qfalse; -+ return st_foreach_check((st_table *)DATA_PTR(self), numhash_i, self, 0) ? Qtrue : Qfalse; - } - - void -diff --git a/gc.c b/gc.c -index 80c3e05..a222b17 100644 ---- a/gc.c -+++ b/gc.c -@@ -20,6 +20,7 @@ - #include "vm_core.h" - #include "internal.h" - #include "gc.h" -+#include "pool_alloc.h" - #include "constant.h" - #include "ruby_atomic.h" - #include -@@ -37,7 +38,12 @@ - - #if defined _WIN32 || defined __CYGWIN__ - #include -+#elif defined(HAVE_POSIX_MEMALIGN) -+#elif defined(HAVE_MEMALIGN) -+#include - #endif -+static void aligned_free(void *); -+static void *aligned_malloc(size_t alignment, size_t size); - - #ifdef HAVE_VALGRIND_MEMCHECK_H - # include -@@ -356,6 +362,24 @@ typedef struct mark_stack { - - #define CALC_EXACT_MALLOC_SIZE 0 - -+#ifdef POOL_ALLOC_API -+/* POOL ALLOC API */ -+#define POOL_ALLOC_PART 1 -+#include "pool_alloc.inc.h" -+#undef POOL_ALLOC_PART -+ -+typedef struct pool_layout_t pool_layout_t; -+struct pool_layout_t { -+ pool_header -+ p6, /* st_table && st_table_entry */ -+ p11; /* st_table.bins init size */ -+} pool_layout = { -+ INIT_POOL(void*[6]), -+ INIT_POOL(void*[11]) -+}; -+static void pool_finalize_header(pool_header *header); -+#endif -+ - typedef struct rb_objspace { - struct { - size_t limit; -@@ -365,6 +389,9 @@ typedef struct rb_objspace { - size_t allocations; - #endif - } malloc_params; -+#ifdef POOL_ALLOC_API -+ pool_layout_t *pool_headers; -+#endif - struct { - size_t increment; - struct heaps_slot *ptr; -@@ -430,7 +457,11 @@ typedef struct rb_objspace { - #define ruby_initial_gc_stress initial_params.gc_stress - int *ruby_initial_gc_stress_ptr = &ruby_initial_gc_stress; - #else -+# ifdef POOL_ALLOC_API -+static rb_objspace_t rb_objspace = {{GC_MALLOC_LIMIT}, &pool_layout, {HEAP_MIN_SLOTS}}; -+# else - static rb_objspace_t rb_objspace = {{GC_MALLOC_LIMIT}, {HEAP_MIN_SLOTS}}; -+# endif - int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress; - #endif - #define malloc_limit objspace->malloc_params.limit -@@ -481,6 +512,10 @@ rb_objspace_alloc(void) - memset(objspace, 0, sizeof(*objspace)); - malloc_limit = initial_malloc_limit; - ruby_gc_stress = ruby_initial_gc_stress; -+#ifdef POOL_ALLOC_API -+ objspace->pool_headers = (pool_layout_t*) malloc(sizeof(pool_layout)); -+ memcpy(objspace->pool_headers, &pool_layout, sizeof(pool_layout)); -+#endif - - return objspace; - } -@@ -624,6 +659,13 @@ rb_objspace_free(rb_objspace_t *objspace) - heaps = 0; - } - free_stack_chunks(&objspace->mark_stack); -+#ifdef POOL_ALLOC_API -+ if (objspace->pool_headers) { -+ pool_finalize_header(&objspace->pool_headers->p6); -+ pool_finalize_header(&objspace->pool_headers->p11); -+ free(objspace->pool_headers); -+ } -+#endif - free(objspace); - } - #endif -@@ -1148,6 +1190,27 @@ rb_gc_stats_enabled() - return gc_statistics ? Qtrue : Qfalse; - } - -+#ifdef POOL_ALLOC_API -+/* POOL ALLOC API */ -+#define POOL_ALLOC_PART 2 -+#include "pool_alloc.inc.h" -+#undef POOL_ALLOC_PART -+ -+void -+ruby_xpool_free(void *ptr) -+{ -+ pool_free_entry((void**)ptr); -+} -+ -+#define CONCRET_POOL_MALLOC(pnts) \ -+void * ruby_xpool_malloc_##pnts##p () { \ -+ return pool_alloc_entry(&rb_objspace.pool_headers->p##pnts ); \ -+} -+CONCRET_POOL_MALLOC(6) -+CONCRET_POOL_MALLOC(11) -+#undef CONCRET_POOL_MALLOC -+ -+#endif - - /* - * call-seq: -@@ -1661,6 +1724,55 @@ allocate_sorted_heaps(rb_objspace_t *objspace, size_t next_heaps_length) - heaps_length = next_heaps_length; - } - -+static void * -+aligned_malloc(size_t alignment, size_t size) -+{ -+ void *res; -+ -+#if defined __MINGW32__ -+ res = __mingw_aligned_malloc(size, alignment); -+#elif defined _WIN32 && !defined __CYGWIN__ -+ 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 -+ -+#if defined(_DEBUG) || defined(GC_DEBUG) -+ /* alignment must be a power of 2 */ -+ assert((alignment - 1) & alignment == 0); -+ assert(alignment % sizeof(void*) == 0); -+#endif -+ return res; -+} -+ -+static void -+aligned_free(void *ptr) -+{ -+#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 -+} -+ - static void - assign_heap_slot(rb_objspace_t *objspace) - { -diff --git a/hash.c b/hash.c -index 8423558..4cb2e2d 100644 ---- a/hash.c -+++ b/hash.c -@@ -44,7 +44,7 @@ rb_any_cmp(VALUE a, VALUE b) - if (FIXNUM_P(a) && FIXNUM_P(b)) { - return a != b; - } -- if (TYPE(a) == T_STRING && RBASIC(a)->klass == rb_cString && -+ if (RB_TYPE_P(a, T_STRING) && RBASIC(a)->klass == rb_cString && - TYPE(b) == T_STRING && RBASIC(b)->klass == rb_cString) { - return rb_str_hash_cmp(a, b); - } -@@ -80,20 +80,14 @@ rb_any_hash(VALUE a) - VALUE hval; - st_index_t hnum; - -- switch (TYPE(a)) { -- case T_FIXNUM: -- case T_SYMBOL: -- case T_NIL: -- case T_FALSE: -- case T_TRUE: -- hnum = rb_hash_end(rb_hash_start((unsigned int)a)); -- break; -- -- case T_STRING: -+ if (SPECIAL_CONST_P(a)) { -+ if (a == Qundef) return 0; -+ hnum = rb_hash_end(rb_hash_start((st_index_t)a)); -+ } -+ else if (BUILTIN_TYPE(a) == T_STRING) { - hnum = rb_str_hash(a); -- break; -- -- default: -+ } -+ else { - hval = rb_hash(a); - hnum = FIX2LONG(hval); - } -@@ -106,10 +100,8 @@ static const struct st_hash_type objhash = { - rb_any_hash, - }; - --static const struct st_hash_type identhash = { -- st_numcmp, -- st_numhash, --}; -+extern const struct st_hash_type st_hashtype_num; -+#define identhash st_hashtype_num - - typedef int st_foreach_func(st_data_t, st_data_t, st_data_t); - -@@ -124,7 +116,6 @@ foreach_safe_i(st_data_t key, st_data_t value, struct foreach_safe_arg *arg) - { - int status; - -- if (key == Qundef) return ST_CONTINUE; - status = (*arg->func)(key, value, arg->arg); - if (status == ST_CONTINUE) { - return ST_CHECK; -@@ -140,7 +131,7 @@ st_foreach_safe(st_table *table, int (*func)(ANYARGS), st_data_t a) - arg.tbl = table; - arg.func = (st_foreach_func *)func; - arg.arg = a; -- if (st_foreach(table, foreach_safe_i, (st_data_t)&arg)) { -+ if (st_foreach_check(table, foreach_safe_i, (st_data_t)&arg, 0)) { - rb_raise(rb_eRuntimeError, "hash modified during iteration"); - } - } -@@ -154,21 +145,21 @@ struct hash_foreach_arg { - }; - - static int --hash_foreach_iter(st_data_t key, st_data_t value, struct hash_foreach_arg *arg) -+hash_foreach_iter(st_data_t key, st_data_t value, st_data_t argp) - { -+ struct hash_foreach_arg *arg = (struct hash_foreach_arg *)argp; - int status; - st_table *tbl; - - tbl = RHASH(arg->hash)->ntbl; -- if ((VALUE)key == Qundef) return ST_CONTINUE; - status = (*arg->func)((VALUE)key, (VALUE)value, arg->arg); - if (RHASH(arg->hash)->ntbl != tbl) { - rb_raise(rb_eRuntimeError, "rehash occurred during iteration"); - } - switch (status) { - case ST_DELETE: -- st_delete_safe(tbl, &key, 0, Qundef); - FL_SET(arg->hash, HASH_DELETED); -+ return ST_DELETE; - case ST_CONTINUE: - break; - case ST_STOP: -@@ -184,7 +175,7 @@ hash_foreach_ensure(VALUE hash) - - if (RHASH(hash)->iter_lev == 0) { - if (FL_TEST(hash, HASH_DELETED)) { -- st_cleanup_safe(RHASH(hash)->ntbl, Qundef); -+ st_cleanup_safe(RHASH(hash)->ntbl, (st_data_t)Qundef); - FL_UNSET(hash, HASH_DELETED); - } - } -@@ -192,9 +183,10 @@ hash_foreach_ensure(VALUE hash) - } - - static VALUE --hash_foreach_call(struct hash_foreach_arg *arg) -+hash_foreach_call(VALUE arg) - { -- if (st_foreach(RHASH(arg->hash)->ntbl, hash_foreach_iter, (st_data_t)arg)) { -+ VALUE hash = ((struct hash_foreach_arg *)arg)->hash; -+ if (st_foreach_check(RHASH(hash)->ntbl, hash_foreach_iter, (st_data_t)arg, (st_data_t)Qundef)) { - rb_raise(rb_eRuntimeError, "hash modified during iteration"); - } - return Qnil; -@@ -447,7 +439,7 @@ rb_hash_rehash_i(VALUE key, VALUE value, VALUE arg) - { - st_table *tbl = (st_table *)arg; - -- if (key != Qundef) st_insert(tbl, key, value); -+ st_insert(tbl, (st_data_t)key, (st_data_t)value); - return ST_CONTINUE; - } - -@@ -490,6 +482,20 @@ rb_hash_rehash(VALUE hash) - return hash; - } - -+static VALUE -+hash_default_value(VALUE hash, VALUE key) -+{ -+ if (rb_method_basic_definition_p(CLASS_OF(hash), id_default)) { -+ VALUE ifnone = RHASH_IFNONE(hash); -+ if (!FL_TEST(hash, HASH_PROC_DEFAULT)) return ifnone; -+ if (key == Qundef) return Qnil; -+ return rb_funcall(ifnone, id_yield, 2, hash, key); -+ } -+ else { -+ return rb_funcall(hash, id_default, 1, key); -+ } -+} -+ - /* - * call-seq: - * hsh[key] -> value -@@ -510,13 +516,7 @@ rb_hash_aref(VALUE hash, VALUE key) - st_data_t val; - - if (!RHASH(hash)->ntbl || !st_lookup(RHASH(hash)->ntbl, key, &val)) { -- if (!FL_TEST(hash, HASH_PROC_DEFAULT) && -- rb_method_basic_definition_p(CLASS_OF(hash), id_default)) { -- return RHASH_IFNONE(hash); -- } -- else { -- return rb_funcall(hash, id_default, 1, key); -- } -+ return hash_default_value(hash, key); - } - return (VALUE)val; - } -@@ -659,7 +659,7 @@ rb_hash_default(int argc, VALUE *argv, VALUE hash) - static VALUE - rb_hash_set_default(VALUE hash, VALUE ifnone) - { -- rb_hash_modify(hash); -+ rb_hash_modify_check(hash); - RHASH_IFNONE(hash) = ifnone; - FL_UNSET(hash, HASH_PROC_DEFAULT); - return ifnone; -@@ -707,7 +707,7 @@ rb_hash_set_default_proc(VALUE hash, VALUE proc) - { - VALUE b; - -- rb_hash_modify(hash); -+ rb_hash_modify_check(hash); - b = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc"); - if (NIL_P(b) || !rb_obj_is_proc(b)) { - rb_raise(rb_eTypeError, -@@ -776,7 +776,7 @@ rb_hash_delete_key(VALUE hash, VALUE key) - if (!RHASH(hash)->ntbl) - return Qundef; - if (RHASH(hash)->iter_lev > 0) { -- if (st_delete_safe(RHASH(hash)->ntbl, &ktmp, &val, Qundef)) { -+ if (st_delete_safe(RHASH(hash)->ntbl, &ktmp, &val, (st_data_t)Qundef)) { - FL_SET(hash, HASH_DELETED); - return (VALUE)val; - } -@@ -809,7 +809,7 @@ rb_hash_delete(VALUE hash, VALUE key) - { - VALUE val; - -- rb_hash_modify(hash); -+ rb_hash_modify_check(hash); - val = rb_hash_delete_key(hash, key); - if (val != Qundef) return val; - if (rb_block_given_p()) { -@@ -828,7 +828,6 @@ shift_i(VALUE key, VALUE value, VALUE arg) - { - struct shift_var *var = (struct shift_var *)arg; - -- if (key == Qundef) return ST_CONTINUE; - if (var->key != Qundef) return ST_STOP; - var->key = key; - var->val = value; -@@ -840,7 +839,6 @@ shift_i_safe(VALUE key, VALUE value, VALUE arg) - { - struct shift_var *var = (struct shift_var *)arg; - -- if (key == Qundef) return ST_CONTINUE; - var->key = key; - var->val = value; - return ST_STOP; -@@ -864,29 +862,25 @@ rb_hash_shift(VALUE hash) - { - struct shift_var var; - -- rb_hash_modify(hash); -- var.key = Qundef; -- rb_hash_foreach(hash, RHASH(hash)->iter_lev > 0 ? shift_i_safe : shift_i, -- (VALUE)&var); -- -- if (var.key != Qundef) { -- if (RHASH(hash)->iter_lev > 0) { -- rb_hash_delete_key(hash, var.key); -+ rb_hash_modify_check(hash); -+ if (RHASH(hash)->ntbl) { -+ var.key = Qundef; -+ rb_hash_foreach(hash, RHASH(hash)->iter_lev > 0 ? shift_i_safe : shift_i, -+ (VALUE)&var); -+ -+ if (var.key != Qundef) { -+ if (RHASH(hash)->iter_lev > 0) { -+ rb_hash_delete_key(hash, var.key); -+ } -+ return rb_assoc_new(var.key, var.val); - } -- return rb_assoc_new(var.key, var.val); -- } -- else if (FL_TEST(hash, HASH_PROC_DEFAULT)) { -- return rb_funcall(RHASH_IFNONE(hash), id_yield, 2, hash, Qnil); -- } -- else { -- return RHASH_IFNONE(hash); - } -+ return hash_default_value(hash, Qnil); - } - - static int - delete_if_i(VALUE key, VALUE value, VALUE hash) - { -- if (key == Qundef) return ST_CONTINUE; - if (RTEST(rb_yield_values(2, key, value))) { - rb_hash_delete_key(hash, key); - } -@@ -912,8 +906,9 @@ VALUE - rb_hash_delete_if(VALUE hash) - { - RETURN_ENUMERATOR(hash, 0, 0); -- rb_hash_modify(hash); -- rb_hash_foreach(hash, delete_if_i, hash); -+ rb_hash_modify_check(hash); -+ if (RHASH(hash)->ntbl) -+ rb_hash_foreach(hash, delete_if_i, hash); - return hash; - } - -@@ -984,7 +979,6 @@ rb_hash_values_at(int argc, VALUE *argv, VALUE hash) - static int - select_i(VALUE key, VALUE value, VALUE result) - { -- if (key == Qundef) return ST_CONTINUE; - if (RTEST(rb_yield_values(2, key, value))) - rb_hash_aset(result, key, value); - return ST_CONTINUE; -@@ -1018,7 +1012,6 @@ rb_hash_select(VALUE hash) - static int - keep_if_i(VALUE key, VALUE value, VALUE hash) - { -- if (key == Qundef) return ST_CONTINUE; - if (!RTEST(rb_yield_values(2, key, value))) { - return ST_DELETE; - } -@@ -1040,7 +1033,7 @@ rb_hash_select_bang(VALUE hash) - st_index_t n; - - RETURN_ENUMERATOR(hash, 0, 0); -- rb_hash_modify(hash); -+ rb_hash_modify_check(hash); - if (!RHASH(hash)->ntbl) - return Qnil; - n = RHASH(hash)->ntbl->num_entries; -@@ -1065,8 +1058,9 @@ VALUE - rb_hash_keep_if(VALUE hash) - { - RETURN_ENUMERATOR(hash, 0, 0); -- rb_hash_modify(hash); -- rb_hash_foreach(hash, keep_if_i, hash); -+ rb_hash_modify_check(hash); -+ if (RHASH(hash)->ntbl) -+ rb_hash_foreach(hash, keep_if_i, hash); - return hash; - } - -@@ -1144,9 +1138,7 @@ rb_hash_aset(VALUE hash, VALUE key, VALUE val) - static int - replace_i(VALUE key, VALUE val, VALUE hash) - { -- if (key != Qundef) { -- rb_hash_aset(hash, key, val); -- } -+ rb_hash_aset(hash, key, val); - - return ST_CONTINUE; - } -@@ -1227,7 +1219,6 @@ rb_hash_empty_p(VALUE hash) - static int - each_value_i(VALUE key, VALUE value) - { -- if (key == Qundef) return ST_CONTINUE; - rb_yield(value); - return ST_CONTINUE; - } -@@ -1262,7 +1253,6 @@ rb_hash_each_value(VALUE hash) - static int - each_key_i(VALUE key, VALUE value) - { -- if (key == Qundef) return ST_CONTINUE; - rb_yield(key); - return ST_CONTINUE; - } -@@ -1296,7 +1286,6 @@ rb_hash_each_key(VALUE hash) - static int - each_pair_i(VALUE key, VALUE value) - { -- if (key == Qundef) return ST_CONTINUE; - rb_yield(rb_assoc_new(key, value)); - return ST_CONTINUE; - } -@@ -1334,7 +1323,6 @@ rb_hash_each_pair(VALUE hash) - static int - to_a_i(VALUE key, VALUE value, VALUE ary) - { -- if (key == Qundef) return ST_CONTINUE; - rb_ary_push(ary, rb_assoc_new(key, value)); - return ST_CONTINUE; - } -@@ -1367,7 +1355,6 @@ inspect_i(VALUE key, VALUE value, VALUE str) - { - VALUE str2; - -- if (key == Qundef) return ST_CONTINUE; - str2 = rb_inspect(key); - if (RSTRING_LEN(str) > 1) { - rb_str_cat2(str, ", "); -@@ -1434,7 +1421,6 @@ rb_hash_to_hash(VALUE hash) - static int - keys_i(VALUE key, VALUE value, VALUE ary) - { -- if (key == Qundef) return ST_CONTINUE; - rb_ary_push(ary, key); - return ST_CONTINUE; - } -@@ -1465,7 +1451,6 @@ rb_hash_keys(VALUE hash) - static int - values_i(VALUE key, VALUE value, VALUE ary) - { -- if (key == Qundef) return ST_CONTINUE; - rb_ary_push(ary, value); - return ST_CONTINUE; - } -@@ -1524,7 +1509,6 @@ rb_hash_search_value(VALUE key, VALUE value, VALUE arg) - { - VALUE *data = (VALUE *)arg; - -- if (key == Qundef) return ST_CONTINUE; - if (rb_equal(value, data[1])) { - data[0] = Qtrue; - return ST_STOP; -@@ -1568,7 +1552,6 @@ eql_i(VALUE key, VALUE val1, VALUE arg) - struct equal_data *data = (struct equal_data *)arg; - st_data_t val2; - -- if (key == Qundef) return ST_CONTINUE; - if (!st_lookup(data->tbl, key, &val2)) { - data->result = Qfalse; - return ST_STOP; -@@ -1599,7 +1582,7 @@ hash_equal(VALUE hash1, VALUE hash2, int eql) - struct equal_data data; - - if (hash1 == hash2) return Qtrue; -- if (TYPE(hash2) != T_HASH) { -+ if (!RB_TYPE_P(hash2, T_HASH)) { - if (!rb_respond_to(hash2, rb_intern("to_hash"))) { - return Qfalse; - } -@@ -1670,7 +1653,6 @@ hash_i(VALUE key, VALUE val, VALUE arg) - st_index_t *hval = (st_index_t *)arg; - st_index_t hdata[2]; - -- if (key == Qundef) return ST_CONTINUE; - hdata[0] = rb_hash(key); - hdata[1] = rb_hash(val); - *hval ^= st_hash(hdata, sizeof(hdata), 0); -@@ -1711,7 +1693,6 @@ rb_hash_hash(VALUE hash) - static int - rb_hash_invert_i(VALUE key, VALUE value, VALUE hash) - { -- if (key == Qundef) return ST_CONTINUE; - rb_hash_aset(hash, value, key); - return ST_CONTINUE; - } -@@ -1740,7 +1721,6 @@ rb_hash_invert(VALUE hash) - static int - rb_hash_update_i(VALUE key, VALUE value, VALUE hash) - { -- if (key == Qundef) return ST_CONTINUE; - hash_update(hash, key); - st_insert(RHASH(hash)->ntbl, key, value); - return ST_CONTINUE; -@@ -1749,7 +1729,6 @@ rb_hash_update_i(VALUE key, VALUE value, VALUE hash) - static int - rb_hash_update_block_i(VALUE key, VALUE value, VALUE hash) - { -- if (key == Qundef) return ST_CONTINUE; - if (rb_hash_has_key(hash, key)) { - value = rb_yield_values(3, key, rb_hash_aref(hash, key), value); - } -@@ -1806,7 +1785,6 @@ rb_hash_update_func_i(VALUE key, VALUE value, VALUE arg0) - struct update_arg *arg = (struct update_arg *)arg0; - VALUE hash = arg->hash; - -- if (key == Qundef) return ST_CONTINUE; - if (rb_hash_has_key(hash, key)) { - value = (*arg->func)(key, rb_hash_aref(hash, key), value); - } -@@ -1863,7 +1841,6 @@ assoc_i(VALUE key, VALUE val, VALUE arg) - { - VALUE *args = (VALUE *)arg; - -- if (key == Qundef) return ST_CONTINUE; - if (RTEST(rb_equal(args[0], key))) { - args[1] = rb_assoc_new(key, val); - return ST_STOP; -@@ -1901,7 +1878,6 @@ rassoc_i(VALUE key, VALUE val, VALUE arg) - { - VALUE *args = (VALUE *)arg; - -- if (key == Qundef) return ST_CONTINUE; - if (RTEST(rb_equal(args[0], val))) { - args[1] = rb_assoc_new(key, val); - return ST_STOP; -@@ -2198,7 +2174,7 @@ rb_env_path_tainted(void) - } - - #if defined(_WIN32) || (defined(HAVE_SETENV) && defined(HAVE_UNSETENV)) --#elif defined __sun__ -+#elif defined __sun - static int - in_origenv(const char *str) - { -@@ -2286,7 +2262,7 @@ ruby_setenv(const char *name, const char *value) - rb_sys_fail("unsetenv"); - #endif - } --#elif defined __sun__ -+#elif defined __sun - size_t len; - char **env_ptr, *str; - if (strchr(name, '=')) { -@@ -3084,11 +3060,9 @@ env_invert(void) - static int - env_replace_i(VALUE key, VALUE val, VALUE keys) - { -- if (key != Qundef) { -- env_aset(Qnil, key, val); -- if (rb_ary_includes(keys, key)) { -- rb_ary_delete(keys, key); -- } -+ env_aset(Qnil, key, val); -+ if (rb_ary_includes(keys, key)) { -+ rb_ary_delete(keys, key); - } - return ST_CONTINUE; - } -@@ -3120,12 +3094,10 @@ env_replace(VALUE env, VALUE hash) - static int - env_update_i(VALUE key, VALUE val) - { -- if (key != Qundef) { -- if (rb_block_given_p()) { -- val = rb_yield_values(3, key, rb_f_getenv(Qnil, key), val); -- } -- env_aset(Qnil, key, val); -+ if (rb_block_given_p()) { -+ val = rb_yield_values(3, key, rb_f_getenv(Qnil, key), val); - } -+ env_aset(Qnil, key, val); - return ST_CONTINUE; - } - -@@ -3150,15 +3122,116 @@ env_update(VALUE env, VALUE hash) - } - - /* -- * A Hash is a collection of key-value pairs. It is -- * similar to an Array, except that indexing is done via -- * arbitrary keys of any object type, not an integer index. Hashes enumerate -- * their values in the order that the corresponding keys were inserted. -+ * A Hash is a dictionary-like collection of unique keys and their values. -+ * Also called associative arrays, they are similar to Arrays, but where an -+ * Array uses integers as its index, a Hash allows you to use any object -+ * type. -+ * -+ * Hashes enumerate their values in the order that the corresponding keys -+ * were inserted. -+ * -+ * A Hash can be easily created by using its implicit form: -+ * -+ * grades = { "Jane Doe" => 10, "Jim Doe" => 6 } -+ * -+ * Hashes allow an alternate syntax form when your keys are always symbols. -+ * Instead of -+ * -+ * options = { :font_size => 10, :font_family => "Arial" } -+ * -+ * You could write it as: -+ * -+ * options = { font_size: 10, font_family: "Arial" } -+ * -+ * Each named key is a symbol you can access in hash: -+ * -+ * options[:font_size] # => 10 -+ * -+ * A Hash can also be created through its ::new method: -+ * -+ * grades = Hash.new -+ * grades["Dorothy Doe"] = 9 - * - * Hashes have a default value that is returned when accessing -- * keys that do not exist in the hash. By default, that value is -- * nil. -+ * keys that do not exist in the hash. If no default is set +nil+ is used. -+ * You can set the default value by sending it as an argument to Hash.new: -+ * -+ * grades = Hash.new(0) -+ * -+ * Or by using the #default= method: -+ * -+ * grades = {"Timmy Doe" => 8} -+ * grades.default = 0 -+ * -+ * Accessing a value in a Hash requires using its key: -+ * -+ * puts grades["Jane Doe"] # => 10 -+ * -+ * === Common Uses -+ * -+ * Hashes are an easy way to represent data structures, such as -+ * -+ * books = {} -+ * books[:matz] = "The Ruby Language" -+ * books[:black] = "The Well-Grounded Rubyist" -+ * -+ * Hashes are also commonly used as a way to have named parameters in -+ * functions. Note that no brackets are used below. If a hash is the last -+ * argument on a method call, no braces are needed, thus creating a really -+ * clean interface: -+ * -+ * Person.create(name: "John Doe", age: 27) -+ * -+ * def self.create(params) -+ * @name = params[:name] -+ * @age = params[:age] -+ * end -+ * -+ * === Hash Keys -+ * -+ * Two objects refer to the same hash key when their hash value -+ * is identical and the two objects are eql? to each other. -+ * -+ * A user-defined class may be used as a hash key if the hash -+ * and eql? methods are overridden to provide meaningful -+ * behavior. By default, separate instances refer to separate hash keys. -+ * -+ * A typical implementation of hash is based on the -+ * object's data while eql? is usually aliased to the overridden -+ * == method: -+ * -+ * class Book -+ * attr_reader :author, :title -+ * -+ * def initialize(author, title) -+ * @author = author -+ * @title = title -+ * end -+ * -+ * def ==(other) -+ * self.class === other and -+ * other.author == @author and -+ * other.title == @title -+ * end -+ * -+ * alias eql? == -+ * -+ * def hash -+ * @author.hash ^ @title.hash # XOR -+ * end -+ * end -+ * -+ * book1 = Book.new 'matz', 'Ruby in a Nutshell' -+ * book2 = Book.new 'matz', 'Ruby in a Nutshell' -+ * -+ * reviews = {} -+ * -+ * reviews[book1] = 'Great reference!' -+ * reviews[book2] = 'Nice and compact!' -+ * -+ * reviews.length #=> 1 - * -+ * See also Object#hash and Object#eql? - */ - - void -diff --git a/include/ruby/st.h b/include/ruby/st.h -index 50f2a75..119dfde 100644 ---- a/include/ruby/st.h -+++ b/include/ruby/st.h -@@ -36,7 +36,7 @@ typedef unsigned long st_data_t; - #elif SIZEOF_LONG_LONG == SIZEOF_VOIDP - typedef unsigned LONG_LONG st_data_t; - #else --# error ---->> st.c requires sizeof(void*) == sizeof(long) to be compiled. <<---- -+# error ---->> st.c requires sizeof(void*) == sizeof(long) or sizeof(LONG_LONG) to be compiled. <<---- - #endif - #define ST_DATA_T_DEFINED - -@@ -74,6 +74,11 @@ struct st_hash_type { - - #define ST_INDEX_BITS (sizeof(st_index_t) * CHAR_BIT) - -+typedef struct st_packed_entry { -+ st_index_t hash; -+ st_data_t key, val; -+} st_packed_entry; -+ - struct st_table { - const struct st_hash_type *type; - st_index_t num_bins; -@@ -91,8 +96,17 @@ struct st_table { - __extension__ - #endif - st_index_t num_entries : ST_INDEX_BITS - 1; -- struct st_table_entry **bins; -- struct st_table_entry *head, *tail; -+ union { -+ struct { -+ struct st_table_entry **bins; -+ struct st_table_entry *head, *tail; -+ } big; -+ struct { -+ struct st_packed_entry *entries; -+ st_index_t real_entries; -+ } packed; -+ st_packed_entry upacked; -+ } as; - }; - - #define st_is_member(table,key) st_lookup((table),(key),(st_data_t *)0) -@@ -114,6 +128,7 @@ int st_insert2(st_table *, st_data_t, st_data_t, st_data_t (*)(st_data_t)); - int st_lookup(st_table *, st_data_t, st_data_t *); - int st_get_key(st_table *, st_data_t, st_data_t *); - int st_foreach(st_table *, int (*)(ANYARGS), st_data_t); -+int st_foreach_check(st_table *, int (*)(ANYARGS), st_data_t, st_data_t); - int st_reverse_foreach(st_table *, int (*)(ANYARGS), st_data_t); - void st_add_direct(st_table *, st_data_t, st_data_t); - void st_free_table(st_table *); -diff --git a/pool_alloc.h b/pool_alloc.h -new file mode 100644 -index 0000000..957708e ---- /dev/null -+++ b/pool_alloc.h -@@ -0,0 +1,11 @@ -+#ifndef POOL_ALLOC_H -+#define POOL_ALLOC_H -+ -+#define POOL_ALLOC_API -+#ifdef POOL_ALLOC_API -+void ruby_xpool_free(void *ptr); -+void *ruby_xpool_malloc_6p(); -+void *ruby_xpool_malloc_11p(); -+#endif -+ -+#endif -diff --git a/pool_alloc.inc.h b/pool_alloc.inc.h -new file mode 100644 -index 0000000..a7879ab ---- /dev/null -+++ b/pool_alloc.inc.h -@@ -0,0 +1,156 @@ -+/* -+ * this is generic pool allocator -+ * you should define following macroses: -+ * ITEM_NAME - unique identifier, which allows to hold functions in a namespace -+ * ITEM_TYPEDEF(name) - passed to typedef to localize item type -+ * free_entry - desired name of function for free entry -+ * alloc_entry - defired name of function for allocate entry -+ */ -+ -+#if POOL_ALLOC_PART == 1 -+#ifdef HEAP_ALIGN_LOG -+#define DEFAULT_POOL_SIZE (1 << HEAP_ALIGN_LOG) -+#else -+#define DEFAULT_POOL_SIZE (sizeof(void*) * 2048) -+#endif -+typedef unsigned int pool_holder_counter; -+ -+typedef struct pool_entry_list pool_entry_list; -+typedef struct pool_holder pool_holder; -+ -+typedef struct pool_header { -+ pool_holder *first; -+ pool_holder *_black_magick; -+ pool_holder_counter size; // size of entry in sizeof(void*) items -+ pool_holder_counter total; // size of entry in sizeof(void*) items -+} pool_header; -+ -+struct pool_holder { -+ pool_holder_counter free, total; -+ pool_header *header; -+ void *freep; -+ pool_holder *fore, *back; -+ void *data[1]; -+}; -+#define POOL_DATA_SIZE(pool_size) (((pool_size) - sizeof(void*) * 6 - offsetof(pool_holder, data)) / sizeof(void*)) -+#define POOL_ENTRY_SIZE(item_type) ((sizeof(item_type) - 1) / sizeof(void*) + 1) -+#define POOL_HOLDER_COUNT(pool_size, item_type) (POOL_DATA_SIZE(pool_size)/POOL_ENTRY_SIZE(item_type)) -+#define INIT_POOL(item_type) {NULL, NULL, POOL_ENTRY_SIZE(item_type), POOL_HOLDER_COUNT(DEFAULT_POOL_SIZE, item_type)} -+ -+#elif POOL_ALLOC_PART == 2 -+static pool_holder * -+pool_holder_alloc(pool_header *header) -+{ -+ pool_holder *holder; -+ pool_holder_counter i, size, count; -+ register void **ptr; -+ -+ size_t sz = offsetof(pool_holder, data) + -+ header->size * header->total * sizeof(void*); -+#define objspace (&rb_objspace) -+ vm_malloc_prepare(objspace, DEFAULT_POOL_SIZE); -+ if (header->first != NULL) return header->first; -+ TRY_WITH_GC(holder = (pool_holder*) aligned_malloc(DEFAULT_POOL_SIZE, sz)); -+ malloc_increase += DEFAULT_POOL_SIZE; -+#if CALC_EXACT_MALLOC_SIZE -+ objspace->malloc_params.allocated_size += DEFAULT_POOL_SIZE; -+ objspace->malloc_params.allocations++; -+#endif -+#undef objspace -+ -+ size = header->size; -+ count = header->total; -+ holder->free = count; -+ holder->total = count; -+ holder->header = header; -+ holder->fore = NULL; -+ holder->back = NULL; -+ holder->freep = &holder->data; -+ ptr = holder->data; -+ for(i = count - 1; i; i-- ) { -+ ptr = *ptr = ptr + size; -+ } -+ *ptr = NULL; -+ header->first = holder; -+ return holder; -+} -+ -+static inline void -+pool_holder_unchaing(pool_header *header, pool_holder *holder) -+{ -+ register pool_holder *fore = holder->fore, *back = holder->back; -+ holder->fore = NULL; -+ holder->back = NULL; -+ if (fore != NULL) fore->back = back; -+ else header->_black_magick = back; -+ if (back != NULL) back->fore = fore; -+ else header->first = fore; -+} -+ -+static inline pool_holder * -+entry_holder(void **entry) -+{ -+ return (pool_holder*)(((uintptr_t)entry) & ~(DEFAULT_POOL_SIZE - 1)); -+} -+ -+static inline void -+pool_free_entry(void **entry) -+{ -+ pool_holder *holder = entry_holder(entry); -+ pool_header *header = holder->header; -+ -+ if (holder->free++ == 0) { -+ register pool_holder *first = header->first; -+ if (first == NULL) { -+ header->first = holder; -+ } else { -+ holder->back = first; -+ holder->fore = first->fore; -+ first->fore = holder; -+ if (holder->fore) -+ holder->fore->back = holder; -+ else -+ header->_black_magick = holder; -+ } -+ } else if (holder->free == holder->total && header->first != holder ) { -+ pool_holder_unchaing(header, holder); -+ aligned_free(holder); -+#if CALC_EXACT_MALLOC_SIZE -+ rb_objspace.malloc_params.allocated_size -= DEFAULT_POOL_SIZE; -+ rb_objspace.malloc_params.allocations--; -+#endif -+ return; -+ } -+ -+ *entry = holder->freep; -+ holder->freep = entry; -+} -+ -+static inline void* -+pool_alloc_entry(pool_header *header) -+{ -+ pool_holder *holder = header->first; -+ void **result; -+ if (holder == NULL) { -+ holder = pool_holder_alloc(header); -+ } -+ -+ result = holder->freep; -+ holder->freep = *result; -+ -+ if (--holder->free == 0) { -+ pool_holder_unchaing(header, holder); -+ } -+ -+ return result; -+} -+ -+static void -+pool_finalize_header(pool_header *header) -+{ -+ if (header->first) { -+ aligned_free(header->first); -+ header->first = NULL; -+ } -+} -+#endif -diff --git a/st.c b/st.c -index fda5784..0194022 100644 ---- a/st.c -+++ b/st.c -@@ -7,6 +7,7 @@ - #include "st.h" - #else - #include "ruby/ruby.h" -+#include "pool_alloc.h" - #endif - - #include -@@ -25,8 +26,17 @@ struct st_table_entry { - st_table_entry *fore, *back; - }; - --#define ST_DEFAULT_MAX_DENSITY 5 -+#define STATIC_ASSERT(name, expr) typedef int static_assert_##name##_check[(expr) ? 1 : -1]; -+ -+#define ST_DEFAULT_MAX_DENSITY 2 - #define ST_DEFAULT_INIT_TABLE_SIZE 11 -+#define ST_DEFAULT_SECOND_TABLE_SIZE 19 -+#define ST_DEFAULT_PACKED_TABLE_SIZE 19 -+#define PACKED_UNIT (int)(sizeof(st_packed_entry) / sizeof(st_table_entry*)) -+#define MAX_PACKED_HASH (int)(ST_DEFAULT_PACKED_TABLE_SIZE * sizeof(st_table_entry*) / sizeof(st_packed_entry)) -+ -+STATIC_ASSERT(st_packed_entry, sizeof(st_packed_entry) == sizeof(st_table_entry*[PACKED_UNIT])) -+STATIC_ASSERT(st_packed_bins, sizeof(st_packed_entry[MAX_PACKED_HASH]) <= sizeof(st_table_entry*[ST_DEFAULT_PACKED_TABLE_SIZE])) - - /* - * DEFAULT_MAX_DENSITY is the default for the largest we allow the -@@ -38,7 +48,8 @@ struct st_table_entry { - * - */ - --static const struct st_hash_type type_numhash = { -+#define type_numhash st_hashtype_num -+const struct st_hash_type st_hashtype_num = { - st_numcmp, - st_numhash, - }; -@@ -61,20 +72,128 @@ static void rehash(st_table *); - #ifdef RUBY - #define malloc xmalloc - #define calloc xcalloc -+#define realloc xrealloc - #define free(x) xfree(x) - #endif - - #define numberof(array) (int)(sizeof(array) / sizeof((array)[0])) - --#define alloc(type) (type*)malloc((size_t)sizeof(type)) --#define Calloc(n,s) (char*)calloc((n),(s)) -- - #define EQUAL(table,x,y) ((x)==(y) || (*(table)->type->compare)((x),(y)) == 0) - --/* remove cast to unsigned int in the future */ --#define do_hash(key,table) (unsigned int)(st_index_t)(*(table)->type->hash)((key)) -+#define do_hash(key,table) (st_index_t)(*(table)->type->hash)((key)) - #define do_hash_bin(key,table) (do_hash((key), (table))%(table)->num_bins) - -+/* preparation for possible allocation improvements */ -+#ifdef POOL_ALLOC_API -+#define st_alloc_entry() (st_table_entry *)ruby_xpool_malloc_6p() -+#define st_free_entry(entry) ruby_xpool_free(entry) -+#define st_alloc_table() (st_table *)ruby_xpool_malloc_6p() -+#define st_dealloc_table(table) ruby_xpool_free(table) -+static inline st_table_entry ** -+st_alloc_bins(st_index_t size) -+{ -+ st_table_entry **result; -+ if (size == 11) { -+ result = (st_table_entry **) ruby_xpool_malloc_11p(); -+ memset(result, 0, 11 * sizeof(st_table_entry *)); -+ } -+ else -+ result = (st_table_entry **) ruby_xcalloc(size, sizeof(st_table_entry*)); -+ return result; -+} -+static inline void -+st_free_bins(st_table_entry **bins, st_index_t size) -+{ -+ if (size == 11) -+ ruby_xpool_free(bins); -+ else -+ ruby_xfree(bins); -+} -+static inline st_table_entry** -+st_realloc_bins(st_table_entry **bins, st_index_t newsize, st_index_t oldsize) -+{ -+ st_table_entry **new_bins = st_alloc_bins(newsize); -+ st_free_bins(bins, oldsize); -+ return new_bins; -+} -+#else -+#define st_alloc_entry() (st_table_entry *)malloc(sizeof(st_table_entry)) -+#define st_free_entry(entry) free(entry) -+#define st_alloc_table() (st_table *)malloc(sizeof(st_table)) -+#define st_dealloc_table(table) free(table) -+#define st_alloc_bins(size) (st_table_entry **)calloc(size, sizeof(st_table_entry *)) -+#define st_free_bins(bins, size) free(bins) -+static inline st_table_entry** -+st_realloc_bins(st_table_entry **bins, st_index_t newsize, st_index_t oldsize) -+{ -+ bins = (st_table_entry **)realloc(bins, newsize * sizeof(st_table_entry *)); -+ MEMZERO(bins, st_table_entry*, newsize); -+ return bins; -+} -+#endif -+ -+/* Shortage */ -+#define bins as.big.bins -+#define head as.big.head -+#define tail as.big.tail -+#define real_entries as.packed.real_entries -+ -+/* preparation for possible packing improvements */ -+#define PACKED_BINS(table) ((table)->as.packed.entries) -+#define PACKED_ENT(table, i) PACKED_BINS(table)[i] -+#define PKEY(table, i) PACKED_ENT((table), (i)).key -+#define PVAL(table, i) PACKED_ENT((table), (i)).val -+#define PHASH(table, i) PACKED_ENT((table), (i)).hash -+#define PKEY_SET(table, i, v) (PKEY((table), (i)) = (v)) -+#define PVAL_SET(table, i, v) (PVAL((table), (i)) = (v)) -+#define PHASH_SET(table, i, v) (PHASH((table), (i)) = (v)) -+ -+/* this function depends much on packed layout, so that it placed here */ -+static inline void -+remove_packed_entry(st_table *table, st_index_t i) -+{ -+ table->real_entries--; -+ table->num_entries--; -+ if (i < table->real_entries) { -+ MEMMOVE(&PACKED_ENT(table, i), &PACKED_ENT(table, i+1), -+ st_packed_entry, table->real_entries - i); -+ } -+} -+ -+static inline void -+remove_safe_packed_entry(st_table *table, st_index_t i, st_data_t never) -+{ -+ table->num_entries--; -+ PKEY_SET(table, i, never); -+ PVAL_SET(table, i, never); -+ PHASH_SET(table, i, 0); -+} -+ -+/* ultrapacking */ -+#define real_upacked num_bins -+#define MAX_UPACKED_HASH 1 -+#define ULTRAPACKED(table) ((table)->real_upacked <= 1) -+#define UPACKED_ENT(table) ((table)->as.upacked) -+#define UPKEY(table) UPACKED_ENT(table).key -+#define UPVAL(table) UPACKED_ENT(table).val -+#define UPHASH(table) UPACKED_ENT(table).hash -+#define UPKEY_SET(table, v) (UPACKED_ENT(table).key = (v)) -+#define UPVAL_SET(table, v) (UPACKED_ENT(table).val = (v)) -+#define UPHASH_SET(table, v) (UPACKED_ENT(table).hash = (v)) -+static inline void -+remove_upacked_entry(st_table *table) -+{ -+ table->real_upacked = table->num_entries = 0; -+} -+ -+static inline void -+remove_safe_upacked_entry(st_table *table, st_data_t never) -+{ -+ table->num_entries = 0; -+ UPKEY_SET(table, never); -+ UPVAL_SET(table, never); -+ UPHASH_SET(table, 0); -+} - /* - * MINSIZE is the minimum size of a dictionary. - */ -@@ -85,8 +204,8 @@ static void rehash(st_table *); - Table of prime numbers 2^n+a, 2<=n<=30. - */ - static const unsigned int primes[] = { -- 8 + 3, -- 16 + 3, -+ ST_DEFAULT_INIT_TABLE_SIZE, -+ ST_DEFAULT_SECOND_TABLE_SIZE, - 32 + 5, - 64 + 3, - 128 + 3, -@@ -161,8 +280,6 @@ stat_col(void) - } - #endif - --#define MAX_PACKED_NUMHASH (ST_DEFAULT_INIT_TABLE_SIZE/2) -- - st_table* - st_init_table_with_size(const struct st_hash_type *type, st_index_t size) - { -@@ -181,14 +298,19 @@ st_init_table_with_size(const struct st_hash_type *type, st_index_t size) - } - #endif - -- size = new_size(size); /* round up to prime number */ - -- tbl = alloc(st_table); -+ tbl = st_alloc_table(); - tbl->type = type; - tbl->num_entries = 0; -- tbl->entries_packed = type == &type_numhash && size/2 <= MAX_PACKED_NUMHASH; -+ tbl->entries_packed = size <= MAX_PACKED_HASH; -+ if (tbl->entries_packed) { -+ size = size <= MAX_UPACKED_HASH ? 0 : ST_DEFAULT_PACKED_TABLE_SIZE; -+ } -+ else { -+ size = new_size(size); /* round up to prime number */ -+ } - tbl->num_bins = size; -- tbl->bins = (st_table_entry **)Calloc(size, sizeof(st_table_entry*)); -+ tbl->bins = size ? st_alloc_bins(size) : 0; - tbl->head = 0; - tbl->tail = 0; - -@@ -243,17 +365,23 @@ st_clear(st_table *table) - register st_table_entry *ptr, *next; - st_index_t i; - -+ if (ULTRAPACKED(table)) { -+ remove_upacked_entry(table); -+ return; -+ } -+ - if (table->entries_packed) { - table->num_entries = 0; -+ table->real_entries = 0; - return; - } - -- for(i = 0; i < table->num_bins; i++) { -+ for (i = 0; i < table->num_bins; i++) { - ptr = table->bins[i]; - table->bins[i] = 0; - while (ptr != 0) { - next = ptr->next; -- free(ptr); -+ st_free_entry(ptr); - ptr = next; - } - } -@@ -266,14 +394,19 @@ void - st_free_table(st_table *table) - { - st_clear(table); -- free(table->bins); -- free(table); -+ if (!ULTRAPACKED(table)) { -+ st_free_bins(table->bins, table->num_bins); -+ } -+ st_dealloc_table(table); - } - - size_t - st_memsize(const st_table *table) - { -- if (table->entries_packed) { -+ if (ULTRAPACKED(table)) { -+ return sizeof(st_table); -+ } -+ else if (table->entries_packed) { - return table->num_bins * sizeof (void *) + sizeof(st_table); - } - else { -@@ -306,46 +439,77 @@ count_collision(const struct st_hash_type *type) - #define FOUND_ENTRY - #endif - --#define FIND_ENTRY(table, ptr, hash_val, bin_pos) do {\ -- (bin_pos) = (hash_val)%(table)->num_bins;\ -- (ptr) = (table)->bins[(bin_pos)];\ -- FOUND_ENTRY;\ -- if (PTR_NOT_EQUAL((table), (ptr), (hash_val), key)) {\ -- COLLISION;\ -- while (PTR_NOT_EQUAL((table), (ptr)->next, (hash_val), key)) {\ -- (ptr) = (ptr)->next;\ -- }\ -- (ptr) = (ptr)->next;\ -- }\ --} while (0) -+#define FIND_ENTRY(table, ptr, hash_val, bin_pos) \ -+ ((ptr) = find_entry((table), key, (hash_val), ((bin_pos) = (hash_val)%(table)->num_bins))) -+ -+static st_table_entry * -+find_entry(st_table *table, st_data_t key, st_index_t hash_val, st_index_t bin_pos) -+{ -+ register st_table_entry *ptr = table->bins[bin_pos]; -+ FOUND_ENTRY; -+ if (PTR_NOT_EQUAL(table, ptr, hash_val, key)) { -+ COLLISION; -+ while (PTR_NOT_EQUAL(table, ptr->next, hash_val, key)) { -+ ptr = ptr->next; -+ } -+ ptr = ptr->next; -+ } -+ return ptr; -+} -+ -+static inline st_index_t -+find_packed_index(st_table *table, st_index_t hash_val, st_data_t key) -+{ -+ st_index_t i = 0; -+ while (i < table->real_entries && -+ (PHASH(table, i) != hash_val || !EQUAL(table, key, PKEY(table, i)))) { -+ i++; -+ } -+ return i; -+} -+ -+static inline int -+check_upacked(st_table *table, st_index_t hash_val, st_data_t key) -+{ -+ return table->num_entries && -+ UPHASH(table) == hash_val && -+ EQUAL(table, key, UPKEY(table)); -+} - - #define collision_check 0 - - int - st_lookup(st_table *table, register st_data_t key, st_data_t *value) - { -- st_index_t hash_val, bin_pos; -+ st_index_t hash_val; - register st_table_entry *ptr; - -+ hash_val = do_hash(key, table); -+ -+ if (ULTRAPACKED(table)) { -+ if (check_upacked(table, hash_val, key)) { -+ if (value != 0) *value = UPVAL(table); -+ return 1; -+ } -+ return 0; -+ } -+ - if (table->entries_packed) { -- st_index_t i; -- for (i = 0; i < table->num_entries; i++) { -- if ((st_data_t)table->bins[i*2] == key) { -- if (value !=0) *value = (st_data_t)table->bins[i*2+1]; -- return 1; -- } -- } -+ st_index_t i = find_packed_index(table, hash_val, key); -+ if (i < table->real_entries) { -+ if (value != 0) *value = PVAL(table, i); -+ return 1; -+ } - return 0; - } - -- hash_val = do_hash(key, table); -- FIND_ENTRY(table, ptr, hash_val, bin_pos); -+ ptr = find_entry(table, key, hash_val, hash_val % table->num_bins); - - if (ptr == 0) { - return 0; - } - else { -- if (value != 0) *value = ptr->record; -+ if (value != 0) *value = ptr->record; - return 1; - } - } -@@ -353,22 +517,29 @@ st_lookup(st_table *table, register st_data_t key, st_data_t *value) - int - st_get_key(st_table *table, register st_data_t key, st_data_t *result) - { -- st_index_t hash_val, bin_pos; -+ st_index_t hash_val; - register st_table_entry *ptr; - -+ hash_val = do_hash(key, table); -+ -+ if (ULTRAPACKED(table)) { -+ if (check_upacked(table, hash_val, key)) { -+ if (result != 0) *result = UPKEY(table); -+ return 1; -+ } -+ return 0; -+ } -+ - if (table->entries_packed) { -- st_index_t i; -- for (i = 0; i < table->num_entries; i++) { -- if ((st_data_t)table->bins[i*2] == key) { -- if (result !=0) *result = (st_data_t)table->bins[i*2]; -- return 1; -- } -- } -+ st_index_t i = find_packed_index(table, hash_val, key); -+ if (i < table->real_entries) { -+ if (result != 0) *result = PKEY(table, i); -+ return 1; -+ } - return 0; - } - -- hash_val = do_hash(key, table); -- FIND_ENTRY(table, ptr, hash_val, bin_pos); -+ ptr = find_entry(table, key, hash_val, hash_val % table->num_bins); - - if (ptr == 0) { - return 0; -@@ -382,85 +553,151 @@ st_get_key(st_table *table, register st_data_t key, st_data_t *result) - #undef collision_check - #define collision_check 1 - --#define MORE_PACKABLE_P(table) \ -- ((st_index_t)((table)->num_entries+1) * 2 <= (table)->num_bins && \ -- (table)->num_entries+1 <= MAX_PACKED_NUMHASH) -- --#define ADD_DIRECT(table, key, value, hash_val, bin_pos)\ --do {\ -- st_table_entry *entry;\ -- if ((table)->num_entries > ST_DEFAULT_MAX_DENSITY * (table)->num_bins) {\ -- rehash(table);\ -- (bin_pos) = (hash_val) % (table)->num_bins;\ -- }\ -- \ -- entry = alloc(st_table_entry);\ -- \ -- entry->hash = (hash_val);\ -- entry->key = (key);\ -- entry->record = (value);\ -- entry->next = (table)->bins[(bin_pos)];\ -- if ((table)->head != 0) {\ -- entry->fore = 0;\ -- (entry->back = (table)->tail)->fore = entry;\ -- (table)->tail = entry;\ -- }\ -- else {\ -- (table)->head = (table)->tail = entry;\ -- entry->fore = entry->back = 0;\ -- }\ -- (table)->bins[(bin_pos)] = entry;\ -- (table)->num_entries++;\ --} while (0) -+static inline st_table_entry * -+new_entry(st_table * table, st_data_t key, st_data_t value, -+ st_index_t hash_val, register st_index_t bin_pos) -+{ -+ register st_table_entry *entry = st_alloc_entry(); -+ -+ entry->next = table->bins[bin_pos]; -+ table->bins[bin_pos] = entry; -+ entry->hash = hash_val; -+ entry->key = key; -+ entry->record = value; -+ -+ return entry; -+} -+ -+static inline void -+add_direct(st_table *table, st_data_t key, st_data_t value, -+ st_index_t hash_val, register st_index_t bin_pos) -+{ -+ register st_table_entry *entry; -+ if (table->num_entries > ST_DEFAULT_MAX_DENSITY * table->num_bins) { -+ rehash(table); -+ bin_pos = hash_val % table->num_bins; -+ } -+ -+ entry = new_entry(table, key, value, hash_val, bin_pos); -+ -+ if (table->head != 0) { -+ entry->fore = 0; -+ (entry->back = table->tail)->fore = entry; -+ table->tail = entry; -+ } -+ else { -+ table->head = table->tail = entry; -+ entry->fore = entry->back = 0; -+ } -+ table->num_entries++; -+} - - static void - unpack_entries(register st_table *table) - { - st_index_t i; -- struct st_table_entry *packed_bins[MAX_PACKED_NUMHASH*2]; -+ st_packed_entry packed_bins[MAX_PACKED_HASH]; -+ register st_table_entry *entry, *preventry = 0, **chain; - st_table tmp_table = *table; - -- memcpy(packed_bins, table->bins, sizeof(struct st_table_entry *) * table->num_entries*2); -- table->bins = packed_bins; -+ MEMCPY(packed_bins, PACKED_BINS(table), st_packed_entry, MAX_PACKED_HASH); -+ table->as.packed.entries = packed_bins; - tmp_table.entries_packed = 0; -- tmp_table.num_entries = 0; -- memset(tmp_table.bins, 0, sizeof(struct st_table_entry *) * tmp_table.num_bins); -- for (i = 0; i < table->num_entries; i++) { -- st_insert(&tmp_table, (st_data_t)packed_bins[i*2], (st_data_t)packed_bins[i*2+1]); -- } -+#if ST_DEFAULT_INIT_TABLE_SIZE == ST_DEFAULT_PACKED_TABLE_SIZE -+ MEMZERO(tmp_table.bins, st_table_entry*, tmp_table.num_bins); -+#else -+ tmp_table.bins = st_realloc_bins(tmp_table.bins, ST_DEFAULT_INIT_TABLE_SIZE, tmp_table.num_bins); -+ tmp_table.num_bins = ST_DEFAULT_INIT_TABLE_SIZE; -+#endif -+ i = 0; -+ chain = &tmp_table.head; -+ do { -+ st_data_t key = packed_bins[i].key; -+ st_data_t val = packed_bins[i].val; -+ st_index_t hash = packed_bins[i].hash; -+ entry = new_entry(&tmp_table, key, val, hash, -+ hash % ST_DEFAULT_INIT_TABLE_SIZE); -+ *chain = entry; -+ entry->back = preventry; -+ preventry = entry; -+ chain = &entry->fore; -+ } while (++i < MAX_PACKED_HASH); -+ *chain = NULL; -+ tmp_table.tail = entry; - *table = tmp_table; - } - -+static void -+add_packed_direct(st_table *table, st_data_t key, st_data_t value, st_index_t hash_val) -+{ -+ if (table->real_entries < MAX_PACKED_HASH) { -+ st_index_t i = table->real_entries++; -+ PKEY_SET(table, i, key); -+ PVAL_SET(table, i, value); -+ PHASH_SET(table, i, hash_val); -+ table->num_entries++; -+ } -+ else { -+ unpack_entries(table); -+ add_direct(table, key, value, hash_val, hash_val % table->num_bins); -+ } -+} -+ -+static void -+add_upacked_direct(register st_table *table, register st_data_t key, st_data_t value, st_index_t hash_val) -+{ -+ if (table->real_upacked) { -+ st_packed_entry *entries = (st_packed_entry *) st_alloc_bins(ST_DEFAULT_PACKED_TABLE_SIZE); -+ entries[0] = UPACKED_ENT(table); -+ entries[1].hash = hash_val; -+ entries[1].key = key; -+ entries[1].val = value; -+ table->num_bins = ST_DEFAULT_PACKED_TABLE_SIZE; -+ table->real_entries = 2; -+ table->num_entries++; -+ table->as.packed.entries = entries; -+ } -+ else { -+ table->real_upacked = 1; -+ table->num_entries = 1; -+ UPHASH_SET(table, hash_val); -+ UPKEY_SET(table, key); -+ UPVAL_SET(table, value); -+ } -+} -+ - int - st_insert(register st_table *table, register st_data_t key, st_data_t value) - { -- st_index_t hash_val, bin_pos; -+ st_index_t hash_val; -+ register st_index_t bin_pos; - register st_table_entry *ptr; - -+ hash_val = do_hash(key, table); -+ -+ if (ULTRAPACKED(table)) { -+ if (check_upacked(table, hash_val, key)) { -+ UPVAL_SET(table, value); -+ return 1; -+ } -+ add_upacked_direct(table, key, value, hash_val); -+ return 0; -+ } -+ - if (table->entries_packed) { -- st_index_t i; -- for (i = 0; i < table->num_entries; i++) { -- if ((st_data_t)table->bins[i*2] == key) { -- table->bins[i*2+1] = (struct st_table_entry*)value; -- return 1; -- } -- } -- if (MORE_PACKABLE_P(table)) { -- i = table->num_entries++; -- table->bins[i*2] = (struct st_table_entry*)key; -- table->bins[i*2+1] = (struct st_table_entry*)value; -- return 0; -- } -- else { -- unpack_entries(table); -+ st_index_t i = find_packed_index(table, hash_val, key); -+ if (i < table->real_entries) { -+ PVAL_SET(table, i, value); -+ return 1; - } -+ add_packed_direct(table, key, value, hash_val); -+ return 0; - } - -- hash_val = do_hash(key, table); - FIND_ENTRY(table, ptr, hash_val, bin_pos); - - if (ptr == 0) { -- ADD_DIRECT(table, key, value, hash_val, bin_pos); -+ add_direct(table, key, value, hash_val, bin_pos); - return 0; - } - else { -@@ -473,34 +710,38 @@ int - st_insert2(register st_table *table, register st_data_t key, st_data_t value, - st_data_t (*func)(st_data_t)) - { -- st_index_t hash_val, bin_pos; -+ st_index_t hash_val; -+ register st_index_t bin_pos; - register st_table_entry *ptr; - -+ hash_val = do_hash(key, table); -+ -+ if (ULTRAPACKED(table)) { -+ if (check_upacked(table, hash_val, key)) { -+ UPVAL_SET(table, value); -+ return 1; -+ } -+ key = (*func)(key); -+ add_upacked_direct(table, key, value, hash_val); -+ return 0; -+ } -+ - if (table->entries_packed) { -- st_index_t i; -- for (i = 0; i < table->num_entries; i++) { -- if ((st_data_t)table->bins[i*2] == key) { -- table->bins[i*2+1] = (struct st_table_entry*)value; -- return 1; -- } -- } -- if (MORE_PACKABLE_P(table)) { -- i = table->num_entries++; -- table->bins[i*2] = (struct st_table_entry*)key; -- table->bins[i*2+1] = (struct st_table_entry*)value; -- return 0; -- } -- else { -- unpack_entries(table); -- } -+ st_index_t i = find_packed_index(table, hash_val, key); -+ if (i < table->real_entries) { -+ PVAL_SET(table, i, value); -+ return 1; -+ } -+ key = (*func)(key); -+ add_packed_direct(table, key, value, hash_val); -+ return 0; - } - -- hash_val = do_hash(key, table); - FIND_ENTRY(table, ptr, hash_val, bin_pos); - - if (ptr == 0) { - key = (*func)(key); -- ADD_DIRECT(table, key, value, hash_val, bin_pos); -+ add_direct(table, key, value, hash_val, bin_pos); - return 0; - } - else { -@@ -512,36 +753,30 @@ st_insert2(register st_table *table, register st_data_t key, st_data_t value, - void - st_add_direct(st_table *table, st_data_t key, st_data_t value) - { -- st_index_t hash_val, bin_pos; -+ st_index_t hash_val; -+ -+ hash_val = do_hash(key, table); -+ if (ULTRAPACKED(table)) { -+ add_upacked_direct(table, key, value, hash_val); -+ return; -+ } - - if (table->entries_packed) { -- int i; -- if (MORE_PACKABLE_P(table)) { -- i = table->num_entries++; -- table->bins[i*2] = (struct st_table_entry*)key; -- table->bins[i*2+1] = (struct st_table_entry*)value; -- return; -- } -- else { -- unpack_entries(table); -- } -+ add_packed_direct(table, key, value, hash_val); -+ return; - } - -- hash_val = do_hash(key, table); -- bin_pos = hash_val % table->num_bins; -- ADD_DIRECT(table, key, value, hash_val, bin_pos); -+ add_direct(table, key, value, hash_val, hash_val % table->num_bins); - } - - static void - rehash(register st_table *table) - { - register st_table_entry *ptr, **new_bins; -- st_index_t i, new_num_bins, hash_val; -+ st_index_t new_num_bins, hash_val; - - new_num_bins = new_size(table->num_bins+1); -- new_bins = (st_table_entry**) -- xrealloc(table->bins, new_num_bins * sizeof(st_table_entry*)); -- for (i = 0; i < new_num_bins; ++i) new_bins[i] = 0; -+ new_bins = st_realloc_bins(table->bins, new_num_bins, table->num_bins); - table->num_bins = new_num_bins; - table->bins = new_bins; - -@@ -558,34 +793,37 @@ st_table* - st_copy(st_table *old_table) - { - st_table *new_table; -- st_table_entry *ptr, *entry, *prev, **tail; -+ st_table_entry *ptr, *entry, *prev, **tailp; - st_index_t num_bins = old_table->num_bins; - st_index_t hash_val; - -- new_table = alloc(st_table); -+ new_table = st_alloc_table(); - if (new_table == 0) { - return 0; - } - - *new_table = *old_table; -- new_table->bins = (st_table_entry**) -- Calloc((unsigned)num_bins, sizeof(st_table_entry*)); -+ if (ULTRAPACKED(old_table)) { -+ return new_table; -+ } -+ -+ new_table->bins = st_alloc_bins(num_bins); - - if (new_table->bins == 0) { -- free(new_table); -+ st_dealloc_table(new_table); - return 0; - } - - if (old_table->entries_packed) { -- memcpy(new_table->bins, old_table->bins, sizeof(struct st_table_entry *) * old_table->num_bins); -+ MEMCPY(new_table->bins, old_table->bins, st_table_entry*, old_table->num_bins); - return new_table; - } - - if ((ptr = old_table->head) != 0) { - prev = 0; -- tail = &new_table->head; -+ tailp = &new_table->head; - do { -- entry = alloc(st_table_entry); -+ entry = st_alloc_entry(); - if (entry == 0) { - st_free_table(new_table); - return 0; -@@ -595,8 +833,8 @@ st_copy(st_table *old_table) - entry->next = new_table->bins[hash_val]; - new_table->bins[hash_val] = entry; - entry->back = prev; -- *tail = prev = entry; -- tail = &entry->fore; -+ *tailp = prev = entry; -+ tailp = &entry->fore; - } while ((ptr = ptr->fore) != 0); - new_table->tail = prev; - } -@@ -604,21 +842,22 @@ st_copy(st_table *old_table) - return new_table; - } - --#define REMOVE_ENTRY(table, ptr) do \ -- { \ -- if ((ptr)->fore == 0 && (ptr)->back == 0) { \ -- (table)->head = 0; \ -- (table)->tail = 0; \ -- } \ -- else { \ -- st_table_entry *fore = (ptr)->fore, *back = (ptr)->back; \ -- if (fore) fore->back = back; \ -- if (back) back->fore = fore; \ -- if ((ptr) == (table)->head) (table)->head = fore; \ -- if ((ptr) == (table)->tail) (table)->tail = back; \ -- } \ -- (table)->num_entries--; \ -- } while (0) -+static inline void -+remove_entry(st_table *table, st_table_entry *ptr) -+{ -+ if (ptr->fore == 0 && ptr->back == 0) { -+ table->head = 0; -+ table->tail = 0; -+ } -+ else { -+ st_table_entry *fore = ptr->fore, *back = ptr->back; -+ if (fore) fore->back = back; -+ if (back) back->fore = fore; -+ if (ptr == table->head) table->head = fore; -+ if (ptr == table->tail) table->tail = back; -+ } -+ table->num_entries--; -+} - - int - st_delete(register st_table *table, register st_data_t *key, st_data_t *value) -@@ -627,30 +866,38 @@ st_delete(register st_table *table, register st_data_t *key, st_data_t *value) - st_table_entry **prev; - register st_table_entry *ptr; - -+ hash_val = do_hash(*key, table); -+ -+ if (ULTRAPACKED(table)) { -+ if (check_upacked(table, hash_val, *key)) { -+ if (value != 0) *value = UPVAL(table); -+ *key = UPKEY(table); -+ remove_upacked_entry(table); -+ return 1; -+ } -+ return 0; -+ } -+ - if (table->entries_packed) { -- st_index_t i; -- for (i = 0; i < table->num_entries; i++) { -- if ((st_data_t)table->bins[i*2] == *key) { -- if (value != 0) *value = (st_data_t)table->bins[i*2+1]; -- table->num_entries--; -- memmove(&table->bins[i*2], &table->bins[(i+1)*2], -- sizeof(struct st_table_entry*) * 2*(table->num_entries-i)); -- return 1; -- } -+ st_index_t i = find_packed_index(table, hash_val, *key); -+ if (i < table->real_entries) { -+ if (value != 0) *value = PVAL(table, i); -+ *key = PKEY(table, i); -+ remove_packed_entry(table, i); -+ return 1; - } - if (value != 0) *value = 0; - return 0; - } - -- hash_val = do_hash_bin(*key, table); -- -- for (prev = &table->bins[hash_val]; (ptr = *prev) != 0; prev = &ptr->next) { -+ prev = &table->bins[hash_val % table->num_bins]; -+ for (;(ptr = *prev) != 0; prev = &ptr->next) { - if (EQUAL(table, *key, ptr->key)) { - *prev = ptr->next; -- REMOVE_ENTRY(table, ptr); -+ remove_entry(table, ptr); - if (value != 0) *value = ptr->record; - *key = ptr->key; -- free(ptr); -+ st_free_entry(ptr); - return 1; - } - } -@@ -665,25 +912,36 @@ st_delete_safe(register st_table *table, register st_data_t *key, st_data_t *val - st_index_t hash_val; - register st_table_entry *ptr; - -+ hash_val = do_hash(*key, table); -+ -+ if (ULTRAPACKED(table)) { -+ if (check_upacked(table, hash_val, *key)) { -+ if (value != 0) *value = UPVAL(table); -+ *key = UPKEY(table); -+ remove_safe_upacked_entry(table, never); -+ return 1; -+ } -+ if (value != 0) *value = 0; -+ return 0; -+ } -+ - if (table->entries_packed) { -- st_index_t i; -- for (i = 0; i < table->num_entries; i++) { -- if ((st_data_t)table->bins[i*2] == *key) { -- if (value != 0) *value = (st_data_t)table->bins[i*2+1]; -- table->bins[i*2] = (void *)never; -- return 1; -- } -+ st_index_t i = find_packed_index(table, hash_val, *key); -+ if (i < table->real_entries) { -+ if (value != 0) *value = PVAL(table, i); -+ *key = PKEY(table, i); -+ remove_safe_packed_entry(table, i, never); -+ return 1; - } - if (value != 0) *value = 0; - return 0; - } - -- hash_val = do_hash_bin(*key, table); -- ptr = table->bins[hash_val]; -+ ptr = table->bins[hash_val % table->num_bins]; - - for (; ptr != 0; ptr = ptr->next) { - if ((ptr->key != never) && EQUAL(table, ptr->key, *key)) { -- REMOVE_ENTRY(table, ptr); -+ remove_entry(table, ptr); - *key = ptr->key; - if (value != 0) *value = ptr->record; - ptr->key = ptr->record = never; -@@ -701,17 +959,23 @@ st_cleanup_safe(st_table *table, st_data_t never) - st_table_entry *ptr, **last, *tmp; - st_index_t i; - -+ if (ULTRAPACKED(table)) { -+ table->real_upacked = table->num_entries; -+ return; -+ } -+ - if (table->entries_packed) { - st_index_t i = 0, j = 0; -- while ((st_data_t)table->bins[i*2] != never) { -- if (i++ == table->num_entries) return; -+ while (PKEY(table, i) != never) { -+ if (i++ == table->real_entries) return; - } -- for (j = i; ++i < table->num_entries;) { -- if ((st_data_t)table->bins[i*2] == never) continue; -- table->bins[j*2] = table->bins[i*2]; -- table->bins[j*2+1] = table->bins[i*2+1]; -+ for (j = i; ++i < table->real_entries;) { -+ if (PKEY(table, i) == never) continue; -+ PACKED_ENT(table, j) = PACKED_ENT(table, i); - j++; - } -+ table->real_entries = j; -+ /* table->num_entries really should be equal j at this moment, but let set it anyway */ - table->num_entries = j; - return; - } -@@ -722,7 +986,7 @@ st_cleanup_safe(st_table *table, st_data_t never) - if (ptr->key == never) { - tmp = ptr; - *last = ptr = ptr->next; -- free(tmp); -+ st_free_entry(tmp); - } - else { - ptr = *(last = &ptr->next); -@@ -732,50 +996,78 @@ st_cleanup_safe(st_table *table, st_data_t never) - } - - int --st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) -+st_foreach_check(st_table *table, int (*func)(ANYARGS), st_data_t arg, st_data_t never) - { - st_table_entry *ptr, **last, *tmp; - enum st_retval retval; -- st_index_t i; -+ st_data_t key, val; -+ st_index_t hash, i = 0; -+ -+ if (table->num_entries == 0) { -+ return 0; -+ } -+ -+ if (ULTRAPACKED(table)) { -+ key = UPKEY(table); -+ val = UPVAL(table); -+ hash = UPHASH(table); -+ if (key == never) return 0; -+ retval = (*func)(key, val, arg); -+ if (!ULTRAPACKED(table)) { -+ goto packed; -+ } -+ switch(retval) { -+ case ST_CHECK: -+ if (UPHASH(table) == 0 && UPKEY(table) == never) -+ break; -+ if (check_upacked(table, hash, key)) -+ break; -+ goto deleted; -+ case ST_DELETE: -+ remove_safe_upacked_entry(table, never); -+ case ST_CONTINUE: -+ case ST_STOP: -+ break; -+ } -+ return 0; -+ } - - if (table->entries_packed) { -- for (i = 0; i < table->num_entries; i++) { -- st_index_t j; -- st_data_t key, val; -- key = (st_data_t)table->bins[i*2]; -- val = (st_data_t)table->bins[i*2+1]; -- retval = (*func)(key, val, arg); -+ for (i = 0; i < table->real_entries; i++) { -+ key = PKEY(table, i); -+ val = PVAL(table, i); -+ hash = PHASH(table, i); -+ if (key == never) continue; -+ retval = (*func)(key, val, arg); -+ packed: - if (!table->entries_packed) { -- FIND_ENTRY(table, ptr, key, i); -+ FIND_ENTRY(table, ptr, hash, i); - if (retval == ST_CHECK) { - if (!ptr) goto deleted; - goto unpacked_continue; - } - goto unpacked; - } -- switch (retval) { -+ switch (retval) { - case ST_CHECK: /* check if hash is modified during iteration */ -- for (j = 0; j < table->num_entries; j++) { -- if ((st_data_t)table->bins[j*2] == key) -- break; -- } -- if (j == table->num_entries) { -+ if (PHASH(table, i) == 0 && PKEY(table, i) == never) { -+ break; -+ } -+ i = find_packed_index(table, hash, key); -+ if (i == table->real_entries) { - goto deleted; -- } -+ } - /* fall through */ - case ST_CONTINUE: - break; - case ST_STOP: - return 0; - case ST_DELETE: -- table->num_entries--; -- memmove(&table->bins[i*2], &table->bins[(i+1)*2], -- sizeof(struct st_table_entry*) * 2*(table->num_entries-i)); -- i--; -- break; -- } -- } -- return 0; -+ remove_safe_packed_entry(table, i, never); -+ break; -+ } -+ } -+ return 0; - } - else { - ptr = table->head; -@@ -783,6 +1075,8 @@ st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) - - if (ptr != 0) { - do { -+ if (ptr->key == never) -+ goto unpacked_continue; - i = ptr->hash % table->num_bins; - retval = (*func)(ptr->key, ptr->record, arg); - unpacked: -@@ -808,10 +1102,100 @@ st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) - for (; (tmp = *last) != 0; last = &tmp->next) { - if (ptr == tmp) { - tmp = ptr->fore; -+ remove_entry(table, ptr); -+ ptr->key = ptr->record = never; -+ ptr->hash = 0; -+ ptr = tmp; -+ break; -+ } -+ } -+ } -+ } while (ptr && table->head); -+ } -+ return 0; -+} -+ -+int -+st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) -+{ -+ st_table_entry *ptr, **last, *tmp; -+ enum st_retval retval; -+ st_data_t key, val; -+ st_index_t hash, i = 0; -+ -+ if (table->num_entries == 0) { -+ return 0; -+ } -+ -+ if (ULTRAPACKED(table)) { -+ key = UPKEY(table); -+ val = UPVAL(table); -+ hash = UPHASH(table); -+ retval = (*func)(key, val, arg); -+ if (!ULTRAPACKED(table)) { -+ goto packed; -+ } -+ switch (retval) { -+ case ST_DELETE: -+ remove_upacked_entry(table); -+ case ST_CONTINUE: -+ case ST_CHECK: -+ case ST_STOP: -+ break; -+ } -+ return 0; -+ } -+ -+ if (table->entries_packed) { -+ for (i = 0; i < table->real_entries; i++) { -+ key = PKEY(table, i); -+ val = PVAL(table, i); -+ hash = PHASH(table, i); -+ retval = (*func)(key, val, arg); -+ packed: -+ if (!table->entries_packed) { -+ FIND_ENTRY(table, ptr, hash, i); -+ if (!ptr) return 0; -+ goto unpacked; -+ } -+ switch (retval) { -+ case ST_CONTINUE: -+ break; -+ case ST_CHECK: -+ case ST_STOP: -+ return 0; -+ case ST_DELETE: -+ remove_packed_entry(table, i); -+ i--; -+ break; -+ } -+ } -+ return 0; -+ } -+ else { -+ ptr = table->head; -+ } -+ -+ if (ptr != 0) { -+ do { -+ i = ptr->hash % table->num_bins; -+ retval = (*func)(ptr->key, ptr->record, arg); -+ unpacked: -+ switch (retval) { -+ case ST_CONTINUE: -+ ptr = ptr->fore; -+ break; -+ case ST_CHECK: -+ case ST_STOP: -+ return 0; -+ case ST_DELETE: -+ last = &table->bins[ptr->hash % table->num_bins]; -+ for (; (tmp = *last) != 0; last = &tmp->next) { -+ if (ptr == tmp) { -+ tmp = ptr->fore; - *last = ptr->next; -- REMOVE_ENTRY(table, ptr); -- free(ptr); -- if (ptr == tmp) return 0; -+ remove_entry(table, ptr); -+ st_free_entry(ptr); - ptr = tmp; - break; - } -@@ -834,13 +1218,13 @@ st_reverse_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) - for (i = table->num_entries-1; 0 <= i; i--) { - int j; - st_data_t key, val; -- key = (st_data_t)table->bins[i*2]; -- val = (st_data_t)table->bins[i*2+1]; -+ key = PKEY(table, i); -+ val = PVAL(table, i); - retval = (*func)(key, val, arg); - switch (retval) { - case ST_CHECK: /* check if hash is modified during iteration */ - for (j = 0; j < table->num_entries; j++) { -- if ((st_data_t)table->bins[j*2] == key) -+ if (PKEY(table, j) == key) - break; - } - if (j == table->num_entries) { -@@ -854,9 +1238,7 @@ st_reverse_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) - case ST_STOP: - return 0; - case ST_DELETE: -- table->num_entries--; -- memmove(&table->bins[i*2], &table->bins[(i+1)*2], -- sizeof(struct st_table_entry*) * 2*(table->num_entries-i)); -+ remove_packed_entry(table, i); - break; - } - } -@@ -889,8 +1271,8 @@ st_reverse_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) - if (ptr == tmp) { - tmp = ptr->back; - *last = ptr->next; -- REMOVE_ENTRY(table, ptr); -- free(ptr); -+ remove_entry(table, ptr); -+ st_free_entry(ptr); - ptr = tmp; - break; - } diff --git a/patches/ruby/1.9.3/p374/railsexpress/11-falcon-sparse-array.patch b/patches/ruby/1.9.3/p374/railsexpress/11-falcon-sparse-array.patch deleted file mode 100644 index 145b9a52d8..0000000000 --- a/patches/ruby/1.9.3/p374/railsexpress/11-falcon-sparse-array.patch +++ /dev/null @@ -1,2590 +0,0 @@ -diff --git a/class.c b/class.c -index 4fbdf18..50e23e4 100644 ---- a/class.c -+++ b/class.c -@@ -31,7 +31,7 @@ - #include "internal.h" - #include - --extern st_table *rb_class_tbl; -+extern sa_table rb_class_tbl; - static ID id_attached; - - /** -@@ -50,14 +50,24 @@ static VALUE - class_alloc(VALUE flags, VALUE klass) - { - rb_classext_t *ext = ALLOC(rb_classext_t); -+ rb_class_cache_t *cache = ALLOC(rb_class_cache_t); - NEWOBJ(obj, struct RClass); - OBJSETUP(obj, klass, flags); - obj->ptr = ext; -- RCLASS_IV_TBL(obj) = 0; -- RCLASS_CONST_TBL(obj) = 0; -- RCLASS_M_TBL(obj) = 0; -- RCLASS_SUPER(obj) = 0; -- RCLASS_IV_INDEX_TBL(obj) = 0; -+ obj->cache = cache; -+ MEMZERO(ext, struct rb_classext_struct, 1); -+ MEMZERO(cache, struct rb_class_cache_struct, 1); -+ return (VALUE)obj; -+} -+ -+static VALUE -+iclass_alloc() -+{ -+ rb_class_cache_t *cache = ALLOC(rb_class_cache_t); -+ NEWOBJ(obj, struct RClass); -+ OBJSETUP(obj, rb_cClass, T_ICLASS); -+ obj->cache = cache; -+ MEMZERO(cache, struct rb_class_cache_struct, 1); - return (VALUE)obj; - } - -@@ -77,7 +87,6 @@ rb_class_boot(VALUE super) - VALUE klass = class_alloc(T_CLASS, rb_cClass); - - RCLASS_SUPER(klass) = super; -- RCLASS_M_TBL(klass) = st_init_numtable(); - - OBJ_INFECT(klass, super); - return (VALUE)klass; -@@ -120,43 +129,30 @@ rb_class_new(VALUE super) - return rb_class_boot(super); - } - --struct clone_method_data { -- st_table *tbl; -- VALUE klass; --}; -- - VALUE rb_iseq_clone(VALUE iseqval, VALUE newcbase); - --static int --clone_method(ID mid, const rb_method_entry_t *me, struct clone_method_data *data) -+static void -+clone_method(ID mid, const rb_method_entry_t *me, VALUE klass) - { - VALUE newiseqval; - if (me->def && me->def->type == VM_METHOD_TYPE_ISEQ) { - rb_iseq_t *iseq; -- newiseqval = rb_iseq_clone(me->def->body.iseq->self, data->klass); -+ newiseqval = rb_iseq_clone(me->def->body.iseq->self, klass); - GetISeqPtr(newiseqval, iseq); -- rb_add_method(data->klass, mid, VM_METHOD_TYPE_ISEQ, iseq, me->flag); -+ rb_add_method(klass, mid, VM_METHOD_TYPE_ISEQ, iseq, me->flag); - RB_GC_GUARD(newiseqval); - } - else { -- rb_method_entry_set(data->klass, mid, me, me->flag); -+ rb_method_entry_set(klass, mid, me, me->flag); - } -- return ST_CONTINUE; - } - --static int --clone_const(ID key, const rb_const_entry_t *ce, st_table *tbl) -+static void -+clone_const(sa_index_t key, st_data_t ce, sa_table *tbl) - { - rb_const_entry_t *nce = ALLOC(rb_const_entry_t); -- *nce = *ce; -- st_insert(tbl, key, (st_data_t)nce); -- return ST_CONTINUE; --} -- --static int --clone_const_i(st_data_t key, st_data_t value, st_data_t data) --{ -- return clone_const((ID)key, (const rb_const_entry_t *)value, (st_table *)data); -+ *nce = *(const rb_const_entry_t*)ce; -+ sa_insert(tbl, (sa_index_t)key, (st_data_t)nce); - } - - static void -@@ -177,6 +173,7 @@ class_init_copy_check(VALUE clone, VALUE orig) - VALUE - rb_mod_init_copy(VALUE clone, VALUE orig) - { -+ ID id; - if (RB_TYPE_P(clone, T_CLASS)) { - class_init_copy_check(clone, orig); - } -@@ -186,36 +183,22 @@ rb_mod_init_copy(VALUE clone, VALUE orig) - rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone); - } - RCLASS_SUPER(clone) = RCLASS_SUPER(orig); -- if (RCLASS_IV_TBL(orig)) { -- st_data_t id; - -- if (RCLASS_IV_TBL(clone)) { -- st_free_table(RCLASS_IV_TBL(clone)); -- } -- RCLASS_IV_TBL(clone) = st_copy(RCLASS_IV_TBL(orig)); -- CONST_ID(id, "__classpath__"); -- st_delete(RCLASS_IV_TBL(clone), &id, 0); -- CONST_ID(id, "__classid__"); -- st_delete(RCLASS_IV_TBL(clone), &id, 0); -- } -- if (RCLASS_CONST_TBL(orig)) { -- if (RCLASS_CONST_TBL(clone)) { -- rb_free_const_table(RCLASS_CONST_TBL(clone)); -- } -- RCLASS_CONST_TBL(clone) = st_init_numtable(); -- st_foreach(RCLASS_CONST_TBL(orig), clone_const_i, (st_data_t)RCLASS_CONST_TBL(clone)); -- } -- if (RCLASS_M_TBL(orig)) { -- struct clone_method_data data; -+ sa_copy_to(RCLASS_IV_TBL(orig), RCLASS_IV_TBL(clone)); -+ CONST_ID(id, "__classpath__"); -+ sa_delete(RCLASS_IV_TBL(clone), (sa_index_t)id, 0); -+ CONST_ID(id, "__classid__"); -+ sa_delete(RCLASS_IV_TBL(clone), (sa_index_t)id, 0); - -- if (RCLASS_M_TBL(clone)) { -- rb_free_m_table(RCLASS_M_TBL(clone)); -- } -- data.tbl = RCLASS_M_TBL(clone) = st_init_numtable(); -- data.klass = clone; -- st_foreach(RCLASS_M_TBL(orig), clone_method, -- (st_data_t)&data); -- } -+ sa_clear(RCLASS_CONST_TBL(clone)); -+ SA_FOREACH_START(RCLASS_CONST_TBL(orig)); -+ clone_const(entry->key, value, RCLASS_CONST_TBL(clone)); -+ SA_FOREACH_END(); -+ -+ rb_free_m_table(RCLASS_M_TBL(clone)); -+ SA_FOREACH_START(RCLASS_M_TBL(orig)); -+ clone_method(entry->key, (const rb_method_entry_t *)value, clone); -+ SA_FOREACH_END(); - - return clone; - } -@@ -228,7 +211,6 @@ rb_singleton_class_clone(VALUE obj) - if (!FL_TEST(klass, FL_SINGLETON)) - return klass; - else { -- struct clone_method_data data; - /* copy singleton(unnamed) class */ - VALUE clone = class_alloc((RBASIC(klass)->flags & ~(FL_MARK)), 0); - -@@ -240,18 +222,16 @@ rb_singleton_class_clone(VALUE obj) - } - - RCLASS_SUPER(clone) = RCLASS_SUPER(klass); -- if (RCLASS_IV_TBL(klass)) { -- RCLASS_IV_TBL(clone) = st_copy(RCLASS_IV_TBL(klass)); -- } -- if (RCLASS_CONST_TBL(klass)) { -- RCLASS_CONST_TBL(clone) = st_init_numtable(); -- st_foreach(RCLASS_CONST_TBL(klass), clone_const_i, (st_data_t)RCLASS_CONST_TBL(clone)); -- } -- RCLASS_M_TBL(clone) = st_init_numtable(); -- data.tbl = RCLASS_M_TBL(clone); -- data.klass = (VALUE)clone; -- st_foreach(RCLASS_M_TBL(klass), clone_method, -- (st_data_t)&data); -+ sa_copy_to(RCLASS_IV_TBL(klass), RCLASS_IV_TBL(clone)); -+ -+ SA_FOREACH_START(RCLASS_CONST_TBL(klass)); -+ clone_const(entry->key, value, RCLASS_CONST_TBL(clone)); -+ SA_FOREACH_END(); -+ -+ SA_FOREACH_START(RCLASS_M_TBL(klass)); -+ clone_method(entry->key, (const rb_method_entry_t*)value, clone); -+ SA_FOREACH_END(); -+ - rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone); - FL_SET(clone, FL_SINGLETON); - return (VALUE)clone; -@@ -266,10 +246,7 @@ void - rb_singleton_class_attached(VALUE klass, VALUE obj) - { - if (FL_TEST(klass, FL_SINGLETON)) { -- if (!RCLASS_IV_TBL(klass)) { -- RCLASS_IV_TBL(klass) = st_init_numtable(); -- } -- st_insert(RCLASS_IV_TBL(klass), id_attached, obj); -+ sa_insert(RCLASS_IV_TBL(klass), (sa_index_t)id_attached, obj); - } - } - -@@ -356,12 +333,12 @@ make_singleton_class(VALUE obj) - static VALUE - boot_defclass(const char *name, VALUE super) - { -- extern st_table *rb_class_tbl; -+ extern sa_table rb_class_tbl; - VALUE obj = rb_class_boot(super); - ID id = rb_intern(name); - - rb_name_class(obj, id); -- st_add_direct(rb_class_tbl, id, obj); -+ sa_insert(&rb_class_tbl, (sa_index_t)id, obj); - rb_const_set((rb_cObject ? rb_cObject : obj), id, obj); - return obj; - } -@@ -485,7 +462,7 @@ rb_define_class(const char *name, VALUE super) - rb_warn("no super class for `%s', Object assumed", name); - } - klass = rb_define_class_id(id, super); -- st_add_direct(rb_class_tbl, id, klass); -+ sa_insert(&rb_class_tbl, (sa_index_t)id, klass); - rb_name_class(klass, id); - rb_const_set(rb_cObject, id, klass); - rb_class_inherited(super, klass); -@@ -566,8 +543,6 @@ rb_module_new(void) - { - VALUE mdl = class_alloc(T_MODULE, rb_cModule); - -- RCLASS_M_TBL(mdl) = st_init_numtable(); -- - return (VALUE)mdl; - } - -@@ -596,7 +571,7 @@ rb_define_module(const char *name) - rb_raise(rb_eTypeError, "%s is not a module", rb_obj_classname(module)); - } - module = rb_define_module_id(id); -- st_add_direct(rb_class_tbl, id, module); -+ sa_insert(&rb_class_tbl, (sa_index_t)id, module); - rb_const_set(rb_cObject, id, module); - - return module; -@@ -631,27 +606,15 @@ rb_define_module_id_under(VALUE outer, ID id) - static VALUE - include_class_new(VALUE module, VALUE super) - { -- VALUE klass = class_alloc(T_ICLASS, rb_cClass); -+ VALUE klass; - - if (BUILTIN_TYPE(module) == T_ICLASS) { - module = RBASIC(module)->klass; - } -- if (!RCLASS_IV_TBL(module)) { -- RCLASS_IV_TBL(module) = st_init_numtable(); -- } -- if (!RCLASS_CONST_TBL(module)) { -- RCLASS_CONST_TBL(module) = st_init_numtable(); -- } -- RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module); -- RCLASS_CONST_TBL(klass) = RCLASS_CONST_TBL(module); -- RCLASS_M_TBL(klass) = RCLASS_M_TBL(module); -+ klass = iclass_alloc(); -+ RBASIC(klass)->klass = module; -+ RCLASS_EXT(klass) = RCLASS_EXT(module); - RCLASS_SUPER(klass) = super; -- if (TYPE(module) == T_ICLASS) { -- RBASIC(klass)->klass = RBASIC(module)->klass; -- } -- else { -- RBASIC(klass)->klass = module; -- } - OBJ_INFECT(klass, module); - OBJ_INFECT(klass, super); - -@@ -678,13 +641,13 @@ rb_include_module(VALUE klass, VALUE module) - while (module) { - int superclass_seen = FALSE; - -- if (RCLASS_M_TBL(klass) == RCLASS_M_TBL(module)) -+ if (RCLASS_EXT(klass) == RCLASS_EXT(module)) - rb_raise(rb_eArgError, "cyclic include detected"); - /* ignore if the module included already in superclasses */ - for (p = RCLASS_SUPER(klass); p; p = RCLASS_SUPER(p)) { - switch (BUILTIN_TYPE(p)) { - case T_ICLASS: -- if (RCLASS_M_TBL(p) == RCLASS_M_TBL(module)) { -+ if (RCLASS_EXT(p) == RCLASS_EXT(module)) { - if (!superclass_seen) { - c = p; /* move insertion point */ - } -@@ -697,7 +660,7 @@ rb_include_module(VALUE klass, VALUE module) - } - } - c = RCLASS_SUPER(c) = include_class_new(module, RCLASS_SUPER(c)); -- if (RMODULE_M_TBL(module) && RMODULE_M_TBL(module)->num_entries) -+ if (RMODULE_M_TBL(module)->num_entries) - changed = 1; - skip: - module = RCLASS_SUPER(module); -@@ -828,58 +791,58 @@ ins_methods_push(ID name, long type, VALUE ary, long visi) - } - - static int --ins_methods_i(st_data_t name, st_data_t type, st_data_t ary) -+ins_methods_i(sa_index_t name, st_data_t type, st_data_t ary) - { - return ins_methods_push((ID)name, (long)type, (VALUE)ary, -1); /* everything but private */ - } - - static int --ins_methods_prot_i(st_data_t name, st_data_t type, st_data_t ary) -+ins_methods_prot_i(sa_index_t name, st_data_t type, st_data_t ary) - { - return ins_methods_push((ID)name, (long)type, (VALUE)ary, NOEX_PROTECTED); - } - - static int --ins_methods_priv_i(st_data_t name, st_data_t type, st_data_t ary) -+ins_methods_priv_i(sa_index_t name, st_data_t type, st_data_t ary) - { - return ins_methods_push((ID)name, (long)type, (VALUE)ary, NOEX_PRIVATE); - } - - static int --ins_methods_pub_i(st_data_t name, st_data_t type, st_data_t ary) -+ins_methods_pub_i(sa_index_t name, st_data_t type, st_data_t ary) - { - return ins_methods_push((ID)name, (long)type, (VALUE)ary, NOEX_PUBLIC); - } - - static int --method_entry_i(st_data_t key, st_data_t value, st_data_t data) -+method_entry_i(sa_index_t key, st_data_t value, st_data_t data) - { - const rb_method_entry_t *me = (const rb_method_entry_t *)value; -- st_table *list = (st_table *)data; -+ sa_table *list = (sa_table *)data; - long type; - - if ((ID)key == ID_ALLOCATOR) { - return ST_CONTINUE; - } - -- if (!st_lookup(list, key, 0)) { -+ if (!sa_lookup(list, key, 0)) { - if (UNDEFINED_METHOD_ENTRY_P(me)) { - type = -1; /* none */ - } - else { - type = VISI(me->flag); - } -- st_add_direct(list, key, type); -+ sa_insert(list, key, type); - } - return ST_CONTINUE; - } - - static VALUE --class_instance_method_list(int argc, VALUE *argv, VALUE mod, int obj, int (*func) (st_data_t, st_data_t, st_data_t)) -+class_instance_method_list(int argc, VALUE *argv, VALUE mod, int obj, int (*func) (sa_index_t, st_data_t, st_data_t)) - { - VALUE ary; - int recur; -- st_table *list; -+ sa_table list = SA_EMPTY_TABLE; - - if (argc == 0) { - recur = TRUE; -@@ -890,16 +853,15 @@ class_instance_method_list(int argc, VALUE *argv, VALUE mod, int obj, int (*func - recur = RTEST(r); - } - -- list = st_init_numtable(); - for (; mod; mod = RCLASS_SUPER(mod)) { -- st_foreach(RCLASS_M_TBL(mod), method_entry_i, (st_data_t)list); -+ sa_foreach(RCLASS_M_TBL(mod), method_entry_i, (st_data_t)&list); - if (BUILTIN_TYPE(mod) == T_ICLASS) continue; - if (obj && FL_TEST(mod, FL_SINGLETON)) continue; - if (!recur) break; - } - ary = rb_ary_new(); -- st_foreach(list, func, ary); -- st_free_table(list); -+ sa_foreach(&list, func, ary); -+ sa_clear(&list); - - return ary; - } -@@ -1113,7 +1075,7 @@ VALUE - rb_obj_singleton_methods(int argc, VALUE *argv, VALUE obj) - { - VALUE recur, ary, klass; -- st_table *list; -+ sa_table list = SA_EMPTY_TABLE; - - if (argc == 0) { - recur = Qtrue; -@@ -1122,20 +1084,19 @@ rb_obj_singleton_methods(int argc, VALUE *argv, VALUE obj) - rb_scan_args(argc, argv, "01", &recur); - } - klass = CLASS_OF(obj); -- list = st_init_numtable(); - if (klass && FL_TEST(klass, FL_SINGLETON)) { -- st_foreach(RCLASS_M_TBL(klass), method_entry_i, (st_data_t)list); -+ sa_foreach(RCLASS_M_TBL(klass), method_entry_i, (st_data_t)&list); - klass = RCLASS_SUPER(klass); - } - if (RTEST(recur)) { - while (klass && (FL_TEST(klass, FL_SINGLETON) || TYPE(klass) == T_ICLASS)) { -- st_foreach(RCLASS_M_TBL(klass), method_entry_i, (st_data_t)list); -+ sa_foreach(RCLASS_M_TBL(klass), method_entry_i, (st_data_t)&list); - klass = RCLASS_SUPER(klass); - } - } - ary = rb_ary_new(); -- st_foreach(list, ins_methods_i, ary); -- st_free_table(list); -+ sa_foreach(&list, ins_methods_i, ary); -+ sa_clear(&list); - - return ary; - } -diff --git a/common.mk b/common.mk -index 1d8e442..0d767ab 100644 ---- a/common.mk -+++ b/common.mk -@@ -79,6 +79,7 @@ COMMONOBJS = array.$(OBJEXT) \ - safe.$(OBJEXT) \ - signal.$(OBJEXT) \ - sprintf.$(OBJEXT) \ -+ sp_ar.$(OBJEXT) \ - st.$(OBJEXT) \ - strftime.$(OBJEXT) \ - string.$(OBJEXT) \ -@@ -703,6 +704,7 @@ signal.$(OBJEXT): {$(VPATH)}signal.c $(RUBY_H_INCLUDES) \ - $(VM_CORE_H_INCLUDES) {$(VPATH)}debug.h - sprintf.$(OBJEXT): {$(VPATH)}sprintf.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \ - {$(VPATH)}regex.h {$(VPATH)}vsnprintf.c $(ENCODING_H_INCLUDES) -+sp_ar.$(OBJEXT): {$(VPATH)}sp_ar.c $(RUBY_H_INCLUDES) - st.$(OBJEXT): {$(VPATH)}st.c $(RUBY_H_INCLUDES) {$(VPATH)}pool_alloc.h - strftime.$(OBJEXT): {$(VPATH)}strftime.c $(RUBY_H_INCLUDES) \ - {$(VPATH)}timev.h -diff --git a/constant.h b/constant.h -index 8232910..9106847 100644 ---- a/constant.h -+++ b/constant.h -@@ -23,7 +23,7 @@ typedef struct rb_const_entry_struct { - - VALUE rb_mod_private_constant(int argc, VALUE *argv, VALUE obj); - VALUE rb_mod_public_constant(int argc, VALUE *argv, VALUE obj); --void rb_free_const_table(st_table *tbl); -+void rb_free_const_table(sa_table *tbl); - VALUE rb_public_const_get(VALUE klass, ID id); - VALUE rb_public_const_get_at(VALUE klass, ID id); - VALUE rb_public_const_get_from(VALUE klass, ID id); -diff --git a/ext/objspace/objspace.c b/ext/objspace/objspace.c -index 66e33a3..4b31f92 100644 ---- a/ext/objspace/objspace.c -+++ b/ext/objspace/objspace.c -@@ -60,20 +60,10 @@ memsize_of(VALUE obj) - break; - case T_MODULE: - case T_CLASS: -- size += st_memsize(RCLASS_M_TBL(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); -+ size += sa_memsize(RCLASS_M_TBL(obj)); -+ size += sa_memsize(RCLASS_IV_TBL(obj)); -+ size += sa_memsize(RCLASS_IV_INDEX_TBL(obj)); -+ size += sa_memsize(RCLASS_CONST_TBL(obj)); - break; - case T_STRING: - size += rb_str_memsize(obj); -diff --git a/gc.c b/gc.c -index a222b17..3571723 100644 ---- a/gc.c -+++ b/gc.c -@@ -688,7 +688,7 @@ rb_objspace_free(rb_objspace_t *objspace) - - #define HEAP_OBJ_LIMIT (unsigned int)(HEAP_SIZE / sizeof(struct RVALUE)) - --extern st_table *rb_class_tbl; -+extern sa_table rb_class_tbl; - - int ruby_disable_gc_stress = 0; - -@@ -2356,6 +2356,15 @@ mark_tbl(rb_objspace_t *objspace, st_table *tbl) - st_foreach(tbl, mark_entry, (st_data_t)&arg); - } - -+static void -+mark_sa_tbl(rb_objspace_t *objspace, sa_table *tbl) -+{ -+ if (!tbl) return; -+ SA_FOREACH_START(tbl); -+ gc_mark(objspace, (VALUE)value); -+ SA_FOREACH_END(); -+} -+ - static int - mark_key(VALUE key, VALUE value, st_data_t data) - { -@@ -2432,74 +2441,52 @@ rb_mark_method_entry(const rb_method_entry_t *me) - mark_method_entry(&rb_objspace, me); - } - --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; -- mark_method_entry(arg->objspace, me); -- return ST_CONTINUE; --} -- - static void --mark_m_tbl(rb_objspace_t *objspace, st_table *tbl) --{ -- struct mark_tbl_arg arg; -- if (!tbl) return; -- arg.objspace = objspace; -- st_foreach(tbl, mark_method_entry_i, (st_data_t)&arg); --} -- --static int --free_method_entry_i(ID key, rb_method_entry_t *me, st_data_t data) -+mark_m_tbl(rb_objspace_t *objspace, sa_table *tbl) - { -- if (!me->mark) { -- rb_free_method_entry(me); -- } -- return ST_CONTINUE; -+ SA_FOREACH_START(tbl); -+ mark_method_entry(objspace, (const rb_method_entry_t*)value); -+ SA_FOREACH_END(); - } - - void --rb_free_m_table(st_table *tbl) -+rb_free_m_table(sa_table *tbl) - { -- st_foreach(tbl, free_method_entry_i, 0); -- st_free_table(tbl); --} -- --static int --mark_const_entry_i(ID key, const rb_const_entry_t *ce, st_data_t data) --{ -- struct mark_tbl_arg *arg = (void*)data; -- gc_mark(arg->objspace, ce->value); -- return ST_CONTINUE; -+ SA_FOREACH_START(tbl); -+ if (!((rb_method_entry_t*)value)->mark) { -+ rb_free_method_entry((rb_method_entry_t*)value); -+ } -+ SA_FOREACH_END(); -+ sa_clear(tbl); - } - - static void --mark_const_tbl(rb_objspace_t *objspace, st_table *tbl) -+mark_const_tbl(rb_objspace_t *objspace, sa_table *tbl) - { -- struct mark_tbl_arg arg; -- if (!tbl) return; -- arg.objspace = objspace; -- st_foreach(tbl, mark_const_entry_i, (st_data_t)&arg); -+ SA_FOREACH_START(tbl); -+ gc_mark(objspace, ((const rb_const_entry_t*)value)->value); -+ SA_FOREACH_END(); - } - --static int --free_const_entry_i(ID key, rb_const_entry_t *ce, st_data_t data) -+void -+rb_free_const_table(sa_table *tbl) - { -- xfree(ce); -- return ST_CONTINUE; -+ SA_FOREACH_START(tbl); -+ xfree((rb_const_entry_t*)value); -+ SA_FOREACH_END(); -+ sa_clear(tbl); - } - - void --rb_free_const_table(st_table *tbl) -+rb_mark_tbl(st_table *tbl) - { -- st_foreach(tbl, free_const_entry_i, 0); -- st_free_table(tbl); -+ mark_tbl(&rb_objspace, tbl); - } - - void --rb_mark_tbl(st_table *tbl) -+rb_mark_sa_tbl(sa_table *tbl) - { -- mark_tbl(&rb_objspace, tbl); -+ mark_sa_tbl(&rb_objspace, tbl); - } - - void -@@ -2707,7 +2694,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr) - case T_CLASS: - case T_MODULE: - mark_m_tbl(objspace, RCLASS_M_TBL(obj)); -- mark_tbl(objspace, RCLASS_IV_TBL(obj)); -+ mark_sa_tbl(objspace, RCLASS_IV_TBL(obj)); - mark_const_tbl(objspace, RCLASS_CONST_TBL(obj)); - ptr = RCLASS_SUPER(obj); - goto again; -@@ -3282,15 +3269,11 @@ obj_free(rb_objspace_t *objspace, VALUE obj) - case T_CLASS: - rb_clear_cache_by_class((VALUE)obj); - rb_free_m_table(RCLASS_M_TBL(obj)); -- 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)); -- } -+ sa_clear(RCLASS_IV_TBL(obj)); -+ rb_free_const_table(RCLASS_CONST_TBL(obj)); -+ sa_clear(RCLASS_IV_INDEX_TBL(obj)); -+ sa_clear(&RCLASS(obj)->cache->m_cache_tbl); -+ xfree(RCLASS(obj)->cache); - xfree(RANY(obj)->as.klass.ptr); - break; - case T_STRING: -@@ -3342,8 +3325,9 @@ obj_free(rb_objspace_t *objspace, VALUE obj) - case T_COMPLEX: - break; - case T_ICLASS: -+ sa_clear(&RCLASS(obj)->cache->m_cache_tbl); -+ xfree(RCLASS(obj)->cache); - /* iClass shares table with the module */ -- xfree(RANY(obj)->as.klass.ptr); - break; - - case T_FLOAT: -@@ -3458,7 +3442,7 @@ gc_marks(rb_objspace_t *objspace) - rb_mark_end_proc(); - rb_gc_mark_global_tbl(); - -- mark_tbl(objspace, rb_class_tbl); -+ mark_sa_tbl(objspace, &rb_class_tbl); - - /* mark generic instance variables for special constants */ - rb_mark_generic_ivar_tbl(); -diff --git a/include/ruby/intern.h b/include/ruby/intern.h -index ab1cc94..53ca8b0 100644 ---- a/include/ruby/intern.h -+++ b/include/ruby/intern.h -@@ -415,6 +415,7 @@ size_t ruby_stack_length(VALUE**); - int rb_during_gc(void); - void rb_gc_mark_locations(VALUE*, VALUE*); - void rb_mark_tbl(struct st_table*); -+void rb_mark_sa_tbl(sa_table*); - void rb_mark_set(struct st_table*); - void rb_mark_hash(struct st_table*); - void rb_gc_mark_maybe(VALUE); -@@ -848,7 +849,7 @@ VALUE rb_f_trace_var(int, VALUE*); - VALUE rb_f_untrace_var(int, VALUE*); - VALUE rb_f_global_variables(void); - void rb_alias_variable(ID, ID); --struct st_table* rb_generic_ivar_table(VALUE); -+sa_table* rb_generic_ivar_table(VALUE); - void rb_copy_generic_ivar(VALUE,VALUE); - void rb_mark_generic_ivar(VALUE); - void rb_mark_generic_ivar_tbl(void); -diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h -index 2f97b33..1c84e14 100644 ---- a/include/ruby/ruby.h -+++ b/include/ruby/ruby.h -@@ -605,7 +605,7 @@ struct RObject { - struct { - long numiv; - VALUE *ivptr; -- struct st_table *iv_index_tbl; /* shortcut for RCLASS_IV_INDEX_TBL(rb_obj_class(obj)) */ -+ struct sa_table *iv_index_tbl; /* shortcut for RCLASS_IV_INDEX_TBL(rb_obj_class(obj)) */ - } heap; - VALUE ary[ROBJECT_EMBED_LEN_MAX]; - } as; -@@ -626,12 +626,13 @@ struct RObject { - - /** @internal */ - typedef struct rb_classext_struct rb_classext_t; -+typedef struct rb_class_cache_struct rb_class_cache_t; - - struct RClass { - struct RBasic basic; -+ VALUE super; - rb_classext_t *ptr; -- struct st_table *m_tbl; -- struct st_table *iv_index_tbl; -+ rb_class_cache_t *cache; - }; - #define RCLASS_SUPER(c) rb_class_get_superclass(c) - #define RMODULE_IV_TBL(m) RCLASS_IV_TBL(m) -diff --git a/include/ruby/st.h b/include/ruby/st.h -index 119dfde..aff94fc 100644 ---- a/include/ruby/st.h -+++ b/include/ruby/st.h -@@ -151,6 +151,51 @@ st_index_t st_hash_start(st_index_t h); - #pragma GCC visibility pop - #endif - -+typedef unsigned int sa_index_t; -+#define SA_STOP ST_STOP -+#define SA_CONTINUE ST_CONTINUE -+ -+#define SA_EMPTY 0 -+ -+typedef struct sa_entry { -+ sa_index_t next; -+ sa_index_t key; -+ st_data_t value; -+} sa_entry; -+ -+typedef struct sa_table { -+ sa_index_t num_bins; -+ sa_index_t num_entries; -+ sa_index_t free_pos; -+ sa_entry *entries; -+} sa_table; -+ -+#define SA_EMPTY_TABLE {0, 0, 0, 0}; -+void sa_init_table(sa_table *, sa_index_t); -+sa_table *sa_new_table(); -+int sa_insert(sa_table *, sa_index_t, st_data_t); -+int sa_lookup(sa_table *, sa_index_t, st_data_t *); -+int sa_delete(sa_table *, sa_index_t, st_data_t *); -+void sa_clear(sa_table *); -+void sa_clear_no_free(sa_table *); -+void sa_free_table(sa_table *); -+int sa_foreach(sa_table *, int (*)(ANYARGS), st_data_t); -+size_t sa_memsize(const sa_table *); -+sa_table *sa_copy(sa_table*); -+void sa_copy_to(sa_table*, sa_table*); -+typedef int (*sa_iter_func)(sa_index_t key, st_data_t val, st_data_t arg); -+ -+#define SA_FOREACH_START_I(table, entry) do { \ -+ sa_table *T##entry = (table); \ -+ sa_index_t K##entry; \ -+ for(K##entry = 0; K##entry < T##entry->num_bins; K##entry++) { \ -+ sa_entry *entry = T##entry->entries + K##entry; \ -+ if (entry->next != SA_EMPTY) { \ -+ st_data_t value = entry->value -+#define SA_FOREACH_END() } } } while(0) -+ -+#define SA_FOREACH_START(table) SA_FOREACH_START_I(table, entry) -+ - #if defined(__cplusplus) - #if 0 - { /* satisfy cc-mode */ -diff --git a/internal.h b/internal.h -index f5af903..4af90b6 100644 ---- a/internal.h -+++ b/internal.h -@@ -24,18 +24,24 @@ struct rb_deprecated_classext_struct { - }; - - struct rb_classext_struct { -- VALUE super; -- struct st_table *iv_tbl; -- struct st_table *const_tbl; -+ sa_table m_tbl; -+ sa_table iv_tbl; -+ sa_table const_tbl; -+ sa_table iv_index_tbl; -+}; -+ -+struct rb_class_cache_struct { -+ VALUE method_cache_version; -+ sa_table m_cache_tbl; - }; - - #undef RCLASS_SUPER - #define RCLASS_EXT(c) (RCLASS(c)->ptr) --#define RCLASS_SUPER(c) (RCLASS_EXT(c)->super) --#define RCLASS_IV_TBL(c) (RCLASS_EXT(c)->iv_tbl) --#define RCLASS_CONST_TBL(c) (RCLASS_EXT(c)->const_tbl) --#define RCLASS_M_TBL(c) (RCLASS(c)->m_tbl) --#define RCLASS_IV_INDEX_TBL(c) (RCLASS(c)->iv_index_tbl) -+#define RCLASS_SUPER(c) (RCLASS(c)->super) -+#define RCLASS_IV_TBL(c) (&RCLASS_EXT(c)->iv_tbl) -+#define RCLASS_CONST_TBL(c) (&RCLASS_EXT(c)->const_tbl) -+#define RCLASS_M_TBL(c) (&RCLASS_EXT(c)->m_tbl) -+#define RCLASS_IV_INDEX_TBL(c) (&RCLASS_EXT(c)->iv_index_tbl) - - struct vtm; /* defined by timev.h */ - -diff --git a/marshal.c b/marshal.c -index 6ae3a55..48d9d9b 100644 ---- a/marshal.c -+++ b/marshal.c -@@ -506,7 +506,7 @@ w_uclass(VALUE obj, VALUE super, struct dump_arg *arg) - } - - static int --w_obj_each(ID id, VALUE value, struct dump_call_arg *arg) -+w_obj_each(sa_index_t id, VALUE value, struct dump_call_arg *arg) - { - if (id == rb_id_encoding()) return ST_CONTINUE; - if (id == rb_intern("E")) return ST_CONTINUE; -@@ -553,13 +553,13 @@ w_encoding(VALUE obj, long num, struct dump_call_arg *arg) - } - - static void --w_ivar(VALUE obj, st_table *tbl, struct dump_call_arg *arg) -+w_ivar(VALUE obj, sa_table *tbl, struct dump_call_arg *arg) - { - long num = tbl ? tbl->num_entries : 0; - - w_encoding(obj, num, arg); - if (tbl) { -- st_foreach_safe(tbl, w_obj_each, (st_data_t)arg); -+ sa_foreach(tbl, w_obj_each, (st_data_t)arg); - } - } - -@@ -586,7 +586,7 @@ static void - w_object(VALUE obj, struct dump_arg *arg, int limit) - { - struct dump_call_arg c_arg; -- st_table *ivtbl = 0; -+ sa_table *ivtbl = 0; - st_data_t num; - int hasiv = 0; - #define has_ivars(obj, ivtbl) (((ivtbl) = rb_generic_ivar_table(obj)) != 0 || \ -@@ -651,7 +651,7 @@ w_object(VALUE obj, struct dump_arg *arg, int limit) - } - if (rb_respond_to(obj, s_dump)) { - VALUE v; -- st_table *ivtbl2 = 0; -+ sa_table *ivtbl2 = 0; - int hasiv2; - - v = rb_funcall(obj, s_dump, 1, INT2NUM(limit)); -diff --git a/method.h b/method.h -index 9229896..2fecd57 100644 ---- a/method.h -+++ b/method.h -@@ -100,6 +100,6 @@ int rb_method_entry_eq(const rb_method_entry_t *m1, const rb_method_entry_t *m2) - void rb_mark_method_entry(const rb_method_entry_t *me); - void rb_free_method_entry(rb_method_entry_t *me); - void rb_sweep_method_entry(void *vm); --void rb_free_m_table(st_table *tbl); -+void rb_free_m_table(sa_table *tbl); - - #endif /* METHOD_H */ -diff --git a/object.c b/object.c -index 59611fd..4522d08 100644 ---- a/object.c -+++ b/object.c -@@ -236,17 +236,8 @@ init_copy(VALUE dest, VALUE obj) - break; - case T_CLASS: - case T_MODULE: -- if (RCLASS_IV_TBL(dest)) { -- st_free_table(RCLASS_IV_TBL(dest)); -- RCLASS_IV_TBL(dest) = 0; -- } -- if (RCLASS_CONST_TBL(dest)) { -- rb_free_const_table(RCLASS_CONST_TBL(dest)); -- RCLASS_CONST_TBL(dest) = 0; -- } -- if (RCLASS_IV_TBL(obj)) { -- RCLASS_IV_TBL(dest) = st_copy(RCLASS_IV_TBL(obj)); -- } -+ rb_free_const_table(RCLASS_CONST_TBL(dest)); -+ sa_copy_to(RCLASS_IV_TBL(obj), RCLASS_IV_TBL(dest)); - break; - } - } -@@ -537,7 +528,7 @@ rb_obj_is_kind_of(VALUE obj, VALUE c) - } - - while (cl) { -- if (cl == c || RCLASS_M_TBL(cl) == RCLASS_M_TBL(c)) -+ if (cl == c || RCLASS_EXT(cl) == RCLASS_EXT(c)) - return Qtrue; - cl = RCLASS_SUPER(cl); - } -@@ -1362,13 +1353,13 @@ rb_class_inherited_p(VALUE mod, VALUE arg) - rb_raise(rb_eTypeError, "compared with non class/module"); - } - while (mod) { -- if (RCLASS_M_TBL(mod) == RCLASS_M_TBL(arg)) -+ if (RCLASS_EXT(mod) == RCLASS_EXT(arg)) - return Qtrue; - mod = RCLASS_SUPER(mod); - } - /* not mod < arg; check if mod > arg */ - while (arg) { -- if (RCLASS_M_TBL(arg) == RCLASS_M_TBL(start)) -+ if (RCLASS_EXT(arg) == RCLASS_EXT(start)) - return Qfalse; - arg = RCLASS_SUPER(arg); - } -diff --git a/sp_ar.c b/sp_ar.c -new file mode 100644 -index 0000000..2ed69bf ---- /dev/null -+++ b/sp_ar.c -@@ -0,0 +1,374 @@ -+/* -+ * sparse array lib -+ * inspired by Lua table -+ * written by Sokolov Yura aka funny_falcon -+ */ -+#ifdef NOT_RUBY -+#include "regint.h" -+#include "st.h" -+#else -+#include "ruby/ruby.h" -+#endif -+ -+#include -+#ifdef HAVE_STDLIB_H -+#include -+#endif -+#include -+ -+#ifdef RUBY -+#define malloc xmalloc -+#define calloc xcalloc -+#define realloc xrealloc -+#define free xfree -+#endif -+ -+#define sa_table_alloc() (sa_table*)malloc(sizeof(sa_table)) -+#define sa_table_xalloc() (sa_table*)calloc(1, sizeof(sa_table)) -+#define sa_table_dealloc(table) free(table) -+#define sa_entry_alloc(n) (sa_entry*)calloc((n), sizeof(sa_entry)) -+#define sa_entry_dealloc(entries) free(entries) -+ -+#define SA_LAST 1 -+#define SA_OFFSET 2 -+ -+#define SA_MIN_SIZE 4 -+ -+void -+sa_init_table(register sa_table *table, sa_index_t num_bins) -+{ -+ if (num_bins) { -+ table->num_entries = 0; -+ table->entries = sa_entry_alloc(num_bins); -+ table->num_bins = num_bins; -+ table->free_pos = num_bins; -+ } -+ else { -+ memset(table, 0, sizeof(sa_table)); -+ } -+} -+ -+sa_table* -+sa_new_table() -+{ -+ sa_table* table = sa_table_alloc(); -+ sa_init_table(table, 0); -+ return table; -+} -+ -+static inline sa_index_t -+calc_pos(register sa_table* table, sa_index_t key) -+{ -+ /* this formula is empirical */ -+ /* it has no good avalance, but works well in our case */ -+ key ^= key >> 16; -+ key *= 0x445229; -+ return (key + (key >> 16)) % table->num_bins; -+} -+ -+static void -+fix_empty(register sa_table* table) -+{ -+ while(--table->free_pos && -+ table->entries[table->free_pos-1].next != SA_EMPTY); -+} -+ -+#define FLOOR_TO_4 ((~((sa_index_t)0)) << 2) -+static sa_index_t -+find_empty(register sa_table* table, register sa_index_t pos) -+{ -+ sa_index_t new_pos = table->free_pos-1; -+ sa_entry *entry; -+ pos &= FLOOR_TO_4; -+ entry = table->entries+pos; -+ -+ if (entry->next == SA_EMPTY) { new_pos = pos; goto check; } -+ pos++; entry++; -+ if (entry->next == SA_EMPTY) { new_pos = pos; goto check; } -+ pos++; entry++; -+ if (entry->next == SA_EMPTY) { new_pos = pos; goto check; } -+ pos++; entry++; -+ if (entry->next == SA_EMPTY) { new_pos = pos; goto check; } -+ -+check: -+ if (new_pos+1 == table->free_pos) fix_empty(table); -+ return new_pos; -+} -+ -+static void resize(register sa_table* table); -+static int insert_into_chain(register sa_table*, register sa_index_t, st_data_t, sa_index_t pos); -+static int insert_into_main(register sa_table*, sa_index_t, st_data_t, sa_index_t pos, sa_index_t prev_pos); -+ -+int -+sa_insert(register sa_table* table, register sa_index_t key, st_data_t value) -+{ -+ sa_index_t pos, main_pos; -+ register sa_entry *entry; -+ -+ if (table->num_bins == 0) { -+ sa_init_table(table, SA_MIN_SIZE); -+ } -+ -+ pos = calc_pos(table, key); -+ entry = table->entries + pos; -+ -+ if (entry->next == SA_EMPTY) { -+ entry->next = SA_LAST; -+ entry->key = key; -+ entry->value = value; -+ table->num_entries++; -+ if (pos+1 == table->free_pos) fix_empty(table); -+ return 0; -+ } -+ -+ if (entry->key == key) { -+ entry->value = value; -+ return 1; -+ } -+ -+ if (table->num_entries + (table->num_entries >> 2) > table->num_bins) { -+ resize(table); -+ return sa_insert(table, key, value); -+ } -+ -+ main_pos = calc_pos(table, entry->key); -+ if (main_pos == pos) { -+ return insert_into_chain(table, key, value, pos); -+ } -+ else { -+ if (!table->free_pos) { -+ resize(table); -+ return sa_insert(table, key, value); -+ } -+ return insert_into_main(table, key, value, pos, main_pos); -+ } -+} -+ -+static int -+insert_into_chain(register sa_table* table, register sa_index_t key, st_data_t value, sa_index_t pos) -+{ -+ sa_entry *entry = table->entries + pos, *new_entry; -+ sa_index_t new_pos; -+ -+ while (entry->next != SA_LAST) { -+ pos = entry->next - SA_OFFSET; -+ entry = table->entries + pos; -+ if (entry->key == key) { -+ entry->value = value; -+ return 1; -+ } -+ } -+ -+ if (!table->free_pos) { -+ resize(table); -+ return sa_insert(table, key, value); -+ } -+ -+ new_pos = find_empty(table, pos); -+ new_entry = table->entries + new_pos; -+ entry->next = new_pos + SA_OFFSET; -+ -+ new_entry->next = SA_LAST; -+ new_entry->key = key; -+ new_entry->value = value; -+ table->num_entries++; -+ return 0; -+} -+ -+static int -+insert_into_main(register sa_table* table, sa_index_t key, st_data_t value, sa_index_t pos, sa_index_t prev_pos) -+{ -+ sa_entry *entry = table->entries + pos; -+ sa_index_t new_pos = find_empty(table, pos); -+ sa_entry *new_entry = table->entries + new_pos; -+ sa_index_t npos; -+ -+ *new_entry = *entry; -+ -+ while((npos = table->entries[prev_pos].next - SA_OFFSET) != pos) { -+ prev_pos = npos; -+ } -+ table->entries[prev_pos].next = new_pos + SA_OFFSET; -+ -+ entry->next = SA_LAST; -+ entry->key = key; -+ entry->value = value; -+ table->num_entries++; -+ return 0; -+} -+ -+static sa_index_t -+new_size(sa_index_t num_entries) -+{ -+ sa_index_t msb = num_entries; -+ msb |= msb >> 1; -+ msb |= msb >> 2; -+ msb |= msb >> 4; -+ msb |= msb >> 8; -+ msb |= msb >> 16; -+ msb = ((msb >> 4) + 1) << 3; -+ return (num_entries & (msb | (msb >> 1))) + (msb >> 1); -+} -+ -+static void -+resize(register sa_table *table) -+{ -+ sa_table tmp_table; -+ sa_entry *entry; -+ sa_index_t i; -+ -+ if (table->num_entries == 0) { -+ sa_entry_dealloc(table->entries); -+ memset(table, 0, sizeof(sa_table)); -+ return; -+ } -+ -+ sa_init_table(&tmp_table, new_size(table->num_entries + (table->num_entries >> 2))); -+ entry = table->entries; -+ -+ for(i = 0; i < table->num_bins; i++, entry++) { -+ if (entry->next != SA_EMPTY) { -+ sa_insert(&tmp_table, entry->key, entry->value); -+ } -+ } -+ sa_entry_dealloc(table->entries); -+ *table = tmp_table; -+} -+ -+int -+sa_lookup(register sa_table *table, register sa_index_t key, st_data_t *value) -+{ -+ register sa_entry *entry; -+ -+ if (table->num_entries == 0) return 0; -+ -+ entry = table->entries + calc_pos(table, key); -+ if (entry->next == SA_EMPTY) return 0; -+ -+ if (entry->key == key) goto found; -+ if (entry->next == SA_LAST) return 0; -+ -+ entry = table->entries + (entry->next - SA_OFFSET); -+ if (entry->key == key) goto found; -+ -+ while(entry->next != SA_LAST) { -+ entry = table->entries + (entry->next - SA_OFFSET); -+ if (entry->key == key) goto found; -+ } -+ return 0; -+found: -+ if (value) *value = entry->value; -+ return 1; -+} -+ -+void -+sa_clear(sa_table *table) -+{ -+ sa_entry_dealloc(table->entries); -+ memset(table, 0, sizeof(sa_table)); -+} -+ -+void -+sa_clear_no_free(sa_table *table) -+{ -+ memset(table->entries, 0, sizeof(sa_entry) * table->num_bins); -+ table->num_entries = 0; -+ table->free_pos = table->num_bins; -+} -+ -+void -+sa_free_table(sa_table *table) -+{ -+ sa_entry_dealloc(table->entries); -+ sa_table_dealloc(table); -+} -+ -+int -+sa_delete(sa_table *table, sa_index_t key, st_data_t *value) -+{ -+ sa_index_t pos, prev_pos = ~0; -+ sa_entry *entry; -+ -+ if (table->num_entries == 0) goto not_found; -+ -+ pos = calc_pos(table, key); -+ entry = table->entries + pos; -+ -+ if (entry->next == SA_EMPTY) goto not_found; -+ -+ do { -+ if (entry->key == key) { -+ if (value) *value = entry->value; -+ if (entry->next != SA_LAST) { -+ sa_index_t npos = entry->next - SA_OFFSET; -+ *entry = table->entries[npos]; -+ memset(table->entries + npos, 0, sizeof(sa_entry)); -+ } -+ else { -+ memset(table->entries + pos, 0, sizeof(sa_entry)); -+ if (~prev_pos) { -+ table->entries[prev_pos].next = SA_LAST; -+ } -+ } -+ table->num_entries--; -+ if (table->num_entries < table->num_bins / 4) { -+ resize(table); -+ } -+ return 1; -+ } -+ if (entry->next == SA_LAST) break; -+ prev_pos = pos; -+ pos = entry->next - SA_OFFSET; -+ entry = table->entries + pos; -+ } while(1); -+ -+not_found: -+ if (value) *value = 0; -+ return 0; -+} -+ -+int -+sa_foreach(register sa_table *table, int (*func)(), st_data_t arg) -+{ -+ sa_index_t i; -+ if (table->num_bins == 0) { -+ return 0; -+ } -+ for(i = 0; i < table->num_bins ; i++) { -+ if (table->entries[i].next != SA_EMPTY) { -+ sa_index_t key = table->entries[i].key; -+ st_data_t val = table->entries[i].value; -+ if ((*func)(key, val, arg) == SA_STOP) break; -+ } -+ } -+ return 0; -+} -+ -+size_t -+sa_memsize(const sa_table *table) -+{ -+ return sizeof(sa_table) + table->num_bins * sizeof(sa_entry); -+} -+ -+sa_table* -+sa_copy(sa_table *table) -+{ -+ sa_table *new_table = sa_table_alloc(); -+ *new_table = *table; -+ if (table->num_bins) { -+ new_table->entries = sa_entry_alloc(table->num_bins); -+ memcpy(new_table->entries, table->entries, table->num_bins*sizeof(sa_entry)); -+ } -+ return new_table; -+} -+ -+void -+sa_copy_to(sa_table *from, sa_table *to) -+{ -+ sa_entry_dealloc(to->entries); -+ *to = *from; -+ if (to->num_bins) { -+ to->entries = sa_entry_alloc(to->num_bins); -+ memcpy(to->entries, from->entries, from->num_bins*sizeof(sa_entry)); -+ } -+} -diff --git a/test/ruby/test_marshal.rb b/test/ruby/test_marshal.rb -index 0f3f794..2316c15 100644 ---- a/test/ruby/test_marshal.rb -+++ b/test/ruby/test_marshal.rb -@@ -312,7 +312,7 @@ class TestMarshal < Test::Unit::TestCase - assert_equal(a.instance_variable_get(i), b.instance_variable_get(i), bug1932) - end - end -- a.__send__(a.methods(true).grep(/=\z/)[0], a) -+ a.__send__(a.methods(true).grep(/\Ar.+=\z/)[0], a) - assert_nothing_raised(bug1932) do - b = Marshal.load(Marshal.dump(a)) - assert_equal(ClassISO8859_1, b.class, bug1932) -diff --git a/test/ruby/test_method.rb b/test/ruby/test_method.rb -index ea6c5f2..6ccd37c 100644 ---- a/test/ruby/test_method.rb -+++ b/test/ruby/test_method.rb -@@ -406,7 +406,7 @@ class TestMethod < Test::Unit::TestCase - obj = a.new - assert_equal([:a], obj.public_methods(false), bug) - obj.extend(m) -- assert_equal([:m1, :a], obj.public_methods(false), bug) -+ assert_equal([:a, :m1], obj.public_methods(false).sort, bug) - end - - def test_visibility -diff --git a/test/ruby/test_module.rb b/test/ruby/test_module.rb -index 6176f48..a67d845 100644 ---- a/test/ruby/test_module.rb -+++ b/test/ruby/test_module.rb -@@ -870,7 +870,7 @@ class TestModule < Test::Unit::TestCase - (class << self ; self ; end).class_eval do - define_method :method_added do |sym| - memo << sym -- memo << mod.instance_methods(false) -+ memo << mod.instance_methods(false).sort - memo << (mod.instance_method(sym) rescue nil) - end - end -@@ -887,10 +887,10 @@ class TestModule < Test::Unit::TestCase - assert_equal [:f, :g], memo.shift - assert_equal mod.instance_method(:f), memo.shift - assert_equal :a, memo.shift -- assert_equal [:f, :g, :a], memo.shift -+ assert_equal [:a, :f, :g], memo.shift - assert_equal mod.instance_method(:a), memo.shift - assert_equal :a=, memo.shift -- assert_equal [:f, :g, :a, :a=], memo.shift -+ assert_equal [:a, :a=, :f, :g], memo.shift - assert_equal mod.instance_method(:a=), memo.shift - end - -diff --git a/time.c b/time.c -index 755812f..83edc83 100644 ---- a/time.c -+++ b/time.c -@@ -4712,16 +4712,14 @@ time_mload(VALUE time, VALUE str) - long nsec; - VALUE submicro, nano_num, nano_den, offset; - wideval_t timew; -- st_data_t data; - - time_modify(time); - - #define get_attr(attr, iffound) \ - attr = rb_attr_get(str, id_##attr); \ - if (!NIL_P(attr)) { \ -- data = id_##attr; \ - iffound; \ -- st_delete(rb_generic_ivar_table(str), &data, 0); \ -+ sa_delete(rb_generic_ivar_table(str), (sa_index_t)id_##attr, 0); \ - } - - get_attr(nano_num, {}); -diff --git a/variable.c b/variable.c -index 3da500e..4a61453 100644 ---- a/variable.c -+++ b/variable.c -@@ -19,15 +19,15 @@ - #include "constant.h" - #include "internal.h" - --st_table *rb_global_tbl; --st_table *rb_class_tbl; -+sa_table rb_global_tbl; -+sa_table rb_class_tbl; - static ID autoload, classpath, tmp_classpath, classid; - - void - Init_var_tables(void) - { -- rb_global_tbl = st_init_numtable(); -- rb_class_tbl = st_init_numtable(); -+ sa_init_table(&rb_global_tbl, 0); -+ sa_init_table(&rb_class_tbl, 0); - CONST_ID(autoload, "__autoload__"); - CONST_ID(classpath, "__classpath__"); - CONST_ID(tmp_classpath, "__tmp_classpath__"); -@@ -43,7 +43,7 @@ struct fc_result { - }; - - static VALUE --fc_path(struct fc_result *fc, ID name) -+fc_path(struct fc_result *fc, sa_index_t name) - { - VALUE path, tmp; - -@@ -51,8 +51,7 @@ fc_path(struct fc_result *fc, ID name) - while (fc) { - st_data_t n; - if (fc->track == rb_cObject) break; -- if (RCLASS_IV_TBL(fc->track) && -- st_lookup(RCLASS_IV_TBL(fc->track), (st_data_t)classpath, &n)) { -+ if (sa_lookup(RCLASS_IV_TBL(fc->track), (sa_index_t)classpath, &n)) { - tmp = rb_str_dup((VALUE)n); - rb_str_cat2(tmp, "::"); - rb_str_append(tmp, path); -@@ -70,7 +69,7 @@ fc_path(struct fc_result *fc, ID name) - } - - static int --fc_i(ID key, rb_const_entry_t *ce, struct fc_result *res) -+fc_i(sa_index_t key, rb_const_entry_t *ce, struct fc_result *res) - { - VALUE value = ce->value; - if (!rb_is_const_id(key)) return ST_CONTINUE; -@@ -98,7 +97,7 @@ fc_i(ID key, rb_const_entry_t *ce, struct fc_result *res) - arg.klass = res->klass; - arg.track = value; - arg.prev = res; -- st_foreach(RCLASS_CONST_TBL(value), fc_i, (st_data_t)&arg); -+ sa_foreach(RCLASS_CONST_TBL(value), fc_i, (st_data_t)&arg); - if (arg.path) { - res->path = arg.path; - return ST_STOP; -@@ -123,18 +122,14 @@ find_class_path(VALUE klass) - arg.track = rb_cObject; - arg.prev = 0; - if (RCLASS_CONST_TBL(rb_cObject)) { -- st_foreach_safe(RCLASS_CONST_TBL(rb_cObject), fc_i, (st_data_t)&arg); -+ sa_foreach(RCLASS_CONST_TBL(rb_cObject), fc_i, (st_data_t)&arg); - } - if (arg.path == 0) { -- st_foreach_safe(rb_class_tbl, fc_i, (st_data_t)&arg); -+ sa_foreach(&rb_class_tbl, fc_i, (st_data_t)&arg); - } - if (arg.path) { -- st_data_t tmp = tmp_classpath; -- if (!RCLASS_IV_TBL(klass)) { -- RCLASS_IV_TBL(klass) = st_init_numtable(); -- } -- st_insert(RCLASS_IV_TBL(klass), (st_data_t)classpath, arg.path); -- st_delete(RCLASS_IV_TBL(klass), &tmp, 0); -+ sa_insert(RCLASS_IV_TBL(klass), (sa_index_t)classpath, arg.path); -+ sa_delete(RCLASS_IV_TBL(klass), (sa_index_t)tmp_classpath, 0); - return arg.path; - } - return Qnil; -@@ -147,16 +142,15 @@ classname(VALUE klass) - st_data_t n; - - if (!klass) klass = rb_cObject; -- if (RCLASS_IV_TBL(klass)) { -- if (!st_lookup(RCLASS_IV_TBL(klass), (st_data_t)classpath, &n)) { -- if (!st_lookup(RCLASS_IV_TBL(klass), (st_data_t)classid, &n)) { -+ if (RCLASS_IV_TBL(klass)->num_entries) { -+ if (!sa_lookup(RCLASS_IV_TBL(klass), (sa_index_t)classpath, &n)) { -+ if (!sa_lookup(RCLASS_IV_TBL(klass), (sa_index_t)classid, &n)) { - return find_class_path(klass); - } - path = rb_str_dup(rb_id2str(SYM2ID((VALUE)n))); - OBJ_FREEZE(path); -- st_insert(RCLASS_IV_TBL(klass), (st_data_t)classpath, (st_data_t)path); -- n = classid; -- st_delete(RCLASS_IV_TBL(klass), &n, 0); -+ sa_insert(RCLASS_IV_TBL(klass), (sa_index_t)classpath, (st_data_t)path); -+ sa_delete(RCLASS_IV_TBL(klass), (sa_index_t)classid, 0); - } - else { - path = (VALUE)n; -@@ -192,8 +186,7 @@ rb_class_path(VALUE klass) - st_data_t n = (st_data_t)path; - - if (!NIL_P(path)) return path; -- if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass), -- (st_data_t)tmp_classpath, &n)) { -+ if (sa_lookup(RCLASS_IV_TBL(klass), (sa_index_t)tmp_classpath, &n)) { - return (VALUE)n; - } - else { -@@ -364,7 +357,7 @@ rb_global_entry(ID id) - struct global_entry *entry; - st_data_t data; - -- if (!st_lookup(rb_global_tbl, (st_data_t)id, &data)) { -+ if (!sa_lookup(&rb_global_tbl, (sa_index_t)id, &data)) { - struct global_variable *var; - entry = ALLOC(struct global_entry); - var = ALLOC(struct global_variable); -@@ -378,7 +371,7 @@ rb_global_entry(ID id) - - var->block_trace = 0; - var->trace = 0; -- st_add_direct(rb_global_tbl, id, (st_data_t)entry); -+ sa_insert(&rb_global_tbl, (sa_index_t)id, (st_data_t)entry); - } - else { - entry = (struct global_entry *)data; -@@ -454,8 +447,8 @@ readonly_setter(VALUE val, ID id, void *data, struct global_variable *gvar) - rb_name_error(id, "%s is a read-only variable", rb_id2name(id)); - } - --static int --mark_global_entry(ID key, struct global_entry *entry) -+static void -+mark_global_entry(struct global_entry *entry) - { - struct trace_var *trace; - struct global_variable *var = entry->var; -@@ -466,14 +459,14 @@ mark_global_entry(ID key, struct global_entry *entry) - if (trace->data) rb_gc_mark_maybe(trace->data); - trace = trace->next; - } -- return ST_CONTINUE; - } - - void - rb_gc_mark_global_tbl(void) - { -- if (rb_global_tbl) -- st_foreach_safe(rb_global_tbl, mark_global_entry, 0); -+ SA_FOREACH_START(&rb_global_tbl); -+ mark_global_entry((struct global_entry*) value); -+ SA_FOREACH_END(); - } - - static ID -@@ -635,7 +628,7 @@ rb_f_untrace_var(int argc, VALUE *argv) - rb_secure(4); - rb_scan_args(argc, argv, "11", &var, &cmd); - id = rb_to_id(var); -- if (!st_lookup(rb_global_tbl, (st_data_t)id, &data)) { -+ if (!sa_lookup(&rb_global_tbl, (sa_index_t)id, &data)) { - rb_name_error(id, "undefined global variable %s", rb_id2name(id)); - } - -@@ -742,13 +735,6 @@ rb_gvar_defined(struct global_entry *entry) - return Qtrue; - } - --static int --gvar_i(ID key, struct global_entry *entry, VALUE ary) --{ -- rb_ary_push(ary, ID2SYM(key)); -- return ST_CONTINUE; --} -- - /* - * call-seq: - * global_variables -> array -@@ -765,7 +751,9 @@ rb_f_global_variables(void) - char buf[2]; - int i; - -- st_foreach_safe(rb_global_tbl, gvar_i, ary); -+ SA_FOREACH_START(&rb_global_tbl); -+ rb_ary_push(ary, ID2SYM(entry->key)); -+ SA_FOREACH_END(); - buf[0] = '$'; - for (i = 1; i <= 9; ++i) { - buf[1] = (char)(i + '0'); -@@ -784,10 +772,10 @@ rb_alias_variable(ID name1, ID name2) - rb_raise(rb_eSecurityError, "Insecure: can't alias global variable"); - - entry2 = rb_global_entry(name2); -- if (!st_lookup(rb_global_tbl, (st_data_t)name1, &data1)) { -+ if (!sa_lookup(&rb_global_tbl, (sa_index_t)name1, &data1)) { - entry1 = ALLOC(struct global_entry); - entry1->id = name1; -- st_add_direct(rb_global_tbl, name1, (st_data_t)entry1); -+ sa_insert(&rb_global_tbl, (sa_index_t)name1, (st_data_t)entry1); - } - else if ((entry1 = (struct global_entry *)data1)->var != entry2->var) { - struct global_variable *var = entry1->var; -@@ -815,7 +803,7 @@ rb_alias_variable(ID name1, ID name2) - static int special_generic_ivar = 0; - static st_table *generic_iv_tbl; - --st_table* -+sa_table* - rb_generic_ivar_table(VALUE obj) - { - st_data_t tbl; -@@ -823,7 +811,7 @@ rb_generic_ivar_table(VALUE obj) - if (!FL_TEST(obj, FL_EXIVAR)) return 0; - if (!generic_iv_tbl) return 0; - if (!st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) return 0; -- return (st_table *)tbl; -+ return (sa_table *)tbl; - } - - static VALUE -@@ -833,7 +821,7 @@ generic_ivar_get(VALUE obj, ID id, int warn) - - if (generic_iv_tbl) { - if (st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) { -- if (st_lookup((st_table *)tbl, (st_data_t)id, &val)) { -+ if (sa_lookup((sa_table *)tbl, (sa_index_t)id, &val)) { - return (VALUE)val; - } - } -@@ -847,7 +835,6 @@ generic_ivar_get(VALUE obj, ID id, int warn) - static void - generic_ivar_set(VALUE obj, ID id, VALUE val) - { -- st_table *tbl; - st_data_t data; - - if (rb_special_const_p(obj)) { -@@ -859,24 +846,22 @@ generic_ivar_set(VALUE obj, ID id, VALUE val) - } - if (!st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) { - FL_SET(obj, FL_EXIVAR); -- tbl = st_init_numtable(); -- st_add_direct(generic_iv_tbl, (st_data_t)obj, (st_data_t)tbl); -- st_add_direct(tbl, (st_data_t)id, (st_data_t)val); -- return; -+ data = (st_data_t)sa_new_table(); -+ st_add_direct(generic_iv_tbl, (st_data_t)obj, data); - } -- st_insert((st_table *)data, (st_data_t)id, (st_data_t)val); -+ sa_insert((sa_table *)data, (sa_index_t)id, (st_data_t)val); - } - - static VALUE - generic_ivar_defined(VALUE obj, ID id) - { -- st_table *tbl; -+ sa_table *tbl; - st_data_t data; - - if (!generic_iv_tbl) return Qfalse; - if (!st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) return Qfalse; -- tbl = (st_table *)data; -- if (st_lookup(tbl, (st_data_t)id, &data)) { -+ tbl = (sa_table *)data; -+ if (sa_lookup(tbl, (sa_index_t)id, &data)) { - return Qtrue; - } - return Qfalse; -@@ -885,18 +870,18 @@ generic_ivar_defined(VALUE obj, ID id) - static int - generic_ivar_remove(VALUE obj, ID id, st_data_t *valp) - { -- st_table *tbl; -+ sa_table *tbl; - st_data_t data, key = (st_data_t)id; - int status; - - if (!generic_iv_tbl) return 0; - if (!st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) return 0; -- tbl = (st_table *)data; -- status = st_delete(tbl, &key, valp); -+ tbl = (sa_table *)data; -+ status = sa_delete(tbl, (sa_index_t)id, valp); - if (tbl->num_entries == 0) { - key = (st_data_t)obj; - st_delete(generic_iv_tbl, &key, &data); -- st_free_table((st_table *)data); -+ sa_free_table(tbl); - } - return status; - } -@@ -908,22 +893,17 @@ rb_mark_generic_ivar(VALUE obj) - - if (!generic_iv_tbl) return; - if (st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) { -- rb_mark_tbl((st_table *)tbl); -+ rb_mark_sa_tbl((sa_table *)tbl); - } - } - - static int --givar_mark_i(ID key, VALUE value) --{ -- rb_gc_mark(value); -- return ST_CONTINUE; --} -- --static int --givar_i(VALUE obj, st_table *tbl) -+givar_i(VALUE obj, sa_table *tbl) - { - if (rb_special_const_p(obj)) { -- st_foreach_safe(tbl, givar_mark_i, 0); -+ SA_FOREACH_START(tbl); -+ rb_gc_mark((VALUE)value); -+ SA_FOREACH_END(); - } - return ST_CONTINUE; - } -@@ -943,7 +923,7 @@ rb_free_generic_ivar(VALUE obj) - - if (!generic_iv_tbl) return; - if (st_delete(generic_iv_tbl, &key, &tbl)) -- st_free_table((st_table *)tbl); -+ sa_free_table((sa_table *)tbl); - } - - RUBY_FUNC_EXPORTED size_t -@@ -951,7 +931,7 @@ rb_generic_ivar_memsize(VALUE obj) - { - st_data_t tbl; - if (st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) -- return st_memsize((st_table *)tbl); -+ return sa_memsize((sa_table *)tbl); - return 0; - } - -@@ -970,17 +950,17 @@ rb_copy_generic_ivar(VALUE clone, VALUE obj) - return; - } - if (st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) { -- st_table *tbl = (st_table *)data; -+ sa_table *tbl = (sa_table *)data; - - if (tbl->num_entries == 0) - goto clear; - - if (st_lookup(generic_iv_tbl, (st_data_t)clone, &data)) { -- st_free_table((st_table *)data); -- st_insert(generic_iv_tbl, (st_data_t)clone, (st_data_t)st_copy(tbl)); -+ sa_free_table((sa_table *)data); -+ st_insert(generic_iv_tbl, (st_data_t)clone, (st_data_t)sa_copy(tbl)); - } - else { -- st_add_direct(generic_iv_tbl, (st_data_t)clone, (st_data_t)st_copy(tbl)); -+ st_add_direct(generic_iv_tbl, (st_data_t)clone, (st_data_t)sa_copy(tbl)); - FL_SET(clone, FL_EXIVAR); - } - } -@@ -990,7 +970,7 @@ static VALUE - ivar_get(VALUE obj, ID id, int warn) - { - VALUE val, *ptr; -- struct st_table *iv_index_tbl; -+ sa_table *iv_index_tbl; - long len; - st_data_t index; - -@@ -1000,7 +980,7 @@ ivar_get(VALUE obj, ID id, int warn) - ptr = ROBJECT_IVPTR(obj); - iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); - if (!iv_index_tbl) break; -- if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break; -+ if (!sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) break; - if (len <= (long)index) break; - val = ptr[index]; - if (val != Qundef) -@@ -1008,7 +988,7 @@ ivar_get(VALUE obj, ID id, int warn) - break; - case T_CLASS: - case T_MODULE: -- if (RCLASS_IV_TBL(obj) && st_lookup(RCLASS_IV_TBL(obj), (st_data_t)id, &index)) -+ if (sa_lookup(RCLASS_IV_TBL(obj), (sa_index_t)id, &index)) - return (VALUE)index; - break; - default: -@@ -1037,7 +1017,7 @@ rb_attr_get(VALUE obj, ID id) - VALUE - rb_ivar_set(VALUE obj, ID id, VALUE val) - { -- struct st_table *iv_index_tbl; -+ struct sa_table *iv_index_tbl; - st_data_t index; - long i, len; - int ivar_extended; -@@ -1051,14 +1031,11 @@ rb_ivar_set(VALUE obj, ID id, VALUE val) - if (!iv_index_tbl) { - VALUE klass = rb_obj_class(obj); - iv_index_tbl = RCLASS_IV_INDEX_TBL(klass); -- if (!iv_index_tbl) { -- iv_index_tbl = RCLASS_IV_INDEX_TBL(klass) = st_init_numtable(); -- } - } - ivar_extended = 0; -- if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) { -+ if (!sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) { - index = iv_index_tbl->num_entries; -- st_add_direct(iv_index_tbl, (st_data_t)id, index); -+ sa_insert(iv_index_tbl, (sa_index_t)id, index); - ivar_extended = 1; - } - len = ROBJECT_NUMIV(obj); -@@ -1098,8 +1075,7 @@ rb_ivar_set(VALUE obj, ID id, VALUE val) - break; - case T_CLASS: - case T_MODULE: -- if (!RCLASS_IV_TBL(obj)) RCLASS_IV_TBL(obj) = st_init_numtable(); -- st_insert(RCLASS_IV_TBL(obj), (st_data_t)id, val); -+ sa_insert(RCLASS_IV_TBL(obj), (sa_index_t)id, val); - break; - default: - generic_ivar_set(obj, id, val); -@@ -1112,13 +1088,13 @@ VALUE - rb_ivar_defined(VALUE obj, ID id) - { - VALUE val; -- struct st_table *iv_index_tbl; -+ struct sa_table *iv_index_tbl; - st_data_t index; - switch (TYPE(obj)) { - case T_OBJECT: - iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); - if (!iv_index_tbl) break; -- if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break; -+ if (!sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) break; - if (ROBJECT_NUMIV(obj) <= (long)index) break; - val = ROBJECT_IVPTR(obj)[index]; - if (val != Qundef) -@@ -1126,7 +1102,7 @@ rb_ivar_defined(VALUE obj, ID id) - break; - case T_CLASS: - case T_MODULE: -- if (RCLASS_IV_TBL(obj) && st_lookup(RCLASS_IV_TBL(obj), (st_data_t)id, 0)) -+ if (sa_lookup(RCLASS_IV_TBL(obj), (sa_index_t)id, 0)) - return Qtrue; - break; - default: -@@ -1137,40 +1113,26 @@ rb_ivar_defined(VALUE obj, ID id) - return Qfalse; - } - --struct obj_ivar_tag { -- VALUE obj; -- int (*func)(ID key, VALUE val, st_data_t arg); -- st_data_t arg; --}; -- --static int --obj_ivar_i(st_data_t key, st_data_t index, st_data_t arg) --{ -- struct obj_ivar_tag *data = (struct obj_ivar_tag *)arg; -- if ((long)index < ROBJECT_NUMIV(data->obj)) { -- VALUE val = ROBJECT_IVPTR(data->obj)[(long)index]; -- if (val != Qundef) { -- return (data->func)((ID)key, val, data->arg); -- } -- } -- return ST_CONTINUE; --} -- - static void - obj_ivar_each(VALUE obj, int (*func)(ANYARGS), st_data_t arg) - { -- st_table *tbl; -- struct obj_ivar_tag data; -+ sa_table *tbl; -+ long numiv = ROBJECT_NUMIV(obj); -+ VALUE *vars = ROBJECT_IVPTR(obj); - - tbl = ROBJECT_IV_INDEX_TBL(obj); -- if (!tbl) -+ if (!tbl || !numiv) - return; - -- data.obj = obj; -- data.func = (int (*)(ID key, VALUE val, st_data_t arg))func; -- data.arg = arg; -- -- st_foreach_safe(tbl, obj_ivar_i, (st_data_t)&data); -+ SA_FOREACH_START(tbl); -+ if ((long)value < numiv) { -+ VALUE val = vars[value]; -+ if (val != Qundef) { -+ if (((sa_iter_func)func)(entry->key, val, arg) == SA_STOP) -+ break; -+ } -+ } -+ SA_FOREACH_END(); - } - - void -@@ -1182,9 +1144,7 @@ rb_ivar_foreach(VALUE obj, int (*func)(ANYARGS), st_data_t arg) - break; - case T_CLASS: - case T_MODULE: -- if (RCLASS_IV_TBL(obj)) { -- st_foreach_safe(RCLASS_IV_TBL(obj), func, arg); -- } -+ sa_foreach(RCLASS_IV_TBL(obj), func, arg); - break; - default: - if (!generic_iv_tbl) break; -@@ -1192,7 +1152,7 @@ rb_ivar_foreach(VALUE obj, int (*func)(ANYARGS), st_data_t arg) - st_data_t tbl; - - if (st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) { -- st_foreach_safe((st_table *)tbl, func, arg); -+ sa_foreach((sa_table *)tbl, func, arg); - } - } - break; -@@ -1202,11 +1162,11 @@ rb_ivar_foreach(VALUE obj, int (*func)(ANYARGS), st_data_t arg) - st_index_t - rb_ivar_count(VALUE obj) - { -- st_table *tbl; -+ sa_table *tbl; - switch (TYPE(obj)) { - case T_OBJECT: - if ((tbl = ROBJECT_IV_INDEX_TBL(obj)) != 0) { -- st_index_t i, count, num = tbl->num_entries; -+ sa_index_t i, count, num = tbl->num_entries; - const VALUE *const ivptr = ROBJECT_IVPTR(obj); - for (i = count = 0; i < num; ++i) { - if (ivptr[i] != Qundef) { -@@ -1228,7 +1188,7 @@ rb_ivar_count(VALUE obj) - st_data_t data; - - if (st_lookup(generic_iv_tbl, (st_data_t)obj, &data) && -- (tbl = (st_table *)data) != 0) { -+ (tbl = (sa_table *)data) != 0) { - return tbl->num_entries; - } - } -@@ -1238,7 +1198,7 @@ rb_ivar_count(VALUE obj) - } - - static int --ivar_i(ID key, VALUE val, VALUE ary) -+ivar_i(sa_index_t key, VALUE val, VALUE ary) - { - if (rb_is_instance_id(key)) { - rb_ary_push(ary, ID2SYM(key)); -@@ -1301,7 +1261,7 @@ rb_obj_remove_instance_variable(VALUE obj, VALUE name) - VALUE val = Qnil; - const ID id = rb_to_id(name); - st_data_t n, v; -- struct st_table *iv_index_tbl; -+ struct sa_table *iv_index_tbl; - st_data_t index; - - if (!OBJ_UNTRUSTED(obj) && rb_safe_level() >= 4) -@@ -1315,7 +1275,7 @@ rb_obj_remove_instance_variable(VALUE obj, VALUE name) - case T_OBJECT: - iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); - if (!iv_index_tbl) break; -- if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break; -+ if (!sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) break; - if (ROBJECT_NUMIV(obj) <= (long)index) break; - val = ROBJECT_IVPTR(obj)[index]; - if (val != Qundef) { -@@ -1326,14 +1286,14 @@ rb_obj_remove_instance_variable(VALUE obj, VALUE name) - case T_CLASS: - case T_MODULE: - n = id; -- if (RCLASS_IV_TBL(obj) && st_delete(RCLASS_IV_TBL(obj), &n, &v)) { -+ if (sa_delete(RCLASS_IV_TBL(obj), (sa_index_t)id, &v)) { - return (VALUE)v; - } - break; - default: - if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) { - v = val; -- if (generic_ivar_remove(obj, (st_data_t)id, &v)) { -+ if (generic_ivar_remove(obj, id, &v)) { - return (VALUE)v; - } - } -@@ -1410,20 +1370,20 @@ rb_mod_const_missing(VALUE klass, VALUE name) - static void - autoload_mark(void *ptr) - { -- rb_mark_tbl((st_table *)ptr); -+ rb_mark_sa_tbl((sa_table *)ptr); - } - - static void - autoload_free(void *ptr) - { -- st_free_table((st_table *)ptr); -+ sa_free_table((sa_table *)ptr); - } - - static size_t - autoload_memsize(const void *ptr) - { -- const st_table *tbl = ptr; -- return st_memsize(tbl); -+ const sa_table *tbl = ptr; -+ return sa_memsize(tbl); - } - - static const rb_data_type_t autoload_data_type = { -@@ -1432,14 +1392,14 @@ static const rb_data_type_t autoload_data_type = { - }; - - #define check_autoload_table(av) \ -- (struct st_table *)rb_check_typeddata((av), &autoload_data_type) -+ (struct sa_table *)rb_check_typeddata((av), &autoload_data_type) - - void - rb_autoload(VALUE mod, ID id, const char *file) - { - st_data_t av; - VALUE fn; -- struct st_table *tbl; -+ struct sa_table *tbl; - - if (!rb_is_const_id(id)) { - rb_raise(rb_eNameError, "autoload must be constant name: %s", rb_id2name(id)); -@@ -1448,43 +1408,41 @@ rb_autoload(VALUE mod, ID id, const char *file) - rb_raise(rb_eArgError, "empty file name"); - } - -- if ((tbl = RCLASS_CONST_TBL(mod)) && st_lookup(tbl, (st_data_t)id, &av) && ((rb_const_entry_t*)av)->value != Qundef) -+ if (sa_lookup(RCLASS_CONST_TBL(mod), (sa_index_t)id, &av) && ((rb_const_entry_t*)av)->value != Qundef) - return; - - rb_const_set(mod, id, Qundef); - tbl = RCLASS_IV_TBL(mod); -- if (tbl && st_lookup(tbl, (st_data_t)autoload, &av)) { -+ if (sa_lookup(tbl, (sa_index_t)autoload, &av)) { - tbl = check_autoload_table((VALUE)av); - } - else { -- if (!tbl) tbl = RCLASS_IV_TBL(mod) = st_init_numtable(); - av = (st_data_t)TypedData_Wrap_Struct(0, &autoload_data_type, 0); -- st_add_direct(tbl, (st_data_t)autoload, av); -- DATA_PTR(av) = tbl = st_init_numtable(); -+ sa_insert(tbl, (sa_index_t)autoload, av); -+ DATA_PTR(av) = tbl = sa_new_table(); - } - fn = rb_str_new2(file); - FL_UNSET(fn, FL_TAINT); - OBJ_FREEZE(fn); -- st_insert(tbl, (st_data_t)id, (st_data_t)rb_node_newnode(NODE_MEMO, fn, rb_safe_level(), 0)); -+ sa_insert(tbl, (sa_index_t)id, (st_data_t)rb_node_newnode(NODE_MEMO, fn, rb_safe_level(), 0)); - } - - static NODE* - autoload_delete(VALUE mod, ID id) - { -- st_data_t val, load = 0, n = id; -+ st_data_t val, load = 0; - rb_const_entry_t *ce; - -- st_delete(RCLASS_CONST_TBL(mod), &n, &val); -+ sa_delete(RCLASS_CONST_TBL(mod), (sa_index_t)id, &val); - ce = (rb_const_entry_t*)val; - if (ce) xfree(ce); -- if (st_lookup(RCLASS_IV_TBL(mod), (st_data_t)autoload, &val)) { -- struct st_table *tbl = check_autoload_table((VALUE)val); -+ if (sa_lookup(RCLASS_IV_TBL(mod), (sa_index_t)autoload, &val)) { -+ struct sa_table *tbl = check_autoload_table((VALUE)val); - -- st_delete(tbl, &n, &load); -+ sa_delete(tbl, (sa_index_t)id, &load); - - if (tbl->num_entries == 0) { -- n = autoload; -- st_delete(RCLASS_IV_TBL(mod), &n, &val); -+ sa_delete(RCLASS_IV_TBL(mod), (sa_index_t)autoload, &val); - } - } - -@@ -1509,14 +1467,14 @@ static NODE * - autoload_node(VALUE mod, ID id, const char **loadingpath) - { - VALUE file; -- struct st_table *tbl; -+ struct sa_table *tbl; - st_data_t val; - NODE *load; - const char *loading; - int safe; - -- if (!st_lookup(RCLASS_IV_TBL(mod), autoload, &val) || -- !(tbl = check_autoload_table((VALUE)val)) || !st_lookup(tbl, (st_data_t)id, &val)) { -+ if (!sa_lookup(RCLASS_IV_TBL(mod), (sa_index_t)autoload, &val) || -+ !(tbl = check_autoload_table((VALUE)val)) || !sa_lookup(tbl, (sa_index_t)id, &val)) { - return 0; - } - load = (NODE *)val; -@@ -1541,10 +1499,10 @@ autoload_node(VALUE mod, ID id, const char **loadingpath) - static int - autoload_node_id(VALUE mod, ID id) - { -- struct st_table *tbl = RCLASS_CONST_TBL(mod); -+ struct sa_table *tbl = RCLASS_CONST_TBL(mod); - st_data_t val; - -- if (!tbl || !st_lookup(tbl, (st_data_t)id, &val) || ((rb_const_entry_t*)val)->value != Qundef) { -+ if (!tbl || !sa_lookup(tbl, (sa_index_t)id, &val) || ((rb_const_entry_t*)val)->value != Qundef) { - return 0; - } - return 1; -@@ -1593,7 +1551,7 @@ rb_const_get_0(VALUE klass, ID id, int exclude, int recurse, int visibility) - while (RTEST(tmp)) { - VALUE am = 0; - st_data_t data; -- while (RCLASS_CONST_TBL(tmp) && st_lookup(RCLASS_CONST_TBL(tmp), (st_data_t)id, &data)) { -+ while (sa_lookup(RCLASS_CONST_TBL(tmp), (sa_index_t)id, &data)) { - rb_const_entry_t *ce = (rb_const_entry_t *)data; - if (visibility && ce->flag == CONST_PRIVATE) { - rb_name_error(id, "private constant %s::%s referenced", rb_class2name(klass), rb_id2name(id)); -@@ -1686,12 +1644,12 @@ VALUE - rb_const_remove(VALUE mod, ID id) - { - VALUE val; -- st_data_t v, n = id; -+ st_data_t v; - - if (!OBJ_UNTRUSTED(mod) && rb_safe_level() >= 4) - rb_raise(rb_eSecurityError, "Insecure: can't remove constant"); - rb_check_frozen(mod); -- if (!RCLASS_CONST_TBL(mod) || !st_delete(RCLASS_CONST_TBL(mod), &n, &v)) { -+ if (!sa_delete(RCLASS_CONST_TBL(mod), (sa_index_t)id, &v)) { - if (rb_const_defined_at(mod, id)) { - rb_name_error(id, "cannot remove %s::%s", - rb_class2name(mod), rb_id2name(id)); -@@ -1711,27 +1669,20 @@ rb_const_remove(VALUE mod, ID id) - return val; - } - --static int --sv_i(ID key, rb_const_entry_t *ce, st_table *tbl) --{ -- if (rb_is_const_id(key)) { -- if (!st_lookup(tbl, (st_data_t)key, 0)) { -- st_insert(tbl, (st_data_t)key, (st_data_t)ce); -- } -- } -- return ST_CONTINUE; --} -- - void* - rb_mod_const_at(VALUE mod, void *data) - { -- st_table *tbl = data; -+ sa_table *tbl = data; - if (!tbl) { -- tbl = st_init_numtable(); -+ tbl = sa_new_table(); - } -- if (RCLASS_CONST_TBL(mod)) { -- st_foreach_safe(RCLASS_CONST_TBL(mod), sv_i, (st_data_t)tbl); -+ SA_FOREACH_START(RCLASS_CONST_TBL(mod)); -+ if (rb_is_const_id(entry->key)) { -+ if (!sa_lookup(tbl, entry->key, 0)) { -+ sa_insert(tbl, entry->key, value); -+ } - } -+ SA_FOREACH_END(); - return tbl; - } - -@@ -1748,25 +1699,21 @@ rb_mod_const_of(VALUE mod, void *data) - return data; - } - --static int --list_i(st_data_t key, st_data_t value, VALUE ary) --{ -- ID sym = (ID)key; -- rb_const_entry_t *ce = (rb_const_entry_t *)value; -- if (ce->flag != CONST_PRIVATE) rb_ary_push(ary, ID2SYM(sym)); -- return ST_CONTINUE; --} -- - VALUE - rb_const_list(void *data) - { -- st_table *tbl = data; -+ sa_table *tbl = data; - VALUE ary; - - if (!tbl) return rb_ary_new2(0); - ary = rb_ary_new2(tbl->num_entries); -- st_foreach_safe(tbl, list_i, ary); -- st_free_table(tbl); -+ -+ SA_FOREACH_START(tbl); -+ rb_const_entry_t *ce = (rb_const_entry_t *)value; -+ if (ce->flag != CONST_PRIVATE) rb_ary_push(ary, ID2SYM(entry->key)); -+ SA_FOREACH_END(); -+ -+ sa_free_table(tbl); - - return ary; - } -@@ -1790,7 +1737,7 @@ VALUE - rb_mod_constants(int argc, VALUE *argv, VALUE mod) - { - VALUE inherit; -- st_table *tbl; -+ sa_table *tbl; - - if (argc == 0) { - inherit = Qtrue; -@@ -1817,7 +1764,7 @@ rb_const_defined_0(VALUE klass, ID id, int exclude, int recurse, int visibility) - tmp = klass; - retry: - while (tmp) { -- if (RCLASS_CONST_TBL(tmp) && st_lookup(RCLASS_CONST_TBL(tmp), (st_data_t)id, &value)) { -+ if (sa_lookup(RCLASS_CONST_TBL(tmp), (sa_index_t)id, &value)) { - rb_const_entry_t *ce = (rb_const_entry_t *)value; - if (visibility && ce->flag == CONST_PRIVATE) { - return (int)Qfalse; -@@ -1885,6 +1832,7 @@ void - rb_const_set(VALUE klass, ID id, VALUE val) - { - rb_const_entry_t *ce; -+ st_data_t value; - VALUE visibility = CONST_PUBLIC; - - if (NIL_P(klass)) { -@@ -1893,21 +1841,14 @@ rb_const_set(VALUE klass, ID id, VALUE val) - } - - check_before_mod_set(klass, id, val, "constant"); -- if (!RCLASS_CONST_TBL(klass)) { -- RCLASS_CONST_TBL(klass) = st_init_numtable(); -- } -- else { -- st_data_t value; -- -- if (st_lookup(RCLASS_CONST_TBL(klass), (st_data_t)id, &value)) { -- rb_const_entry_t *ce = (rb_const_entry_t*)value; -- if (ce->value == Qundef) -- autoload_delete(klass, id); -- else { -- visibility = ce->flag; -- rb_warn("already initialized constant %s", rb_id2name(id)); -- } -- } -+ if (sa_lookup(RCLASS_CONST_TBL(klass), (sa_index_t)id, &value)) { -+ rb_const_entry_t *ce = (rb_const_entry_t*)value; -+ if (ce->value == Qundef) -+ autoload_delete(klass, id); -+ else { -+ visibility = ce->flag; -+ rb_warn("already initialized constant %s", rb_id2name(id)); -+ } - } - - rb_vm_change_state(); -@@ -1916,7 +1857,7 @@ rb_const_set(VALUE klass, ID id, VALUE val) - ce->flag = (rb_const_flag_t)visibility; - ce->value = val; - -- st_insert(RCLASS_CONST_TBL(klass), (st_data_t)id, (st_data_t)ce); -+ sa_insert(RCLASS_CONST_TBL(klass), (sa_index_t)id, (st_data_t)ce); - } - - void -@@ -1958,8 +1899,7 @@ set_const_visibility(VALUE mod, int argc, VALUE *argv, rb_const_flag_t flag) - for (i = 0; i < argc; i++) { - VALUE val = argv[i]; - id = rb_to_id(val); -- if (RCLASS_CONST_TBL(mod) && -- st_lookup(RCLASS_CONST_TBL(mod), (st_data_t)id, &v)) { -+ if (sa_lookup(RCLASS_CONST_TBL(mod), (sa_index_t)id, &v)) { - ((rb_const_entry_t*)v)->flag = flag; - } - else { -@@ -2008,7 +1948,7 @@ original_module(VALUE c) - } - - #define CVAR_LOOKUP(v,r) do {\ -- if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass),(st_data_t)id,(v))) {\ -+ if (sa_lookup(RCLASS_IV_TBL(klass),(sa_index_t)id,(v))) {\ - r;\ - }\ - if (FL_TEST(klass, FL_SINGLETON) ) {\ -@@ -2027,7 +1967,7 @@ original_module(VALUE c) - klass = RCLASS_SUPER(klass);\ - }\ - while (klass) {\ -- if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass),(st_data_t)id,(v))) {\ -+ if (sa_lookup(RCLASS_IV_TBL(klass),(sa_index_t)id,(v))) {\ - r;\ - }\ - klass = RCLASS_SUPER(klass);\ -@@ -2043,15 +1983,13 @@ rb_cvar_set(VALUE klass, ID id, VALUE val) - CVAR_LOOKUP(0, {if (!front) front = klass; target = klass;}); - if (target) { - if (front && target != front) { -- st_data_t did = id; -- - if (RTEST(ruby_verbose)) { - rb_warning("class variable %s of %s is overtaken by %s", - rb_id2name(id), rb_class2name(original_module(front)), - rb_class2name(original_module(target))); - } - if (BUILTIN_TYPE(front) == T_CLASS) { -- st_delete(RCLASS_IV_TBL(front),&did,0); -+ sa_delete(RCLASS_IV_TBL(front),(sa_index_t)id,0); - } - } - } -@@ -2060,11 +1998,7 @@ rb_cvar_set(VALUE klass, ID id, VALUE val) - } - - check_before_mod_set(target, id, val, "class variable"); -- if (!RCLASS_IV_TBL(target)) { -- RCLASS_IV_TBL(target) = st_init_numtable(); -- } -- -- st_insert(RCLASS_IV_TBL(target), (st_data_t)id, (st_data_t)val); -+ sa_insert(RCLASS_IV_TBL(target), (sa_index_t)id, (st_data_t)val); - } - - VALUE -@@ -2080,15 +2014,13 @@ rb_cvar_get(VALUE klass, ID id) - rb_id2name(id), rb_class2name(tmp)); - } - if (front && target != front) { -- st_data_t did = id; -- - if (RTEST(ruby_verbose)) { - rb_warning("class variable %s of %s is overtaken by %s", - rb_id2name(id), rb_class2name(original_module(front)), - rb_class2name(original_module(target))); - } - if (BUILTIN_TYPE(front) == T_CLASS) { -- st_delete(RCLASS_IV_TBL(front),&did,0); -+ sa_delete(RCLASS_IV_TBL(front),(sa_index_t)id,0); - } - } - return (VALUE)value; -@@ -2134,7 +2066,7 @@ rb_define_class_variable(VALUE klass, const char *name, VALUE val) - } - - static int --cv_i(ID key, VALUE value, VALUE ary) -+cv_i(sa_index_t key, VALUE value, VALUE ary) - { - if (rb_is_class_id(key)) { - VALUE kval = ID2SYM(key); -@@ -2167,7 +2099,7 @@ rb_mod_class_variables(VALUE obj) - VALUE ary = rb_ary_new(); - - if (RCLASS_IV_TBL(obj)) { -- st_foreach_safe(RCLASS_IV_TBL(obj), cv_i, ary); -+ sa_foreach(RCLASS_IV_TBL(obj), cv_i, ary); - } - return ary; - } -@@ -2196,7 +2128,7 @@ VALUE - rb_mod_remove_cvar(VALUE mod, VALUE name) - { - const ID id = rb_to_id(name); -- st_data_t val, n = id; -+ st_data_t val; - - if (!rb_is_class_id(id)) { - rb_name_error(id, "wrong class variable name %s", rb_id2name(id)); -@@ -2204,7 +2136,7 @@ rb_mod_remove_cvar(VALUE mod, VALUE name) - if (!OBJ_UNTRUSTED(mod) && rb_safe_level() >= 4) - rb_raise(rb_eSecurityError, "Insecure: can't remove class variable"); - rb_check_frozen(mod); -- if (RCLASS_IV_TBL(mod) && st_delete(RCLASS_IV_TBL(mod), &n, &val)) { -+ if (RCLASS_IV_TBL(mod) && sa_delete(RCLASS_IV_TBL(mod), (sa_index_t)id, &val)) { - return (VALUE)val; - } - if (rb_cvar_defined(mod, id)) { -diff --git a/vm.c b/vm.c -index 04ef956..6edabf6 100644 ---- a/vm.c -+++ b/vm.c -@@ -1055,7 +1055,7 @@ static void - add_opt_method(VALUE klass, ID mid, VALUE bop) - { - rb_method_entry_t *me; -- if (st_lookup(RCLASS_M_TBL(klass), mid, (void *)&me) && me->def && -+ if (sa_lookup(RCLASS_M_TBL(klass), (sa_index_t)mid, (void *)&me) && me->def && - me->def->type == VM_METHOD_TYPE_CFUNC) { - st_insert(vm_opt_method_table, (st_data_t)me, (st_data_t)bop); - } -diff --git a/vm_insnhelper.c b/vm_insnhelper.c -index 4f709e6..1bfd131 100644 ---- a/vm_insnhelper.c -+++ b/vm_insnhelper.c -@@ -1183,7 +1183,7 @@ vm_get_ev_const(rb_thread_t *th, const rb_iseq_t *iseq, - st_data_t data; - search_continue: - if (RCLASS_CONST_TBL(klass) && -- st_lookup(RCLASS_CONST_TBL(klass), id, &data)) { -+ sa_lookup(RCLASS_CONST_TBL(klass), (sa_index_t)id, &data)) { - val = ((rb_const_entry_t*)data)->value; - if (val == Qundef) { - if (am == klass) break; -@@ -1293,10 +1293,10 @@ vm_getivar(VALUE obj, ID id, IC ic) - st_data_t index; - long len = ROBJECT_NUMIV(obj); - VALUE *ptr = ROBJECT_IVPTR(obj); -- struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); -+ struct sa_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); - - if (iv_index_tbl) { -- if (st_lookup(iv_index_tbl, id, &index)) { -+ if (sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) { - if ((long)index < len) { - val = ptr[index]; - } -@@ -1346,9 +1346,9 @@ vm_setivar(VALUE obj, ID id, VALUE val, IC ic) - } - } - else { -- struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); -+ struct sa_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); - -- if (iv_index_tbl && st_lookup(iv_index_tbl, (st_data_t)id, &index)) { -+ if (iv_index_tbl && sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) { - ic->ic_class = klass; - ic->ic_value.index = index; - ic->ic_vmstat = GET_VM_STATE_VERSION(); -diff --git a/vm_method.c b/vm_method.c -index 6e33603..6567440 100644 ---- a/vm_method.c -+++ b/vm_method.c -@@ -2,38 +2,33 @@ - * This file is included by vm.c - */ - --#define CACHE_SIZE 0x800 --#define CACHE_MASK 0x7ff --#define EXPR1(c,m) ((((c)>>3)^(m))&CACHE_MASK) -- - static void rb_vm_check_redefinition_opt_method(const rb_method_entry_t *me); - - static ID object_id, respond_to_missing; - static ID removed, singleton_removed, undefined, singleton_undefined; - static ID added, singleton_added, attached; - --struct cache_entry { /* method hash table. */ -- VALUE filled_version; /* filled state version */ -- ID mid; /* method's id */ -- VALUE klass; /* receiver's class */ -- rb_method_entry_t *me; --}; -- --static struct cache_entry cache[CACHE_SIZE]; - #define ruby_running (GET_VM()->running) - /* int ruby_running = 0; */ - -+static int -+methods_cache_clear_callback(void *vstart, void *vend, size_t stride, void *data) -+{ -+ VALUE v = (VALUE)vstart; -+ for (; v != (VALUE)vend; v += stride) { -+ switch(BUILTIN_TYPE(v)) { -+ case T_CLASS: -+ case T_MODULE: -+ case T_ICLASS: -+ RCLASS(v)->cache->method_cache_version = 0; -+ } -+ } -+ return 0; -+} - static void - vm_clear_global_method_cache(void) - { -- struct cache_entry *ent, *end; -- -- ent = cache; -- end = ent + CACHE_SIZE; -- while (ent < end) { -- ent->filled_version = 0; -- ent++; -- } -+ rb_objspace_each_objects(methods_cache_clear_callback, NULL); - } - - void -@@ -162,7 +157,7 @@ rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type, - rb_method_definition_t *def, rb_method_flag_t noex) - { - rb_method_entry_t *me; -- st_table *mtbl; -+ sa_table *mtbl; - st_data_t data; - - if (NIL_P(klass)) { -@@ -190,7 +185,7 @@ rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type, - mtbl = RCLASS_M_TBL(klass); - - /* check re-definition */ -- if (st_lookup(mtbl, mid, &data)) { -+ if (sa_lookup(mtbl, (sa_index_t)mid, &data)) { - rb_method_entry_t *old_me = (rb_method_entry_t *)data; - rb_method_definition_t *old_def = old_me->def; - -@@ -248,7 +243,7 @@ rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type, - } - } - -- st_insert(mtbl, mid, (st_data_t) me); -+ sa_insert(mtbl, (sa_index_t)mid, (st_data_t) me); - - return me; - } -@@ -371,7 +366,7 @@ search_method(VALUE klass, ID id) - return 0; - } - -- while (!st_lookup(RCLASS_M_TBL(klass), id, &body)) { -+ while (!sa_lookup(RCLASS_M_TBL(klass), (sa_index_t)id, &body)) { - klass = RCLASS_SUPER(klass); - if (!klass) { - return 0; -@@ -393,20 +388,10 @@ rb_method_entry_get_without_cache(VALUE klass, ID id) - rb_method_entry_t *me = search_method(klass, id); - - if (ruby_running) { -- struct cache_entry *ent; -- ent = cache + EXPR1(klass, id); -- ent->filled_version = GET_VM_STATE_VERSION(); -- ent->klass = klass; -- - if (UNDEFINED_METHOD_ENTRY_P(me)) { -- ent->mid = id; -- ent->me = 0; -- me = 0; -- } -- else { -- ent->mid = id; -- ent->me = me; -+ me = 0; - } -+ sa_insert(&RCLASS(klass)->cache->m_cache_tbl, (sa_index_t)id, (st_data_t)me); - } - - return me; -@@ -415,21 +400,23 @@ rb_method_entry_get_without_cache(VALUE klass, ID id) - rb_method_entry_t * - rb_method_entry(VALUE klass, ID id) - { -- struct cache_entry *ent; -+ rb_class_cache_t *cache = RCLASS(klass)->cache; -+ rb_method_entry_t *me; - -- ent = cache + EXPR1(klass, id); -- if (ent->filled_version == GET_VM_STATE_VERSION() && -- ent->mid == id && ent->klass == klass) { -- return ent->me; -+ if (cache->method_cache_version != GET_VM_STATE_VERSION()) { -+ sa_clear_no_free(&cache->m_cache_tbl); -+ cache->method_cache_version = GET_VM_STATE_VERSION(); -+ } -+ else if (sa_lookup(&cache->m_cache_tbl, (sa_index_t)id, (st_data_t*)&me)) { -+ return me; - } -- - return rb_method_entry_get_without_cache(klass, id); - } - - static void - remove_method(VALUE klass, ID mid) - { -- st_data_t key, data; -+ st_data_t data; - rb_method_entry_t *me = 0; - - if (klass == rb_cObject) { -@@ -443,14 +430,13 @@ remove_method(VALUE klass, ID mid) - rb_warn("removing `%s' may cause serious problems", rb_id2name(mid)); - } - -- if (!st_lookup(RCLASS_M_TBL(klass), mid, &data) || -+ if (!sa_lookup(RCLASS_M_TBL(klass), (sa_index_t)mid, &data) || - !(me = (rb_method_entry_t *)data) || - (!me->def || me->def->type == VM_METHOD_TYPE_UNDEF)) { - rb_name_error(mid, "method `%s' not defined in %s", - rb_id2name(mid), rb_class2name(klass)); - } -- key = (st_data_t)mid; -- st_delete(RCLASS_M_TBL(klass), &key, &data); -+ sa_delete(RCLASS_M_TBL(klass), (sa_index_t)mid, &data); - - rb_vm_check_redefinition_opt_method(me); - rb_clear_cache_for_undef(klass, mid); diff --git a/patches/ruby/1.9.3/p374/railsexpress/12-falcon-array-queue.patch b/patches/ruby/1.9.3/p374/railsexpress/12-falcon-array-queue.patch deleted file mode 100644 index e99cafa1ee..0000000000 --- a/patches/ruby/1.9.3/p374/railsexpress/12-falcon-array-queue.patch +++ /dev/null @@ -1,301 +0,0 @@ -diff --git a/array.c b/array.c -index c33d106..a459a4a 100644 ---- a/array.c -+++ b/array.c -@@ -255,15 +255,24 @@ rb_ary_modify(VALUE ary) - rb_ary_modify_check(ary); - if (ARY_SHARED_P(ary)) { - long len = RARRAY_LEN(ary); -+ VALUE shared = ARY_SHARED(ary); - if (len <= RARRAY_EMBED_LEN_MAX) { - VALUE *ptr = ARY_HEAP_PTR(ary); -- VALUE shared = ARY_SHARED(ary); - FL_UNSET_SHARED(ary); - FL_SET_EMBED(ary); - MEMCPY(ARY_EMBED_PTR(ary), ptr, VALUE, len); - rb_ary_decrement_share(shared); - ARY_SET_EMBED_LEN(ary, len); - } -+ else if (ARY_SHARED_NUM(shared) == 1 && len > RARRAY_LEN(shared)>>1) { -+ long shift = RARRAY_PTR(ary) - RARRAY_PTR(shared); -+ ARY_SET_PTR(ary, RARRAY_PTR(shared)); -+ ARY_SET_CAPA(ary, RARRAY_LEN(shared)); -+ MEMMOVE(RARRAY_PTR(ary), RARRAY_PTR(ary)+shift, VALUE, len); -+ FL_UNSET_SHARED(ary); -+ FL_SET_EMBED(shared); -+ rb_ary_decrement_share(shared); -+ } - else { - VALUE *ptr = ALLOC_N(VALUE, len); - MEMCPY(ptr, RARRAY_PTR(ary), VALUE, len); -@@ -274,6 +283,38 @@ rb_ary_modify(VALUE ary) - } - } - -+static void -+ary_ensure_room_for_push(VALUE ary, long add_len) -+{ -+ long new_len = RARRAY_LEN(ary) + add_len; -+ long capa; -+ -+ if (ARY_SHARED_P(ary)) { -+ if (new_len > RARRAY_EMBED_LEN_MAX) { -+ VALUE shared = ARY_SHARED(ary); -+ if (ARY_SHARED_NUM(shared) == 1) { -+ if (RARRAY_PTR(ary) - RARRAY_PTR(shared) + new_len <= RARRAY_LEN(shared)) { -+ rb_ary_modify_check(ary); -+ } -+ else { -+ /* if array is shared, than it is likely it participate in push/shift pattern */ -+ rb_ary_modify(ary); -+ capa = ARY_CAPA(ary); -+ if (new_len > capa - (capa >> 6)) { -+ ary_double_capa(ary, new_len); -+ } -+ } -+ return; -+ } -+ } -+ } -+ rb_ary_modify(ary); -+ capa = ARY_CAPA(ary); -+ if (new_len > capa) { -+ ary_double_capa(ary, new_len); -+ } -+} -+ - VALUE - rb_ary_freeze(VALUE ary) - { -@@ -446,8 +487,9 @@ ary_make_shared(VALUE ary) - OBJSETUP(shared, 0, T_ARRAY); - FL_UNSET_EMBED(shared); - -- ARY_SET_LEN((VALUE)shared, RARRAY_LEN(ary)); -+ ARY_SET_LEN((VALUE)shared, ARY_CAPA(ary)); - ARY_SET_PTR((VALUE)shared, RARRAY_PTR(ary)); -+ rb_mem_clear(RARRAY_PTR(shared) + RARRAY_LEN(ary), ARY_CAPA(ary) - RARRAY_LEN(ary)); - FL_SET_SHARED_ROOT(shared); - ARY_SET_SHARED_NUM((VALUE)shared, 1); - FL_SET_SHARED(ary); -@@ -737,8 +779,6 @@ ary_take_first_or_last(int argc, VALUE *argv, VALUE ary, enum ary_take_pos_flags - return ary_make_partial(ary, rb_cArray, offset, n); - } - --static VALUE rb_ary_push_1(VALUE ary, VALUE item); -- - /* - * call-seq: - * ary << obj -> ary -@@ -755,8 +795,12 @@ static VALUE rb_ary_push_1(VALUE ary, VALUE item); - VALUE - rb_ary_push(VALUE ary, VALUE item) - { -- rb_ary_modify(ary); -- return rb_ary_push_1(ary, item); -+ long idx = RARRAY_LEN(ary); -+ -+ ary_ensure_room_for_push(ary, 1); -+ RARRAY_PTR(ary)[idx] = item; -+ ARY_SET_LEN(ary, idx + 1); -+ return ary; - } - - static VALUE -@@ -772,6 +816,18 @@ rb_ary_push_1(VALUE ary, VALUE item) - return ary; - } - -+static VALUE -+rb_ary_cat(VALUE ary, const VALUE *ptr, long len) -+{ -+ long oldlen = RARRAY_LEN(ary); -+ -+ ary_ensure_room_for_push(ary, len); -+ -+ MEMCPY(RARRAY_PTR(ary) + oldlen, ptr, VALUE, len); -+ ARY_SET_LEN(ary, oldlen + len); -+ return ary; -+} -+ - /* - * call-seq: - * ary.push(obj, ... ) -> ary -@@ -788,11 +844,7 @@ rb_ary_push_1(VALUE ary, VALUE item) - static VALUE - rb_ary_push_m(int argc, VALUE *argv, VALUE ary) - { -- rb_ary_modify(ary); -- while (argc--) { -- rb_ary_push_1(ary, *argv++); -- } -- return ary; -+ return rb_ary_cat(ary, argv, argc); - } - - VALUE -@@ -920,6 +972,55 @@ rb_ary_shift_m(int argc, VALUE *argv, VALUE ary) - return result; - } - -+static void -+ary_ensure_room_for_unshift(VALUE ary, int argc) -+{ -+ long len = RARRAY_LEN(ary); -+ long new_len = len + argc; -+ long capa; -+ VALUE *head, *sharedp; -+ -+ if (ARY_SHARED_P(ary)) { -+ VALUE shared = ARY_SHARED(ary); -+ capa = RARRAY_LEN(shared); -+ if (ARY_SHARED_NUM(shared) == 1 && capa > new_len) { -+ head = RARRAY_PTR(ary); -+ sharedp = RARRAY_PTR(shared); -+ goto makeroom_if_need; -+ } -+ } -+ -+ rb_ary_modify(ary); -+ capa = ARY_CAPA(ary); -+ if (capa - (capa >> 6) <= new_len) { -+ ary_double_capa(ary, new_len); -+ } -+ -+ /* use shared array for big "queues" */ -+ if (new_len > ARY_DEFAULT_SIZE * 4) { -+ /* make a room for unshifted items */ -+ capa = ARY_CAPA(ary); -+ ary_make_shared(ary); -+ -+ head = sharedp = RARRAY_PTR(ary); -+ goto makeroom; -+makeroom_if_need: -+ if (head - sharedp < argc) { -+ long room; -+makeroom: -+ room = capa - new_len; -+ room -= room >> 4; -+ MEMMOVE(sharedp + argc + room, head, VALUE, len); -+ head = sharedp + argc + room; -+ } -+ ARY_SET_PTR(ary, head - argc); -+ } -+ else { -+ /* sliding items */ -+ MEMMOVE(RARRAY_PTR(ary) + argc, RARRAY_PTR(ary), VALUE, len); -+ } -+} -+ - /* - * call-seq: - * ary.unshift(obj, ...) -> ary -@@ -935,19 +1036,16 @@ rb_ary_shift_m(int argc, VALUE *argv, VALUE ary) - static VALUE - rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary) - { -- long len; -+ long len = RARRAY_LEN(ary); - -- rb_ary_modify(ary); -- if (argc == 0) return ary; -- if (ARY_CAPA(ary) <= (len = RARRAY_LEN(ary)) + argc) { -- ary_double_capa(ary, len + argc); -+ if (argc == 0) { -+ rb_ary_modify_check(ary); -+ return ary; - } - -- /* sliding items */ -- MEMMOVE(RARRAY_PTR(ary) + argc, RARRAY_PTR(ary), VALUE, len); -+ ary_ensure_room_for_unshift(ary, argc); - MEMCPY(RARRAY_PTR(ary), argv, VALUE, argc); -- ARY_INCREASE_LEN(ary, argc); -- -+ ARY_SET_LEN(ary, len + argc); - return ary; - } - -@@ -1309,15 +1407,12 @@ rb_ary_splice(VALUE ary, long beg, long len, VALUE rpl) - rpl = rb_ary_to_ary(rpl); - rlen = RARRAY_LEN(rpl); - } -- rb_ary_modify(ary); - if (beg >= RARRAY_LEN(ary)) { - if (beg > ARY_MAX_SIZE - rlen) { - rb_raise(rb_eIndexError, "index %ld too big", beg); - } -+ ary_ensure_room_for_push(ary, rlen-len); /* len is 0 or negative */ - len = beg + rlen; -- if (len >= ARY_CAPA(ary)) { -- ary_double_capa(ary, len); -- } - rb_mem_clear(RARRAY_PTR(ary) + RARRAY_LEN(ary), beg - RARRAY_LEN(ary)); - if (rlen > 0) { - MEMCPY(RARRAY_PTR(ary) + beg, RARRAY_PTR(rpl), VALUE, rlen); -@@ -1327,6 +1422,7 @@ rb_ary_splice(VALUE ary, long beg, long len, VALUE rpl) - else { - long alen; - -+ rb_ary_modify(ary); - alen = RARRAY_LEN(ary) + rlen - len; - if (alen >= ARY_CAPA(ary)) { - ary_double_capa(ary, alen); -@@ -2116,12 +2212,13 @@ rb_ary_sort_bang(VALUE ary) - if (RARRAY_LEN(ary) > 1) { - VALUE tmp = ary_make_substitution(ary); /* only ary refers tmp */ - struct ary_sort_data data; -+ long len = RARRAY_LEN(ary); - - RBASIC(tmp)->klass = 0; - data.ary = tmp; - data.opt_methods = 0; - data.opt_inited = 0; -- ruby_qsort(RARRAY_PTR(tmp), RARRAY_LEN(tmp), sizeof(VALUE), -+ ruby_qsort(RARRAY_PTR(tmp), len, sizeof(VALUE), - rb_block_given_p()?sort_1:sort_2, &data); - - if (ARY_EMBED_P(tmp)) { -@@ -2138,7 +2235,7 @@ rb_ary_sort_bang(VALUE ary) - if (ARY_HEAP_PTR(ary) == ARY_HEAP_PTR(tmp)) { - assert(!ARY_EMBED_P(ary)); - FL_UNSET_SHARED(ary); -- ARY_SET_CAPA(ary, ARY_CAPA(tmp)); -+ ARY_SET_CAPA(ary, RARRAY_LEN(tmp)); - } - else { - assert(!ARY_SHARED_P(tmp)); -@@ -2153,8 +2250,8 @@ rb_ary_sort_bang(VALUE ary) - xfree(ARY_HEAP_PTR(ary)); - } - ARY_SET_PTR(ary, RARRAY_PTR(tmp)); -- ARY_SET_HEAP_LEN(ary, RARRAY_LEN(tmp)); -- ARY_SET_CAPA(ary, ARY_CAPA(tmp)); -+ ARY_SET_HEAP_LEN(ary, len); -+ ARY_SET_CAPA(ary, RARRAY_LEN(tmp)); - } - /* tmp was lost ownership for the ptr */ - FL_UNSET(tmp, FL_FREEZE); -diff --git a/test/ruby/test_array.rb b/test/ruby/test_array.rb -index 28d3e41..bcad2c0 100644 ---- a/test/ruby/test_array.rb -+++ b/test/ruby/test_array.rb -@@ -414,6 +414,18 @@ class TestArray < Test::Unit::TestCase - a = @cls[1, 2, 3] - a[-1, 0] = a - assert_equal([1, 2, 1, 2, 3, 3], a) -+ -+ a = @cls[] -+ a[5,0] = [5] -+ assert_equal([nil, nil, nil, nil, nil, 5], a) -+ -+ a = @cls[1] -+ a[1,0] = [2] -+ assert_equal([1, 2], a) -+ -+ a = @cls[1] -+ a[1,1] = [2] -+ assert_equal([1, 2], a) - end - - def test_assoc diff --git a/patches/ruby/1.9.3/p385/railsexpress/01-fix-make-clean.patch b/patches/ruby/1.9.3/p385/railsexpress/01-fix-make-clean.patch deleted file mode 100644 index bd3b673664..0000000000 --- a/patches/ruby/1.9.3/p385/railsexpress/01-fix-make-clean.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/lib/mkmf.rb b/lib/mkmf.rb -index 7c706e8..c381a38 100644 ---- a/lib/mkmf.rb -+++ b/lib/mkmf.rb -@@ -2191,7 +2191,7 @@ def init_mkmf(config = CONFIG, rbconfig = RbConfig::CONFIG) - $LOCAL_LIBS = "" - - $cleanfiles = config_string('CLEANFILES') {|s| Shellwords.shellwords(s)} || [] -- $cleanfiles << "mkmf.log" -+ $cleanfiles << "mkmf.log .*.time" - $distcleanfiles = config_string('DISTCLEANFILES') {|s| Shellwords.shellwords(s)} || [] - $distcleandirs = config_string('DISTCLEANDIRS') {|s| Shellwords.shellwords(s)} || [] - diff --git a/patches/ruby/1.9.3/p385/railsexpress/02-railsbench-gc.patch b/patches/ruby/1.9.3/p385/railsexpress/02-railsbench-gc.patch deleted file mode 100644 index a7411ac8d4..0000000000 --- a/patches/ruby/1.9.3/p385/railsexpress/02-railsbench-gc.patch +++ /dev/null @@ -1,1235 +0,0 @@ -diff --git a/configure.in b/configure.in -index c64d981..6099a92 100644 ---- a/configure.in -+++ b/configure.in -@@ -2416,6 +2416,10 @@ if test "$EXEEXT" = .exe; then - AC_SUBST(EXECUTABLE_EXTS) - fi - -+dnl enable gc debugging -+AC_ARG_ENABLE(gcdebug, -+ AS_HELP_STRING([--enable-gcdebug], [build garbage collector with debugging enabled]), -+ [AC_DEFINE(GC_DEBUG,1)]) - dnl } - dnl build section { - -diff --git a/gc.c b/gc.c -index f307ecb..0be1ec9 100644 ---- a/gc.c -+++ b/gc.c -@@ -98,6 +98,15 @@ ruby_gc_params_t initial_params = { - #endif - }; - -+#ifndef HAVE_LONG_LONG -+#define LONG_LONG long -+#endif -+ -+static int heap_min_slots = 10000; -+static int heap_slots_increment = 10000; -+static int initial_heap_slots_increment = 10000; -+static double heap_slots_growth_factor = 1.8; -+ - #define nomem_error GET_VM()->special_exceptions[ruby_error_nomemory] - - #if SIZEOF_LONG == SIZEOF_VOIDP -@@ -302,7 +311,7 @@ typedef struct RVALUE { - struct RComplex complex; - } as; - #ifdef GC_DEBUG -- const char *file; -+ VALUE file; - int line; - #endif - } RVALUE; -@@ -372,11 +381,25 @@ typedef struct rb_objspace { - size_t free_min; - size_t final_num; - size_t do_heap_free; -+ unsigned long max_blocks_to_free; -+ unsigned long freed_blocks; - } heap; - struct { -+ unsigned long processed; -+ unsigned long freed_objects; -+ unsigned long freelist_size; -+ unsigned long zombies; -+ unsigned long free_counts[T_MASK+1]; -+ unsigned long live_counts[T_MASK+1]; -+ unsigned long gc_time_accumulator_before_gc; -+ unsigned long live_after_last_mark_phase; -+ } stats; -+ struct { - int dont_gc; - int dont_lazy_sweep; - int during_gc; -+ int gc_statistics; -+ int verbose_gc_stats; - } flags; - struct { - st_table *table; -@@ -393,6 +416,14 @@ typedef struct rb_objspace { - struct gc_list *global_list; - size_t count; - int gc_stress; -+ long heap_size; -+ unsigned LONG_LONG gc_time_accumulator; -+ FILE* gc_data_file; -+ long gc_collections; -+ unsigned LONG_LONG gc_allocated_size; -+ unsigned LONG_LONG gc_num_allocations; -+ unsigned long live_objects; -+ unsigned LONG_LONG allocated_objects; - } rb_objspace_t; - - #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE -@@ -415,6 +446,16 @@ int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress; - #define heaps_freed objspace->heap.freed - #define dont_gc objspace->flags.dont_gc - #define during_gc objspace->flags.during_gc -+#define gc_statistics objspace->flags.gc_statistics -+#define verbose_gc_stats objspace->flags.verbose_gc_stats -+#define heap_size objspace->heap_size -+#define gc_time_accumulator objspace->gc_time_accumulator -+#define gc_data_file objspace->gc_data_file -+#define gc_collections objspace->gc_collections -+#define gc_allocated_size objspace->gc_allocated_size -+#define gc_num_allocations objspace->gc_num_allocations -+#define live_objects objspace->live_objects -+#define allocated_objects objspace->allocated_objects - #define finalizer_table objspace->final.table - #define deferred_final_list objspace->final.deferred - #define global_List objspace->global_list -@@ -422,6 +463,14 @@ int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress; - #define initial_malloc_limit initial_params.initial_malloc_limit - #define initial_heap_min_slots initial_params.initial_heap_min_slots - #define initial_free_min initial_params.initial_free_min -+#define free_counts objspace->stats.free_counts -+#define live_counts objspace->stats.live_counts -+#define processed objspace->stats.processed -+#define zombies objspace->stats.zombies -+#define freelist_size objspace->stats.freelist_size -+#define freed_objects objspace->stats.freed_objects -+#define gc_time_accumulator_before_gc objspace->stats.gc_time_accumulator_before_gc -+#define live_after_last_mark_phase objspace->stats.live_after_last_mark_phase - - static void rb_objspace_call_finalizer(rb_objspace_t *objspace); - -@@ -444,24 +493,59 @@ static void init_mark_stack(mark_stack_t *stack); - void - rb_gc_set_params(void) - { -- char *malloc_limit_ptr, *heap_min_slots_ptr, *free_min_ptr; -+ char *envp; -+ -+ rb_objspace_t *objspace = &rb_objspace; -+ -+ gc_data_file = stderr; - - if (rb_safe_level() > 0) return; - -- malloc_limit_ptr = getenv("RUBY_GC_MALLOC_LIMIT"); -- if (malloc_limit_ptr != NULL) { -- int malloc_limit_i = atoi(malloc_limit_ptr); -+ envp = getenv("RUBY_GC_STATS"); -+ if (envp != NULL) { -+ int i = atoi(envp); -+ if (i > 0) { -+ verbose_gc_stats = 1; -+ fprintf(stderr, "RUBY_GC_STATS=%d\n", verbose_gc_stats); -+ } -+ /* child processes should not inherit RUBY_GC_STATS */ -+ ruby_unsetenv("RUBY_GC_STATS"); -+ } -+ -+ envp = getenv("RUBY_GC_DATA_FILE"); -+ if (envp != NULL) { -+ FILE* data_file = fopen(envp, "w"); -+ if (data_file != NULL) { -+ gc_data_file = data_file; -+ } -+ else { -+ fprintf(stderr, "can't open gc log file %s for writing, using default\n", envp); -+ } -+ /* child processes should not inherit RUBY_GC_DATA_FILE to avoid clobbering */ -+ ruby_unsetenv("RUBY_GC_DATA_FILE"); -+ } -+ -+ envp = getenv("RUBY_GC_MALLOC_LIMIT"); -+ if (envp != NULL) { -+ int malloc_limit_i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_GC_MALLOC_LIMIT=%s\n", envp); -+ } - if (RTEST(ruby_verbose)) - fprintf(stderr, "malloc_limit=%d (%d)\n", - malloc_limit_i, initial_malloc_limit); - if (malloc_limit_i > 0) { - initial_malloc_limit = malloc_limit_i; -+ // malloc_limit = initial_malloc_limit; - } - } - -- heap_min_slots_ptr = getenv("RUBY_HEAP_MIN_SLOTS"); -- if (heap_min_slots_ptr != NULL) { -- int heap_min_slots_i = atoi(heap_min_slots_ptr); -+ envp = getenv("RUBY_HEAP_MIN_SLOTS"); -+ if (envp != NULL) { -+ int heap_min_slots_i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_MIN_SLOTS=%s\n", envp); -+ } - if (RTEST(ruby_verbose)) - fprintf(stderr, "heap_min_slots=%d (%d)\n", - heap_min_slots_i, initial_heap_min_slots); -@@ -471,15 +555,42 @@ rb_gc_set_params(void) - } - } - -- free_min_ptr = getenv("RUBY_FREE_MIN"); -- if (free_min_ptr != NULL) { -- int free_min_i = atoi(free_min_ptr); -+ if (!(envp = getenv("RUBY_FREE_MIN"))) -+ envp = getenv("RUBY_HEAP_FREE_MIN"); -+ if (envp != NULL) { -+ int free_min_i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_FREE_MIN=%s\n", envp); -+ } - if (RTEST(ruby_verbose)) - fprintf(stderr, "free_min=%d (%d)\n", free_min_i, initial_free_min); - if (free_min_i > 0) { - initial_free_min = free_min_i; - } - } -+ -+ envp = getenv("RUBY_HEAP_SLOTS_INCREMENT"); -+ if (envp != NULL) { -+ int i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_INCREMENT=%s\n", envp); -+ } -+ heap_slots_increment = i; -+ initial_heap_slots_increment = heap_slots_increment; -+ } -+ -+ envp = getenv("RUBY_HEAP_SLOTS_GROWTH_FACTOR"); -+ if (envp != NULL) { -+ double d = atof(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_GROWTH_FACTOR=%s\n", envp); -+ } -+ if (d > 0) { -+ heap_slots_growth_factor = d; -+ } -+ } -+ -+ fflush(gc_data_file); - } - - #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE -@@ -776,6 +887,11 @@ vm_malloc_fixup(rb_objspace_t *objspace, void *mem, size_t size) - mem = (size_t *)mem + 1; - #endif - -+ if (gc_statistics) { -+ gc_allocated_size += size; -+ gc_num_allocations += 1; -+ } -+ - return mem; - } - -@@ -836,6 +952,13 @@ vm_xrealloc(rb_objspace_t *objspace, void *ptr, size_t size) - mem = (size_t *)mem + 1; - #endif - -+ /* TODO: we can't count correctly unless we store old size on heap -+ if (gc_statistics) { -+ gc_allocated_size += size; -+ gc_num_allocations += 1; -+ } -+ */ -+ - return mem; - } - -@@ -917,7 +1040,6 @@ ruby_xfree(void *x) - vm_xfree(&rb_objspace, x); - } - -- - /* - * call-seq: - * GC.enable -> true or false -@@ -963,6 +1085,455 @@ rb_gc_disable(void) - return old ? Qtrue : Qfalse; - } - -+/* -+ * call-seq: -+ * GC.enable_stats => true or false -+ * -+ * Enables garbage collection statistics, returning true if garbage -+ * collection statistics was already enabled. -+ * -+ * GC.enable_stats #=> false or true -+ * GC.enable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = gc_statistics; -+ gc_statistics = 1; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_stats => true or false -+ * -+ * Disables garbage collection statistics, returning true if garbage -+ * collection statistics was already disabled. -+ * -+ * GC.disable_stats #=> false or true -+ * GC.disable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = gc_statistics; -+ gc_statistics = 0; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.stats_enabled? => true or false -+ * -+ * Check whether GC stats have been enabled. -+ * -+ * GC.stats_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_stats_enabled() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return gc_statistics ? Qtrue : Qfalse; -+} -+ -+ -+/* -+ * call-seq: -+ * GC.clear_stats => nil -+ * -+ * Clears garbage collection statistics, returning nil. This resets the number -+ * of collections (GC.collections) and the time used (GC.time) to 0. -+ * -+ * GC.clear_stats #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_clear_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ gc_collections = 0; -+ gc_time_accumulator = 0; -+ gc_time_accumulator_before_gc = 0; -+ gc_allocated_size = 0; -+ gc_num_allocations = 0; -+ return Qnil; -+} -+ -+/* -+ * call-seq: -+ * GC.allocated_size => Integer -+ * -+ * Returns the size of memory (in bytes) allocated since GC statistics collection -+ * was enabled. -+ * -+ * GC.allocated_size #=> 35 -+ * -+ */ -+ -+VALUE -+rb_gc_allocated_size() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_allocated_size); -+#else -+ return ULONG2NUM(gc_allocated_size); -+#endif -+} -+ -+/* -+ * call-seq: -+ * GC.num_allocations => Integer -+ * -+ * Returns the number of memory allocations since GC statistics collection -+ * was enabled. -+ * -+ * GC.num_allocations #=> 150 -+ * -+ */ -+VALUE -+rb_gc_num_allocations() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_num_allocations); -+#else -+ return ULONG2NUM(gc_num_allocations); -+#endif -+} -+ -+/* -+ * call-seq: -+ * GC.enable_trace => true or false -+ * -+ * Enables garbage collection tracing, returning true if garbage -+ * collection tracing was already enabled. -+ * -+ * GC.enable_trace #=> false or true -+ * GC.enable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_trace() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = verbose_gc_stats; -+ verbose_gc_stats = 1; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_trace => true or false -+ * -+ * Disables garbage collection tracing, returning true if garbage -+ * collection tracing was already disabled. -+ * -+ * GC.disable_trace #=> false or true -+ * GC.disable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_trace() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = verbose_gc_stats; -+ verbose_gc_stats = 0; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.trace_enabled? => true or false -+ * -+ * Check whether GC tracing has been enabled. -+ * -+ * GC.trace_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_trace_enabled() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return verbose_gc_stats ? Qtrue : Qfalse; -+} -+ -+ -+const char* GC_LOGFILE_IVAR = "@gc_logfile_name"; -+ -+/* -+ * call-seq: -+ * GC.log_file(filename=nil, mode="w") => boolean -+ * -+ * Changes the GC data log file. Closes the currently open logfile. -+ * Returns true if the file was successfully opened for -+ * writing. Returns false if the file could not be opened for -+ * writing. Returns the name of the current logfile (or nil) if no -+ * parameter is given. Restores logging to stderr when given nil as -+ * an argument. -+ * -+ * GC.log_file #=> nil -+ * GC.log_file "/tmp/gc.log" #=> true -+ * GC.log_file #=> "/tmp/gc.log" -+ * GC.log_file nil #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_log_file(int argc, VALUE *argv, VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ VALUE filename = Qnil; -+ VALUE mode_str = Qnil; -+ FILE* f = NULL; -+ const char* mode = "w"; -+ -+ VALUE current_logfile_name = rb_iv_get(rb_mGC, GC_LOGFILE_IVAR); -+ -+ if (argc==0) -+ return current_logfile_name; -+ -+ rb_scan_args(argc, argv, "02", &filename, &mode_str); -+ -+ if (filename == Qnil) { -+ /* close current logfile and reset logfile to stderr */ -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+ } -+ return Qtrue; -+ } -+ -+ /* we have a real logfile name */ -+ filename = StringValue(filename); -+ -+ if (rb_equal(current_logfile_name, filename) == Qtrue) { -+ /* do nothing if we get the file name we're already logging to */ -+ return Qtrue; -+ } -+ -+ /* get mode for file opening */ -+ if (mode_str != Qnil) -+ { -+ mode = RSTRING_PTR(StringValue(mode_str)); -+ } -+ -+ /* try to open file in given mode */ -+ if (f = fopen(RSTRING_PTR(filename), mode)) { -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ } -+ gc_data_file = f; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, filename); -+ } else { -+ return Qfalse; -+ } -+ return Qtrue; -+} -+ -+/* -+ * call-seq: -+ * GC.log String => String -+ * -+ * Logs string to the GC data file and returns it. -+ * -+ * GC.log "manual GC call" #=> "manual GC call" -+ * -+ */ -+ -+VALUE -+rb_gc_log(self, original_str) -+ VALUE self, original_str; -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ if (original_str == Qnil) { -+ fprintf(gc_data_file, "\n"); -+ } -+ else { -+ VALUE str = StringValue(original_str); -+ char *p = RSTRING_PTR(str); -+ fprintf(gc_data_file, "%s\n", p); -+ } -+ return original_str; -+} -+ -+/* -+ * call-seq: -+ * GC.dump => nil -+ * -+ * dumps information about the current GC data structures to the GC log file -+ * -+ * GC.dump #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_dump() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ size_t i; -+ -+ for (i = 0; i < heaps_used; i++) { -+ size_t limit = objspace->heap.sorted[i].slot->limit; -+ fprintf(gc_data_file, "HEAP[%2lu]: size=%7lu\n", (unsigned long)i, (unsigned long)limit); -+ } -+ -+ return Qnil; -+} -+ -+static const char* obj_type(VALUE tp); -+ -+#ifdef GC_DEBUG -+/* -+ * call-seq: -+ * GC.dump_file_and_line_info(String, boolean) => nil -+ * -+ * dumps information on which currently allocated object was created by which file and on which line -+ * -+ * GC.dump_file_and_line_info(String, boolean) #=> nil -+ * -+ * The second parameter specifies whether class names should be included in the dump. -+ * Note that including class names will allocate additional string objects on the heap. -+ * -+ */ -+ -+VALUE -+rb_gc_dump_file_and_line_info(int argc, VALUE *argv) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ VALUE filename, str, include_classnames = Qnil; -+ char *fname = NULL; -+ char *klass = NULL; -+ FILE* f = NULL; -+ size_t i = 0; -+ -+ rb_scan_args(argc, argv, "11", &filename, &include_classnames); -+ -+ str = StringValue(filename); -+ fname = RSTRING_PTR(str); -+ f = fopen(fname, "w"); -+ -+ for (i = 0; i < heaps_used; i++) { -+ RVALUE *p, *pend; -+ -+ p = objspace->heap.sorted[i].start; pend = objspace->heap.sorted[i].end; -+ for (;p < pend; p++) { -+ if (p->as.basic.flags) { -+ const char *src_filename = (p->file && p->file != Qnil )? RSTRING_PTR(p->file) : ""; -+ fprintf(f, "%s:%s:%d", obj_type(p->as.basic.flags & T_MASK), src_filename, (int)p->line); -+ // rb_obj_classname will create objects on the heap, we need a better solution -+ if (include_classnames == Qtrue) { -+ /* write the class */ -+ fprintf(f, ":"); -+ switch (BUILTIN_TYPE(p)) { -+ case T_NONE: -+ fprintf(f, "__none__"); -+ break; -+ case T_UNDEF: -+ fprintf(f, "__undef__"); -+ break; -+ case T_NODE: -+ fprintf(f, "__node__"); -+ break; -+ default: -+ if (!p->as.basic.klass) { -+ fprintf(f, "__unknown__"); -+ } else { -+ fprintf(f, "%s", rb_obj_classname((VALUE)p)); -+ } -+ } -+ /* print object size for some known object types */ -+ switch (BUILTIN_TYPE(p)) { -+ case T_STRING: -+ fprintf(f, ":%lu", RSTRING_LEN(p)); -+ break; -+ case T_ARRAY: -+ fprintf(f, ":%lu", RARRAY_LEN(p)); -+ break; -+ case T_HASH: -+ fprintf(f, ":%lu", (long unsigned int)RHASH_SIZE(p)); -+ break; -+ } -+ } -+ fprintf(f, "\n"); -+ } -+ } -+ } -+ fclose(f); -+ return Qnil; -+} -+#endif -+ -+/* -+ * call-seq: -+ * GC.heap_slots => Integer -+ * -+ * Returns the number of heap slots available for object allocations. -+ * -+ * GC.heap_slots #=> 10000 -+ * -+ */ -+VALUE -+rb_gc_heap_slots() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return LONG2NUM(heap_size); -+} -+ -+ -+/* -+ * call-seq: -+ * GC.collections => Integer -+ * -+ * Returns the number of garbage collections performed while GC statistics collection -+ * was enabled. -+ * -+ * GC.collections #=> 35 -+ * -+ */ -+ -+VALUE -+rb_gc_collections() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return LONG2NUM(gc_collections); -+} -+ -+/* -+ * call-seq: -+ * GC.time => Integer -+ * -+ * Returns the time spent during garbage collection while GC statistics collection -+ * was enabled (in micro seconds). -+ * -+ * GC.time #=> 20000 -+ * -+ */ -+ -+VALUE -+rb_gc_time() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return LL2NUM(gc_time_accumulator); -+#else -+ return LONG2NUM(gc_time_accumulator); -+#endif -+} -+ - VALUE rb_mGC; - - void -@@ -1034,6 +1605,12 @@ allocate_sorted_heaps(rb_objspace_t *objspace, size_t next_heaps_length) - static void - assign_heap_slot(rb_objspace_t *objspace) - { -+ /* -+ if (gc_statistics & verbose_gc_stats) { -+ fprintf(gc_data_file, "assigning heap slot\n"); -+ } -+ */ -+ - RVALUE *p, *pend, *membase; - struct heaps_slot *slot; - size_t hi, lo, mid; -@@ -1095,6 +1672,7 @@ assign_heap_slot(rb_objspace_t *objspace) - if (lomem == 0 || lomem > p) lomem = p; - if (himem < pend) himem = pend; - heaps_used++; -+ heap_size += objs; - - while (p < pend) { - p->as.free.flags = 0; -@@ -1151,7 +1729,7 @@ initial_expand_heap(rb_objspace_t *objspace) - static void - set_heaps_increment(rb_objspace_t *objspace) - { -- size_t next_heaps_length = (size_t)(heaps_used * 1.8); -+ size_t next_heaps_length = (size_t)(heaps_used * heap_slots_growth_factor); - - if (next_heaps_length == heaps_used) { - next_heaps_length++; -@@ -1184,6 +1762,22 @@ rb_during_gc(void) - - #define RANY(o) ((RVALUE*)(o)) - -+#ifdef GC_DEBUG -+static VALUE -+_rb_sourcefile(void) -+{ -+ rb_thread_t *th = GET_THREAD(); -+ rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp); -+ -+ if (cfp) { -+ return cfp->iseq->filename; -+ } -+ else { -+ return Qnil; -+ } -+} -+#endif -+ - VALUE - rb_newobj(void) - { -@@ -1215,9 +1809,11 @@ rb_newobj(void) - - MEMZERO((void*)obj, RVALUE, 1); - #ifdef GC_DEBUG -- RANY(obj)->file = rb_sourcefile(); -+ RANY(obj)->file = _rb_sourcefile(); - RANY(obj)->line = rb_sourceline(); - #endif -+ live_objects++; -+ allocated_objects++; - GC_PROF_INC_LIVE_NUM; - - return obj; -@@ -1769,6 +2365,12 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr) - { - register RVALUE *obj = RANY(ptr); - -+#ifdef GC_DEBUG -+ if (obj->file && obj->file != Qnil && is_pointer_to_heap(objspace, (void*)obj->file)) { -+ gc_mark(objspace, obj->file, lev); -+ } -+#endif -+ - goto marking; /* skip */ - - again: -@@ -1779,6 +2381,12 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr) - obj->as.basic.flags |= FL_MARK; - objspace->heap.live_num++; - -+#ifdef GC_DEBUG -+ if (obj->file && obj->file != Qnil && is_pointer_to_heap(objspace, (void*)obj->file)) { -+ gc_mark(objspace, obj->file, lev); -+ } -+#endif -+ - marking: - if (FL_TEST(obj, FL_EXIVAR)) { - rb_mark_generic_ivar(ptr); -@@ -2121,6 +2729,25 @@ free_unused_heaps(rb_objspace_t *objspace) - } - } - -+static inline unsigned long -+elapsed_musecs(struct timeval since) -+{ -+ struct timeval now; -+ struct timeval temp; -+ -+ gettimeofday(&now, NULL); -+ -+ if ((now.tv_usec-since.tv_usec)<0) { -+ temp.tv_sec = now.tv_sec-since.tv_sec-1; -+ temp.tv_usec = 1000000+now.tv_usec-since.tv_usec; -+ } else { -+ temp.tv_sec = now.tv_sec-since.tv_sec; -+ temp.tv_usec = now.tv_usec-since.tv_usec; -+ } -+ -+ return temp.tv_sec*1000000 + temp.tv_usec; -+} -+ - static void - slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - { -@@ -2128,14 +2755,23 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - RVALUE *p, *pend; - RVALUE *free = freelist, *final = deferred_final_list; - int deferred; -+ int do_gc_stats = gc_statistics & verbose_gc_stats; -+ -+ struct timeval tv1; -+ if (gc_statistics) gettimeofday(&tv1, NULL); - - p = sweep_slot->slot; pend = p + sweep_slot->limit; - while (p < pend) { - if (!(p->as.basic.flags & FL_MARK)) { -+ if (do_gc_stats && !p->as.basic.flags) { -+ /* slot was free before GC */ -+ freelist_size++; -+ } - if (p->as.basic.flags && - ((deferred = obj_free(objspace, (VALUE)p)) || - (FL_TEST(p, FL_FINALIZE)))) { - if (!deferred) { -+ if (do_gc_stats) zombies++; - p->as.free.flags = T_ZOMBIE; - RDATA(p)->dfree = 0; - } -@@ -2145,6 +2781,10 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - final_num++; - } - else { -+ if (do_gc_stats) { -+ VALUE obt = p->as.basic.flags & T_MASK; -+ if (obt) free_counts[obt]++; -+ } - add_freelist(objspace, p); - free_num++; - } -@@ -2152,13 +2792,22 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - else if (BUILTIN_TYPE(p) == T_ZOMBIE) { - /* objects to be finalized */ - /* do nothing remain marked */ -+ if (do_gc_stats) zombies++; - } - else { - RBASIC(p)->flags &= ~FL_MARK; -+ if (do_gc_stats) { -+ live_counts[p->as.basic.flags & T_MASK]++; -+ } - } - p++; -+ processed++; - } -- if (final_num + free_num == sweep_slot->limit && -+ -+ freed_objects += free_num; -+ -+ if (objspace->heap.freed_blocks < objspace->heap.max_blocks_to_free && -+ final_num + free_num == sweep_slot->limit && - objspace->heap.free_num > objspace->heap.do_heap_free) { - RVALUE *pp; - -@@ -2169,6 +2818,8 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - sweep_slot->limit = final_num; - freelist = free; /* cancel this page from freelist */ - unlink_heap_slot(objspace, sweep_slot); -+ objspace->heap.freed_blocks += 1; -+ heap_size -= final_num + free_num; - } - else { - objspace->heap.free_num += free_num; -@@ -2181,6 +2832,10 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - RUBY_VM_SET_FINALIZER_INTERRUPT(th); - } - } -+ -+ if (gc_statistics) { -+ gc_time_accumulator += elapsed_musecs(tv1); -+ } - } - - static int -@@ -2201,6 +2856,21 @@ ready_to_gc(rb_objspace_t *objspace) - static void - before_gc_sweep(rb_objspace_t *objspace) - { -+ if (gc_statistics & verbose_gc_stats) { -+ /* -+ fprintf(gc_data_file, "Sweep started\n"); -+ */ -+ freed_objects = 0; -+ processed = 0; -+ zombies = 0; -+ freelist_size = 0; -+ MEMZERO((void*)free_counts, unsigned long, T_MASK+1); -+ MEMZERO((void*)live_counts, unsigned long, T_MASK+1); -+ } -+ -+ objspace->heap.max_blocks_to_free = heaps_used - (heap_min_slots / HEAP_OBJ_LIMIT); -+ objspace->heap.freed_blocks = 0; -+ - freelist = 0; - objspace->heap.do_heap_free = (size_t)((heaps_used * HEAP_OBJ_LIMIT) * 0.65); - objspace->heap.free_min = (size_t)((heaps_used * HEAP_OBJ_LIMIT) * 0.2); -@@ -2220,8 +2890,13 @@ before_gc_sweep(rb_objspace_t *objspace) - static void - after_gc_sweep(rb_objspace_t *objspace) - { -+ int i; -+ struct timeval tv1; -+ - GC_PROF_SET_MALLOC_INFO; - -+ if (gc_statistics) gettimeofday(&tv1, NULL); -+ - if (objspace->heap.free_num < objspace->heap.free_min) { - set_heaps_increment(objspace); - heaps_increment(objspace); -@@ -2234,6 +2909,29 @@ after_gc_sweep(rb_objspace_t *objspace) - malloc_increase = 0; - - free_unused_heaps(objspace); -+ -+ if (gc_statistics) { -+ gc_time_accumulator += elapsed_musecs(tv1); -+ -+ if (verbose_gc_stats) { -+ /* log gc stats if requested */ -+ fprintf(gc_data_file, "GC time: %lu musec\n", (unsigned long)(gc_time_accumulator-gc_time_accumulator_before_gc)); -+ fprintf(gc_data_file, "objects processed: %7lu\n", (unsigned long)processed); -+ fprintf(gc_data_file, "live objects : %7lu\n", (unsigned long)live_after_last_mark_phase); -+ fprintf(gc_data_file, "freelist objects : %7lu\n", (unsigned long)freelist_size); -+ fprintf(gc_data_file, "freed objects : %7lu\n", (unsigned long)freed_objects); -+ fprintf(gc_data_file, "zombies : %7lu\n", (unsigned long)zombies); -+ for(i=0; i0 || live_counts[i]>0) { -+ fprintf(gc_data_file, -+ "kept %7lu / freed %7lu objects of type %s\n", -+ (unsigned long)live_counts[i], (unsigned long)free_counts[i], obj_type((int)i)); -+ } -+ } -+ rb_gc_dump(); -+ fflush(gc_data_file); -+ } -+ } - } - - static int -@@ -2267,9 +2965,11 @@ rest_sweep(rb_objspace_t *objspace) - - static void gc_marks(rb_objspace_t *objspace); - -+/* only called from rb_new_obj */ - static int - gc_lazy_sweep(rb_objspace_t *objspace) - { -+ struct timeval gctv1; - int res; - INIT_GC_PROF_PARAMS; - -@@ -2291,7 +2991,6 @@ gc_lazy_sweep(rb_objspace_t *objspace) - GC_PROF_TIMER_STOP(Qfalse); - return res; - } -- after_gc_sweep(objspace); - } - else { - if (heaps_increment(objspace)) { -@@ -2299,6 +2998,18 @@ gc_lazy_sweep(rb_objspace_t *objspace) - return TRUE; - } - } -+ after_gc_sweep(objspace); -+ -+ if (gc_statistics) { -+ gc_time_accumulator_before_gc = gc_time_accumulator; -+ gc_collections++; -+ gettimeofday(&gctv1, NULL); -+ /* -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "Garbage collection started (gc_lazy_sweep)\n"); -+ } -+ */ -+ } - - gc_marks(objspace); - -@@ -2307,6 +3018,10 @@ gc_lazy_sweep(rb_objspace_t *objspace) - set_heaps_increment(objspace); - } - -+ if (gc_statistics) { -+ gc_time_accumulator += elapsed_musecs(gctv1); -+ } -+ - GC_PROF_SWEEP_TIMER_START; - if(!(res = lazy_sweep(objspace))) { - after_gc_sweep(objspace); -@@ -2318,6 +3033,7 @@ gc_lazy_sweep(rb_objspace_t *objspace) - GC_PROF_SWEEP_TIMER_STOP; - - GC_PROF_TIMER_STOP(Qtrue); -+ - return res; - } - -@@ -2544,9 +3260,15 @@ gc_marks(rb_objspace_t *objspace) - rb_thread_t *th = GET_THREAD(); - GC_PROF_MARK_TIMER_START; - -+ /* -+ if (gc_statistics & verbose_gc_stats) { -+ fprintf(gc_data_file, "Marking objects\n"); -+ } -+ */ -+ - objspace->heap.live_num = 0; - objspace->count++; -- -+ live_objects = 0; - - SET_STACK_END; - -@@ -2578,11 +3300,15 @@ gc_marks(rb_objspace_t *objspace) - gc_mark_stacked_objects(objspace); - - GC_PROF_MARK_TIMER_STOP; -+ -+ live_after_last_mark_phase = objspace->heap.live_num; - } - - static int - garbage_collect(rb_objspace_t *objspace) - { -+ struct timeval gctv1; -+ - INIT_GC_PROF_PARAMS; - - if (GC_NOTIFY) printf("start garbage_collect()\n"); -@@ -2598,15 +3324,31 @@ garbage_collect(rb_objspace_t *objspace) - - rest_sweep(objspace); - -+ if (gc_statistics) { -+ gc_time_accumulator_before_gc = gc_time_accumulator; -+ gc_collections++; -+ gettimeofday(&gctv1, NULL); -+ /* -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "Garbage collection started (garbage_collect)\n"); -+ } -+ */ -+ } -+ - during_gc++; - gc_marks(objspace); - -+ if (gc_statistics) { -+ gc_time_accumulator += elapsed_musecs(gctv1); -+ } -+ - GC_PROF_SWEEP_TIMER_START; - gc_sweep(objspace); - GC_PROF_SWEEP_TIMER_STOP; - - GC_PROF_TIMER_STOP(Qtrue); - if (GC_NOTIFY) printf("end garbage_collect()\n"); -+ - return TRUE; - } - -@@ -3095,6 +3837,39 @@ rb_gc_call_finalizer_at_exit(void) - rb_objspace_call_finalizer(&rb_objspace); - } - -+static const char* obj_type(VALUE type) -+{ -+ switch (type) { -+ case T_NIL : return "NIL"; -+ case T_OBJECT : return "OBJECT"; -+ case T_CLASS : return "CLASS"; -+ case T_ICLASS : return "ICLASS"; -+ case T_MODULE : return "MODULE"; -+ case T_FLOAT : return "FLOAT"; -+ case T_COMPLEX: return "COMPLEX"; -+ case T_RATIONAL: return "RATIONAL"; -+ case T_STRING : return "STRING"; -+ case T_REGEXP : return "REGEXP"; -+ case T_ARRAY : return "ARRAY"; -+ case T_FIXNUM : return "FIXNUM"; -+ case T_HASH : return "HASH"; -+ case T_STRUCT : return "STRUCT"; -+ case T_BIGNUM : return "BIGNUM"; -+ case T_FILE : return "FILE"; -+ -+ case T_TRUE : return "TRUE"; -+ case T_FALSE : return "FALSE"; -+ case T_DATA : return "DATA"; -+ case T_MATCH : return "MATCH"; -+ case T_SYMBOL : return "SYMBOL"; -+ case T_ZOMBIE : return "ZOMBIE"; -+ -+ case T_UNDEF : return "UNDEF"; -+ case T_NODE : return "NODE"; -+ default: return "____"; -+ } -+} -+ - static void - rb_objspace_call_finalizer(rb_objspace_t *objspace) - { -@@ -3403,6 +4178,49 @@ count_objects(int argc, VALUE *argv, VALUE os) - return hash; - } - -+/* call-seq: -+ * ObjectSpace.live_objects => number -+ * -+ * Returns the count of objects currently allocated in the system. This goes -+ * down after the garbage collector runs. -+ */ -+static -+VALUE os_live_objects(VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return ULONG2NUM(live_objects); -+} -+ -+unsigned long rb_os_live_objects() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return live_objects; -+} -+ -+/* call-seq: -+ * ObjectSpace.allocated_objects => number -+ * -+ * Returns the count of objects allocated since the Ruby interpreter has -+ * started. This number can only increase. To know how many objects are -+ * currently allocated, use ObjectSpace::live_objects -+ */ -+static -+VALUE os_allocated_objects(VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if defined(HAVE_LONG_LONG) -+ return ULL2NUM(allocated_objects); -+#else -+ return ULONG2NUM(allocated_objects); -+#endif -+} -+ -+unsigned LONG_LONG rb_os_allocated_objects() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return allocated_objects; -+} -+ - /* - * call-seq: - * GC.count -> Integer -@@ -3695,6 +4513,28 @@ Init_GC(void) - rb_define_singleton_method(rb_mGC, "stat", gc_stat, -1); - rb_define_method(rb_mGC, "garbage_collect", rb_gc_start, 0); - -+ rb_define_singleton_method(rb_mGC, "enable_stats", rb_gc_enable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "disable_stats", rb_gc_disable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "stats_enabled?", rb_gc_stats_enabled, 0); -+ rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0); -+ rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); -+ rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); -+ -+ rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); -+ rb_define_singleton_method(rb_mGC, "log_file", rb_gc_log_file, -1); -+ rb_define_singleton_method(rb_mGC, "enable_trace", rb_gc_enable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "disable_trace", rb_gc_disable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "trace_enabled?", rb_gc_trace_enabled, 0); -+ -+ rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); -+ rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); -+ rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); -+#ifdef GC_DEBUG -+ rb_define_singleton_method(rb_mGC, "dump_file_and_line_info", rb_gc_dump_file_and_line_info, -1); -+#endif -+ - 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); -@@ -3708,6 +4548,9 @@ Init_GC(void) - rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1); - rb_define_module_function(rb_mObSpace, "garbage_collect", rb_gc_start, 0); - -+ rb_define_module_function(rb_mObSpace, "live_objects", os_live_objects, 0); -+ rb_define_module_function(rb_mObSpace, "allocated_objects", os_allocated_objects, 0); -+ - rb_define_module_function(rb_mObSpace, "define_finalizer", define_final, -1); - rb_define_module_function(rb_mObSpace, "undefine_finalizer", undefine_final, 1); - diff --git a/patches/ruby/1.9.3/p385/railsexpress/03-display-more-detailed-stack-trace.patch b/patches/ruby/1.9.3/p385/railsexpress/03-display-more-detailed-stack-trace.patch deleted file mode 100644 index 5c7ad30352..0000000000 --- a/patches/ruby/1.9.3/p385/railsexpress/03-display-more-detailed-stack-trace.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/eval_error.c b/eval_error.c -index fd06adf..69c3b48 100644 ---- a/eval_error.c -+++ b/eval_error.c -@@ -164,8 +164,8 @@ error_print(void) - int skip = eclass == rb_eSysStackError; - - #define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5) --#define TRACE_HEAD 8 --#define TRACE_TAIL 5 -+#define TRACE_HEAD 100 -+#define TRACE_TAIL 100 - - for (i = 1; i < len; i++) { - if (TYPE(ptr[i]) == T_STRING) { diff --git a/patches/ruby/1.9.3/p385/railsexpress/04-fork-support-for-gc-logging.patch b/patches/ruby/1.9.3/p385/railsexpress/04-fork-support-for-gc-logging.patch deleted file mode 100644 index bb263566cc..0000000000 --- a/patches/ruby/1.9.3/p385/railsexpress/04-fork-support-for-gc-logging.patch +++ /dev/null @@ -1,68 +0,0 @@ -diff --git a/gc.c b/gc.c -index 0be1ec9..c198770 100644 ---- a/gc.c -+++ b/gc.c -@@ -1345,6 +1345,34 @@ rb_gc_log_file(int argc, VALUE *argv, VALUE self) - } - - /* -+ * Called from process.c before a fork. Flushes the gc log file to -+ * avoid writing the buffered output twice (once in the parent, and -+ * once in the child). -+ */ -+void -+rb_gc_before_fork() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ fflush(gc_data_file); -+} -+ -+/* -+ * Called from process.c after a fork in the child process. Turns off -+ * logging, disables GC stats and resets all gc counters and timing -+ * information. -+ */ -+void -+rb_gc_after_fork() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ rb_gc_disable_stats(); -+ rb_gc_clear_stats(); -+ rb_gc_disable_trace(); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+} -+ -+/* - * call-seq: - * GC.log String => String - * -diff --git a/include/ruby/intern.h b/include/ruby/intern.h -index 9745afd..7c3d970 100644 ---- a/include/ruby/intern.h -+++ b/include/ruby/intern.h -@@ -426,6 +426,8 @@ void rb_gc_call_finalizer_at_exit(void); - VALUE rb_gc_enable(void); - VALUE rb_gc_disable(void); - VALUE rb_gc_start(void); -+void rb_gc_before_fork _((void)); -+void rb_gc_after_fork _((void)); - #define Init_stack(addr) ruby_init_stack(addr) - void rb_gc_set_params(void); - /* hash.c */ -diff --git a/process.c b/process.c -index 99cfc69..8bee602 100644 ---- a/process.c -+++ b/process.c -@@ -2804,9 +2804,11 @@ rb_f_fork(VALUE obj) - rb_pid_t pid; - - rb_secure(2); -+ rb_gc_before_fork(); - - switch (pid = rb_fork(0, 0, 0, Qnil)) { - case 0: -+ rb_gc_after_fork(); - rb_thread_atfork(); - if (rb_block_given_p()) { - int status; diff --git a/patches/ruby/1.9.3/p385/railsexpress/05-track-live-dataset-size.patch b/patches/ruby/1.9.3/p385/railsexpress/05-track-live-dataset-size.patch deleted file mode 100644 index e1775107b6..0000000000 --- a/patches/ruby/1.9.3/p385/railsexpress/05-track-live-dataset-size.patch +++ /dev/null @@ -1,45 +0,0 @@ -diff --git a/gc.c b/gc.c -index c198770..68dd48a 100644 ---- a/gc.c -+++ b/gc.c -@@ -281,7 +281,6 @@ getrusage_time(void) - #define GC_PROF_DEC_LIVE_NUM - #endif - -- - #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__) - #pragma pack(push, 1) /* magic for reducing sizeof(RVALUE): 24 -> 20 */ - #endif -@@ -1562,6 +1561,24 @@ rb_gc_time() - #endif - } - -+/* -+ * call-seq: -+ * GC.heap_slots_live_after_last_gc => Integer -+ * -+ * Returns the number of heap slots which were live after the last garbage collection. -+ * -+ * GC.heap_slots_live_after_last_gc #=> 231223 -+ * -+ */ -+VALUE -+rb_gc_heap_slots_live_after_last_gc() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return ULONG2NUM(live_after_last_mark_phase); -+} -+ -+ -+ - VALUE rb_mGC; - - void -@@ -4548,6 +4565,7 @@ Init_GC(void) - rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); - rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); - rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots_live_after_last_gc", rb_gc_heap_slots_live_after_last_gc, 0); - rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); - - rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); diff --git a/patches/ruby/1.9.3/p385/railsexpress/06-webrick_204_304_keep_alive_fix.patch b/patches/ruby/1.9.3/p385/railsexpress/06-webrick_204_304_keep_alive_fix.patch deleted file mode 100644 index 34d9b78133..0000000000 --- a/patches/ruby/1.9.3/p385/railsexpress/06-webrick_204_304_keep_alive_fix.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/lib/webrick/httpresponse.rb b/lib/webrick/httpresponse.rb -index 0d36c07..ce72b3f 100644 ---- a/lib/webrick/httpresponse.rb -+++ b/lib/webrick/httpresponse.rb -@@ -202,7 +202,7 @@ module WEBrick - if @header['connection'] == "close" - @keep_alive = false - elsif keep_alive? -- if chunked? || @header['content-length'] -+ if chunked? || @header['content-length'] || @status == 304 || @status == 204 - @header['connection'] = "Keep-Alive" - else - msg = "Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true" diff --git a/patches/ruby/1.9.3/p385/railsexpress/07-export-a-few-more-symbols-for-ruby-prof.patch b/patches/ruby/1.9.3/p385/railsexpress/07-export-a-few-more-symbols-for-ruby-prof.patch deleted file mode 100644 index 3ce29ada20..0000000000 --- a/patches/ruby/1.9.3/p385/railsexpress/07-export-a-few-more-symbols-for-ruby-prof.patch +++ /dev/null @@ -1,140 +0,0 @@ -diff --git a/gc.c b/gc.c -index 68dd48a..463a2d9 100644 ---- a/gc.c -+++ b/gc.c -@@ -1052,6 +1052,7 @@ ruby_xfree(void *x) - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_enable(void) - { -@@ -1074,6 +1075,7 @@ rb_gc_enable(void) - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_disable(void) - { -@@ -1096,6 +1098,7 @@ rb_gc_disable(void) - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_enable_stats() - { -@@ -1117,6 +1120,7 @@ rb_gc_enable_stats() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_disable_stats() - { -@@ -1136,6 +1140,7 @@ rb_gc_disable_stats() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_stats_enabled() - { -@@ -1155,6 +1160,7 @@ rb_gc_stats_enabled() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_clear_stats() - { -@@ -1178,6 +1184,7 @@ rb_gc_clear_stats() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_allocated_size() - { -@@ -1222,6 +1229,7 @@ rb_gc_num_allocations() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_enable_trace() - { -@@ -1243,6 +1251,7 @@ rb_gc_enable_trace() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_disable_trace() - { -@@ -1262,6 +1271,7 @@ rb_gc_disable_trace() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_trace_enabled() - { -@@ -1290,6 +1300,7 @@ const char* GC_LOGFILE_IVAR = "@gc_logfile_name"; - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_log_file(int argc, VALUE *argv, VALUE self) - { -@@ -1381,6 +1392,7 @@ rb_gc_after_fork() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_log(self, original_str) - VALUE self, original_str; -@@ -1407,6 +1419,7 @@ rb_gc_log(self, original_str) - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_dump() - { -@@ -1437,6 +1450,7 @@ static const char* obj_type(VALUE tp); - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_dump_file_and_line_info(int argc, VALUE *argv) - { -@@ -1532,6 +1546,7 @@ rb_gc_heap_slots() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_collections() - { -@@ -1550,6 +1565,7 @@ rb_gc_collections() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_time() - { -@@ -4260,6 +4276,7 @@ VALUE os_allocated_objects(VALUE self) - #endif - } - -+RUBY_FUNC_EXPORTED - unsigned LONG_LONG rb_os_allocated_objects() - { - rb_objspace_t *objspace = &rb_objspace; diff --git a/patches/ruby/1.9.3/p385/railsexpress/08-thread-variables.patch b/patches/ruby/1.9.3/p385/railsexpress/08-thread-variables.patch deleted file mode 100644 index 303fb18d86..0000000000 --- a/patches/ruby/1.9.3/p385/railsexpress/08-thread-variables.patch +++ /dev/null @@ -1,319 +0,0 @@ -diff --git a/NEWS b/NEWS -index 30fec33..9f6c172 100644 ---- a/NEWS -+++ b/NEWS -@@ -103,6 +103,16 @@ with all sufficient information, see the ChangeLog file. - * String#prepend - * String#byteslice - -+ * Thread -+ * added method: -+ * added Thread#thread_variable_get for getting thread local variables -+ (these are different than Fiber local variables). -+ * added Thread#thread_variable_set for setting thread local variables. -+ * added Thread#thread_variables for getting a list of the thread local -+ variable keys. -+ * added Thread#thread_variable? for testing to see if a particular thread -+ variable has been set. -+ - * Time - * extended method: - * Time#strftime supports %:z and %::z. -diff --git a/test/ruby/test_thread.rb b/test/ruby/test_thread.rb -index e8cb3b1..9ff491d 100644 ---- a/test/ruby/test_thread.rb -+++ b/test/ruby/test_thread.rb -@@ -27,6 +27,79 @@ class TestThread < Test::Unit::TestCase - end - end - -+ def test_main_thread_variable_in_enumerator -+ assert_equal Thread.main, Thread.current -+ -+ Thread.current.thread_variable_set :foo, "bar" -+ -+ thread, value = Fiber.new { -+ Fiber.yield [Thread.current, Thread.current.thread_variable_get(:foo)] -+ }.resume -+ -+ assert_equal Thread.current, thread -+ assert_equal Thread.current.thread_variable_get(:foo), value -+ end -+ -+ def test_thread_variable_in_enumerator -+ Thread.new { -+ Thread.current.thread_variable_set :foo, "bar" -+ -+ thread, value = Fiber.new { -+ Fiber.yield [Thread.current, Thread.current.thread_variable_get(:foo)] -+ }.resume -+ -+ assert_equal Thread.current, thread -+ assert_equal Thread.current.thread_variable_get(:foo), value -+ }.join -+ end -+ -+ def test_thread_variables -+ assert_equal [], Thread.new { Thread.current.thread_variables }.join.value -+ -+ t = Thread.new { -+ Thread.current.thread_variable_set(:foo, "bar") -+ Thread.current.thread_variables -+ } -+ assert_equal [:foo], t.join.value -+ end -+ -+ def test_thread_variable? -+ refute Thread.new { Thread.current.thread_variable?("foo") }.join.value -+ t = Thread.new { -+ Thread.current.thread_variable_set("foo", "bar") -+ }.join -+ -+ assert t.thread_variable?("foo") -+ assert t.thread_variable?(:foo) -+ refute t.thread_variable?(:bar) -+ end -+ -+ def test_thread_variable_strings_and_symbols_are_the_same_key -+ t = Thread.new {}.join -+ t.thread_variable_set("foo", "bar") -+ assert_equal "bar", t.thread_variable_get(:foo) -+ end -+ -+ def test_thread_variable_frozen -+ t = Thread.new { }.join -+ t.freeze -+ assert_raises(RuntimeError) do -+ t.thread_variable_set(:foo, "bar") -+ end -+ end -+ -+ def test_thread_variable_security -+ t = Thread.new { sleep } -+ -+ assert_raises(SecurityError) do -+ Thread.new { $SAFE = 4; t.thread_variable_get(:foo) }.join -+ end -+ -+ assert_raises(SecurityError) do -+ Thread.new { $SAFE = 4; t.thread_variable_set(:foo, :baz) }.join -+ end -+ end -+ - def test_mutex_synchronize - m = Mutex.new - r = 0 -diff --git a/thread.c b/thread.c -index c7da34b..ce1fa3f 100644 ---- a/thread.c -+++ b/thread.c -@@ -2112,7 +2112,9 @@ rb_thread_local_aset(VALUE thread, ID id, VALUE val) - * thr[sym] = obj -> obj - * - * Attribute Assignment---Sets or creates the value of a thread-local variable, -- * using either a symbol or a string. See also Thread#[]. -+ * using either a symbol or a string. See also Thread#[]. For -+ * thread-local variables, please see Thread#thread_variable_set -+ * and Thread#thread_variable_get. - */ - - static VALUE -@@ -2123,6 +2125,80 @@ rb_thread_aset(VALUE self, VALUE id, VALUE val) - - /* - * call-seq: -+ * thr.thread_variable_get(key) -> obj or nil -+ * -+ * Returns the value of a thread local variable that has been set. Note that -+ * these are different than fiber local values. For fiber local values, -+ * please see Thread#[] and Thread#[]=. -+ * -+ * Thread local values are carried along with threads, and do not respect -+ * fibers. For example: -+ * -+ * Thread.new { -+ * Thread.current.thread_variable_set("foo", "bar") # set a thread local -+ * Thread.current["foo"] = "bar" # set a fiber local -+ * -+ * Fiber.new { -+ * Fiber.yield [ -+ * Thread.current.thread_variable_get("foo"), # get the thread local -+ * Thread.current["foo"], # get the fiber local -+ * ] -+ * }.resume -+ * }.join.value # => ['bar', nil] -+ * -+ * The value "bar" is returned for the thread local, where nil is returned -+ * for the fiber local. The fiber is executed in the same thread, so the -+ * thread local values are available. -+ * -+ * See also Thread#[] -+ */ -+ -+static VALUE -+rb_thread_variable_get(VALUE thread, VALUE id) -+{ -+ VALUE locals; -+ rb_thread_t *th; -+ -+ GetThreadPtr(thread, th); -+ -+ if (rb_safe_level() >= 4 && th != GET_THREAD()) { -+ rb_raise(rb_eSecurityError, "Insecure: can't access thread locals"); -+ } -+ -+ locals = rb_iv_get(thread, "locals"); -+ return rb_hash_aref(locals, ID2SYM(rb_to_id(id))); -+} -+ -+/* -+ * call-seq: -+ * thr.thread_variable_set(key, value) -+ * -+ * Sets a thread local with +key+ to +value+. Note that these are local to -+ * threads, and not to fibers. Please see Thread#thread_variable_get and -+ * Thread#[] for more information. -+ */ -+ -+static VALUE -+rb_thread_variable_set(VALUE thread, VALUE id, VALUE val) -+{ -+ VALUE locals; -+ rb_thread_t *th; -+ -+ GetThreadPtr(thread, th); -+ -+ if (rb_safe_level() >= 4 && th != GET_THREAD()) { -+ rb_raise(rb_eSecurityError, "Insecure: can't modify thread locals"); -+ } -+ if (OBJ_FROZEN(thread)) { -+ rb_error_frozen("thread locals"); -+ } -+ -+ locals = rb_iv_get(thread, "locals"); -+ return rb_hash_aset(locals, ID2SYM(rb_to_id(id)), val); -+} -+ -+/* -+ * call-seq: - * thr.key?(sym) -> true or false - * - * Returns true if the given string (or symbol) exists as a -@@ -2993,6 +3069,9 @@ rb_gc_save_machine_context(rb_thread_t *th) - - /* - * -+ * For thread-local variables, please see Thread#thread_local_get -+ * and Thread#thread_local_set. -+ * - */ - - void -@@ -3195,6 +3274,76 @@ thgroup_list_i(st_data_t key, st_data_t val, st_data_t data) - return ST_CONTINUE; - } - -+static int -+keys_i(VALUE key, VALUE value, VALUE ary) -+{ -+ rb_ary_push(ary, key); -+ return ST_CONTINUE; -+} -+ -+/* -+ * call-seq: -+ * thr.thread_variables -> array -+ * -+ * Returns an an array of the names of the thread-local variables (as Symbols). -+ * -+ * thr = Thread.new do -+ * Thread.current.thread_variable_set(:cat, 'meow') -+ * Thread.current.thread_variable_set("dog", 'woof') -+ * end -+ * thr.join #=> # -+ * thr.thread_variables #=> [:dog, :cat] -+ * -+ * Note that these are not fiber local variables. Please see Thread#[] and -+ * Thread#thread_variable_get for more details. -+ */ -+ -+static VALUE -+rb_thread_variables(VALUE thread) -+{ -+ VALUE locals; -+ VALUE ary; -+ -+ locals = rb_iv_get(thread, "locals"); -+ ary = rb_ary_new(); -+ rb_hash_foreach(locals, keys_i, ary); -+ -+ return ary; -+} -+ -+/* -+ * call-seq: -+ * thr.thread_variable?(key) -> true or false -+ * -+ * Returns true if the given string (or symbol) exists as a -+ * thread-local variable. -+ * -+ * me = Thread.current -+ * me.thread_variable_set(:oliver, "a") -+ * me.thread_variable?(:oliver) #=> true -+ * me.thread_variable?(:stanley) #=> false -+ * -+ * Note that these are not fiber local variables. Please see Thread#[] and -+ * Thread#thread_variable_get for more details. -+ */ -+ -+static VALUE -+rb_thread_variable_p(VALUE thread, VALUE key) -+{ -+ VALUE locals; -+ -+ locals = rb_iv_get(thread, "locals"); -+ -+ if (!RHASH(locals)->ntbl) -+ return Qfalse; -+ -+ if (st_lookup(RHASH(locals)->ntbl, ID2SYM(rb_to_id(key)), 0)) { -+ return Qtrue; -+ } -+ -+ return Qfalse; -+} -+ - /* - * call-seq: - * thgrp.list -> array -@@ -4680,6 +4829,10 @@ Init_Thread(void) - rb_define_method(rb_cThread, "priority", rb_thread_priority, 0); - rb_define_method(rb_cThread, "priority=", rb_thread_priority_set, 1); - rb_define_method(rb_cThread, "status", rb_thread_status, 0); -+ rb_define_method(rb_cThread, "thread_variable_get", rb_thread_variable_get, 1); -+ rb_define_method(rb_cThread, "thread_variable_set", rb_thread_variable_set, 2); -+ rb_define_method(rb_cThread, "thread_variables", rb_thread_variables, 0); -+ rb_define_method(rb_cThread, "thread_variable?", rb_thread_variable_p, 1); - rb_define_method(rb_cThread, "alive?", rb_thread_alive_p, 0); - rb_define_method(rb_cThread, "stop?", rb_thread_stop_p, 0); - rb_define_method(rb_cThread, "abort_on_exception", rb_thread_abort_exc, 0); -diff --git a/vm.c b/vm.c -index 4c44aa4..1517e73 100644 ---- a/vm.c -+++ b/vm.c -@@ -1909,6 +1909,7 @@ ruby_thread_init(VALUE self) - GetThreadPtr(self, th); - - th_init(th, self); -+ rb_iv_set(self, "locals", rb_hash_new()); - th->vm = vm; - - th->top_wrapper = 0; -@@ -2177,6 +2178,7 @@ Init_VM(void) - - /* create main thread */ - th_self = th->self = TypedData_Wrap_Struct(rb_cThread, &thread_data_type, th); -+ rb_iv_set(th_self, "locals", rb_hash_new()); - vm->main_thread = th; - vm->running_thread = th; - th->vm = vm; diff --git a/patches/ruby/1.9.3/p385/railsexpress/09-faster-loading.patch b/patches/ruby/1.9.3/p385/railsexpress/09-faster-loading.patch deleted file mode 100644 index 31c3ef328d..0000000000 --- a/patches/ruby/1.9.3/p385/railsexpress/09-faster-loading.patch +++ /dev/null @@ -1,747 +0,0 @@ -diff --git a/array.c b/array.c -index e427cb3..c33d106 100644 ---- a/array.c -+++ b/array.c -@@ -295,6 +295,22 @@ rb_ary_frozen_p(VALUE ary) - return Qfalse; - } - -+/* This can be used to take a snapshot of an array (with -+ e.g. rb_ary_replace) and check later whether the array has been -+ modified from the snapshot. The snapshot is cheap, though if -+ something does modify the array it will pay the cost of copying -+ it. */ -+VALUE -+rb_ary_shared_with_p(VALUE ary1, VALUE ary2) -+{ -+ if (!ARY_EMBED_P(ary1) && ARY_SHARED_P(ary1) -+ && !ARY_EMBED_P(ary2) && ARY_SHARED_P(ary2) -+ && RARRAY(ary1)->as.heap.aux.shared == RARRAY(ary2)->as.heap.aux.shared) { -+ return Qtrue; -+ } -+ return Qfalse; -+} -+ - static VALUE - ary_alloc(VALUE klass) - { -diff --git a/file.c b/file.c -index fd64116..1abf821 100644 ---- a/file.c -+++ b/file.c -@@ -149,23 +149,32 @@ file_path_convert(VALUE name) - return name; - } - --static VALUE --rb_get_path_check(VALUE obj, int level) -+VALUE -+rb_get_path_check_to_string(VALUE obj, int level) - { - VALUE tmp; - ID to_path; -- rb_encoding *enc; - - if (insecure_obj_p(obj, level)) { - rb_insecure_operation(); - } - -+ if (RB_TYPE_P(obj, T_STRING)) { -+ return obj; -+ } - CONST_ID(to_path, "to_path"); - tmp = rb_check_funcall(obj, to_path, 0, 0); - if (tmp == Qundef) { - tmp = obj; - } - StringValue(tmp); -+ return tmp; -+} -+ -+VALUE -+rb_get_path_check_convert(VALUE obj, VALUE tmp, int level) -+{ -+ rb_encoding *enc; - - tmp = file_path_convert(tmp); - if (obj != tmp && insecure_obj_p(tmp, level)) { -@@ -183,6 +192,13 @@ rb_get_path_check(VALUE obj, int level) - return rb_str_new4(tmp); - } - -+static VALUE -+rb_get_path_check(VALUE obj, int level) -+{ -+ VALUE tmp = rb_get_path_check_to_string(obj, level); -+ return rb_get_path_check_convert(obj, tmp, level); -+} -+ - VALUE - rb_get_path_no_checksafe(VALUE obj) - { -@@ -3250,7 +3266,6 @@ rb_file_expand_path(VALUE fname, VALUE dname) - VALUE - rb_file_expand_path_fast(VALUE fname, VALUE dname) - { -- check_expand_path_args(fname, dname); - return rb_file_expand_path_internal(fname, dname, 0, 0, EXPAND_PATH_BUFFER()); - } - -@@ -5241,7 +5256,7 @@ rb_find_file_ext_safe(VALUE *filep, const char *const *ext, int safe_level) - rb_raise(rb_eSecurityError, "loading from non-absolute path %s", f); - } - -- RB_GC_GUARD(load_path) = rb_get_load_path(); -+ RB_GC_GUARD(load_path) = rb_get_expanded_load_path(); - if (!load_path) return 0; - - fname = rb_str_dup(*filep); -@@ -5306,7 +5321,7 @@ rb_find_file_safe(VALUE path, int safe_level) - rb_raise(rb_eSecurityError, "loading from non-absolute path %s", f); - } - -- RB_GC_GUARD(load_path) = rb_get_load_path(); -+ RB_GC_GUARD(load_path) = rb_get_expanded_load_path(); - if (load_path) { - long i; - -diff --git a/hash.c b/hash.c -index fbd8237..8423558 100644 ---- a/hash.c -+++ b/hash.c -@@ -1087,7 +1087,7 @@ clear_i(VALUE key, VALUE value, VALUE dummy) - * - */ - --static VALUE -+VALUE - rb_hash_clear(VALUE hash) - { - rb_hash_modify_check(hash); -diff --git a/include/ruby/intern.h b/include/ruby/intern.h -index 7c3d970..ab1cc94 100644 ---- a/include/ruby/intern.h -+++ b/include/ruby/intern.h -@@ -56,6 +56,7 @@ VALUE rb_ary_tmp_new(long); - void rb_ary_free(VALUE); - void rb_ary_modify(VALUE); - VALUE rb_ary_freeze(VALUE); -+VALUE rb_ary_shared_with_p(VALUE, VALUE); - VALUE rb_ary_aref(int, VALUE*, VALUE); - VALUE rb_ary_subseq(VALUE, long, long); - void rb_ary_store(VALUE, long, VALUE); -@@ -443,6 +444,7 @@ VALUE rb_hash_lookup(VALUE, VALUE); - VALUE rb_hash_lookup2(VALUE, VALUE, VALUE); - VALUE rb_hash_fetch(VALUE, VALUE); - VALUE rb_hash_aset(VALUE, VALUE, VALUE); -+VALUE rb_hash_clear(VALUE); - VALUE rb_hash_delete_if(VALUE); - VALUE rb_hash_delete(VALUE,VALUE); - typedef VALUE rb_hash_update_func(VALUE newkey, VALUE oldkey, VALUE value); -diff --git a/internal.h b/internal.h -index 59c9284..f5af903 100644 ---- a/internal.h -+++ b/internal.h -@@ -94,6 +94,8 @@ VALUE rb_home_dir(const char *user, VALUE result); - VALUE rb_realpath_internal(VALUE basedir, VALUE path, int strict); - VALUE rb_file_expand_path_fast(VALUE, VALUE); - VALUE rb_file_expand_path_internal(VALUE, VALUE, int, int, VALUE); -+VALUE rb_get_path_check_to_string(VALUE, int); -+VALUE rb_get_path_check_convert(VALUE, VALUE, int); - void Init_File(void); - - #ifdef _WIN32 -@@ -119,6 +121,7 @@ VALUE rb_iseq_clone(VALUE iseqval, VALUE newcbase); - - /* load.c */ - VALUE rb_get_load_path(void); -+VALUE rb_get_expanded_load_path(void); - - /* math.c */ - VALUE rb_math_atan2(VALUE, VALUE); -diff --git a/load.c b/load.c -index 163ec4c..e766880 100644 ---- a/load.c -+++ b/load.c -@@ -18,7 +18,6 @@ VALUE ruby_dln_librefs; - #define IS_DLEXT(e) (strcmp((e), DLEXT) == 0) - #endif - -- - static const char *const loadable_ext[] = { - ".rb", DLEXT, - #ifdef DLEXT2 -@@ -34,21 +33,120 @@ rb_get_load_path(void) - return load_path; - } - --VALUE --rb_get_expanded_load_path(void) -+enum expand_type { -+ EXPAND_ALL, -+ EXPAND_RELATIVE, -+ EXPAND_HOME, -+ EXPAND_NON_CACHE -+}; -+ -+/* Construct expanded load path and store it to cache. -+ We rebuild load path partially if the cache is invalid. -+ We don't cache non string object and expand it every times. We ensure that -+ string objects in $LOAD_PATH are frozen. -+ */ -+static void -+rb_construct_expanded_load_path(int type, int *has_relative, int *has_non_cache) - { -- VALUE load_path = rb_get_load_path(); -+ rb_vm_t *vm = GET_VM(); -+ VALUE load_path = vm->load_path; -+ VALUE expanded_load_path = vm->expanded_load_path; - VALUE ary; - long i; -+ int level = rb_safe_level(); - - ary = rb_ary_new2(RARRAY_LEN(load_path)); - for (i = 0; i < RARRAY_LEN(load_path); ++i) { -- VALUE path = rb_file_expand_path_fast(RARRAY_PTR(load_path)[i], Qnil); -- rb_str_freeze(path); -- rb_ary_push(ary, path); -+ VALUE path, as_str, expanded_path; -+ int is_string, non_cache; -+ char *as_cstr; -+ as_str = path = RARRAY_PTR(load_path)[i]; -+ is_string = RB_TYPE_P(path, T_STRING) ? 1 : 0; -+ non_cache = !is_string ? 1 : 0; -+ as_str = rb_get_path_check_to_string(path, level); -+ as_cstr = RSTRING_PTR(as_str); -+ -+ if (!non_cache) { -+ if ((type == EXPAND_RELATIVE && -+ rb_is_absolute_path(as_cstr)) || -+ (type == EXPAND_HOME && -+ (!as_cstr[0] || as_cstr[0] != '~')) || -+ (type == EXPAND_NON_CACHE)) { -+ /* Use cached expanded path. */ -+ rb_ary_push(ary, RARRAY_PTR(expanded_load_path)[i]); -+ continue; -+ } -+ } -+ if (!*has_relative && !rb_is_absolute_path(as_cstr)) -+ *has_relative = 1; -+ if (!*has_non_cache && non_cache) -+ *has_non_cache = 1; -+ /* Freeze only string object. We expand other objects every times. */ -+ if (is_string) -+ rb_str_freeze(path); -+ as_str = rb_get_path_check_convert(path, as_str, level); -+ expanded_path = rb_file_expand_path_fast(as_str, Qnil); -+ rb_str_freeze(expanded_path); -+ rb_ary_push(ary, expanded_path); - } - rb_obj_freeze(ary); -- return ary; -+ vm->expanded_load_path = ary; -+ rb_ary_replace(vm->load_path_snapshot, vm->load_path); -+} -+ -+static VALUE -+load_path_getcwd(void) -+{ -+ char *cwd = my_getcwd(); -+ VALUE cwd_str = rb_filesystem_str_new_cstr(cwd); -+ xfree(cwd); -+ return cwd_str; -+} -+ -+VALUE -+rb_get_expanded_load_path(void) -+{ -+ rb_vm_t *vm = GET_VM(); -+ const VALUE non_cache = Qtrue; -+ -+ if (!rb_ary_shared_with_p(vm->load_path_snapshot, vm->load_path)) { -+ /* The load path was modified. Rebuild the expanded load path. */ -+ int has_relative = 0, has_non_cache = 0; -+ rb_construct_expanded_load_path(EXPAND_ALL, &has_relative, &has_non_cache); -+ if (has_relative) { -+ vm->load_path_check_cache = load_path_getcwd(); -+ } -+ else if (has_non_cache) { -+ /* Non string object. */ -+ vm->load_path_check_cache = non_cache; -+ } -+ else { -+ vm->load_path_check_cache = 0; -+ } -+ } -+ else if (vm->load_path_check_cache == non_cache) { -+ int has_relative = 1, has_non_cache = 1; -+ /* Expand only non-cacheable objects. */ -+ rb_construct_expanded_load_path(EXPAND_NON_CACHE, -+ &has_relative, &has_non_cache); -+ } -+ else if (vm->load_path_check_cache) { -+ int has_relative = 1, has_non_cache = 1; -+ VALUE cwd = load_path_getcwd(); -+ if (!rb_str_equal(vm->load_path_check_cache, cwd)) { -+ /* Current working directory or filesystem encoding was changed. -+ Expand relative load path and non-cacheable objects again. */ -+ vm->load_path_check_cache = cwd; -+ rb_construct_expanded_load_path(EXPAND_RELATIVE, -+ &has_relative, &has_non_cache); -+ } -+ else { -+ /* Expand only tilde (User HOME) and non-cacheable objects. */ -+ rb_construct_expanded_load_path(EXPAND_HOME, -+ &has_relative, &has_non_cache); -+ } -+ } -+ return vm->expanded_load_path; - } - - static VALUE -@@ -63,12 +161,121 @@ get_loaded_features(void) - return GET_VM()->loaded_features; - } - -+static void -+reset_loaded_features_snapshot(void) -+{ -+ rb_vm_t *vm = GET_VM(); -+ rb_ary_replace(vm->loaded_features_snapshot, vm->loaded_features); -+} -+ -+static VALUE -+get_loaded_features_index_raw(void) -+{ -+ return GET_VM()->loaded_features_index; -+} -+ - static st_table * - get_loading_table(void) - { - return GET_VM()->loading_table; - } - -+static void -+features_index_add_single(VALUE short_feature, VALUE offset) -+{ -+ VALUE features_index, this_feature_index; -+ features_index = get_loaded_features_index_raw(); -+ if ((this_feature_index = rb_hash_lookup(features_index, short_feature)) == Qnil) { -+ this_feature_index = rb_ary_new(); -+ rb_hash_aset(features_index, short_feature, this_feature_index); -+ } -+ rb_ary_push(this_feature_index, offset); -+} -+ -+/* Add to the loaded-features index all the required entries for -+ `feature`, located at `offset` in $LOADED_FEATURES. We add an -+ index entry at each string `short_feature` for which -+ feature == "#{prefix}#{short_feature}#{e}" -+ where `e` is empty or matches %r{^\.[^./]*$}, and `prefix` is empty -+ or ends in '/'. This maintains the invariant that `rb_feature_p()` -+ relies on for its fast lookup. -+*/ -+static void -+features_index_add(VALUE feature, VALUE offset) -+{ -+ VALUE short_feature; -+ const char *feature_str, *feature_end, *ext, *p; -+ -+ feature_str = StringValuePtr(feature); -+ feature_end = feature_str + RSTRING_LEN(feature); -+ -+ for (ext = feature_end; ext > feature_str; ext--) -+ if (*ext == '.' || *ext == '/') -+ break; -+ if (*ext != '.') -+ ext = NULL; -+ /* Now `ext` points to the only string matching %r{^\.[^./]*$} that is -+ at the end of `feature`, or is NULL if there is no such string. */ -+ -+ p = ext ? ext : feature_end; -+ while (1) { -+ p--; -+ while (p >= feature_str && *p != '/') -+ p--; -+ if (p < feature_str) -+ break; -+ /* Now *p == '/'. We reach this point for every '/' in `feature`. */ -+ short_feature = rb_str_substr(feature, p + 1 - feature_str, feature_end - p - 1); -+ features_index_add_single(short_feature, offset); -+ if (ext) { -+ short_feature = rb_str_substr(feature, p + 1 - feature_str, ext - p - 1); -+ features_index_add_single(short_feature, offset); -+ } -+ } -+ features_index_add_single(feature, offset); -+ if (ext) { -+ short_feature = rb_str_substr(feature, 0, ext - feature_str); -+ features_index_add_single(short_feature, offset); -+ } -+} -+ -+static VALUE -+get_loaded_features_index(void) -+{ -+ VALUE features; -+ int i; -+ rb_vm_t *vm = GET_VM(); -+ -+ if (!rb_ary_shared_with_p(vm->loaded_features_snapshot, vm->loaded_features)) { -+ /* The sharing was broken; something (other than us in rb_provide_feature()) -+ modified loaded_features. Rebuild the index. */ -+ rb_hash_clear(vm->loaded_features_index); -+ features = vm->loaded_features; -+ for (i = 0; i < RARRAY_LEN(features); i++) { -+ VALUE entry, as_str; -+ as_str = entry = rb_ary_entry(features, i); -+ StringValue(as_str); -+ if (as_str != entry) -+ rb_ary_store(features, i, as_str); -+ rb_str_freeze(as_str); -+ features_index_add(as_str, INT2FIX(i)); -+ } -+ reset_loaded_features_snapshot(); -+ } -+ return vm->loaded_features_index; -+} -+ -+/* This searches `load_path` for a value such that -+ name == "#{load_path[i]}/#{feature}" -+ if `feature` is a suffix of `name`, or otherwise -+ name == "#{load_path[i]}/#{feature}#{ext}" -+ for an acceptable string `ext`. It returns -+ `load_path[i].to_str` if found, else 0. -+ -+ If type is 's', then `ext` is acceptable only if IS_DLEXT(ext); -+ if 'r', then only if IS_RBEXT(ext); otherwise `ext` may be absent -+ or have any value matching `%r{^\.[^./]*$}`. -+*/ - static VALUE - loaded_feature_path(const char *name, long vlen, const char *feature, long len, - int type, VALUE load_path) -@@ -77,7 +284,7 @@ loaded_feature_path(const char *name, long vlen, const char *feature, long len, - long plen; - const char *e; - -- if(vlen < len) return 0; -+ if (vlen < len+1) return 0; - if (!strncmp(name+(vlen-len),feature,len)){ - plen = vlen - len - 1; - } else { -@@ -88,23 +295,22 @@ loaded_feature_path(const char *name, long vlen, const char *feature, long len, - return 0; - plen = e - name - len - 1; - } -+ if (type == 's' && !IS_DLEXT(&name[plen+len+1]) -+ || type == 'r' && !IS_RBEXT(&name[plen+len+1]) -+ || name[plen] != '/') { -+ return 0; -+ } -+ /* Now name == "#{prefix}/#{feature}#{ext}" where ext is acceptable -+ (possibly empty) and prefix is some string of length plen. */ -+ - for (i = 0; i < RARRAY_LEN(load_path); ++i) { - VALUE p = RARRAY_PTR(load_path)[i]; - const char *s = StringValuePtr(p); - long n = RSTRING_LEN(p); - - if (n != plen ) continue; -- if (n && (strncmp(name, s, n) || name[n] != '/')) continue; -- switch (type) { -- case 's': -- if (IS_DLEXT(&name[n+len+1])) return p; -- break; -- case 'r': -- if (IS_RBEXT(&name[n+len+1])) return p; -- break; -- default: -- return p; -- } -+ if (n && strncmp(name, s, n)) continue; -+ return p; - } - return 0; - } -@@ -132,7 +338,7 @@ loaded_feature_path_i(st_data_t v, st_data_t b, st_data_t f) - static int - rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const char **fn) - { -- VALUE v, features, p, load_path = 0; -+ VALUE features, features_index, feature_val, this_feature_index, v, p, load_path = 0; - const char *f, *e; - long i, len, elen, n; - st_table *loading_tbl; -@@ -151,8 +357,39 @@ rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const c - type = 0; - } - features = get_loaded_features(); -- for (i = 0; i < RARRAY_LEN(features); ++i) { -- v = RARRAY_PTR(features)[i]; -+ features_index = get_loaded_features_index(); -+ -+ feature_val = rb_str_new(feature, len); -+ this_feature_index = rb_hash_lookup(features_index, feature_val); -+ /* We search `features` for an entry such that either -+ "#{features[i]}" == "#{load_path[j]}/#{feature}#{e}" -+ for some j, or -+ "#{features[i]}" == "#{feature}#{e}" -+ Here `e` is an "allowed" extension -- either empty or one -+ of the extensions accepted by IS_RBEXT, IS_SOEXT, or -+ IS_DLEXT. Further, if `ext && rb` then `IS_RBEXT(e)`, -+ and if `ext && !rb` then `IS_SOEXT(e) || IS_DLEXT(e)`. -+ -+ If `expanded`, then only the latter form (without load_path[j]) -+ is accepted. Otherwise either form is accepted, *unless* `ext` -+ is false and an otherwise-matching entry of the first form is -+ preceded by an entry of the form -+ "#{features[i2]}" == "#{load_path[j2]}/#{feature}#{e2}" -+ where `e2` matches %r{^\.[^./]*$} but is not an allowed extension. -+ After a "distractor" entry of this form, only entries of the -+ form "#{feature}#{e}" are accepted. -+ -+ In `rb_provide_feature()` and `get_loaded_features_index()` we -+ maintain an invariant that the array `this_feature_index` will -+ point to every entry in `features` which has the form -+ "#{prefix}#{feature}#{e}" -+ where `e` is empty or matches %r{^\.[^./]*$}, and `prefix` is empty -+ or ends in '/'. This includes both match forms above, as well -+ as any distractors, so we may ignore all other entries in `features`. -+ */ -+ for (i = 0; this_feature_index != Qnil && i < RARRAY_LEN(this_feature_index); i++) { -+ long index = FIX2LONG(rb_ary_entry(this_feature_index, i)); -+ v = RARRAY_PTR(features)[index]; - f = StringValuePtr(v); - if ((n = RSTRING_LEN(v)) < len) continue; - if (strncmp(f, feature, len) != 0) { -@@ -175,6 +412,7 @@ rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const c - return 'r'; - } - } -+ - loading_tbl = get_loading_table(); - if (loading_tbl) { - f = 0; -@@ -183,7 +421,7 @@ rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const c - fs.name = feature; - fs.len = len; - fs.type = type; -- fs.load_path = load_path ? load_path : rb_get_load_path(); -+ fs.load_path = load_path ? load_path : rb_get_expanded_load_path(); - fs.result = 0; - st_foreach(loading_tbl, loaded_feature_path_i, (st_data_t)&fs); - if ((f = fs.result) != 0) { -@@ -233,7 +471,7 @@ rb_feature_provided(const char *feature, const char **loading) - - if (*feature == '.' && - (feature[1] == '/' || strncmp(feature+1, "./", 2) == 0)) { -- fullpath = rb_file_expand_path_fast(rb_str_new2(feature), Qnil); -+ fullpath = rb_file_expand_path_fast(rb_get_path(rb_str_new2(feature)), Qnil); - feature = RSTRING_PTR(fullpath); - } - if (ext && !strchr(ext, '/')) { -@@ -254,11 +492,18 @@ rb_feature_provided(const char *feature, const char **loading) - static void - rb_provide_feature(VALUE feature) - { -- if (OBJ_FROZEN(get_loaded_features())) { -+ VALUE features; -+ -+ features = get_loaded_features(); -+ if (OBJ_FROZEN(features)) { - rb_raise(rb_eRuntimeError, - "$LOADED_FEATURES is frozen; cannot append feature"); - } -- rb_ary_push(get_loaded_features(), feature); -+ rb_str_freeze(feature); -+ -+ rb_ary_push(features, feature); -+ features_index_add(feature, INT2FIX(RARRAY_LEN(features)-1)); -+ reset_loaded_features_snapshot(); - } - - void -@@ -774,10 +1019,15 @@ Init_load() - rb_alias_variable(rb_intern("$-I"), id_load_path); - rb_alias_variable(rb_intern("$LOAD_PATH"), id_load_path); - vm->load_path = rb_ary_new(); -+ vm->expanded_load_path = rb_ary_new(); -+ vm->load_path_snapshot = rb_ary_new(); -+ vm->load_path_check_cache = 0; - - rb_define_virtual_variable("$\"", get_loaded_features, 0); - rb_define_virtual_variable("$LOADED_FEATURES", get_loaded_features, 0); - vm->loaded_features = rb_ary_new(); -+ vm->loaded_features_snapshot = rb_ary_new(); -+ vm->loaded_features_index = rb_hash_new(); - - rb_define_global_function("load", rb_f_load, -1); - rb_define_global_function("require", rb_f_require, 1); -diff --git a/ruby.c b/ruby.c -index 3ddd96c..7ffc78e 100644 ---- a/ruby.c -+++ b/ruby.c -@@ -1366,7 +1366,8 @@ process_options(int argc, char **argv, struct cmdline_options *opt) - long i; - VALUE load_path = GET_VM()->load_path; - for (i = 0; i < RARRAY_LEN(load_path); ++i) { -- rb_enc_associate(RARRAY_PTR(load_path)[i], lenc); -+ RARRAY_PTR(load_path)[i] = -+ rb_enc_associate(rb_str_dup(RARRAY_PTR(load_path)[i]), lenc); - } - } - if (!(opt->disable & DISABLE_BIT(gems))) { -diff --git a/test/ruby/test_require.rb b/test/ruby/test_require.rb -index 58a9ee2..ec75096 100644 ---- a/test/ruby/test_require.rb -+++ b/test/ruby/test_require.rb -@@ -356,4 +356,114 @@ class TestRequire < Test::Unit::TestCase - $:.replace(loadpath) - $".replace(features) - end -+ -+ def test_require_changed_current_dir -+ bug7158 = '[ruby-core:47970]' -+ Dir.mktmpdir {|tmp| -+ Dir.chdir(tmp) { -+ Dir.mkdir("a") -+ Dir.mkdir("b") -+ open(File.join("a", "foo.rb"), "w") {} -+ open(File.join("b", "bar.rb"), "w") {|f| -+ f.puts "p :ok" -+ } -+ assert_in_out_err([], <<-INPUT, %w(:ok), [], bug7158) -+ $: << "." -+ Dir.chdir("a") -+ require "foo" -+ Dir.chdir("../b") -+ p :ng unless require "bar" -+ Dir.chdir("..") -+ p :ng if require "b/bar" -+ INPUT -+ } -+ } -+ end -+ -+ def test_require_not_modified_load_path -+ bug7158 = '[ruby-core:47970]' -+ Dir.mktmpdir {|tmp| -+ Dir.chdir(tmp) { -+ open("foo.rb", "w") {} -+ assert_in_out_err([], <<-INPUT, %w(:ok), [], bug7158) -+ a = Object.new -+ def a.to_str -+ "#{tmp}" -+ end -+ $: << a -+ require "foo" -+ last_path = $:.pop -+ p :ok if last_path == a && last_path.class == Object -+ INPUT -+ } -+ } -+ end -+ -+ def test_require_changed_home -+ bug7158 = '[ruby-core:47970]' -+ Dir.mktmpdir {|tmp| -+ Dir.chdir(tmp) { -+ open("foo.rb", "w") {} -+ Dir.mkdir("a") -+ open(File.join("a", "bar.rb"), "w") {} -+ assert_in_out_err([], <<-INPUT, %w(:ok), [], bug7158) -+ $: << '~' -+ ENV['HOME'] = "#{tmp}" -+ require "foo" -+ ENV['HOME'] = "#{tmp}/a" -+ p :ok if require "bar" -+ INPUT -+ } -+ } -+ end -+ -+ def test_require_to_path_redefined_in_load_path -+ bug7158 = '[ruby-core:47970]' -+ Dir.mktmpdir {|tmp| -+ Dir.chdir(tmp) { -+ open("foo.rb", "w") {} -+ assert_in_out_err(["RUBYOPT"=>nil], <<-INPUT, %w(:ok), [], bug7158) -+ a = Object.new -+ def a.to_path -+ "bar" -+ end -+ $: << a -+ begin -+ require "foo" -+ p :ng -+ rescue LoadError -+ end -+ def a.to_path -+ "#{tmp}" -+ end -+ p :ok if require "foo" -+ INPUT -+ } -+ } -+ end -+ -+ def test_require_to_str_redefined_in_load_path -+ bug7158 = '[ruby-core:47970]' -+ Dir.mktmpdir {|tmp| -+ Dir.chdir(tmp) { -+ open("foo.rb", "w") {} -+ assert_in_out_err(["RUBYOPT"=>nil], <<-INPUT, %w(:ok), [], bug7158) -+ a = Object.new -+ def a.to_str -+ "foo" -+ end -+ $: << a -+ begin -+ require "foo" -+ p :ng -+ rescue LoadError -+ end -+ def a.to_str -+ "#{tmp}" -+ end -+ p :ok if require "foo" -+ INPUT -+ } -+ } -+ end - end -diff --git a/vm.c b/vm.c -index 1517e73..04ef956 100644 ---- a/vm.c -+++ b/vm.c -@@ -1591,7 +1591,12 @@ rb_vm_mark(void *ptr) - RUBY_MARK_UNLESS_NULL(vm->thgroup_default); - RUBY_MARK_UNLESS_NULL(vm->mark_object_ary); - RUBY_MARK_UNLESS_NULL(vm->load_path); -+ RUBY_MARK_UNLESS_NULL(vm->load_path_snapshot); -+ RUBY_MARK_UNLESS_NULL(vm->load_path_check_cache); -+ RUBY_MARK_UNLESS_NULL(vm->expanded_load_path); - RUBY_MARK_UNLESS_NULL(vm->loaded_features); -+ RUBY_MARK_UNLESS_NULL(vm->loaded_features_snapshot); -+ RUBY_MARK_UNLESS_NULL(vm->loaded_features_index); - RUBY_MARK_UNLESS_NULL(vm->top_self); - RUBY_MARK_UNLESS_NULL(vm->coverages); - rb_gc_mark_locations(vm->special_exceptions, vm->special_exceptions + ruby_special_error_count); -diff --git a/vm_core.h b/vm_core.h -index dfc0e3c..70c5f5c 100644 ---- a/vm_core.h -+++ b/vm_core.h -@@ -299,7 +299,12 @@ typedef struct rb_vm_struct { - /* load */ - VALUE top_self; - VALUE load_path; -+ VALUE load_path_snapshot; -+ VALUE load_path_check_cache; -+ VALUE expanded_load_path; - VALUE loaded_features; -+ VALUE loaded_features_snapshot; -+ VALUE loaded_features_index; - struct st_table *loading_table; - - /* signal */ diff --git a/patches/ruby/1.9.3/p385/railsexpress/10-falcon-st-opt.patch b/patches/ruby/1.9.3/p385/railsexpress/10-falcon-st-opt.patch deleted file mode 100644 index 1ae44dd701..0000000000 --- a/patches/ruby/1.9.3/p385/railsexpress/10-falcon-st-opt.patch +++ /dev/null @@ -1,2333 +0,0 @@ -diff --git a/common.mk b/common.mk -index ccc9647..1d8e442 100644 ---- a/common.mk -+++ b/common.mk -@@ -638,7 +638,8 @@ file.$(OBJEXT): {$(VPATH)}file.c $(RUBY_H_INCLUDES) {$(VPATH)}io.h \ - gc.$(OBJEXT): {$(VPATH)}gc.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \ - {$(VPATH)}regex.h $(ENCODING_H_INCLUDES) $(VM_CORE_H_INCLUDES) \ - {$(VPATH)}gc.h {$(VPATH)}io.h {$(VPATH)}eval_intern.h {$(VPATH)}util.h \ -- {$(VPATH)}debug.h {$(VPATH)}internal.h {$(VPATH)}constant.h -+ {$(VPATH)}debug.h {$(VPATH)}internal.h {$(VPATH)}constant.h \ -+ {$(VPATH)}pool_alloc.inc.h {$(VPATH)}pool_alloc.h - hash.$(OBJEXT): {$(VPATH)}hash.c $(RUBY_H_INCLUDES) {$(VPATH)}util.h \ - $(ENCODING_H_INCLUDES) - inits.$(OBJEXT): {$(VPATH)}inits.c $(RUBY_H_INCLUDES) \ -@@ -702,7 +703,7 @@ signal.$(OBJEXT): {$(VPATH)}signal.c $(RUBY_H_INCLUDES) \ - $(VM_CORE_H_INCLUDES) {$(VPATH)}debug.h - sprintf.$(OBJEXT): {$(VPATH)}sprintf.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \ - {$(VPATH)}regex.h {$(VPATH)}vsnprintf.c $(ENCODING_H_INCLUDES) --st.$(OBJEXT): {$(VPATH)}st.c $(RUBY_H_INCLUDES) -+st.$(OBJEXT): {$(VPATH)}st.c $(RUBY_H_INCLUDES) {$(VPATH)}pool_alloc.h - strftime.$(OBJEXT): {$(VPATH)}strftime.c $(RUBY_H_INCLUDES) \ - {$(VPATH)}timev.h - string.$(OBJEXT): {$(VPATH)}string.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \ -diff --git a/configure.in b/configure.in -index 6099a92..7b85cc9 100644 ---- a/configure.in -+++ b/configure.in -@@ -1268,6 +1268,30 @@ if test $rb_cv_stack_end_address != no; then - AC_DEFINE_UNQUOTED(STACK_END_ADDRESS, $rb_cv_stack_end_address) - fi - -+AS_CASE(["$target_os"], -+[openbsd*], [ -+ AC_CACHE_CHECK(for heap align log on openbsd, rb_cv_page_size_log, -+ [rb_cv_page_size_log=no -+ for page_log in 12 13; do -+ AC_TRY_RUN([ -+#include -+#include -+ -+int -+main() { -+ if ((int)log2((double)sysconf(_SC_PAGESIZE)) != $page_log) return 1; -+ return 0; -+} -+ ], -+ rb_cv_page_size_log="$page_log"; break) -+ done]) -+ if test $rb_cv_page_size_log != no; then -+ AC_DEFINE_UNQUOTED(HEAP_ALIGN_LOG, $rb_cv_page_size_log) -+ else -+ AC_DEFINE_UNQUOTED(HEAP_ALIGN_LOG, 12) -+ fi -+]) -+ - dnl Checks for library functions. - AC_TYPE_GETGROUPS - AC_TYPE_SIGNAL -@@ -1367,7 +1391,8 @@ AC_CHECK_FUNCS(fmod killpg wait4 waitpid fork spawnv syscall __syscall chroot ge - setsid telldir seekdir fchmod cosh sinh tanh log2 round\ - setuid setgid daemon select_large_fdset setenv unsetenv\ - mktime timegm gmtime_r clock_gettime gettimeofday poll ppoll\ -- pread sendfile shutdown sigaltstack dl_iterate_phdr) -+ pread sendfile shutdown sigaltstack dl_iterate_phdr\ -+ posix_memalign memalign) - - AC_CACHE_CHECK(for unsetenv returns a value, rb_cv_unsetenv_return_value, - [AC_TRY_COMPILE([ -diff --git a/ext/-test-/st/numhash/numhash.c b/ext/-test-/st/numhash/numhash.c -index e186cd4..53d9e1b 100644 ---- a/ext/-test-/st/numhash/numhash.c -+++ b/ext/-test-/st/numhash/numhash.c -@@ -54,7 +54,7 @@ numhash_i(st_data_t key, st_data_t value, st_data_t arg, int error) - static VALUE - numhash_each(VALUE self) - { -- return st_foreach((st_table *)DATA_PTR(self), numhash_i, self) ? Qtrue : Qfalse; -+ return st_foreach_check((st_table *)DATA_PTR(self), numhash_i, self, 0) ? Qtrue : Qfalse; - } - - void -diff --git a/gc.c b/gc.c -index 463a2d9..9037212 100644 ---- a/gc.c -+++ b/gc.c -@@ -20,6 +20,7 @@ - #include "vm_core.h" - #include "internal.h" - #include "gc.h" -+#include "pool_alloc.h" - #include "constant.h" - #include "ruby_atomic.h" - #include -@@ -37,7 +38,12 @@ - - #if defined _WIN32 || defined __CYGWIN__ - #include -+#elif defined(HAVE_POSIX_MEMALIGN) -+#elif defined(HAVE_MEMALIGN) -+#include - #endif -+static void aligned_free(void *); -+static void *aligned_malloc(size_t alignment, size_t size); - - #ifdef HAVE_VALGRIND_MEMCHECK_H - # include -@@ -356,6 +362,24 @@ typedef struct mark_stack { - - #define CALC_EXACT_MALLOC_SIZE 0 - -+#ifdef POOL_ALLOC_API -+/* POOL ALLOC API */ -+#define POOL_ALLOC_PART 1 -+#include "pool_alloc.inc.h" -+#undef POOL_ALLOC_PART -+ -+typedef struct pool_layout_t pool_layout_t; -+struct pool_layout_t { -+ pool_header -+ p6, /* st_table && st_table_entry */ -+ p11; /* st_table.bins init size */ -+} pool_layout = { -+ INIT_POOL(void*[6]), -+ INIT_POOL(void*[11]) -+}; -+static void pool_finalize_header(pool_header *header); -+#endif -+ - typedef struct rb_objspace { - struct { - size_t limit; -@@ -365,6 +389,9 @@ typedef struct rb_objspace { - size_t allocations; - #endif - } malloc_params; -+#ifdef POOL_ALLOC_API -+ pool_layout_t *pool_headers; -+#endif - struct { - size_t increment; - struct heaps_slot *ptr; -@@ -430,7 +457,11 @@ typedef struct rb_objspace { - #define ruby_initial_gc_stress initial_params.gc_stress - int *ruby_initial_gc_stress_ptr = &ruby_initial_gc_stress; - #else -+# ifdef POOL_ALLOC_API -+static rb_objspace_t rb_objspace = {{GC_MALLOC_LIMIT}, &pool_layout, {HEAP_MIN_SLOTS}}; -+# else - static rb_objspace_t rb_objspace = {{GC_MALLOC_LIMIT}, {HEAP_MIN_SLOTS}}; -+# endif - int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress; - #endif - #define malloc_limit objspace->malloc_params.limit -@@ -481,6 +512,10 @@ rb_objspace_alloc(void) - memset(objspace, 0, sizeof(*objspace)); - malloc_limit = initial_malloc_limit; - ruby_gc_stress = ruby_initial_gc_stress; -+#ifdef POOL_ALLOC_API -+ objspace->pool_headers = (pool_layout_t*) malloc(sizeof(pool_layout)); -+ memcpy(objspace->pool_headers, &pool_layout, sizeof(pool_layout)); -+#endif - - return objspace; - } -@@ -624,6 +659,13 @@ rb_objspace_free(rb_objspace_t *objspace) - heaps = 0; - } - free_stack_chunks(&objspace->mark_stack); -+#ifdef POOL_ALLOC_API -+ if (objspace->pool_headers) { -+ pool_finalize_header(&objspace->pool_headers->p6); -+ pool_finalize_header(&objspace->pool_headers->p11); -+ free(objspace->pool_headers); -+ } -+#endif - free(objspace); - } - #endif -@@ -1148,6 +1190,27 @@ rb_gc_stats_enabled() - return gc_statistics ? Qtrue : Qfalse; - } - -+#ifdef POOL_ALLOC_API -+/* POOL ALLOC API */ -+#define POOL_ALLOC_PART 2 -+#include "pool_alloc.inc.h" -+#undef POOL_ALLOC_PART -+ -+void -+ruby_xpool_free(void *ptr) -+{ -+ pool_free_entry((void**)ptr); -+} -+ -+#define CONCRET_POOL_MALLOC(pnts) \ -+void * ruby_xpool_malloc_##pnts##p () { \ -+ return pool_alloc_entry(&rb_objspace.pool_headers->p##pnts ); \ -+} -+CONCRET_POOL_MALLOC(6) -+CONCRET_POOL_MALLOC(11) -+#undef CONCRET_POOL_MALLOC -+ -+#endif - - /* - * call-seq: -@@ -1663,6 +1726,55 @@ allocate_sorted_heaps(rb_objspace_t *objspace, size_t next_heaps_length) - heaps_length = next_heaps_length; - } - -+static void * -+aligned_malloc(size_t alignment, size_t size) -+{ -+ void *res; -+ -+#if defined __MINGW32__ -+ res = __mingw_aligned_malloc(size, alignment); -+#elif defined _WIN32 && !defined __CYGWIN__ -+ 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 -+ -+#if defined(_DEBUG) || defined(GC_DEBUG) -+ /* alignment must be a power of 2 */ -+ assert((alignment - 1) & alignment == 0); -+ assert(alignment % sizeof(void*) == 0); -+#endif -+ return res; -+} -+ -+static void -+aligned_free(void *ptr) -+{ -+#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 -+} -+ - static void - assign_heap_slot(rb_objspace_t *objspace) - { -diff --git a/hash.c b/hash.c -index 8423558..4cb2e2d 100644 ---- a/hash.c -+++ b/hash.c -@@ -44,7 +44,7 @@ rb_any_cmp(VALUE a, VALUE b) - if (FIXNUM_P(a) && FIXNUM_P(b)) { - return a != b; - } -- if (TYPE(a) == T_STRING && RBASIC(a)->klass == rb_cString && -+ if (RB_TYPE_P(a, T_STRING) && RBASIC(a)->klass == rb_cString && - TYPE(b) == T_STRING && RBASIC(b)->klass == rb_cString) { - return rb_str_hash_cmp(a, b); - } -@@ -80,20 +80,14 @@ rb_any_hash(VALUE a) - VALUE hval; - st_index_t hnum; - -- switch (TYPE(a)) { -- case T_FIXNUM: -- case T_SYMBOL: -- case T_NIL: -- case T_FALSE: -- case T_TRUE: -- hnum = rb_hash_end(rb_hash_start((unsigned int)a)); -- break; -- -- case T_STRING: -+ if (SPECIAL_CONST_P(a)) { -+ if (a == Qundef) return 0; -+ hnum = rb_hash_end(rb_hash_start((st_index_t)a)); -+ } -+ else if (BUILTIN_TYPE(a) == T_STRING) { - hnum = rb_str_hash(a); -- break; -- -- default: -+ } -+ else { - hval = rb_hash(a); - hnum = FIX2LONG(hval); - } -@@ -106,10 +100,8 @@ static const struct st_hash_type objhash = { - rb_any_hash, - }; - --static const struct st_hash_type identhash = { -- st_numcmp, -- st_numhash, --}; -+extern const struct st_hash_type st_hashtype_num; -+#define identhash st_hashtype_num - - typedef int st_foreach_func(st_data_t, st_data_t, st_data_t); - -@@ -124,7 +116,6 @@ foreach_safe_i(st_data_t key, st_data_t value, struct foreach_safe_arg *arg) - { - int status; - -- if (key == Qundef) return ST_CONTINUE; - status = (*arg->func)(key, value, arg->arg); - if (status == ST_CONTINUE) { - return ST_CHECK; -@@ -140,7 +131,7 @@ st_foreach_safe(st_table *table, int (*func)(ANYARGS), st_data_t a) - arg.tbl = table; - arg.func = (st_foreach_func *)func; - arg.arg = a; -- if (st_foreach(table, foreach_safe_i, (st_data_t)&arg)) { -+ if (st_foreach_check(table, foreach_safe_i, (st_data_t)&arg, 0)) { - rb_raise(rb_eRuntimeError, "hash modified during iteration"); - } - } -@@ -154,21 +145,21 @@ struct hash_foreach_arg { - }; - - static int --hash_foreach_iter(st_data_t key, st_data_t value, struct hash_foreach_arg *arg) -+hash_foreach_iter(st_data_t key, st_data_t value, st_data_t argp) - { -+ struct hash_foreach_arg *arg = (struct hash_foreach_arg *)argp; - int status; - st_table *tbl; - - tbl = RHASH(arg->hash)->ntbl; -- if ((VALUE)key == Qundef) return ST_CONTINUE; - status = (*arg->func)((VALUE)key, (VALUE)value, arg->arg); - if (RHASH(arg->hash)->ntbl != tbl) { - rb_raise(rb_eRuntimeError, "rehash occurred during iteration"); - } - switch (status) { - case ST_DELETE: -- st_delete_safe(tbl, &key, 0, Qundef); - FL_SET(arg->hash, HASH_DELETED); -+ return ST_DELETE; - case ST_CONTINUE: - break; - case ST_STOP: -@@ -184,7 +175,7 @@ hash_foreach_ensure(VALUE hash) - - if (RHASH(hash)->iter_lev == 0) { - if (FL_TEST(hash, HASH_DELETED)) { -- st_cleanup_safe(RHASH(hash)->ntbl, Qundef); -+ st_cleanup_safe(RHASH(hash)->ntbl, (st_data_t)Qundef); - FL_UNSET(hash, HASH_DELETED); - } - } -@@ -192,9 +183,10 @@ hash_foreach_ensure(VALUE hash) - } - - static VALUE --hash_foreach_call(struct hash_foreach_arg *arg) -+hash_foreach_call(VALUE arg) - { -- if (st_foreach(RHASH(arg->hash)->ntbl, hash_foreach_iter, (st_data_t)arg)) { -+ VALUE hash = ((struct hash_foreach_arg *)arg)->hash; -+ if (st_foreach_check(RHASH(hash)->ntbl, hash_foreach_iter, (st_data_t)arg, (st_data_t)Qundef)) { - rb_raise(rb_eRuntimeError, "hash modified during iteration"); - } - return Qnil; -@@ -447,7 +439,7 @@ rb_hash_rehash_i(VALUE key, VALUE value, VALUE arg) - { - st_table *tbl = (st_table *)arg; - -- if (key != Qundef) st_insert(tbl, key, value); -+ st_insert(tbl, (st_data_t)key, (st_data_t)value); - return ST_CONTINUE; - } - -@@ -490,6 +482,20 @@ rb_hash_rehash(VALUE hash) - return hash; - } - -+static VALUE -+hash_default_value(VALUE hash, VALUE key) -+{ -+ if (rb_method_basic_definition_p(CLASS_OF(hash), id_default)) { -+ VALUE ifnone = RHASH_IFNONE(hash); -+ if (!FL_TEST(hash, HASH_PROC_DEFAULT)) return ifnone; -+ if (key == Qundef) return Qnil; -+ return rb_funcall(ifnone, id_yield, 2, hash, key); -+ } -+ else { -+ return rb_funcall(hash, id_default, 1, key); -+ } -+} -+ - /* - * call-seq: - * hsh[key] -> value -@@ -510,13 +516,7 @@ rb_hash_aref(VALUE hash, VALUE key) - st_data_t val; - - if (!RHASH(hash)->ntbl || !st_lookup(RHASH(hash)->ntbl, key, &val)) { -- if (!FL_TEST(hash, HASH_PROC_DEFAULT) && -- rb_method_basic_definition_p(CLASS_OF(hash), id_default)) { -- return RHASH_IFNONE(hash); -- } -- else { -- return rb_funcall(hash, id_default, 1, key); -- } -+ return hash_default_value(hash, key); - } - return (VALUE)val; - } -@@ -659,7 +659,7 @@ rb_hash_default(int argc, VALUE *argv, VALUE hash) - static VALUE - rb_hash_set_default(VALUE hash, VALUE ifnone) - { -- rb_hash_modify(hash); -+ rb_hash_modify_check(hash); - RHASH_IFNONE(hash) = ifnone; - FL_UNSET(hash, HASH_PROC_DEFAULT); - return ifnone; -@@ -707,7 +707,7 @@ rb_hash_set_default_proc(VALUE hash, VALUE proc) - { - VALUE b; - -- rb_hash_modify(hash); -+ rb_hash_modify_check(hash); - b = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc"); - if (NIL_P(b) || !rb_obj_is_proc(b)) { - rb_raise(rb_eTypeError, -@@ -776,7 +776,7 @@ rb_hash_delete_key(VALUE hash, VALUE key) - if (!RHASH(hash)->ntbl) - return Qundef; - if (RHASH(hash)->iter_lev > 0) { -- if (st_delete_safe(RHASH(hash)->ntbl, &ktmp, &val, Qundef)) { -+ if (st_delete_safe(RHASH(hash)->ntbl, &ktmp, &val, (st_data_t)Qundef)) { - FL_SET(hash, HASH_DELETED); - return (VALUE)val; - } -@@ -809,7 +809,7 @@ rb_hash_delete(VALUE hash, VALUE key) - { - VALUE val; - -- rb_hash_modify(hash); -+ rb_hash_modify_check(hash); - val = rb_hash_delete_key(hash, key); - if (val != Qundef) return val; - if (rb_block_given_p()) { -@@ -828,7 +828,6 @@ shift_i(VALUE key, VALUE value, VALUE arg) - { - struct shift_var *var = (struct shift_var *)arg; - -- if (key == Qundef) return ST_CONTINUE; - if (var->key != Qundef) return ST_STOP; - var->key = key; - var->val = value; -@@ -840,7 +839,6 @@ shift_i_safe(VALUE key, VALUE value, VALUE arg) - { - struct shift_var *var = (struct shift_var *)arg; - -- if (key == Qundef) return ST_CONTINUE; - var->key = key; - var->val = value; - return ST_STOP; -@@ -864,29 +862,25 @@ rb_hash_shift(VALUE hash) - { - struct shift_var var; - -- rb_hash_modify(hash); -- var.key = Qundef; -- rb_hash_foreach(hash, RHASH(hash)->iter_lev > 0 ? shift_i_safe : shift_i, -- (VALUE)&var); -- -- if (var.key != Qundef) { -- if (RHASH(hash)->iter_lev > 0) { -- rb_hash_delete_key(hash, var.key); -+ rb_hash_modify_check(hash); -+ if (RHASH(hash)->ntbl) { -+ var.key = Qundef; -+ rb_hash_foreach(hash, RHASH(hash)->iter_lev > 0 ? shift_i_safe : shift_i, -+ (VALUE)&var); -+ -+ if (var.key != Qundef) { -+ if (RHASH(hash)->iter_lev > 0) { -+ rb_hash_delete_key(hash, var.key); -+ } -+ return rb_assoc_new(var.key, var.val); - } -- return rb_assoc_new(var.key, var.val); -- } -- else if (FL_TEST(hash, HASH_PROC_DEFAULT)) { -- return rb_funcall(RHASH_IFNONE(hash), id_yield, 2, hash, Qnil); -- } -- else { -- return RHASH_IFNONE(hash); - } -+ return hash_default_value(hash, Qnil); - } - - static int - delete_if_i(VALUE key, VALUE value, VALUE hash) - { -- if (key == Qundef) return ST_CONTINUE; - if (RTEST(rb_yield_values(2, key, value))) { - rb_hash_delete_key(hash, key); - } -@@ -912,8 +906,9 @@ VALUE - rb_hash_delete_if(VALUE hash) - { - RETURN_ENUMERATOR(hash, 0, 0); -- rb_hash_modify(hash); -- rb_hash_foreach(hash, delete_if_i, hash); -+ rb_hash_modify_check(hash); -+ if (RHASH(hash)->ntbl) -+ rb_hash_foreach(hash, delete_if_i, hash); - return hash; - } - -@@ -984,7 +979,6 @@ rb_hash_values_at(int argc, VALUE *argv, VALUE hash) - static int - select_i(VALUE key, VALUE value, VALUE result) - { -- if (key == Qundef) return ST_CONTINUE; - if (RTEST(rb_yield_values(2, key, value))) - rb_hash_aset(result, key, value); - return ST_CONTINUE; -@@ -1018,7 +1012,6 @@ rb_hash_select(VALUE hash) - static int - keep_if_i(VALUE key, VALUE value, VALUE hash) - { -- if (key == Qundef) return ST_CONTINUE; - if (!RTEST(rb_yield_values(2, key, value))) { - return ST_DELETE; - } -@@ -1040,7 +1033,7 @@ rb_hash_select_bang(VALUE hash) - st_index_t n; - - RETURN_ENUMERATOR(hash, 0, 0); -- rb_hash_modify(hash); -+ rb_hash_modify_check(hash); - if (!RHASH(hash)->ntbl) - return Qnil; - n = RHASH(hash)->ntbl->num_entries; -@@ -1065,8 +1058,9 @@ VALUE - rb_hash_keep_if(VALUE hash) - { - RETURN_ENUMERATOR(hash, 0, 0); -- rb_hash_modify(hash); -- rb_hash_foreach(hash, keep_if_i, hash); -+ rb_hash_modify_check(hash); -+ if (RHASH(hash)->ntbl) -+ rb_hash_foreach(hash, keep_if_i, hash); - return hash; - } - -@@ -1144,9 +1138,7 @@ rb_hash_aset(VALUE hash, VALUE key, VALUE val) - static int - replace_i(VALUE key, VALUE val, VALUE hash) - { -- if (key != Qundef) { -- rb_hash_aset(hash, key, val); -- } -+ rb_hash_aset(hash, key, val); - - return ST_CONTINUE; - } -@@ -1227,7 +1219,6 @@ rb_hash_empty_p(VALUE hash) - static int - each_value_i(VALUE key, VALUE value) - { -- if (key == Qundef) return ST_CONTINUE; - rb_yield(value); - return ST_CONTINUE; - } -@@ -1262,7 +1253,6 @@ rb_hash_each_value(VALUE hash) - static int - each_key_i(VALUE key, VALUE value) - { -- if (key == Qundef) return ST_CONTINUE; - rb_yield(key); - return ST_CONTINUE; - } -@@ -1296,7 +1286,6 @@ rb_hash_each_key(VALUE hash) - static int - each_pair_i(VALUE key, VALUE value) - { -- if (key == Qundef) return ST_CONTINUE; - rb_yield(rb_assoc_new(key, value)); - return ST_CONTINUE; - } -@@ -1334,7 +1323,6 @@ rb_hash_each_pair(VALUE hash) - static int - to_a_i(VALUE key, VALUE value, VALUE ary) - { -- if (key == Qundef) return ST_CONTINUE; - rb_ary_push(ary, rb_assoc_new(key, value)); - return ST_CONTINUE; - } -@@ -1367,7 +1355,6 @@ inspect_i(VALUE key, VALUE value, VALUE str) - { - VALUE str2; - -- if (key == Qundef) return ST_CONTINUE; - str2 = rb_inspect(key); - if (RSTRING_LEN(str) > 1) { - rb_str_cat2(str, ", "); -@@ -1434,7 +1421,6 @@ rb_hash_to_hash(VALUE hash) - static int - keys_i(VALUE key, VALUE value, VALUE ary) - { -- if (key == Qundef) return ST_CONTINUE; - rb_ary_push(ary, key); - return ST_CONTINUE; - } -@@ -1465,7 +1451,6 @@ rb_hash_keys(VALUE hash) - static int - values_i(VALUE key, VALUE value, VALUE ary) - { -- if (key == Qundef) return ST_CONTINUE; - rb_ary_push(ary, value); - return ST_CONTINUE; - } -@@ -1524,7 +1509,6 @@ rb_hash_search_value(VALUE key, VALUE value, VALUE arg) - { - VALUE *data = (VALUE *)arg; - -- if (key == Qundef) return ST_CONTINUE; - if (rb_equal(value, data[1])) { - data[0] = Qtrue; - return ST_STOP; -@@ -1568,7 +1552,6 @@ eql_i(VALUE key, VALUE val1, VALUE arg) - struct equal_data *data = (struct equal_data *)arg; - st_data_t val2; - -- if (key == Qundef) return ST_CONTINUE; - if (!st_lookup(data->tbl, key, &val2)) { - data->result = Qfalse; - return ST_STOP; -@@ -1599,7 +1582,7 @@ hash_equal(VALUE hash1, VALUE hash2, int eql) - struct equal_data data; - - if (hash1 == hash2) return Qtrue; -- if (TYPE(hash2) != T_HASH) { -+ if (!RB_TYPE_P(hash2, T_HASH)) { - if (!rb_respond_to(hash2, rb_intern("to_hash"))) { - return Qfalse; - } -@@ -1670,7 +1653,6 @@ hash_i(VALUE key, VALUE val, VALUE arg) - st_index_t *hval = (st_index_t *)arg; - st_index_t hdata[2]; - -- if (key == Qundef) return ST_CONTINUE; - hdata[0] = rb_hash(key); - hdata[1] = rb_hash(val); - *hval ^= st_hash(hdata, sizeof(hdata), 0); -@@ -1711,7 +1693,6 @@ rb_hash_hash(VALUE hash) - static int - rb_hash_invert_i(VALUE key, VALUE value, VALUE hash) - { -- if (key == Qundef) return ST_CONTINUE; - rb_hash_aset(hash, value, key); - return ST_CONTINUE; - } -@@ -1740,7 +1721,6 @@ rb_hash_invert(VALUE hash) - static int - rb_hash_update_i(VALUE key, VALUE value, VALUE hash) - { -- if (key == Qundef) return ST_CONTINUE; - hash_update(hash, key); - st_insert(RHASH(hash)->ntbl, key, value); - return ST_CONTINUE; -@@ -1749,7 +1729,6 @@ rb_hash_update_i(VALUE key, VALUE value, VALUE hash) - static int - rb_hash_update_block_i(VALUE key, VALUE value, VALUE hash) - { -- if (key == Qundef) return ST_CONTINUE; - if (rb_hash_has_key(hash, key)) { - value = rb_yield_values(3, key, rb_hash_aref(hash, key), value); - } -@@ -1806,7 +1785,6 @@ rb_hash_update_func_i(VALUE key, VALUE value, VALUE arg0) - struct update_arg *arg = (struct update_arg *)arg0; - VALUE hash = arg->hash; - -- if (key == Qundef) return ST_CONTINUE; - if (rb_hash_has_key(hash, key)) { - value = (*arg->func)(key, rb_hash_aref(hash, key), value); - } -@@ -1863,7 +1841,6 @@ assoc_i(VALUE key, VALUE val, VALUE arg) - { - VALUE *args = (VALUE *)arg; - -- if (key == Qundef) return ST_CONTINUE; - if (RTEST(rb_equal(args[0], key))) { - args[1] = rb_assoc_new(key, val); - return ST_STOP; -@@ -1901,7 +1878,6 @@ rassoc_i(VALUE key, VALUE val, VALUE arg) - { - VALUE *args = (VALUE *)arg; - -- if (key == Qundef) return ST_CONTINUE; - if (RTEST(rb_equal(args[0], val))) { - args[1] = rb_assoc_new(key, val); - return ST_STOP; -@@ -2198,7 +2174,7 @@ rb_env_path_tainted(void) - } - - #if defined(_WIN32) || (defined(HAVE_SETENV) && defined(HAVE_UNSETENV)) --#elif defined __sun__ -+#elif defined __sun - static int - in_origenv(const char *str) - { -@@ -2286,7 +2262,7 @@ ruby_setenv(const char *name, const char *value) - rb_sys_fail("unsetenv"); - #endif - } --#elif defined __sun__ -+#elif defined __sun - size_t len; - char **env_ptr, *str; - if (strchr(name, '=')) { -@@ -3084,11 +3060,9 @@ env_invert(void) - static int - env_replace_i(VALUE key, VALUE val, VALUE keys) - { -- if (key != Qundef) { -- env_aset(Qnil, key, val); -- if (rb_ary_includes(keys, key)) { -- rb_ary_delete(keys, key); -- } -+ env_aset(Qnil, key, val); -+ if (rb_ary_includes(keys, key)) { -+ rb_ary_delete(keys, key); - } - return ST_CONTINUE; - } -@@ -3120,12 +3094,10 @@ env_replace(VALUE env, VALUE hash) - static int - env_update_i(VALUE key, VALUE val) - { -- if (key != Qundef) { -- if (rb_block_given_p()) { -- val = rb_yield_values(3, key, rb_f_getenv(Qnil, key), val); -- } -- env_aset(Qnil, key, val); -+ if (rb_block_given_p()) { -+ val = rb_yield_values(3, key, rb_f_getenv(Qnil, key), val); - } -+ env_aset(Qnil, key, val); - return ST_CONTINUE; - } - -@@ -3150,15 +3122,116 @@ env_update(VALUE env, VALUE hash) - } - - /* -- * A Hash is a collection of key-value pairs. It is -- * similar to an Array, except that indexing is done via -- * arbitrary keys of any object type, not an integer index. Hashes enumerate -- * their values in the order that the corresponding keys were inserted. -+ * A Hash is a dictionary-like collection of unique keys and their values. -+ * Also called associative arrays, they are similar to Arrays, but where an -+ * Array uses integers as its index, a Hash allows you to use any object -+ * type. -+ * -+ * Hashes enumerate their values in the order that the corresponding keys -+ * were inserted. -+ * -+ * A Hash can be easily created by using its implicit form: -+ * -+ * grades = { "Jane Doe" => 10, "Jim Doe" => 6 } -+ * -+ * Hashes allow an alternate syntax form when your keys are always symbols. -+ * Instead of -+ * -+ * options = { :font_size => 10, :font_family => "Arial" } -+ * -+ * You could write it as: -+ * -+ * options = { font_size: 10, font_family: "Arial" } -+ * -+ * Each named key is a symbol you can access in hash: -+ * -+ * options[:font_size] # => 10 -+ * -+ * A Hash can also be created through its ::new method: -+ * -+ * grades = Hash.new -+ * grades["Dorothy Doe"] = 9 - * - * Hashes have a default value that is returned when accessing -- * keys that do not exist in the hash. By default, that value is -- * nil. -+ * keys that do not exist in the hash. If no default is set +nil+ is used. -+ * You can set the default value by sending it as an argument to Hash.new: -+ * -+ * grades = Hash.new(0) -+ * -+ * Or by using the #default= method: -+ * -+ * grades = {"Timmy Doe" => 8} -+ * grades.default = 0 -+ * -+ * Accessing a value in a Hash requires using its key: -+ * -+ * puts grades["Jane Doe"] # => 10 -+ * -+ * === Common Uses -+ * -+ * Hashes are an easy way to represent data structures, such as -+ * -+ * books = {} -+ * books[:matz] = "The Ruby Language" -+ * books[:black] = "The Well-Grounded Rubyist" -+ * -+ * Hashes are also commonly used as a way to have named parameters in -+ * functions. Note that no brackets are used below. If a hash is the last -+ * argument on a method call, no braces are needed, thus creating a really -+ * clean interface: -+ * -+ * Person.create(name: "John Doe", age: 27) -+ * -+ * def self.create(params) -+ * @name = params[:name] -+ * @age = params[:age] -+ * end -+ * -+ * === Hash Keys -+ * -+ * Two objects refer to the same hash key when their hash value -+ * is identical and the two objects are eql? to each other. -+ * -+ * A user-defined class may be used as a hash key if the hash -+ * and eql? methods are overridden to provide meaningful -+ * behavior. By default, separate instances refer to separate hash keys. -+ * -+ * A typical implementation of hash is based on the -+ * object's data while eql? is usually aliased to the overridden -+ * == method: -+ * -+ * class Book -+ * attr_reader :author, :title -+ * -+ * def initialize(author, title) -+ * @author = author -+ * @title = title -+ * end -+ * -+ * def ==(other) -+ * self.class === other and -+ * other.author == @author and -+ * other.title == @title -+ * end -+ * -+ * alias eql? == -+ * -+ * def hash -+ * @author.hash ^ @title.hash # XOR -+ * end -+ * end -+ * -+ * book1 = Book.new 'matz', 'Ruby in a Nutshell' -+ * book2 = Book.new 'matz', 'Ruby in a Nutshell' -+ * -+ * reviews = {} -+ * -+ * reviews[book1] = 'Great reference!' -+ * reviews[book2] = 'Nice and compact!' -+ * -+ * reviews.length #=> 1 - * -+ * See also Object#hash and Object#eql? - */ - - void -diff --git a/include/ruby/st.h b/include/ruby/st.h -index 50f2a75..119dfde 100644 ---- a/include/ruby/st.h -+++ b/include/ruby/st.h -@@ -36,7 +36,7 @@ typedef unsigned long st_data_t; - #elif SIZEOF_LONG_LONG == SIZEOF_VOIDP - typedef unsigned LONG_LONG st_data_t; - #else --# error ---->> st.c requires sizeof(void*) == sizeof(long) to be compiled. <<---- -+# error ---->> st.c requires sizeof(void*) == sizeof(long) or sizeof(LONG_LONG) to be compiled. <<---- - #endif - #define ST_DATA_T_DEFINED - -@@ -74,6 +74,11 @@ struct st_hash_type { - - #define ST_INDEX_BITS (sizeof(st_index_t) * CHAR_BIT) - -+typedef struct st_packed_entry { -+ st_index_t hash; -+ st_data_t key, val; -+} st_packed_entry; -+ - struct st_table { - const struct st_hash_type *type; - st_index_t num_bins; -@@ -91,8 +96,17 @@ struct st_table { - __extension__ - #endif - st_index_t num_entries : ST_INDEX_BITS - 1; -- struct st_table_entry **bins; -- struct st_table_entry *head, *tail; -+ union { -+ struct { -+ struct st_table_entry **bins; -+ struct st_table_entry *head, *tail; -+ } big; -+ struct { -+ struct st_packed_entry *entries; -+ st_index_t real_entries; -+ } packed; -+ st_packed_entry upacked; -+ } as; - }; - - #define st_is_member(table,key) st_lookup((table),(key),(st_data_t *)0) -@@ -114,6 +128,7 @@ int st_insert2(st_table *, st_data_t, st_data_t, st_data_t (*)(st_data_t)); - int st_lookup(st_table *, st_data_t, st_data_t *); - int st_get_key(st_table *, st_data_t, st_data_t *); - int st_foreach(st_table *, int (*)(ANYARGS), st_data_t); -+int st_foreach_check(st_table *, int (*)(ANYARGS), st_data_t, st_data_t); - int st_reverse_foreach(st_table *, int (*)(ANYARGS), st_data_t); - void st_add_direct(st_table *, st_data_t, st_data_t); - void st_free_table(st_table *); -diff --git a/pool_alloc.h b/pool_alloc.h -new file mode 100644 -index 0000000..957708e ---- /dev/null -+++ b/pool_alloc.h -@@ -0,0 +1,11 @@ -+#ifndef POOL_ALLOC_H -+#define POOL_ALLOC_H -+ -+#define POOL_ALLOC_API -+#ifdef POOL_ALLOC_API -+void ruby_xpool_free(void *ptr); -+void *ruby_xpool_malloc_6p(); -+void *ruby_xpool_malloc_11p(); -+#endif -+ -+#endif -diff --git a/pool_alloc.inc.h b/pool_alloc.inc.h -new file mode 100644 -index 0000000..a7879ab ---- /dev/null -+++ b/pool_alloc.inc.h -@@ -0,0 +1,156 @@ -+/* -+ * this is generic pool allocator -+ * you should define following macroses: -+ * ITEM_NAME - unique identifier, which allows to hold functions in a namespace -+ * ITEM_TYPEDEF(name) - passed to typedef to localize item type -+ * free_entry - desired name of function for free entry -+ * alloc_entry - defired name of function for allocate entry -+ */ -+ -+#if POOL_ALLOC_PART == 1 -+#ifdef HEAP_ALIGN_LOG -+#define DEFAULT_POOL_SIZE (1 << HEAP_ALIGN_LOG) -+#else -+#define DEFAULT_POOL_SIZE (sizeof(void*) * 2048) -+#endif -+typedef unsigned int pool_holder_counter; -+ -+typedef struct pool_entry_list pool_entry_list; -+typedef struct pool_holder pool_holder; -+ -+typedef struct pool_header { -+ pool_holder *first; -+ pool_holder *_black_magick; -+ pool_holder_counter size; // size of entry in sizeof(void*) items -+ pool_holder_counter total; // size of entry in sizeof(void*) items -+} pool_header; -+ -+struct pool_holder { -+ pool_holder_counter free, total; -+ pool_header *header; -+ void *freep; -+ pool_holder *fore, *back; -+ void *data[1]; -+}; -+#define POOL_DATA_SIZE(pool_size) (((pool_size) - sizeof(void*) * 6 - offsetof(pool_holder, data)) / sizeof(void*)) -+#define POOL_ENTRY_SIZE(item_type) ((sizeof(item_type) - 1) / sizeof(void*) + 1) -+#define POOL_HOLDER_COUNT(pool_size, item_type) (POOL_DATA_SIZE(pool_size)/POOL_ENTRY_SIZE(item_type)) -+#define INIT_POOL(item_type) {NULL, NULL, POOL_ENTRY_SIZE(item_type), POOL_HOLDER_COUNT(DEFAULT_POOL_SIZE, item_type)} -+ -+#elif POOL_ALLOC_PART == 2 -+static pool_holder * -+pool_holder_alloc(pool_header *header) -+{ -+ pool_holder *holder; -+ pool_holder_counter i, size, count; -+ register void **ptr; -+ -+ size_t sz = offsetof(pool_holder, data) + -+ header->size * header->total * sizeof(void*); -+#define objspace (&rb_objspace) -+ vm_malloc_prepare(objspace, DEFAULT_POOL_SIZE); -+ if (header->first != NULL) return header->first; -+ TRY_WITH_GC(holder = (pool_holder*) aligned_malloc(DEFAULT_POOL_SIZE, sz)); -+ malloc_increase += DEFAULT_POOL_SIZE; -+#if CALC_EXACT_MALLOC_SIZE -+ objspace->malloc_params.allocated_size += DEFAULT_POOL_SIZE; -+ objspace->malloc_params.allocations++; -+#endif -+#undef objspace -+ -+ size = header->size; -+ count = header->total; -+ holder->free = count; -+ holder->total = count; -+ holder->header = header; -+ holder->fore = NULL; -+ holder->back = NULL; -+ holder->freep = &holder->data; -+ ptr = holder->data; -+ for(i = count - 1; i; i-- ) { -+ ptr = *ptr = ptr + size; -+ } -+ *ptr = NULL; -+ header->first = holder; -+ return holder; -+} -+ -+static inline void -+pool_holder_unchaing(pool_header *header, pool_holder *holder) -+{ -+ register pool_holder *fore = holder->fore, *back = holder->back; -+ holder->fore = NULL; -+ holder->back = NULL; -+ if (fore != NULL) fore->back = back; -+ else header->_black_magick = back; -+ if (back != NULL) back->fore = fore; -+ else header->first = fore; -+} -+ -+static inline pool_holder * -+entry_holder(void **entry) -+{ -+ return (pool_holder*)(((uintptr_t)entry) & ~(DEFAULT_POOL_SIZE - 1)); -+} -+ -+static inline void -+pool_free_entry(void **entry) -+{ -+ pool_holder *holder = entry_holder(entry); -+ pool_header *header = holder->header; -+ -+ if (holder->free++ == 0) { -+ register pool_holder *first = header->first; -+ if (first == NULL) { -+ header->first = holder; -+ } else { -+ holder->back = first; -+ holder->fore = first->fore; -+ first->fore = holder; -+ if (holder->fore) -+ holder->fore->back = holder; -+ else -+ header->_black_magick = holder; -+ } -+ } else if (holder->free == holder->total && header->first != holder ) { -+ pool_holder_unchaing(header, holder); -+ aligned_free(holder); -+#if CALC_EXACT_MALLOC_SIZE -+ rb_objspace.malloc_params.allocated_size -= DEFAULT_POOL_SIZE; -+ rb_objspace.malloc_params.allocations--; -+#endif -+ return; -+ } -+ -+ *entry = holder->freep; -+ holder->freep = entry; -+} -+ -+static inline void* -+pool_alloc_entry(pool_header *header) -+{ -+ pool_holder *holder = header->first; -+ void **result; -+ if (holder == NULL) { -+ holder = pool_holder_alloc(header); -+ } -+ -+ result = holder->freep; -+ holder->freep = *result; -+ -+ if (--holder->free == 0) { -+ pool_holder_unchaing(header, holder); -+ } -+ -+ return result; -+} -+ -+static void -+pool_finalize_header(pool_header *header) -+{ -+ if (header->first) { -+ aligned_free(header->first); -+ header->first = NULL; -+ } -+} -+#endif -diff --git a/st.c b/st.c -index fda5784..0194022 100644 ---- a/st.c -+++ b/st.c -@@ -7,6 +7,7 @@ - #include "st.h" - #else - #include "ruby/ruby.h" -+#include "pool_alloc.h" - #endif - - #include -@@ -25,8 +26,17 @@ struct st_table_entry { - st_table_entry *fore, *back; - }; - --#define ST_DEFAULT_MAX_DENSITY 5 -+#define STATIC_ASSERT(name, expr) typedef int static_assert_##name##_check[(expr) ? 1 : -1]; -+ -+#define ST_DEFAULT_MAX_DENSITY 2 - #define ST_DEFAULT_INIT_TABLE_SIZE 11 -+#define ST_DEFAULT_SECOND_TABLE_SIZE 19 -+#define ST_DEFAULT_PACKED_TABLE_SIZE 19 -+#define PACKED_UNIT (int)(sizeof(st_packed_entry) / sizeof(st_table_entry*)) -+#define MAX_PACKED_HASH (int)(ST_DEFAULT_PACKED_TABLE_SIZE * sizeof(st_table_entry*) / sizeof(st_packed_entry)) -+ -+STATIC_ASSERT(st_packed_entry, sizeof(st_packed_entry) == sizeof(st_table_entry*[PACKED_UNIT])) -+STATIC_ASSERT(st_packed_bins, sizeof(st_packed_entry[MAX_PACKED_HASH]) <= sizeof(st_table_entry*[ST_DEFAULT_PACKED_TABLE_SIZE])) - - /* - * DEFAULT_MAX_DENSITY is the default for the largest we allow the -@@ -38,7 +48,8 @@ struct st_table_entry { - * - */ - --static const struct st_hash_type type_numhash = { -+#define type_numhash st_hashtype_num -+const struct st_hash_type st_hashtype_num = { - st_numcmp, - st_numhash, - }; -@@ -61,20 +72,128 @@ static void rehash(st_table *); - #ifdef RUBY - #define malloc xmalloc - #define calloc xcalloc -+#define realloc xrealloc - #define free(x) xfree(x) - #endif - - #define numberof(array) (int)(sizeof(array) / sizeof((array)[0])) - --#define alloc(type) (type*)malloc((size_t)sizeof(type)) --#define Calloc(n,s) (char*)calloc((n),(s)) -- - #define EQUAL(table,x,y) ((x)==(y) || (*(table)->type->compare)((x),(y)) == 0) - --/* remove cast to unsigned int in the future */ --#define do_hash(key,table) (unsigned int)(st_index_t)(*(table)->type->hash)((key)) -+#define do_hash(key,table) (st_index_t)(*(table)->type->hash)((key)) - #define do_hash_bin(key,table) (do_hash((key), (table))%(table)->num_bins) - -+/* preparation for possible allocation improvements */ -+#ifdef POOL_ALLOC_API -+#define st_alloc_entry() (st_table_entry *)ruby_xpool_malloc_6p() -+#define st_free_entry(entry) ruby_xpool_free(entry) -+#define st_alloc_table() (st_table *)ruby_xpool_malloc_6p() -+#define st_dealloc_table(table) ruby_xpool_free(table) -+static inline st_table_entry ** -+st_alloc_bins(st_index_t size) -+{ -+ st_table_entry **result; -+ if (size == 11) { -+ result = (st_table_entry **) ruby_xpool_malloc_11p(); -+ memset(result, 0, 11 * sizeof(st_table_entry *)); -+ } -+ else -+ result = (st_table_entry **) ruby_xcalloc(size, sizeof(st_table_entry*)); -+ return result; -+} -+static inline void -+st_free_bins(st_table_entry **bins, st_index_t size) -+{ -+ if (size == 11) -+ ruby_xpool_free(bins); -+ else -+ ruby_xfree(bins); -+} -+static inline st_table_entry** -+st_realloc_bins(st_table_entry **bins, st_index_t newsize, st_index_t oldsize) -+{ -+ st_table_entry **new_bins = st_alloc_bins(newsize); -+ st_free_bins(bins, oldsize); -+ return new_bins; -+} -+#else -+#define st_alloc_entry() (st_table_entry *)malloc(sizeof(st_table_entry)) -+#define st_free_entry(entry) free(entry) -+#define st_alloc_table() (st_table *)malloc(sizeof(st_table)) -+#define st_dealloc_table(table) free(table) -+#define st_alloc_bins(size) (st_table_entry **)calloc(size, sizeof(st_table_entry *)) -+#define st_free_bins(bins, size) free(bins) -+static inline st_table_entry** -+st_realloc_bins(st_table_entry **bins, st_index_t newsize, st_index_t oldsize) -+{ -+ bins = (st_table_entry **)realloc(bins, newsize * sizeof(st_table_entry *)); -+ MEMZERO(bins, st_table_entry*, newsize); -+ return bins; -+} -+#endif -+ -+/* Shortage */ -+#define bins as.big.bins -+#define head as.big.head -+#define tail as.big.tail -+#define real_entries as.packed.real_entries -+ -+/* preparation for possible packing improvements */ -+#define PACKED_BINS(table) ((table)->as.packed.entries) -+#define PACKED_ENT(table, i) PACKED_BINS(table)[i] -+#define PKEY(table, i) PACKED_ENT((table), (i)).key -+#define PVAL(table, i) PACKED_ENT((table), (i)).val -+#define PHASH(table, i) PACKED_ENT((table), (i)).hash -+#define PKEY_SET(table, i, v) (PKEY((table), (i)) = (v)) -+#define PVAL_SET(table, i, v) (PVAL((table), (i)) = (v)) -+#define PHASH_SET(table, i, v) (PHASH((table), (i)) = (v)) -+ -+/* this function depends much on packed layout, so that it placed here */ -+static inline void -+remove_packed_entry(st_table *table, st_index_t i) -+{ -+ table->real_entries--; -+ table->num_entries--; -+ if (i < table->real_entries) { -+ MEMMOVE(&PACKED_ENT(table, i), &PACKED_ENT(table, i+1), -+ st_packed_entry, table->real_entries - i); -+ } -+} -+ -+static inline void -+remove_safe_packed_entry(st_table *table, st_index_t i, st_data_t never) -+{ -+ table->num_entries--; -+ PKEY_SET(table, i, never); -+ PVAL_SET(table, i, never); -+ PHASH_SET(table, i, 0); -+} -+ -+/* ultrapacking */ -+#define real_upacked num_bins -+#define MAX_UPACKED_HASH 1 -+#define ULTRAPACKED(table) ((table)->real_upacked <= 1) -+#define UPACKED_ENT(table) ((table)->as.upacked) -+#define UPKEY(table) UPACKED_ENT(table).key -+#define UPVAL(table) UPACKED_ENT(table).val -+#define UPHASH(table) UPACKED_ENT(table).hash -+#define UPKEY_SET(table, v) (UPACKED_ENT(table).key = (v)) -+#define UPVAL_SET(table, v) (UPACKED_ENT(table).val = (v)) -+#define UPHASH_SET(table, v) (UPACKED_ENT(table).hash = (v)) -+static inline void -+remove_upacked_entry(st_table *table) -+{ -+ table->real_upacked = table->num_entries = 0; -+} -+ -+static inline void -+remove_safe_upacked_entry(st_table *table, st_data_t never) -+{ -+ table->num_entries = 0; -+ UPKEY_SET(table, never); -+ UPVAL_SET(table, never); -+ UPHASH_SET(table, 0); -+} - /* - * MINSIZE is the minimum size of a dictionary. - */ -@@ -85,8 +204,8 @@ static void rehash(st_table *); - Table of prime numbers 2^n+a, 2<=n<=30. - */ - static const unsigned int primes[] = { -- 8 + 3, -- 16 + 3, -+ ST_DEFAULT_INIT_TABLE_SIZE, -+ ST_DEFAULT_SECOND_TABLE_SIZE, - 32 + 5, - 64 + 3, - 128 + 3, -@@ -161,8 +280,6 @@ stat_col(void) - } - #endif - --#define MAX_PACKED_NUMHASH (ST_DEFAULT_INIT_TABLE_SIZE/2) -- - st_table* - st_init_table_with_size(const struct st_hash_type *type, st_index_t size) - { -@@ -181,14 +298,19 @@ st_init_table_with_size(const struct st_hash_type *type, st_index_t size) - } - #endif - -- size = new_size(size); /* round up to prime number */ - -- tbl = alloc(st_table); -+ tbl = st_alloc_table(); - tbl->type = type; - tbl->num_entries = 0; -- tbl->entries_packed = type == &type_numhash && size/2 <= MAX_PACKED_NUMHASH; -+ tbl->entries_packed = size <= MAX_PACKED_HASH; -+ if (tbl->entries_packed) { -+ size = size <= MAX_UPACKED_HASH ? 0 : ST_DEFAULT_PACKED_TABLE_SIZE; -+ } -+ else { -+ size = new_size(size); /* round up to prime number */ -+ } - tbl->num_bins = size; -- tbl->bins = (st_table_entry **)Calloc(size, sizeof(st_table_entry*)); -+ tbl->bins = size ? st_alloc_bins(size) : 0; - tbl->head = 0; - tbl->tail = 0; - -@@ -243,17 +365,23 @@ st_clear(st_table *table) - register st_table_entry *ptr, *next; - st_index_t i; - -+ if (ULTRAPACKED(table)) { -+ remove_upacked_entry(table); -+ return; -+ } -+ - if (table->entries_packed) { - table->num_entries = 0; -+ table->real_entries = 0; - return; - } - -- for(i = 0; i < table->num_bins; i++) { -+ for (i = 0; i < table->num_bins; i++) { - ptr = table->bins[i]; - table->bins[i] = 0; - while (ptr != 0) { - next = ptr->next; -- free(ptr); -+ st_free_entry(ptr); - ptr = next; - } - } -@@ -266,14 +394,19 @@ void - st_free_table(st_table *table) - { - st_clear(table); -- free(table->bins); -- free(table); -+ if (!ULTRAPACKED(table)) { -+ st_free_bins(table->bins, table->num_bins); -+ } -+ st_dealloc_table(table); - } - - size_t - st_memsize(const st_table *table) - { -- if (table->entries_packed) { -+ if (ULTRAPACKED(table)) { -+ return sizeof(st_table); -+ } -+ else if (table->entries_packed) { - return table->num_bins * sizeof (void *) + sizeof(st_table); - } - else { -@@ -306,46 +439,77 @@ count_collision(const struct st_hash_type *type) - #define FOUND_ENTRY - #endif - --#define FIND_ENTRY(table, ptr, hash_val, bin_pos) do {\ -- (bin_pos) = (hash_val)%(table)->num_bins;\ -- (ptr) = (table)->bins[(bin_pos)];\ -- FOUND_ENTRY;\ -- if (PTR_NOT_EQUAL((table), (ptr), (hash_val), key)) {\ -- COLLISION;\ -- while (PTR_NOT_EQUAL((table), (ptr)->next, (hash_val), key)) {\ -- (ptr) = (ptr)->next;\ -- }\ -- (ptr) = (ptr)->next;\ -- }\ --} while (0) -+#define FIND_ENTRY(table, ptr, hash_val, bin_pos) \ -+ ((ptr) = find_entry((table), key, (hash_val), ((bin_pos) = (hash_val)%(table)->num_bins))) -+ -+static st_table_entry * -+find_entry(st_table *table, st_data_t key, st_index_t hash_val, st_index_t bin_pos) -+{ -+ register st_table_entry *ptr = table->bins[bin_pos]; -+ FOUND_ENTRY; -+ if (PTR_NOT_EQUAL(table, ptr, hash_val, key)) { -+ COLLISION; -+ while (PTR_NOT_EQUAL(table, ptr->next, hash_val, key)) { -+ ptr = ptr->next; -+ } -+ ptr = ptr->next; -+ } -+ return ptr; -+} -+ -+static inline st_index_t -+find_packed_index(st_table *table, st_index_t hash_val, st_data_t key) -+{ -+ st_index_t i = 0; -+ while (i < table->real_entries && -+ (PHASH(table, i) != hash_val || !EQUAL(table, key, PKEY(table, i)))) { -+ i++; -+ } -+ return i; -+} -+ -+static inline int -+check_upacked(st_table *table, st_index_t hash_val, st_data_t key) -+{ -+ return table->num_entries && -+ UPHASH(table) == hash_val && -+ EQUAL(table, key, UPKEY(table)); -+} - - #define collision_check 0 - - int - st_lookup(st_table *table, register st_data_t key, st_data_t *value) - { -- st_index_t hash_val, bin_pos; -+ st_index_t hash_val; - register st_table_entry *ptr; - -+ hash_val = do_hash(key, table); -+ -+ if (ULTRAPACKED(table)) { -+ if (check_upacked(table, hash_val, key)) { -+ if (value != 0) *value = UPVAL(table); -+ return 1; -+ } -+ return 0; -+ } -+ - if (table->entries_packed) { -- st_index_t i; -- for (i = 0; i < table->num_entries; i++) { -- if ((st_data_t)table->bins[i*2] == key) { -- if (value !=0) *value = (st_data_t)table->bins[i*2+1]; -- return 1; -- } -- } -+ st_index_t i = find_packed_index(table, hash_val, key); -+ if (i < table->real_entries) { -+ if (value != 0) *value = PVAL(table, i); -+ return 1; -+ } - return 0; - } - -- hash_val = do_hash(key, table); -- FIND_ENTRY(table, ptr, hash_val, bin_pos); -+ ptr = find_entry(table, key, hash_val, hash_val % table->num_bins); - - if (ptr == 0) { - return 0; - } - else { -- if (value != 0) *value = ptr->record; -+ if (value != 0) *value = ptr->record; - return 1; - } - } -@@ -353,22 +517,29 @@ st_lookup(st_table *table, register st_data_t key, st_data_t *value) - int - st_get_key(st_table *table, register st_data_t key, st_data_t *result) - { -- st_index_t hash_val, bin_pos; -+ st_index_t hash_val; - register st_table_entry *ptr; - -+ hash_val = do_hash(key, table); -+ -+ if (ULTRAPACKED(table)) { -+ if (check_upacked(table, hash_val, key)) { -+ if (result != 0) *result = UPKEY(table); -+ return 1; -+ } -+ return 0; -+ } -+ - if (table->entries_packed) { -- st_index_t i; -- for (i = 0; i < table->num_entries; i++) { -- if ((st_data_t)table->bins[i*2] == key) { -- if (result !=0) *result = (st_data_t)table->bins[i*2]; -- return 1; -- } -- } -+ st_index_t i = find_packed_index(table, hash_val, key); -+ if (i < table->real_entries) { -+ if (result != 0) *result = PKEY(table, i); -+ return 1; -+ } - return 0; - } - -- hash_val = do_hash(key, table); -- FIND_ENTRY(table, ptr, hash_val, bin_pos); -+ ptr = find_entry(table, key, hash_val, hash_val % table->num_bins); - - if (ptr == 0) { - return 0; -@@ -382,85 +553,151 @@ st_get_key(st_table *table, register st_data_t key, st_data_t *result) - #undef collision_check - #define collision_check 1 - --#define MORE_PACKABLE_P(table) \ -- ((st_index_t)((table)->num_entries+1) * 2 <= (table)->num_bins && \ -- (table)->num_entries+1 <= MAX_PACKED_NUMHASH) -- --#define ADD_DIRECT(table, key, value, hash_val, bin_pos)\ --do {\ -- st_table_entry *entry;\ -- if ((table)->num_entries > ST_DEFAULT_MAX_DENSITY * (table)->num_bins) {\ -- rehash(table);\ -- (bin_pos) = (hash_val) % (table)->num_bins;\ -- }\ -- \ -- entry = alloc(st_table_entry);\ -- \ -- entry->hash = (hash_val);\ -- entry->key = (key);\ -- entry->record = (value);\ -- entry->next = (table)->bins[(bin_pos)];\ -- if ((table)->head != 0) {\ -- entry->fore = 0;\ -- (entry->back = (table)->tail)->fore = entry;\ -- (table)->tail = entry;\ -- }\ -- else {\ -- (table)->head = (table)->tail = entry;\ -- entry->fore = entry->back = 0;\ -- }\ -- (table)->bins[(bin_pos)] = entry;\ -- (table)->num_entries++;\ --} while (0) -+static inline st_table_entry * -+new_entry(st_table * table, st_data_t key, st_data_t value, -+ st_index_t hash_val, register st_index_t bin_pos) -+{ -+ register st_table_entry *entry = st_alloc_entry(); -+ -+ entry->next = table->bins[bin_pos]; -+ table->bins[bin_pos] = entry; -+ entry->hash = hash_val; -+ entry->key = key; -+ entry->record = value; -+ -+ return entry; -+} -+ -+static inline void -+add_direct(st_table *table, st_data_t key, st_data_t value, -+ st_index_t hash_val, register st_index_t bin_pos) -+{ -+ register st_table_entry *entry; -+ if (table->num_entries > ST_DEFAULT_MAX_DENSITY * table->num_bins) { -+ rehash(table); -+ bin_pos = hash_val % table->num_bins; -+ } -+ -+ entry = new_entry(table, key, value, hash_val, bin_pos); -+ -+ if (table->head != 0) { -+ entry->fore = 0; -+ (entry->back = table->tail)->fore = entry; -+ table->tail = entry; -+ } -+ else { -+ table->head = table->tail = entry; -+ entry->fore = entry->back = 0; -+ } -+ table->num_entries++; -+} - - static void - unpack_entries(register st_table *table) - { - st_index_t i; -- struct st_table_entry *packed_bins[MAX_PACKED_NUMHASH*2]; -+ st_packed_entry packed_bins[MAX_PACKED_HASH]; -+ register st_table_entry *entry, *preventry = 0, **chain; - st_table tmp_table = *table; - -- memcpy(packed_bins, table->bins, sizeof(struct st_table_entry *) * table->num_entries*2); -- table->bins = packed_bins; -+ MEMCPY(packed_bins, PACKED_BINS(table), st_packed_entry, MAX_PACKED_HASH); -+ table->as.packed.entries = packed_bins; - tmp_table.entries_packed = 0; -- tmp_table.num_entries = 0; -- memset(tmp_table.bins, 0, sizeof(struct st_table_entry *) * tmp_table.num_bins); -- for (i = 0; i < table->num_entries; i++) { -- st_insert(&tmp_table, (st_data_t)packed_bins[i*2], (st_data_t)packed_bins[i*2+1]); -- } -+#if ST_DEFAULT_INIT_TABLE_SIZE == ST_DEFAULT_PACKED_TABLE_SIZE -+ MEMZERO(tmp_table.bins, st_table_entry*, tmp_table.num_bins); -+#else -+ tmp_table.bins = st_realloc_bins(tmp_table.bins, ST_DEFAULT_INIT_TABLE_SIZE, tmp_table.num_bins); -+ tmp_table.num_bins = ST_DEFAULT_INIT_TABLE_SIZE; -+#endif -+ i = 0; -+ chain = &tmp_table.head; -+ do { -+ st_data_t key = packed_bins[i].key; -+ st_data_t val = packed_bins[i].val; -+ st_index_t hash = packed_bins[i].hash; -+ entry = new_entry(&tmp_table, key, val, hash, -+ hash % ST_DEFAULT_INIT_TABLE_SIZE); -+ *chain = entry; -+ entry->back = preventry; -+ preventry = entry; -+ chain = &entry->fore; -+ } while (++i < MAX_PACKED_HASH); -+ *chain = NULL; -+ tmp_table.tail = entry; - *table = tmp_table; - } - -+static void -+add_packed_direct(st_table *table, st_data_t key, st_data_t value, st_index_t hash_val) -+{ -+ if (table->real_entries < MAX_PACKED_HASH) { -+ st_index_t i = table->real_entries++; -+ PKEY_SET(table, i, key); -+ PVAL_SET(table, i, value); -+ PHASH_SET(table, i, hash_val); -+ table->num_entries++; -+ } -+ else { -+ unpack_entries(table); -+ add_direct(table, key, value, hash_val, hash_val % table->num_bins); -+ } -+} -+ -+static void -+add_upacked_direct(register st_table *table, register st_data_t key, st_data_t value, st_index_t hash_val) -+{ -+ if (table->real_upacked) { -+ st_packed_entry *entries = (st_packed_entry *) st_alloc_bins(ST_DEFAULT_PACKED_TABLE_SIZE); -+ entries[0] = UPACKED_ENT(table); -+ entries[1].hash = hash_val; -+ entries[1].key = key; -+ entries[1].val = value; -+ table->num_bins = ST_DEFAULT_PACKED_TABLE_SIZE; -+ table->real_entries = 2; -+ table->num_entries++; -+ table->as.packed.entries = entries; -+ } -+ else { -+ table->real_upacked = 1; -+ table->num_entries = 1; -+ UPHASH_SET(table, hash_val); -+ UPKEY_SET(table, key); -+ UPVAL_SET(table, value); -+ } -+} -+ - int - st_insert(register st_table *table, register st_data_t key, st_data_t value) - { -- st_index_t hash_val, bin_pos; -+ st_index_t hash_val; -+ register st_index_t bin_pos; - register st_table_entry *ptr; - -+ hash_val = do_hash(key, table); -+ -+ if (ULTRAPACKED(table)) { -+ if (check_upacked(table, hash_val, key)) { -+ UPVAL_SET(table, value); -+ return 1; -+ } -+ add_upacked_direct(table, key, value, hash_val); -+ return 0; -+ } -+ - if (table->entries_packed) { -- st_index_t i; -- for (i = 0; i < table->num_entries; i++) { -- if ((st_data_t)table->bins[i*2] == key) { -- table->bins[i*2+1] = (struct st_table_entry*)value; -- return 1; -- } -- } -- if (MORE_PACKABLE_P(table)) { -- i = table->num_entries++; -- table->bins[i*2] = (struct st_table_entry*)key; -- table->bins[i*2+1] = (struct st_table_entry*)value; -- return 0; -- } -- else { -- unpack_entries(table); -+ st_index_t i = find_packed_index(table, hash_val, key); -+ if (i < table->real_entries) { -+ PVAL_SET(table, i, value); -+ return 1; - } -+ add_packed_direct(table, key, value, hash_val); -+ return 0; - } - -- hash_val = do_hash(key, table); - FIND_ENTRY(table, ptr, hash_val, bin_pos); - - if (ptr == 0) { -- ADD_DIRECT(table, key, value, hash_val, bin_pos); -+ add_direct(table, key, value, hash_val, bin_pos); - return 0; - } - else { -@@ -473,34 +710,38 @@ int - st_insert2(register st_table *table, register st_data_t key, st_data_t value, - st_data_t (*func)(st_data_t)) - { -- st_index_t hash_val, bin_pos; -+ st_index_t hash_val; -+ register st_index_t bin_pos; - register st_table_entry *ptr; - -+ hash_val = do_hash(key, table); -+ -+ if (ULTRAPACKED(table)) { -+ if (check_upacked(table, hash_val, key)) { -+ UPVAL_SET(table, value); -+ return 1; -+ } -+ key = (*func)(key); -+ add_upacked_direct(table, key, value, hash_val); -+ return 0; -+ } -+ - if (table->entries_packed) { -- st_index_t i; -- for (i = 0; i < table->num_entries; i++) { -- if ((st_data_t)table->bins[i*2] == key) { -- table->bins[i*2+1] = (struct st_table_entry*)value; -- return 1; -- } -- } -- if (MORE_PACKABLE_P(table)) { -- i = table->num_entries++; -- table->bins[i*2] = (struct st_table_entry*)key; -- table->bins[i*2+1] = (struct st_table_entry*)value; -- return 0; -- } -- else { -- unpack_entries(table); -- } -+ st_index_t i = find_packed_index(table, hash_val, key); -+ if (i < table->real_entries) { -+ PVAL_SET(table, i, value); -+ return 1; -+ } -+ key = (*func)(key); -+ add_packed_direct(table, key, value, hash_val); -+ return 0; - } - -- hash_val = do_hash(key, table); - FIND_ENTRY(table, ptr, hash_val, bin_pos); - - if (ptr == 0) { - key = (*func)(key); -- ADD_DIRECT(table, key, value, hash_val, bin_pos); -+ add_direct(table, key, value, hash_val, bin_pos); - return 0; - } - else { -@@ -512,36 +753,30 @@ st_insert2(register st_table *table, register st_data_t key, st_data_t value, - void - st_add_direct(st_table *table, st_data_t key, st_data_t value) - { -- st_index_t hash_val, bin_pos; -+ st_index_t hash_val; -+ -+ hash_val = do_hash(key, table); -+ if (ULTRAPACKED(table)) { -+ add_upacked_direct(table, key, value, hash_val); -+ return; -+ } - - if (table->entries_packed) { -- int i; -- if (MORE_PACKABLE_P(table)) { -- i = table->num_entries++; -- table->bins[i*2] = (struct st_table_entry*)key; -- table->bins[i*2+1] = (struct st_table_entry*)value; -- return; -- } -- else { -- unpack_entries(table); -- } -+ add_packed_direct(table, key, value, hash_val); -+ return; - } - -- hash_val = do_hash(key, table); -- bin_pos = hash_val % table->num_bins; -- ADD_DIRECT(table, key, value, hash_val, bin_pos); -+ add_direct(table, key, value, hash_val, hash_val % table->num_bins); - } - - static void - rehash(register st_table *table) - { - register st_table_entry *ptr, **new_bins; -- st_index_t i, new_num_bins, hash_val; -+ st_index_t new_num_bins, hash_val; - - new_num_bins = new_size(table->num_bins+1); -- new_bins = (st_table_entry**) -- xrealloc(table->bins, new_num_bins * sizeof(st_table_entry*)); -- for (i = 0; i < new_num_bins; ++i) new_bins[i] = 0; -+ new_bins = st_realloc_bins(table->bins, new_num_bins, table->num_bins); - table->num_bins = new_num_bins; - table->bins = new_bins; - -@@ -558,34 +793,37 @@ st_table* - st_copy(st_table *old_table) - { - st_table *new_table; -- st_table_entry *ptr, *entry, *prev, **tail; -+ st_table_entry *ptr, *entry, *prev, **tailp; - st_index_t num_bins = old_table->num_bins; - st_index_t hash_val; - -- new_table = alloc(st_table); -+ new_table = st_alloc_table(); - if (new_table == 0) { - return 0; - } - - *new_table = *old_table; -- new_table->bins = (st_table_entry**) -- Calloc((unsigned)num_bins, sizeof(st_table_entry*)); -+ if (ULTRAPACKED(old_table)) { -+ return new_table; -+ } -+ -+ new_table->bins = st_alloc_bins(num_bins); - - if (new_table->bins == 0) { -- free(new_table); -+ st_dealloc_table(new_table); - return 0; - } - - if (old_table->entries_packed) { -- memcpy(new_table->bins, old_table->bins, sizeof(struct st_table_entry *) * old_table->num_bins); -+ MEMCPY(new_table->bins, old_table->bins, st_table_entry*, old_table->num_bins); - return new_table; - } - - if ((ptr = old_table->head) != 0) { - prev = 0; -- tail = &new_table->head; -+ tailp = &new_table->head; - do { -- entry = alloc(st_table_entry); -+ entry = st_alloc_entry(); - if (entry == 0) { - st_free_table(new_table); - return 0; -@@ -595,8 +833,8 @@ st_copy(st_table *old_table) - entry->next = new_table->bins[hash_val]; - new_table->bins[hash_val] = entry; - entry->back = prev; -- *tail = prev = entry; -- tail = &entry->fore; -+ *tailp = prev = entry; -+ tailp = &entry->fore; - } while ((ptr = ptr->fore) != 0); - new_table->tail = prev; - } -@@ -604,21 +842,22 @@ st_copy(st_table *old_table) - return new_table; - } - --#define REMOVE_ENTRY(table, ptr) do \ -- { \ -- if ((ptr)->fore == 0 && (ptr)->back == 0) { \ -- (table)->head = 0; \ -- (table)->tail = 0; \ -- } \ -- else { \ -- st_table_entry *fore = (ptr)->fore, *back = (ptr)->back; \ -- if (fore) fore->back = back; \ -- if (back) back->fore = fore; \ -- if ((ptr) == (table)->head) (table)->head = fore; \ -- if ((ptr) == (table)->tail) (table)->tail = back; \ -- } \ -- (table)->num_entries--; \ -- } while (0) -+static inline void -+remove_entry(st_table *table, st_table_entry *ptr) -+{ -+ if (ptr->fore == 0 && ptr->back == 0) { -+ table->head = 0; -+ table->tail = 0; -+ } -+ else { -+ st_table_entry *fore = ptr->fore, *back = ptr->back; -+ if (fore) fore->back = back; -+ if (back) back->fore = fore; -+ if (ptr == table->head) table->head = fore; -+ if (ptr == table->tail) table->tail = back; -+ } -+ table->num_entries--; -+} - - int - st_delete(register st_table *table, register st_data_t *key, st_data_t *value) -@@ -627,30 +866,38 @@ st_delete(register st_table *table, register st_data_t *key, st_data_t *value) - st_table_entry **prev; - register st_table_entry *ptr; - -+ hash_val = do_hash(*key, table); -+ -+ if (ULTRAPACKED(table)) { -+ if (check_upacked(table, hash_val, *key)) { -+ if (value != 0) *value = UPVAL(table); -+ *key = UPKEY(table); -+ remove_upacked_entry(table); -+ return 1; -+ } -+ return 0; -+ } -+ - if (table->entries_packed) { -- st_index_t i; -- for (i = 0; i < table->num_entries; i++) { -- if ((st_data_t)table->bins[i*2] == *key) { -- if (value != 0) *value = (st_data_t)table->bins[i*2+1]; -- table->num_entries--; -- memmove(&table->bins[i*2], &table->bins[(i+1)*2], -- sizeof(struct st_table_entry*) * 2*(table->num_entries-i)); -- return 1; -- } -+ st_index_t i = find_packed_index(table, hash_val, *key); -+ if (i < table->real_entries) { -+ if (value != 0) *value = PVAL(table, i); -+ *key = PKEY(table, i); -+ remove_packed_entry(table, i); -+ return 1; - } - if (value != 0) *value = 0; - return 0; - } - -- hash_val = do_hash_bin(*key, table); -- -- for (prev = &table->bins[hash_val]; (ptr = *prev) != 0; prev = &ptr->next) { -+ prev = &table->bins[hash_val % table->num_bins]; -+ for (;(ptr = *prev) != 0; prev = &ptr->next) { - if (EQUAL(table, *key, ptr->key)) { - *prev = ptr->next; -- REMOVE_ENTRY(table, ptr); -+ remove_entry(table, ptr); - if (value != 0) *value = ptr->record; - *key = ptr->key; -- free(ptr); -+ st_free_entry(ptr); - return 1; - } - } -@@ -665,25 +912,36 @@ st_delete_safe(register st_table *table, register st_data_t *key, st_data_t *val - st_index_t hash_val; - register st_table_entry *ptr; - -+ hash_val = do_hash(*key, table); -+ -+ if (ULTRAPACKED(table)) { -+ if (check_upacked(table, hash_val, *key)) { -+ if (value != 0) *value = UPVAL(table); -+ *key = UPKEY(table); -+ remove_safe_upacked_entry(table, never); -+ return 1; -+ } -+ if (value != 0) *value = 0; -+ return 0; -+ } -+ - if (table->entries_packed) { -- st_index_t i; -- for (i = 0; i < table->num_entries; i++) { -- if ((st_data_t)table->bins[i*2] == *key) { -- if (value != 0) *value = (st_data_t)table->bins[i*2+1]; -- table->bins[i*2] = (void *)never; -- return 1; -- } -+ st_index_t i = find_packed_index(table, hash_val, *key); -+ if (i < table->real_entries) { -+ if (value != 0) *value = PVAL(table, i); -+ *key = PKEY(table, i); -+ remove_safe_packed_entry(table, i, never); -+ return 1; - } - if (value != 0) *value = 0; - return 0; - } - -- hash_val = do_hash_bin(*key, table); -- ptr = table->bins[hash_val]; -+ ptr = table->bins[hash_val % table->num_bins]; - - for (; ptr != 0; ptr = ptr->next) { - if ((ptr->key != never) && EQUAL(table, ptr->key, *key)) { -- REMOVE_ENTRY(table, ptr); -+ remove_entry(table, ptr); - *key = ptr->key; - if (value != 0) *value = ptr->record; - ptr->key = ptr->record = never; -@@ -701,17 +959,23 @@ st_cleanup_safe(st_table *table, st_data_t never) - st_table_entry *ptr, **last, *tmp; - st_index_t i; - -+ if (ULTRAPACKED(table)) { -+ table->real_upacked = table->num_entries; -+ return; -+ } -+ - if (table->entries_packed) { - st_index_t i = 0, j = 0; -- while ((st_data_t)table->bins[i*2] != never) { -- if (i++ == table->num_entries) return; -+ while (PKEY(table, i) != never) { -+ if (i++ == table->real_entries) return; - } -- for (j = i; ++i < table->num_entries;) { -- if ((st_data_t)table->bins[i*2] == never) continue; -- table->bins[j*2] = table->bins[i*2]; -- table->bins[j*2+1] = table->bins[i*2+1]; -+ for (j = i; ++i < table->real_entries;) { -+ if (PKEY(table, i) == never) continue; -+ PACKED_ENT(table, j) = PACKED_ENT(table, i); - j++; - } -+ table->real_entries = j; -+ /* table->num_entries really should be equal j at this moment, but let set it anyway */ - table->num_entries = j; - return; - } -@@ -722,7 +986,7 @@ st_cleanup_safe(st_table *table, st_data_t never) - if (ptr->key == never) { - tmp = ptr; - *last = ptr = ptr->next; -- free(tmp); -+ st_free_entry(tmp); - } - else { - ptr = *(last = &ptr->next); -@@ -732,50 +996,78 @@ st_cleanup_safe(st_table *table, st_data_t never) - } - - int --st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) -+st_foreach_check(st_table *table, int (*func)(ANYARGS), st_data_t arg, st_data_t never) - { - st_table_entry *ptr, **last, *tmp; - enum st_retval retval; -- st_index_t i; -+ st_data_t key, val; -+ st_index_t hash, i = 0; -+ -+ if (table->num_entries == 0) { -+ return 0; -+ } -+ -+ if (ULTRAPACKED(table)) { -+ key = UPKEY(table); -+ val = UPVAL(table); -+ hash = UPHASH(table); -+ if (key == never) return 0; -+ retval = (*func)(key, val, arg); -+ if (!ULTRAPACKED(table)) { -+ goto packed; -+ } -+ switch(retval) { -+ case ST_CHECK: -+ if (UPHASH(table) == 0 && UPKEY(table) == never) -+ break; -+ if (check_upacked(table, hash, key)) -+ break; -+ goto deleted; -+ case ST_DELETE: -+ remove_safe_upacked_entry(table, never); -+ case ST_CONTINUE: -+ case ST_STOP: -+ break; -+ } -+ return 0; -+ } - - if (table->entries_packed) { -- for (i = 0; i < table->num_entries; i++) { -- st_index_t j; -- st_data_t key, val; -- key = (st_data_t)table->bins[i*2]; -- val = (st_data_t)table->bins[i*2+1]; -- retval = (*func)(key, val, arg); -+ for (i = 0; i < table->real_entries; i++) { -+ key = PKEY(table, i); -+ val = PVAL(table, i); -+ hash = PHASH(table, i); -+ if (key == never) continue; -+ retval = (*func)(key, val, arg); -+ packed: - if (!table->entries_packed) { -- FIND_ENTRY(table, ptr, key, i); -+ FIND_ENTRY(table, ptr, hash, i); - if (retval == ST_CHECK) { - if (!ptr) goto deleted; - goto unpacked_continue; - } - goto unpacked; - } -- switch (retval) { -+ switch (retval) { - case ST_CHECK: /* check if hash is modified during iteration */ -- for (j = 0; j < table->num_entries; j++) { -- if ((st_data_t)table->bins[j*2] == key) -- break; -- } -- if (j == table->num_entries) { -+ if (PHASH(table, i) == 0 && PKEY(table, i) == never) { -+ break; -+ } -+ i = find_packed_index(table, hash, key); -+ if (i == table->real_entries) { - goto deleted; -- } -+ } - /* fall through */ - case ST_CONTINUE: - break; - case ST_STOP: - return 0; - case ST_DELETE: -- table->num_entries--; -- memmove(&table->bins[i*2], &table->bins[(i+1)*2], -- sizeof(struct st_table_entry*) * 2*(table->num_entries-i)); -- i--; -- break; -- } -- } -- return 0; -+ remove_safe_packed_entry(table, i, never); -+ break; -+ } -+ } -+ return 0; - } - else { - ptr = table->head; -@@ -783,6 +1075,8 @@ st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) - - if (ptr != 0) { - do { -+ if (ptr->key == never) -+ goto unpacked_continue; - i = ptr->hash % table->num_bins; - retval = (*func)(ptr->key, ptr->record, arg); - unpacked: -@@ -808,10 +1102,100 @@ st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) - for (; (tmp = *last) != 0; last = &tmp->next) { - if (ptr == tmp) { - tmp = ptr->fore; -+ remove_entry(table, ptr); -+ ptr->key = ptr->record = never; -+ ptr->hash = 0; -+ ptr = tmp; -+ break; -+ } -+ } -+ } -+ } while (ptr && table->head); -+ } -+ return 0; -+} -+ -+int -+st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) -+{ -+ st_table_entry *ptr, **last, *tmp; -+ enum st_retval retval; -+ st_data_t key, val; -+ st_index_t hash, i = 0; -+ -+ if (table->num_entries == 0) { -+ return 0; -+ } -+ -+ if (ULTRAPACKED(table)) { -+ key = UPKEY(table); -+ val = UPVAL(table); -+ hash = UPHASH(table); -+ retval = (*func)(key, val, arg); -+ if (!ULTRAPACKED(table)) { -+ goto packed; -+ } -+ switch (retval) { -+ case ST_DELETE: -+ remove_upacked_entry(table); -+ case ST_CONTINUE: -+ case ST_CHECK: -+ case ST_STOP: -+ break; -+ } -+ return 0; -+ } -+ -+ if (table->entries_packed) { -+ for (i = 0; i < table->real_entries; i++) { -+ key = PKEY(table, i); -+ val = PVAL(table, i); -+ hash = PHASH(table, i); -+ retval = (*func)(key, val, arg); -+ packed: -+ if (!table->entries_packed) { -+ FIND_ENTRY(table, ptr, hash, i); -+ if (!ptr) return 0; -+ goto unpacked; -+ } -+ switch (retval) { -+ case ST_CONTINUE: -+ break; -+ case ST_CHECK: -+ case ST_STOP: -+ return 0; -+ case ST_DELETE: -+ remove_packed_entry(table, i); -+ i--; -+ break; -+ } -+ } -+ return 0; -+ } -+ else { -+ ptr = table->head; -+ } -+ -+ if (ptr != 0) { -+ do { -+ i = ptr->hash % table->num_bins; -+ retval = (*func)(ptr->key, ptr->record, arg); -+ unpacked: -+ switch (retval) { -+ case ST_CONTINUE: -+ ptr = ptr->fore; -+ break; -+ case ST_CHECK: -+ case ST_STOP: -+ return 0; -+ case ST_DELETE: -+ last = &table->bins[ptr->hash % table->num_bins]; -+ for (; (tmp = *last) != 0; last = &tmp->next) { -+ if (ptr == tmp) { -+ tmp = ptr->fore; - *last = ptr->next; -- REMOVE_ENTRY(table, ptr); -- free(ptr); -- if (ptr == tmp) return 0; -+ remove_entry(table, ptr); -+ st_free_entry(ptr); - ptr = tmp; - break; - } -@@ -834,13 +1218,13 @@ st_reverse_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) - for (i = table->num_entries-1; 0 <= i; i--) { - int j; - st_data_t key, val; -- key = (st_data_t)table->bins[i*2]; -- val = (st_data_t)table->bins[i*2+1]; -+ key = PKEY(table, i); -+ val = PVAL(table, i); - retval = (*func)(key, val, arg); - switch (retval) { - case ST_CHECK: /* check if hash is modified during iteration */ - for (j = 0; j < table->num_entries; j++) { -- if ((st_data_t)table->bins[j*2] == key) -+ if (PKEY(table, j) == key) - break; - } - if (j == table->num_entries) { -@@ -854,9 +1238,7 @@ st_reverse_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) - case ST_STOP: - return 0; - case ST_DELETE: -- table->num_entries--; -- memmove(&table->bins[i*2], &table->bins[(i+1)*2], -- sizeof(struct st_table_entry*) * 2*(table->num_entries-i)); -+ remove_packed_entry(table, i); - break; - } - } -@@ -889,8 +1271,8 @@ st_reverse_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) - if (ptr == tmp) { - tmp = ptr->back; - *last = ptr->next; -- REMOVE_ENTRY(table, ptr); -- free(ptr); -+ remove_entry(table, ptr); -+ st_free_entry(ptr); - ptr = tmp; - break; - } diff --git a/patches/ruby/1.9.3/p385/railsexpress/11-falcon-sparse-array.patch b/patches/ruby/1.9.3/p385/railsexpress/11-falcon-sparse-array.patch deleted file mode 100644 index 30e917f17d..0000000000 --- a/patches/ruby/1.9.3/p385/railsexpress/11-falcon-sparse-array.patch +++ /dev/null @@ -1,2467 +0,0 @@ -diff --git a/class.c b/class.c -index 4fbdf18..f5cb4a1 100644 ---- a/class.c -+++ b/class.c -@@ -31,7 +31,7 @@ - #include "internal.h" - #include - --extern st_table *rb_class_tbl; -+extern sa_table rb_class_tbl; - static ID id_attached; - - /** -@@ -53,11 +53,15 @@ class_alloc(VALUE flags, VALUE klass) - NEWOBJ(obj, struct RClass); - OBJSETUP(obj, klass, flags); - obj->ptr = ext; -- RCLASS_IV_TBL(obj) = 0; -- RCLASS_CONST_TBL(obj) = 0; -- RCLASS_M_TBL(obj) = 0; -- RCLASS_SUPER(obj) = 0; -- RCLASS_IV_INDEX_TBL(obj) = 0; -+ MEMZERO(ext, struct rb_classext_struct, 1); -+ return (VALUE)obj; -+} -+ -+static VALUE -+iclass_alloc() -+{ -+ NEWOBJ(obj, struct RClass); -+ OBJSETUP(obj, rb_cClass, T_ICLASS); - return (VALUE)obj; - } - -@@ -77,7 +81,6 @@ rb_class_boot(VALUE super) - VALUE klass = class_alloc(T_CLASS, rb_cClass); - - RCLASS_SUPER(klass) = super; -- RCLASS_M_TBL(klass) = st_init_numtable(); - - OBJ_INFECT(klass, super); - return (VALUE)klass; -@@ -120,43 +123,30 @@ rb_class_new(VALUE super) - return rb_class_boot(super); - } - --struct clone_method_data { -- st_table *tbl; -- VALUE klass; --}; -- - VALUE rb_iseq_clone(VALUE iseqval, VALUE newcbase); - --static int --clone_method(ID mid, const rb_method_entry_t *me, struct clone_method_data *data) -+static void -+clone_method(ID mid, const rb_method_entry_t *me, VALUE klass) - { - VALUE newiseqval; - if (me->def && me->def->type == VM_METHOD_TYPE_ISEQ) { - rb_iseq_t *iseq; -- newiseqval = rb_iseq_clone(me->def->body.iseq->self, data->klass); -+ newiseqval = rb_iseq_clone(me->def->body.iseq->self, klass); - GetISeqPtr(newiseqval, iseq); -- rb_add_method(data->klass, mid, VM_METHOD_TYPE_ISEQ, iseq, me->flag); -+ rb_add_method(klass, mid, VM_METHOD_TYPE_ISEQ, iseq, me->flag); - RB_GC_GUARD(newiseqval); - } - else { -- rb_method_entry_set(data->klass, mid, me, me->flag); -+ rb_method_entry_set(klass, mid, me, me->flag); - } -- return ST_CONTINUE; - } - --static int --clone_const(ID key, const rb_const_entry_t *ce, st_table *tbl) -+static void -+clone_const(sa_index_t key, st_data_t ce, sa_table *tbl) - { - rb_const_entry_t *nce = ALLOC(rb_const_entry_t); -- *nce = *ce; -- st_insert(tbl, key, (st_data_t)nce); -- return ST_CONTINUE; --} -- --static int --clone_const_i(st_data_t key, st_data_t value, st_data_t data) --{ -- return clone_const((ID)key, (const rb_const_entry_t *)value, (st_table *)data); -+ *nce = *(const rb_const_entry_t*)ce; -+ sa_insert(tbl, (sa_index_t)key, (st_data_t)nce); - } - - static void -@@ -177,6 +167,7 @@ class_init_copy_check(VALUE clone, VALUE orig) - VALUE - rb_mod_init_copy(VALUE clone, VALUE orig) - { -+ ID id; - if (RB_TYPE_P(clone, T_CLASS)) { - class_init_copy_check(clone, orig); - } -@@ -186,36 +177,22 @@ rb_mod_init_copy(VALUE clone, VALUE orig) - rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone); - } - RCLASS_SUPER(clone) = RCLASS_SUPER(orig); -- if (RCLASS_IV_TBL(orig)) { -- st_data_t id; - -- if (RCLASS_IV_TBL(clone)) { -- st_free_table(RCLASS_IV_TBL(clone)); -- } -- RCLASS_IV_TBL(clone) = st_copy(RCLASS_IV_TBL(orig)); -- CONST_ID(id, "__classpath__"); -- st_delete(RCLASS_IV_TBL(clone), &id, 0); -- CONST_ID(id, "__classid__"); -- st_delete(RCLASS_IV_TBL(clone), &id, 0); -- } -- if (RCLASS_CONST_TBL(orig)) { -- if (RCLASS_CONST_TBL(clone)) { -- rb_free_const_table(RCLASS_CONST_TBL(clone)); -- } -- RCLASS_CONST_TBL(clone) = st_init_numtable(); -- st_foreach(RCLASS_CONST_TBL(orig), clone_const_i, (st_data_t)RCLASS_CONST_TBL(clone)); -- } -- if (RCLASS_M_TBL(orig)) { -- struct clone_method_data data; -+ sa_copy_to(RCLASS_IV_TBL(orig), RCLASS_IV_TBL(clone)); -+ CONST_ID(id, "__classpath__"); -+ sa_delete(RCLASS_IV_TBL(clone), (sa_index_t)id, 0); -+ CONST_ID(id, "__classid__"); -+ sa_delete(RCLASS_IV_TBL(clone), (sa_index_t)id, 0); - -- if (RCLASS_M_TBL(clone)) { -- rb_free_m_table(RCLASS_M_TBL(clone)); -- } -- data.tbl = RCLASS_M_TBL(clone) = st_init_numtable(); -- data.klass = clone; -- st_foreach(RCLASS_M_TBL(orig), clone_method, -- (st_data_t)&data); -- } -+ sa_clear(RCLASS_CONST_TBL(clone)); -+ SA_FOREACH_START(RCLASS_CONST_TBL(orig)); -+ clone_const(entry->key, value, RCLASS_CONST_TBL(clone)); -+ SA_FOREACH_END(); -+ -+ rb_free_m_table(RCLASS_M_TBL(clone)); -+ SA_FOREACH_START(RCLASS_M_TBL(orig)); -+ clone_method(entry->key, (const rb_method_entry_t *)value, clone); -+ SA_FOREACH_END(); - - return clone; - } -@@ -228,7 +205,6 @@ rb_singleton_class_clone(VALUE obj) - if (!FL_TEST(klass, FL_SINGLETON)) - return klass; - else { -- struct clone_method_data data; - /* copy singleton(unnamed) class */ - VALUE clone = class_alloc((RBASIC(klass)->flags & ~(FL_MARK)), 0); - -@@ -240,18 +216,16 @@ rb_singleton_class_clone(VALUE obj) - } - - RCLASS_SUPER(clone) = RCLASS_SUPER(klass); -- if (RCLASS_IV_TBL(klass)) { -- RCLASS_IV_TBL(clone) = st_copy(RCLASS_IV_TBL(klass)); -- } -- if (RCLASS_CONST_TBL(klass)) { -- RCLASS_CONST_TBL(clone) = st_init_numtable(); -- st_foreach(RCLASS_CONST_TBL(klass), clone_const_i, (st_data_t)RCLASS_CONST_TBL(clone)); -- } -- RCLASS_M_TBL(clone) = st_init_numtable(); -- data.tbl = RCLASS_M_TBL(clone); -- data.klass = (VALUE)clone; -- st_foreach(RCLASS_M_TBL(klass), clone_method, -- (st_data_t)&data); -+ sa_copy_to(RCLASS_IV_TBL(klass), RCLASS_IV_TBL(clone)); -+ -+ SA_FOREACH_START(RCLASS_CONST_TBL(klass)); -+ clone_const(entry->key, value, RCLASS_CONST_TBL(clone)); -+ SA_FOREACH_END(); -+ -+ SA_FOREACH_START(RCLASS_M_TBL(klass)); -+ clone_method(entry->key, (const rb_method_entry_t*)value, clone); -+ SA_FOREACH_END(); -+ - rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone); - FL_SET(clone, FL_SINGLETON); - return (VALUE)clone; -@@ -266,10 +240,7 @@ void - rb_singleton_class_attached(VALUE klass, VALUE obj) - { - if (FL_TEST(klass, FL_SINGLETON)) { -- if (!RCLASS_IV_TBL(klass)) { -- RCLASS_IV_TBL(klass) = st_init_numtable(); -- } -- st_insert(RCLASS_IV_TBL(klass), id_attached, obj); -+ sa_insert(RCLASS_IV_TBL(klass), (sa_index_t)id_attached, obj); - } - } - -@@ -356,12 +327,12 @@ make_singleton_class(VALUE obj) - static VALUE - boot_defclass(const char *name, VALUE super) - { -- extern st_table *rb_class_tbl; -+ extern sa_table rb_class_tbl; - VALUE obj = rb_class_boot(super); - ID id = rb_intern(name); - - rb_name_class(obj, id); -- st_add_direct(rb_class_tbl, id, obj); -+ sa_insert(&rb_class_tbl, (sa_index_t)id, obj); - rb_const_set((rb_cObject ? rb_cObject : obj), id, obj); - return obj; - } -@@ -485,7 +456,7 @@ rb_define_class(const char *name, VALUE super) - rb_warn("no super class for `%s', Object assumed", name); - } - klass = rb_define_class_id(id, super); -- st_add_direct(rb_class_tbl, id, klass); -+ sa_insert(&rb_class_tbl, (sa_index_t)id, klass); - rb_name_class(klass, id); - rb_const_set(rb_cObject, id, klass); - rb_class_inherited(super, klass); -@@ -566,8 +537,6 @@ rb_module_new(void) - { - VALUE mdl = class_alloc(T_MODULE, rb_cModule); - -- RCLASS_M_TBL(mdl) = st_init_numtable(); -- - return (VALUE)mdl; - } - -@@ -596,7 +565,7 @@ rb_define_module(const char *name) - rb_raise(rb_eTypeError, "%s is not a module", rb_obj_classname(module)); - } - module = rb_define_module_id(id); -- st_add_direct(rb_class_tbl, id, module); -+ sa_insert(&rb_class_tbl, (sa_index_t)id, module); - rb_const_set(rb_cObject, id, module); - - return module; -@@ -631,27 +600,15 @@ rb_define_module_id_under(VALUE outer, ID id) - static VALUE - include_class_new(VALUE module, VALUE super) - { -- VALUE klass = class_alloc(T_ICLASS, rb_cClass); -+ VALUE klass; - - if (BUILTIN_TYPE(module) == T_ICLASS) { - module = RBASIC(module)->klass; - } -- if (!RCLASS_IV_TBL(module)) { -- RCLASS_IV_TBL(module) = st_init_numtable(); -- } -- if (!RCLASS_CONST_TBL(module)) { -- RCLASS_CONST_TBL(module) = st_init_numtable(); -- } -- RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module); -- RCLASS_CONST_TBL(klass) = RCLASS_CONST_TBL(module); -- RCLASS_M_TBL(klass) = RCLASS_M_TBL(module); -+ klass = iclass_alloc(); -+ RBASIC(klass)->klass = module; -+ RCLASS_EXT(klass) = RCLASS_EXT(module); - RCLASS_SUPER(klass) = super; -- if (TYPE(module) == T_ICLASS) { -- RBASIC(klass)->klass = RBASIC(module)->klass; -- } -- else { -- RBASIC(klass)->klass = module; -- } - OBJ_INFECT(klass, module); - OBJ_INFECT(klass, super); - -@@ -678,13 +635,13 @@ rb_include_module(VALUE klass, VALUE module) - while (module) { - int superclass_seen = FALSE; - -- if (RCLASS_M_TBL(klass) == RCLASS_M_TBL(module)) -+ if (RCLASS_EXT(klass) == RCLASS_EXT(module)) - rb_raise(rb_eArgError, "cyclic include detected"); - /* ignore if the module included already in superclasses */ - for (p = RCLASS_SUPER(klass); p; p = RCLASS_SUPER(p)) { - switch (BUILTIN_TYPE(p)) { - case T_ICLASS: -- if (RCLASS_M_TBL(p) == RCLASS_M_TBL(module)) { -+ if (RCLASS_EXT(p) == RCLASS_EXT(module)) { - if (!superclass_seen) { - c = p; /* move insertion point */ - } -@@ -697,7 +654,7 @@ rb_include_module(VALUE klass, VALUE module) - } - } - c = RCLASS_SUPER(c) = include_class_new(module, RCLASS_SUPER(c)); -- if (RMODULE_M_TBL(module) && RMODULE_M_TBL(module)->num_entries) -+ if (RMODULE_M_TBL(module)->num_entries) - changed = 1; - skip: - module = RCLASS_SUPER(module); -@@ -828,58 +785,58 @@ ins_methods_push(ID name, long type, VALUE ary, long visi) - } - - static int --ins_methods_i(st_data_t name, st_data_t type, st_data_t ary) -+ins_methods_i(sa_index_t name, st_data_t type, st_data_t ary) - { - return ins_methods_push((ID)name, (long)type, (VALUE)ary, -1); /* everything but private */ - } - - static int --ins_methods_prot_i(st_data_t name, st_data_t type, st_data_t ary) -+ins_methods_prot_i(sa_index_t name, st_data_t type, st_data_t ary) - { - return ins_methods_push((ID)name, (long)type, (VALUE)ary, NOEX_PROTECTED); - } - - static int --ins_methods_priv_i(st_data_t name, st_data_t type, st_data_t ary) -+ins_methods_priv_i(sa_index_t name, st_data_t type, st_data_t ary) - { - return ins_methods_push((ID)name, (long)type, (VALUE)ary, NOEX_PRIVATE); - } - - static int --ins_methods_pub_i(st_data_t name, st_data_t type, st_data_t ary) -+ins_methods_pub_i(sa_index_t name, st_data_t type, st_data_t ary) - { - return ins_methods_push((ID)name, (long)type, (VALUE)ary, NOEX_PUBLIC); - } - - static int --method_entry_i(st_data_t key, st_data_t value, st_data_t data) -+method_entry_i(sa_index_t key, st_data_t value, st_data_t data) - { - const rb_method_entry_t *me = (const rb_method_entry_t *)value; -- st_table *list = (st_table *)data; -+ sa_table *list = (sa_table *)data; - long type; - - if ((ID)key == ID_ALLOCATOR) { - return ST_CONTINUE; - } - -- if (!st_lookup(list, key, 0)) { -+ if (!sa_lookup(list, key, 0)) { - if (UNDEFINED_METHOD_ENTRY_P(me)) { - type = -1; /* none */ - } - else { - type = VISI(me->flag); - } -- st_add_direct(list, key, type); -+ sa_insert(list, key, type); - } - return ST_CONTINUE; - } - - static VALUE --class_instance_method_list(int argc, VALUE *argv, VALUE mod, int obj, int (*func) (st_data_t, st_data_t, st_data_t)) -+class_instance_method_list(int argc, VALUE *argv, VALUE mod, int obj, int (*func) (sa_index_t, st_data_t, st_data_t)) - { - VALUE ary; - int recur; -- st_table *list; -+ sa_table list = SA_EMPTY_TABLE; - - if (argc == 0) { - recur = TRUE; -@@ -890,16 +847,15 @@ class_instance_method_list(int argc, VALUE *argv, VALUE mod, int obj, int (*func - recur = RTEST(r); - } - -- list = st_init_numtable(); - for (; mod; mod = RCLASS_SUPER(mod)) { -- st_foreach(RCLASS_M_TBL(mod), method_entry_i, (st_data_t)list); -+ sa_foreach(RCLASS_M_TBL(mod), method_entry_i, (st_data_t)&list); - if (BUILTIN_TYPE(mod) == T_ICLASS) continue; - if (obj && FL_TEST(mod, FL_SINGLETON)) continue; - if (!recur) break; - } - ary = rb_ary_new(); -- st_foreach(list, func, ary); -- st_free_table(list); -+ sa_foreach(&list, func, ary); -+ sa_clear(&list); - - return ary; - } -@@ -1113,7 +1069,7 @@ VALUE - rb_obj_singleton_methods(int argc, VALUE *argv, VALUE obj) - { - VALUE recur, ary, klass; -- st_table *list; -+ sa_table list = SA_EMPTY_TABLE; - - if (argc == 0) { - recur = Qtrue; -@@ -1122,20 +1078,19 @@ rb_obj_singleton_methods(int argc, VALUE *argv, VALUE obj) - rb_scan_args(argc, argv, "01", &recur); - } - klass = CLASS_OF(obj); -- list = st_init_numtable(); - if (klass && FL_TEST(klass, FL_SINGLETON)) { -- st_foreach(RCLASS_M_TBL(klass), method_entry_i, (st_data_t)list); -+ sa_foreach(RCLASS_M_TBL(klass), method_entry_i, (st_data_t)&list); - klass = RCLASS_SUPER(klass); - } - if (RTEST(recur)) { - while (klass && (FL_TEST(klass, FL_SINGLETON) || TYPE(klass) == T_ICLASS)) { -- st_foreach(RCLASS_M_TBL(klass), method_entry_i, (st_data_t)list); -+ sa_foreach(RCLASS_M_TBL(klass), method_entry_i, (st_data_t)&list); - klass = RCLASS_SUPER(klass); - } - } - ary = rb_ary_new(); -- st_foreach(list, ins_methods_i, ary); -- st_free_table(list); -+ sa_foreach(&list, ins_methods_i, ary); -+ sa_clear(&list); - - return ary; - } -diff --git a/common.mk b/common.mk -index 1d8e442..0d767ab 100644 ---- a/common.mk -+++ b/common.mk -@@ -79,6 +79,7 @@ COMMONOBJS = array.$(OBJEXT) \ - safe.$(OBJEXT) \ - signal.$(OBJEXT) \ - sprintf.$(OBJEXT) \ -+ sp_ar.$(OBJEXT) \ - st.$(OBJEXT) \ - strftime.$(OBJEXT) \ - string.$(OBJEXT) \ -@@ -703,6 +704,7 @@ signal.$(OBJEXT): {$(VPATH)}signal.c $(RUBY_H_INCLUDES) \ - $(VM_CORE_H_INCLUDES) {$(VPATH)}debug.h - sprintf.$(OBJEXT): {$(VPATH)}sprintf.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \ - {$(VPATH)}regex.h {$(VPATH)}vsnprintf.c $(ENCODING_H_INCLUDES) -+sp_ar.$(OBJEXT): {$(VPATH)}sp_ar.c $(RUBY_H_INCLUDES) - st.$(OBJEXT): {$(VPATH)}st.c $(RUBY_H_INCLUDES) {$(VPATH)}pool_alloc.h - strftime.$(OBJEXT): {$(VPATH)}strftime.c $(RUBY_H_INCLUDES) \ - {$(VPATH)}timev.h -diff --git a/constant.h b/constant.h -index 8232910..9106847 100644 ---- a/constant.h -+++ b/constant.h -@@ -23,7 +23,7 @@ typedef struct rb_const_entry_struct { - - VALUE rb_mod_private_constant(int argc, VALUE *argv, VALUE obj); - VALUE rb_mod_public_constant(int argc, VALUE *argv, VALUE obj); --void rb_free_const_table(st_table *tbl); -+void rb_free_const_table(sa_table *tbl); - VALUE rb_public_const_get(VALUE klass, ID id); - VALUE rb_public_const_get_at(VALUE klass, ID id); - VALUE rb_public_const_get_from(VALUE klass, ID id); -diff --git a/ext/objspace/objspace.c b/ext/objspace/objspace.c -index 66e33a3..4b31f92 100644 ---- a/ext/objspace/objspace.c -+++ b/ext/objspace/objspace.c -@@ -60,20 +60,10 @@ memsize_of(VALUE obj) - break; - case T_MODULE: - case T_CLASS: -- size += st_memsize(RCLASS_M_TBL(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); -+ size += sa_memsize(RCLASS_M_TBL(obj)); -+ size += sa_memsize(RCLASS_IV_TBL(obj)); -+ size += sa_memsize(RCLASS_IV_INDEX_TBL(obj)); -+ size += sa_memsize(RCLASS_CONST_TBL(obj)); - break; - case T_STRING: - size += rb_str_memsize(obj); -diff --git a/gc.c b/gc.c -index 9037212..25d5166f 100644 ---- a/gc.c -+++ b/gc.c -@@ -688,7 +688,7 @@ rb_objspace_free(rb_objspace_t *objspace) - - #define HEAP_OBJ_LIMIT (unsigned int)(HEAP_SIZE / sizeof(struct RVALUE)) - --extern st_table *rb_class_tbl; -+extern sa_table rb_class_tbl; - - int ruby_disable_gc_stress = 0; - -@@ -2358,6 +2358,15 @@ mark_tbl(rb_objspace_t *objspace, st_table *tbl) - st_foreach(tbl, mark_entry, (st_data_t)&arg); - } - -+static void -+mark_sa_tbl(rb_objspace_t *objspace, sa_table *tbl) -+{ -+ if (!tbl) return; -+ SA_FOREACH_START(tbl); -+ gc_mark(objspace, (VALUE)value); -+ SA_FOREACH_END(); -+} -+ - static int - mark_key(VALUE key, VALUE value, st_data_t data) - { -@@ -2434,74 +2443,52 @@ rb_mark_method_entry(const rb_method_entry_t *me) - mark_method_entry(&rb_objspace, me); - } - --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; -- mark_method_entry(arg->objspace, me); -- return ST_CONTINUE; --} -- - static void --mark_m_tbl(rb_objspace_t *objspace, st_table *tbl) --{ -- struct mark_tbl_arg arg; -- if (!tbl) return; -- arg.objspace = objspace; -- st_foreach(tbl, mark_method_entry_i, (st_data_t)&arg); --} -- --static int --free_method_entry_i(ID key, rb_method_entry_t *me, st_data_t data) -+mark_m_tbl(rb_objspace_t *objspace, sa_table *tbl) - { -- if (!me->mark) { -- rb_free_method_entry(me); -- } -- return ST_CONTINUE; -+ SA_FOREACH_START(tbl); -+ mark_method_entry(objspace, (const rb_method_entry_t*)value); -+ SA_FOREACH_END(); - } - - void --rb_free_m_table(st_table *tbl) -+rb_free_m_table(sa_table *tbl) - { -- st_foreach(tbl, free_method_entry_i, 0); -- st_free_table(tbl); --} -- --static int --mark_const_entry_i(ID key, const rb_const_entry_t *ce, st_data_t data) --{ -- struct mark_tbl_arg *arg = (void*)data; -- gc_mark(arg->objspace, ce->value); -- return ST_CONTINUE; -+ SA_FOREACH_START(tbl); -+ if (!((rb_method_entry_t*)value)->mark) { -+ rb_free_method_entry((rb_method_entry_t*)value); -+ } -+ SA_FOREACH_END(); -+ sa_clear(tbl); - } - - static void --mark_const_tbl(rb_objspace_t *objspace, st_table *tbl) -+mark_const_tbl(rb_objspace_t *objspace, sa_table *tbl) - { -- struct mark_tbl_arg arg; -- if (!tbl) return; -- arg.objspace = objspace; -- st_foreach(tbl, mark_const_entry_i, (st_data_t)&arg); -+ SA_FOREACH_START(tbl); -+ gc_mark(objspace, ((const rb_const_entry_t*)value)->value); -+ SA_FOREACH_END(); - } - --static int --free_const_entry_i(ID key, rb_const_entry_t *ce, st_data_t data) -+void -+rb_free_const_table(sa_table *tbl) - { -- xfree(ce); -- return ST_CONTINUE; -+ SA_FOREACH_START(tbl); -+ xfree((rb_const_entry_t*)value); -+ SA_FOREACH_END(); -+ sa_clear(tbl); - } - - void --rb_free_const_table(st_table *tbl) -+rb_mark_tbl(st_table *tbl) - { -- st_foreach(tbl, free_const_entry_i, 0); -- st_free_table(tbl); -+ mark_tbl(&rb_objspace, tbl); - } - - void --rb_mark_tbl(st_table *tbl) -+rb_mark_sa_tbl(sa_table *tbl) - { -- mark_tbl(&rb_objspace, tbl); -+ mark_sa_tbl(&rb_objspace, tbl); - } - - void -@@ -2709,7 +2696,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr) - case T_CLASS: - case T_MODULE: - mark_m_tbl(objspace, RCLASS_M_TBL(obj)); -- mark_tbl(objspace, RCLASS_IV_TBL(obj)); -+ mark_sa_tbl(objspace, RCLASS_IV_TBL(obj)); - mark_const_tbl(objspace, RCLASS_CONST_TBL(obj)); - ptr = RCLASS_SUPER(obj); - goto again; -@@ -3284,15 +3271,9 @@ obj_free(rb_objspace_t *objspace, VALUE obj) - case T_CLASS: - rb_clear_cache_by_class((VALUE)obj); - rb_free_m_table(RCLASS_M_TBL(obj)); -- 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)); -- } -+ sa_clear(RCLASS_IV_TBL(obj)); -+ rb_free_const_table(RCLASS_CONST_TBL(obj)); -+ sa_clear(RCLASS_IV_INDEX_TBL(obj)); - xfree(RANY(obj)->as.klass.ptr); - break; - case T_STRING: -@@ -3345,7 +3326,6 @@ obj_free(rb_objspace_t *objspace, VALUE obj) - break; - case T_ICLASS: - /* iClass shares table with the module */ -- xfree(RANY(obj)->as.klass.ptr); - break; - - case T_FLOAT: -@@ -3460,7 +3440,7 @@ gc_marks(rb_objspace_t *objspace) - rb_mark_end_proc(); - rb_gc_mark_global_tbl(); - -- mark_tbl(objspace, rb_class_tbl); -+ mark_sa_tbl(objspace, &rb_class_tbl); - - /* mark generic instance variables for special constants */ - rb_mark_generic_ivar_tbl(); -diff --git a/include/ruby/intern.h b/include/ruby/intern.h -index ab1cc94..53ca8b0 100644 ---- a/include/ruby/intern.h -+++ b/include/ruby/intern.h -@@ -415,6 +415,7 @@ size_t ruby_stack_length(VALUE**); - int rb_during_gc(void); - void rb_gc_mark_locations(VALUE*, VALUE*); - void rb_mark_tbl(struct st_table*); -+void rb_mark_sa_tbl(sa_table*); - void rb_mark_set(struct st_table*); - void rb_mark_hash(struct st_table*); - void rb_gc_mark_maybe(VALUE); -@@ -848,7 +849,7 @@ VALUE rb_f_trace_var(int, VALUE*); - VALUE rb_f_untrace_var(int, VALUE*); - VALUE rb_f_global_variables(void); - void rb_alias_variable(ID, ID); --struct st_table* rb_generic_ivar_table(VALUE); -+sa_table* rb_generic_ivar_table(VALUE); - void rb_copy_generic_ivar(VALUE,VALUE); - void rb_mark_generic_ivar(VALUE); - void rb_mark_generic_ivar_tbl(void); -diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h -index 2f97b33..78a2286 100644 ---- a/include/ruby/ruby.h -+++ b/include/ruby/ruby.h -@@ -605,7 +605,7 @@ struct RObject { - struct { - long numiv; - VALUE *ivptr; -- struct st_table *iv_index_tbl; /* shortcut for RCLASS_IV_INDEX_TBL(rb_obj_class(obj)) */ -+ struct sa_table *iv_index_tbl; /* shortcut for RCLASS_IV_INDEX_TBL(rb_obj_class(obj)) */ - } heap; - VALUE ary[ROBJECT_EMBED_LEN_MAX]; - } as; -@@ -629,9 +629,8 @@ typedef struct rb_classext_struct rb_classext_t; - - struct RClass { - struct RBasic basic; -+ VALUE super; - rb_classext_t *ptr; -- struct st_table *m_tbl; -- struct st_table *iv_index_tbl; - }; - #define RCLASS_SUPER(c) rb_class_get_superclass(c) - #define RMODULE_IV_TBL(m) RCLASS_IV_TBL(m) -diff --git a/include/ruby/st.h b/include/ruby/st.h -index 119dfde..aff94fc 100644 ---- a/include/ruby/st.h -+++ b/include/ruby/st.h -@@ -151,6 +151,51 @@ st_index_t st_hash_start(st_index_t h); - #pragma GCC visibility pop - #endif - -+typedef unsigned int sa_index_t; -+#define SA_STOP ST_STOP -+#define SA_CONTINUE ST_CONTINUE -+ -+#define SA_EMPTY 0 -+ -+typedef struct sa_entry { -+ sa_index_t next; -+ sa_index_t key; -+ st_data_t value; -+} sa_entry; -+ -+typedef struct sa_table { -+ sa_index_t num_bins; -+ sa_index_t num_entries; -+ sa_index_t free_pos; -+ sa_entry *entries; -+} sa_table; -+ -+#define SA_EMPTY_TABLE {0, 0, 0, 0}; -+void sa_init_table(sa_table *, sa_index_t); -+sa_table *sa_new_table(); -+int sa_insert(sa_table *, sa_index_t, st_data_t); -+int sa_lookup(sa_table *, sa_index_t, st_data_t *); -+int sa_delete(sa_table *, sa_index_t, st_data_t *); -+void sa_clear(sa_table *); -+void sa_clear_no_free(sa_table *); -+void sa_free_table(sa_table *); -+int sa_foreach(sa_table *, int (*)(ANYARGS), st_data_t); -+size_t sa_memsize(const sa_table *); -+sa_table *sa_copy(sa_table*); -+void sa_copy_to(sa_table*, sa_table*); -+typedef int (*sa_iter_func)(sa_index_t key, st_data_t val, st_data_t arg); -+ -+#define SA_FOREACH_START_I(table, entry) do { \ -+ sa_table *T##entry = (table); \ -+ sa_index_t K##entry; \ -+ for(K##entry = 0; K##entry < T##entry->num_bins; K##entry++) { \ -+ sa_entry *entry = T##entry->entries + K##entry; \ -+ if (entry->next != SA_EMPTY) { \ -+ st_data_t value = entry->value -+#define SA_FOREACH_END() } } } while(0) -+ -+#define SA_FOREACH_START(table) SA_FOREACH_START_I(table, entry) -+ - #if defined(__cplusplus) - #if 0 - { /* satisfy cc-mode */ -diff --git a/internal.h b/internal.h -index f5af903..5927d93 100644 ---- a/internal.h -+++ b/internal.h -@@ -24,18 +24,19 @@ struct rb_deprecated_classext_struct { - }; - - struct rb_classext_struct { -- VALUE super; -- struct st_table *iv_tbl; -- struct st_table *const_tbl; -+ sa_table m_tbl; -+ sa_table iv_tbl; -+ sa_table const_tbl; -+ sa_table iv_index_tbl; - }; - - #undef RCLASS_SUPER - #define RCLASS_EXT(c) (RCLASS(c)->ptr) --#define RCLASS_SUPER(c) (RCLASS_EXT(c)->super) --#define RCLASS_IV_TBL(c) (RCLASS_EXT(c)->iv_tbl) --#define RCLASS_CONST_TBL(c) (RCLASS_EXT(c)->const_tbl) --#define RCLASS_M_TBL(c) (RCLASS(c)->m_tbl) --#define RCLASS_IV_INDEX_TBL(c) (RCLASS(c)->iv_index_tbl) -+#define RCLASS_SUPER(c) (RCLASS(c)->super) -+#define RCLASS_IV_TBL(c) (&RCLASS_EXT(c)->iv_tbl) -+#define RCLASS_CONST_TBL(c) (&RCLASS_EXT(c)->const_tbl) -+#define RCLASS_M_TBL(c) (&RCLASS_EXT(c)->m_tbl) -+#define RCLASS_IV_INDEX_TBL(c) (&RCLASS_EXT(c)->iv_index_tbl) - - struct vtm; /* defined by timev.h */ - -diff --git a/marshal.c b/marshal.c -index 6ae3a55..48d9d9b 100644 ---- a/marshal.c -+++ b/marshal.c -@@ -506,7 +506,7 @@ w_uclass(VALUE obj, VALUE super, struct dump_arg *arg) - } - - static int --w_obj_each(ID id, VALUE value, struct dump_call_arg *arg) -+w_obj_each(sa_index_t id, VALUE value, struct dump_call_arg *arg) - { - if (id == rb_id_encoding()) return ST_CONTINUE; - if (id == rb_intern("E")) return ST_CONTINUE; -@@ -553,13 +553,13 @@ w_encoding(VALUE obj, long num, struct dump_call_arg *arg) - } - - static void --w_ivar(VALUE obj, st_table *tbl, struct dump_call_arg *arg) -+w_ivar(VALUE obj, sa_table *tbl, struct dump_call_arg *arg) - { - long num = tbl ? tbl->num_entries : 0; - - w_encoding(obj, num, arg); - if (tbl) { -- st_foreach_safe(tbl, w_obj_each, (st_data_t)arg); -+ sa_foreach(tbl, w_obj_each, (st_data_t)arg); - } - } - -@@ -586,7 +586,7 @@ static void - w_object(VALUE obj, struct dump_arg *arg, int limit) - { - struct dump_call_arg c_arg; -- st_table *ivtbl = 0; -+ sa_table *ivtbl = 0; - st_data_t num; - int hasiv = 0; - #define has_ivars(obj, ivtbl) (((ivtbl) = rb_generic_ivar_table(obj)) != 0 || \ -@@ -651,7 +651,7 @@ w_object(VALUE obj, struct dump_arg *arg, int limit) - } - if (rb_respond_to(obj, s_dump)) { - VALUE v; -- st_table *ivtbl2 = 0; -+ sa_table *ivtbl2 = 0; - int hasiv2; - - v = rb_funcall(obj, s_dump, 1, INT2NUM(limit)); -diff --git a/method.h b/method.h -index 9229896..2fecd57 100644 ---- a/method.h -+++ b/method.h -@@ -100,6 +100,6 @@ int rb_method_entry_eq(const rb_method_entry_t *m1, const rb_method_entry_t *m2) - void rb_mark_method_entry(const rb_method_entry_t *me); - void rb_free_method_entry(rb_method_entry_t *me); - void rb_sweep_method_entry(void *vm); --void rb_free_m_table(st_table *tbl); -+void rb_free_m_table(sa_table *tbl); - - #endif /* METHOD_H */ -diff --git a/object.c b/object.c -index 59611fd..4522d08 100644 ---- a/object.c -+++ b/object.c -@@ -236,17 +236,8 @@ init_copy(VALUE dest, VALUE obj) - break; - case T_CLASS: - case T_MODULE: -- if (RCLASS_IV_TBL(dest)) { -- st_free_table(RCLASS_IV_TBL(dest)); -- RCLASS_IV_TBL(dest) = 0; -- } -- if (RCLASS_CONST_TBL(dest)) { -- rb_free_const_table(RCLASS_CONST_TBL(dest)); -- RCLASS_CONST_TBL(dest) = 0; -- } -- if (RCLASS_IV_TBL(obj)) { -- RCLASS_IV_TBL(dest) = st_copy(RCLASS_IV_TBL(obj)); -- } -+ rb_free_const_table(RCLASS_CONST_TBL(dest)); -+ sa_copy_to(RCLASS_IV_TBL(obj), RCLASS_IV_TBL(dest)); - break; - } - } -@@ -537,7 +528,7 @@ rb_obj_is_kind_of(VALUE obj, VALUE c) - } - - while (cl) { -- if (cl == c || RCLASS_M_TBL(cl) == RCLASS_M_TBL(c)) -+ if (cl == c || RCLASS_EXT(cl) == RCLASS_EXT(c)) - return Qtrue; - cl = RCLASS_SUPER(cl); - } -@@ -1362,13 +1353,13 @@ rb_class_inherited_p(VALUE mod, VALUE arg) - rb_raise(rb_eTypeError, "compared with non class/module"); - } - while (mod) { -- if (RCLASS_M_TBL(mod) == RCLASS_M_TBL(arg)) -+ if (RCLASS_EXT(mod) == RCLASS_EXT(arg)) - return Qtrue; - mod = RCLASS_SUPER(mod); - } - /* not mod < arg; check if mod > arg */ - while (arg) { -- if (RCLASS_M_TBL(arg) == RCLASS_M_TBL(start)) -+ if (RCLASS_EXT(arg) == RCLASS_EXT(start)) - return Qfalse; - arg = RCLASS_SUPER(arg); - } -diff --git a/sp_ar.c b/sp_ar.c -new file mode 100644 -index 0000000..2ed69bf ---- /dev/null -+++ b/sp_ar.c -@@ -0,0 +1,374 @@ -+/* -+ * sparse array lib -+ * inspired by Lua table -+ * written by Sokolov Yura aka funny_falcon -+ */ -+#ifdef NOT_RUBY -+#include "regint.h" -+#include "st.h" -+#else -+#include "ruby/ruby.h" -+#endif -+ -+#include -+#ifdef HAVE_STDLIB_H -+#include -+#endif -+#include -+ -+#ifdef RUBY -+#define malloc xmalloc -+#define calloc xcalloc -+#define realloc xrealloc -+#define free xfree -+#endif -+ -+#define sa_table_alloc() (sa_table*)malloc(sizeof(sa_table)) -+#define sa_table_xalloc() (sa_table*)calloc(1, sizeof(sa_table)) -+#define sa_table_dealloc(table) free(table) -+#define sa_entry_alloc(n) (sa_entry*)calloc((n), sizeof(sa_entry)) -+#define sa_entry_dealloc(entries) free(entries) -+ -+#define SA_LAST 1 -+#define SA_OFFSET 2 -+ -+#define SA_MIN_SIZE 4 -+ -+void -+sa_init_table(register sa_table *table, sa_index_t num_bins) -+{ -+ if (num_bins) { -+ table->num_entries = 0; -+ table->entries = sa_entry_alloc(num_bins); -+ table->num_bins = num_bins; -+ table->free_pos = num_bins; -+ } -+ else { -+ memset(table, 0, sizeof(sa_table)); -+ } -+} -+ -+sa_table* -+sa_new_table() -+{ -+ sa_table* table = sa_table_alloc(); -+ sa_init_table(table, 0); -+ return table; -+} -+ -+static inline sa_index_t -+calc_pos(register sa_table* table, sa_index_t key) -+{ -+ /* this formula is empirical */ -+ /* it has no good avalance, but works well in our case */ -+ key ^= key >> 16; -+ key *= 0x445229; -+ return (key + (key >> 16)) % table->num_bins; -+} -+ -+static void -+fix_empty(register sa_table* table) -+{ -+ while(--table->free_pos && -+ table->entries[table->free_pos-1].next != SA_EMPTY); -+} -+ -+#define FLOOR_TO_4 ((~((sa_index_t)0)) << 2) -+static sa_index_t -+find_empty(register sa_table* table, register sa_index_t pos) -+{ -+ sa_index_t new_pos = table->free_pos-1; -+ sa_entry *entry; -+ pos &= FLOOR_TO_4; -+ entry = table->entries+pos; -+ -+ if (entry->next == SA_EMPTY) { new_pos = pos; goto check; } -+ pos++; entry++; -+ if (entry->next == SA_EMPTY) { new_pos = pos; goto check; } -+ pos++; entry++; -+ if (entry->next == SA_EMPTY) { new_pos = pos; goto check; } -+ pos++; entry++; -+ if (entry->next == SA_EMPTY) { new_pos = pos; goto check; } -+ -+check: -+ if (new_pos+1 == table->free_pos) fix_empty(table); -+ return new_pos; -+} -+ -+static void resize(register sa_table* table); -+static int insert_into_chain(register sa_table*, register sa_index_t, st_data_t, sa_index_t pos); -+static int insert_into_main(register sa_table*, sa_index_t, st_data_t, sa_index_t pos, sa_index_t prev_pos); -+ -+int -+sa_insert(register sa_table* table, register sa_index_t key, st_data_t value) -+{ -+ sa_index_t pos, main_pos; -+ register sa_entry *entry; -+ -+ if (table->num_bins == 0) { -+ sa_init_table(table, SA_MIN_SIZE); -+ } -+ -+ pos = calc_pos(table, key); -+ entry = table->entries + pos; -+ -+ if (entry->next == SA_EMPTY) { -+ entry->next = SA_LAST; -+ entry->key = key; -+ entry->value = value; -+ table->num_entries++; -+ if (pos+1 == table->free_pos) fix_empty(table); -+ return 0; -+ } -+ -+ if (entry->key == key) { -+ entry->value = value; -+ return 1; -+ } -+ -+ if (table->num_entries + (table->num_entries >> 2) > table->num_bins) { -+ resize(table); -+ return sa_insert(table, key, value); -+ } -+ -+ main_pos = calc_pos(table, entry->key); -+ if (main_pos == pos) { -+ return insert_into_chain(table, key, value, pos); -+ } -+ else { -+ if (!table->free_pos) { -+ resize(table); -+ return sa_insert(table, key, value); -+ } -+ return insert_into_main(table, key, value, pos, main_pos); -+ } -+} -+ -+static int -+insert_into_chain(register sa_table* table, register sa_index_t key, st_data_t value, sa_index_t pos) -+{ -+ sa_entry *entry = table->entries + pos, *new_entry; -+ sa_index_t new_pos; -+ -+ while (entry->next != SA_LAST) { -+ pos = entry->next - SA_OFFSET; -+ entry = table->entries + pos; -+ if (entry->key == key) { -+ entry->value = value; -+ return 1; -+ } -+ } -+ -+ if (!table->free_pos) { -+ resize(table); -+ return sa_insert(table, key, value); -+ } -+ -+ new_pos = find_empty(table, pos); -+ new_entry = table->entries + new_pos; -+ entry->next = new_pos + SA_OFFSET; -+ -+ new_entry->next = SA_LAST; -+ new_entry->key = key; -+ new_entry->value = value; -+ table->num_entries++; -+ return 0; -+} -+ -+static int -+insert_into_main(register sa_table* table, sa_index_t key, st_data_t value, sa_index_t pos, sa_index_t prev_pos) -+{ -+ sa_entry *entry = table->entries + pos; -+ sa_index_t new_pos = find_empty(table, pos); -+ sa_entry *new_entry = table->entries + new_pos; -+ sa_index_t npos; -+ -+ *new_entry = *entry; -+ -+ while((npos = table->entries[prev_pos].next - SA_OFFSET) != pos) { -+ prev_pos = npos; -+ } -+ table->entries[prev_pos].next = new_pos + SA_OFFSET; -+ -+ entry->next = SA_LAST; -+ entry->key = key; -+ entry->value = value; -+ table->num_entries++; -+ return 0; -+} -+ -+static sa_index_t -+new_size(sa_index_t num_entries) -+{ -+ sa_index_t msb = num_entries; -+ msb |= msb >> 1; -+ msb |= msb >> 2; -+ msb |= msb >> 4; -+ msb |= msb >> 8; -+ msb |= msb >> 16; -+ msb = ((msb >> 4) + 1) << 3; -+ return (num_entries & (msb | (msb >> 1))) + (msb >> 1); -+} -+ -+static void -+resize(register sa_table *table) -+{ -+ sa_table tmp_table; -+ sa_entry *entry; -+ sa_index_t i; -+ -+ if (table->num_entries == 0) { -+ sa_entry_dealloc(table->entries); -+ memset(table, 0, sizeof(sa_table)); -+ return; -+ } -+ -+ sa_init_table(&tmp_table, new_size(table->num_entries + (table->num_entries >> 2))); -+ entry = table->entries; -+ -+ for(i = 0; i < table->num_bins; i++, entry++) { -+ if (entry->next != SA_EMPTY) { -+ sa_insert(&tmp_table, entry->key, entry->value); -+ } -+ } -+ sa_entry_dealloc(table->entries); -+ *table = tmp_table; -+} -+ -+int -+sa_lookup(register sa_table *table, register sa_index_t key, st_data_t *value) -+{ -+ register sa_entry *entry; -+ -+ if (table->num_entries == 0) return 0; -+ -+ entry = table->entries + calc_pos(table, key); -+ if (entry->next == SA_EMPTY) return 0; -+ -+ if (entry->key == key) goto found; -+ if (entry->next == SA_LAST) return 0; -+ -+ entry = table->entries + (entry->next - SA_OFFSET); -+ if (entry->key == key) goto found; -+ -+ while(entry->next != SA_LAST) { -+ entry = table->entries + (entry->next - SA_OFFSET); -+ if (entry->key == key) goto found; -+ } -+ return 0; -+found: -+ if (value) *value = entry->value; -+ return 1; -+} -+ -+void -+sa_clear(sa_table *table) -+{ -+ sa_entry_dealloc(table->entries); -+ memset(table, 0, sizeof(sa_table)); -+} -+ -+void -+sa_clear_no_free(sa_table *table) -+{ -+ memset(table->entries, 0, sizeof(sa_entry) * table->num_bins); -+ table->num_entries = 0; -+ table->free_pos = table->num_bins; -+} -+ -+void -+sa_free_table(sa_table *table) -+{ -+ sa_entry_dealloc(table->entries); -+ sa_table_dealloc(table); -+} -+ -+int -+sa_delete(sa_table *table, sa_index_t key, st_data_t *value) -+{ -+ sa_index_t pos, prev_pos = ~0; -+ sa_entry *entry; -+ -+ if (table->num_entries == 0) goto not_found; -+ -+ pos = calc_pos(table, key); -+ entry = table->entries + pos; -+ -+ if (entry->next == SA_EMPTY) goto not_found; -+ -+ do { -+ if (entry->key == key) { -+ if (value) *value = entry->value; -+ if (entry->next != SA_LAST) { -+ sa_index_t npos = entry->next - SA_OFFSET; -+ *entry = table->entries[npos]; -+ memset(table->entries + npos, 0, sizeof(sa_entry)); -+ } -+ else { -+ memset(table->entries + pos, 0, sizeof(sa_entry)); -+ if (~prev_pos) { -+ table->entries[prev_pos].next = SA_LAST; -+ } -+ } -+ table->num_entries--; -+ if (table->num_entries < table->num_bins / 4) { -+ resize(table); -+ } -+ return 1; -+ } -+ if (entry->next == SA_LAST) break; -+ prev_pos = pos; -+ pos = entry->next - SA_OFFSET; -+ entry = table->entries + pos; -+ } while(1); -+ -+not_found: -+ if (value) *value = 0; -+ return 0; -+} -+ -+int -+sa_foreach(register sa_table *table, int (*func)(), st_data_t arg) -+{ -+ sa_index_t i; -+ if (table->num_bins == 0) { -+ return 0; -+ } -+ for(i = 0; i < table->num_bins ; i++) { -+ if (table->entries[i].next != SA_EMPTY) { -+ sa_index_t key = table->entries[i].key; -+ st_data_t val = table->entries[i].value; -+ if ((*func)(key, val, arg) == SA_STOP) break; -+ } -+ } -+ return 0; -+} -+ -+size_t -+sa_memsize(const sa_table *table) -+{ -+ return sizeof(sa_table) + table->num_bins * sizeof(sa_entry); -+} -+ -+sa_table* -+sa_copy(sa_table *table) -+{ -+ sa_table *new_table = sa_table_alloc(); -+ *new_table = *table; -+ if (table->num_bins) { -+ new_table->entries = sa_entry_alloc(table->num_bins); -+ memcpy(new_table->entries, table->entries, table->num_bins*sizeof(sa_entry)); -+ } -+ return new_table; -+} -+ -+void -+sa_copy_to(sa_table *from, sa_table *to) -+{ -+ sa_entry_dealloc(to->entries); -+ *to = *from; -+ if (to->num_bins) { -+ to->entries = sa_entry_alloc(to->num_bins); -+ memcpy(to->entries, from->entries, from->num_bins*sizeof(sa_entry)); -+ } -+} -diff --git a/test/ruby/test_marshal.rb b/test/ruby/test_marshal.rb -index 0f3f794..5c2e502 100644 ---- a/test/ruby/test_marshal.rb -+++ b/test/ruby/test_marshal.rb -@@ -312,7 +312,7 @@ class TestMarshal < Test::Unit::TestCase - assert_equal(a.instance_variable_get(i), b.instance_variable_get(i), bug1932) - end - end -- a.__send__(a.methods(true).grep(/=\z/)[0], a) -+ a.__send__(a.methods(true).grep(/r.*=\z/)[0], a) - assert_nothing_raised(bug1932) do - b = Marshal.load(Marshal.dump(a)) - assert_equal(ClassISO8859_1, b.class, bug1932) -diff --git a/test/ruby/test_method.rb b/test/ruby/test_method.rb -index ea6c5f2..6ccd37c 100644 ---- a/test/ruby/test_method.rb -+++ b/test/ruby/test_method.rb -@@ -406,7 +406,7 @@ class TestMethod < Test::Unit::TestCase - obj = a.new - assert_equal([:a], obj.public_methods(false), bug) - obj.extend(m) -- assert_equal([:m1, :a], obj.public_methods(false), bug) -+ assert_equal([:a, :m1], obj.public_methods(false).sort, bug) - end - - def test_visibility -diff --git a/test/ruby/test_module.rb b/test/ruby/test_module.rb -index 6176f48..a67d845 100644 ---- a/test/ruby/test_module.rb -+++ b/test/ruby/test_module.rb -@@ -870,7 +870,7 @@ class TestModule < Test::Unit::TestCase - (class << self ; self ; end).class_eval do - define_method :method_added do |sym| - memo << sym -- memo << mod.instance_methods(false) -+ memo << mod.instance_methods(false).sort - memo << (mod.instance_method(sym) rescue nil) - end - end -@@ -887,10 +887,10 @@ class TestModule < Test::Unit::TestCase - assert_equal [:f, :g], memo.shift - assert_equal mod.instance_method(:f), memo.shift - assert_equal :a, memo.shift -- assert_equal [:f, :g, :a], memo.shift -+ assert_equal [:a, :f, :g], memo.shift - assert_equal mod.instance_method(:a), memo.shift - assert_equal :a=, memo.shift -- assert_equal [:f, :g, :a, :a=], memo.shift -+ assert_equal [:a, :a=, :f, :g], memo.shift - assert_equal mod.instance_method(:a=), memo.shift - end - -diff --git a/time.c b/time.c -index 755812f..83edc83 100644 ---- a/time.c -+++ b/time.c -@@ -4712,16 +4712,14 @@ time_mload(VALUE time, VALUE str) - long nsec; - VALUE submicro, nano_num, nano_den, offset; - wideval_t timew; -- st_data_t data; - - time_modify(time); - - #define get_attr(attr, iffound) \ - attr = rb_attr_get(str, id_##attr); \ - if (!NIL_P(attr)) { \ -- data = id_##attr; \ - iffound; \ -- st_delete(rb_generic_ivar_table(str), &data, 0); \ -+ sa_delete(rb_generic_ivar_table(str), (sa_index_t)id_##attr, 0); \ - } - - get_attr(nano_num, {}); -diff --git a/variable.c b/variable.c -index 3da500e..4a61453 100644 ---- a/variable.c -+++ b/variable.c -@@ -19,15 +19,15 @@ - #include "constant.h" - #include "internal.h" - --st_table *rb_global_tbl; --st_table *rb_class_tbl; -+sa_table rb_global_tbl; -+sa_table rb_class_tbl; - static ID autoload, classpath, tmp_classpath, classid; - - void - Init_var_tables(void) - { -- rb_global_tbl = st_init_numtable(); -- rb_class_tbl = st_init_numtable(); -+ sa_init_table(&rb_global_tbl, 0); -+ sa_init_table(&rb_class_tbl, 0); - CONST_ID(autoload, "__autoload__"); - CONST_ID(classpath, "__classpath__"); - CONST_ID(tmp_classpath, "__tmp_classpath__"); -@@ -43,7 +43,7 @@ struct fc_result { - }; - - static VALUE --fc_path(struct fc_result *fc, ID name) -+fc_path(struct fc_result *fc, sa_index_t name) - { - VALUE path, tmp; - -@@ -51,8 +51,7 @@ fc_path(struct fc_result *fc, ID name) - while (fc) { - st_data_t n; - if (fc->track == rb_cObject) break; -- if (RCLASS_IV_TBL(fc->track) && -- st_lookup(RCLASS_IV_TBL(fc->track), (st_data_t)classpath, &n)) { -+ if (sa_lookup(RCLASS_IV_TBL(fc->track), (sa_index_t)classpath, &n)) { - tmp = rb_str_dup((VALUE)n); - rb_str_cat2(tmp, "::"); - rb_str_append(tmp, path); -@@ -70,7 +69,7 @@ fc_path(struct fc_result *fc, ID name) - } - - static int --fc_i(ID key, rb_const_entry_t *ce, struct fc_result *res) -+fc_i(sa_index_t key, rb_const_entry_t *ce, struct fc_result *res) - { - VALUE value = ce->value; - if (!rb_is_const_id(key)) return ST_CONTINUE; -@@ -98,7 +97,7 @@ fc_i(ID key, rb_const_entry_t *ce, struct fc_result *res) - arg.klass = res->klass; - arg.track = value; - arg.prev = res; -- st_foreach(RCLASS_CONST_TBL(value), fc_i, (st_data_t)&arg); -+ sa_foreach(RCLASS_CONST_TBL(value), fc_i, (st_data_t)&arg); - if (arg.path) { - res->path = arg.path; - return ST_STOP; -@@ -123,18 +122,14 @@ find_class_path(VALUE klass) - arg.track = rb_cObject; - arg.prev = 0; - if (RCLASS_CONST_TBL(rb_cObject)) { -- st_foreach_safe(RCLASS_CONST_TBL(rb_cObject), fc_i, (st_data_t)&arg); -+ sa_foreach(RCLASS_CONST_TBL(rb_cObject), fc_i, (st_data_t)&arg); - } - if (arg.path == 0) { -- st_foreach_safe(rb_class_tbl, fc_i, (st_data_t)&arg); -+ sa_foreach(&rb_class_tbl, fc_i, (st_data_t)&arg); - } - if (arg.path) { -- st_data_t tmp = tmp_classpath; -- if (!RCLASS_IV_TBL(klass)) { -- RCLASS_IV_TBL(klass) = st_init_numtable(); -- } -- st_insert(RCLASS_IV_TBL(klass), (st_data_t)classpath, arg.path); -- st_delete(RCLASS_IV_TBL(klass), &tmp, 0); -+ sa_insert(RCLASS_IV_TBL(klass), (sa_index_t)classpath, arg.path); -+ sa_delete(RCLASS_IV_TBL(klass), (sa_index_t)tmp_classpath, 0); - return arg.path; - } - return Qnil; -@@ -147,16 +142,15 @@ classname(VALUE klass) - st_data_t n; - - if (!klass) klass = rb_cObject; -- if (RCLASS_IV_TBL(klass)) { -- if (!st_lookup(RCLASS_IV_TBL(klass), (st_data_t)classpath, &n)) { -- if (!st_lookup(RCLASS_IV_TBL(klass), (st_data_t)classid, &n)) { -+ if (RCLASS_IV_TBL(klass)->num_entries) { -+ if (!sa_lookup(RCLASS_IV_TBL(klass), (sa_index_t)classpath, &n)) { -+ if (!sa_lookup(RCLASS_IV_TBL(klass), (sa_index_t)classid, &n)) { - return find_class_path(klass); - } - path = rb_str_dup(rb_id2str(SYM2ID((VALUE)n))); - OBJ_FREEZE(path); -- st_insert(RCLASS_IV_TBL(klass), (st_data_t)classpath, (st_data_t)path); -- n = classid; -- st_delete(RCLASS_IV_TBL(klass), &n, 0); -+ sa_insert(RCLASS_IV_TBL(klass), (sa_index_t)classpath, (st_data_t)path); -+ sa_delete(RCLASS_IV_TBL(klass), (sa_index_t)classid, 0); - } - else { - path = (VALUE)n; -@@ -192,8 +186,7 @@ rb_class_path(VALUE klass) - st_data_t n = (st_data_t)path; - - if (!NIL_P(path)) return path; -- if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass), -- (st_data_t)tmp_classpath, &n)) { -+ if (sa_lookup(RCLASS_IV_TBL(klass), (sa_index_t)tmp_classpath, &n)) { - return (VALUE)n; - } - else { -@@ -364,7 +357,7 @@ rb_global_entry(ID id) - struct global_entry *entry; - st_data_t data; - -- if (!st_lookup(rb_global_tbl, (st_data_t)id, &data)) { -+ if (!sa_lookup(&rb_global_tbl, (sa_index_t)id, &data)) { - struct global_variable *var; - entry = ALLOC(struct global_entry); - var = ALLOC(struct global_variable); -@@ -378,7 +371,7 @@ rb_global_entry(ID id) - - var->block_trace = 0; - var->trace = 0; -- st_add_direct(rb_global_tbl, id, (st_data_t)entry); -+ sa_insert(&rb_global_tbl, (sa_index_t)id, (st_data_t)entry); - } - else { - entry = (struct global_entry *)data; -@@ -454,8 +447,8 @@ readonly_setter(VALUE val, ID id, void *data, struct global_variable *gvar) - rb_name_error(id, "%s is a read-only variable", rb_id2name(id)); - } - --static int --mark_global_entry(ID key, struct global_entry *entry) -+static void -+mark_global_entry(struct global_entry *entry) - { - struct trace_var *trace; - struct global_variable *var = entry->var; -@@ -466,14 +459,14 @@ mark_global_entry(ID key, struct global_entry *entry) - if (trace->data) rb_gc_mark_maybe(trace->data); - trace = trace->next; - } -- return ST_CONTINUE; - } - - void - rb_gc_mark_global_tbl(void) - { -- if (rb_global_tbl) -- st_foreach_safe(rb_global_tbl, mark_global_entry, 0); -+ SA_FOREACH_START(&rb_global_tbl); -+ mark_global_entry((struct global_entry*) value); -+ SA_FOREACH_END(); - } - - static ID -@@ -635,7 +628,7 @@ rb_f_untrace_var(int argc, VALUE *argv) - rb_secure(4); - rb_scan_args(argc, argv, "11", &var, &cmd); - id = rb_to_id(var); -- if (!st_lookup(rb_global_tbl, (st_data_t)id, &data)) { -+ if (!sa_lookup(&rb_global_tbl, (sa_index_t)id, &data)) { - rb_name_error(id, "undefined global variable %s", rb_id2name(id)); - } - -@@ -742,13 +735,6 @@ rb_gvar_defined(struct global_entry *entry) - return Qtrue; - } - --static int --gvar_i(ID key, struct global_entry *entry, VALUE ary) --{ -- rb_ary_push(ary, ID2SYM(key)); -- return ST_CONTINUE; --} -- - /* - * call-seq: - * global_variables -> array -@@ -765,7 +751,9 @@ rb_f_global_variables(void) - char buf[2]; - int i; - -- st_foreach_safe(rb_global_tbl, gvar_i, ary); -+ SA_FOREACH_START(&rb_global_tbl); -+ rb_ary_push(ary, ID2SYM(entry->key)); -+ SA_FOREACH_END(); - buf[0] = '$'; - for (i = 1; i <= 9; ++i) { - buf[1] = (char)(i + '0'); -@@ -784,10 +772,10 @@ rb_alias_variable(ID name1, ID name2) - rb_raise(rb_eSecurityError, "Insecure: can't alias global variable"); - - entry2 = rb_global_entry(name2); -- if (!st_lookup(rb_global_tbl, (st_data_t)name1, &data1)) { -+ if (!sa_lookup(&rb_global_tbl, (sa_index_t)name1, &data1)) { - entry1 = ALLOC(struct global_entry); - entry1->id = name1; -- st_add_direct(rb_global_tbl, name1, (st_data_t)entry1); -+ sa_insert(&rb_global_tbl, (sa_index_t)name1, (st_data_t)entry1); - } - else if ((entry1 = (struct global_entry *)data1)->var != entry2->var) { - struct global_variable *var = entry1->var; -@@ -815,7 +803,7 @@ rb_alias_variable(ID name1, ID name2) - static int special_generic_ivar = 0; - static st_table *generic_iv_tbl; - --st_table* -+sa_table* - rb_generic_ivar_table(VALUE obj) - { - st_data_t tbl; -@@ -823,7 +811,7 @@ rb_generic_ivar_table(VALUE obj) - if (!FL_TEST(obj, FL_EXIVAR)) return 0; - if (!generic_iv_tbl) return 0; - if (!st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) return 0; -- return (st_table *)tbl; -+ return (sa_table *)tbl; - } - - static VALUE -@@ -833,7 +821,7 @@ generic_ivar_get(VALUE obj, ID id, int warn) - - if (generic_iv_tbl) { - if (st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) { -- if (st_lookup((st_table *)tbl, (st_data_t)id, &val)) { -+ if (sa_lookup((sa_table *)tbl, (sa_index_t)id, &val)) { - return (VALUE)val; - } - } -@@ -847,7 +835,6 @@ generic_ivar_get(VALUE obj, ID id, int warn) - static void - generic_ivar_set(VALUE obj, ID id, VALUE val) - { -- st_table *tbl; - st_data_t data; - - if (rb_special_const_p(obj)) { -@@ -859,24 +846,22 @@ generic_ivar_set(VALUE obj, ID id, VALUE val) - } - if (!st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) { - FL_SET(obj, FL_EXIVAR); -- tbl = st_init_numtable(); -- st_add_direct(generic_iv_tbl, (st_data_t)obj, (st_data_t)tbl); -- st_add_direct(tbl, (st_data_t)id, (st_data_t)val); -- return; -+ data = (st_data_t)sa_new_table(); -+ st_add_direct(generic_iv_tbl, (st_data_t)obj, data); - } -- st_insert((st_table *)data, (st_data_t)id, (st_data_t)val); -+ sa_insert((sa_table *)data, (sa_index_t)id, (st_data_t)val); - } - - static VALUE - generic_ivar_defined(VALUE obj, ID id) - { -- st_table *tbl; -+ sa_table *tbl; - st_data_t data; - - if (!generic_iv_tbl) return Qfalse; - if (!st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) return Qfalse; -- tbl = (st_table *)data; -- if (st_lookup(tbl, (st_data_t)id, &data)) { -+ tbl = (sa_table *)data; -+ if (sa_lookup(tbl, (sa_index_t)id, &data)) { - return Qtrue; - } - return Qfalse; -@@ -885,18 +870,18 @@ generic_ivar_defined(VALUE obj, ID id) - static int - generic_ivar_remove(VALUE obj, ID id, st_data_t *valp) - { -- st_table *tbl; -+ sa_table *tbl; - st_data_t data, key = (st_data_t)id; - int status; - - if (!generic_iv_tbl) return 0; - if (!st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) return 0; -- tbl = (st_table *)data; -- status = st_delete(tbl, &key, valp); -+ tbl = (sa_table *)data; -+ status = sa_delete(tbl, (sa_index_t)id, valp); - if (tbl->num_entries == 0) { - key = (st_data_t)obj; - st_delete(generic_iv_tbl, &key, &data); -- st_free_table((st_table *)data); -+ sa_free_table(tbl); - } - return status; - } -@@ -908,22 +893,17 @@ rb_mark_generic_ivar(VALUE obj) - - if (!generic_iv_tbl) return; - if (st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) { -- rb_mark_tbl((st_table *)tbl); -+ rb_mark_sa_tbl((sa_table *)tbl); - } - } - - static int --givar_mark_i(ID key, VALUE value) --{ -- rb_gc_mark(value); -- return ST_CONTINUE; --} -- --static int --givar_i(VALUE obj, st_table *tbl) -+givar_i(VALUE obj, sa_table *tbl) - { - if (rb_special_const_p(obj)) { -- st_foreach_safe(tbl, givar_mark_i, 0); -+ SA_FOREACH_START(tbl); -+ rb_gc_mark((VALUE)value); -+ SA_FOREACH_END(); - } - return ST_CONTINUE; - } -@@ -943,7 +923,7 @@ rb_free_generic_ivar(VALUE obj) - - if (!generic_iv_tbl) return; - if (st_delete(generic_iv_tbl, &key, &tbl)) -- st_free_table((st_table *)tbl); -+ sa_free_table((sa_table *)tbl); - } - - RUBY_FUNC_EXPORTED size_t -@@ -951,7 +931,7 @@ rb_generic_ivar_memsize(VALUE obj) - { - st_data_t tbl; - if (st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) -- return st_memsize((st_table *)tbl); -+ return sa_memsize((sa_table *)tbl); - return 0; - } - -@@ -970,17 +950,17 @@ rb_copy_generic_ivar(VALUE clone, VALUE obj) - return; - } - if (st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) { -- st_table *tbl = (st_table *)data; -+ sa_table *tbl = (sa_table *)data; - - if (tbl->num_entries == 0) - goto clear; - - if (st_lookup(generic_iv_tbl, (st_data_t)clone, &data)) { -- st_free_table((st_table *)data); -- st_insert(generic_iv_tbl, (st_data_t)clone, (st_data_t)st_copy(tbl)); -+ sa_free_table((sa_table *)data); -+ st_insert(generic_iv_tbl, (st_data_t)clone, (st_data_t)sa_copy(tbl)); - } - else { -- st_add_direct(generic_iv_tbl, (st_data_t)clone, (st_data_t)st_copy(tbl)); -+ st_add_direct(generic_iv_tbl, (st_data_t)clone, (st_data_t)sa_copy(tbl)); - FL_SET(clone, FL_EXIVAR); - } - } -@@ -990,7 +970,7 @@ static VALUE - ivar_get(VALUE obj, ID id, int warn) - { - VALUE val, *ptr; -- struct st_table *iv_index_tbl; -+ sa_table *iv_index_tbl; - long len; - st_data_t index; - -@@ -1000,7 +980,7 @@ ivar_get(VALUE obj, ID id, int warn) - ptr = ROBJECT_IVPTR(obj); - iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); - if (!iv_index_tbl) break; -- if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break; -+ if (!sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) break; - if (len <= (long)index) break; - val = ptr[index]; - if (val != Qundef) -@@ -1008,7 +988,7 @@ ivar_get(VALUE obj, ID id, int warn) - break; - case T_CLASS: - case T_MODULE: -- if (RCLASS_IV_TBL(obj) && st_lookup(RCLASS_IV_TBL(obj), (st_data_t)id, &index)) -+ if (sa_lookup(RCLASS_IV_TBL(obj), (sa_index_t)id, &index)) - return (VALUE)index; - break; - default: -@@ -1037,7 +1017,7 @@ rb_attr_get(VALUE obj, ID id) - VALUE - rb_ivar_set(VALUE obj, ID id, VALUE val) - { -- struct st_table *iv_index_tbl; -+ struct sa_table *iv_index_tbl; - st_data_t index; - long i, len; - int ivar_extended; -@@ -1051,14 +1031,11 @@ rb_ivar_set(VALUE obj, ID id, VALUE val) - if (!iv_index_tbl) { - VALUE klass = rb_obj_class(obj); - iv_index_tbl = RCLASS_IV_INDEX_TBL(klass); -- if (!iv_index_tbl) { -- iv_index_tbl = RCLASS_IV_INDEX_TBL(klass) = st_init_numtable(); -- } - } - ivar_extended = 0; -- if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) { -+ if (!sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) { - index = iv_index_tbl->num_entries; -- st_add_direct(iv_index_tbl, (st_data_t)id, index); -+ sa_insert(iv_index_tbl, (sa_index_t)id, index); - ivar_extended = 1; - } - len = ROBJECT_NUMIV(obj); -@@ -1098,8 +1075,7 @@ rb_ivar_set(VALUE obj, ID id, VALUE val) - break; - case T_CLASS: - case T_MODULE: -- if (!RCLASS_IV_TBL(obj)) RCLASS_IV_TBL(obj) = st_init_numtable(); -- st_insert(RCLASS_IV_TBL(obj), (st_data_t)id, val); -+ sa_insert(RCLASS_IV_TBL(obj), (sa_index_t)id, val); - break; - default: - generic_ivar_set(obj, id, val); -@@ -1112,13 +1088,13 @@ VALUE - rb_ivar_defined(VALUE obj, ID id) - { - VALUE val; -- struct st_table *iv_index_tbl; -+ struct sa_table *iv_index_tbl; - st_data_t index; - switch (TYPE(obj)) { - case T_OBJECT: - iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); - if (!iv_index_tbl) break; -- if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break; -+ if (!sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) break; - if (ROBJECT_NUMIV(obj) <= (long)index) break; - val = ROBJECT_IVPTR(obj)[index]; - if (val != Qundef) -@@ -1126,7 +1102,7 @@ rb_ivar_defined(VALUE obj, ID id) - break; - case T_CLASS: - case T_MODULE: -- if (RCLASS_IV_TBL(obj) && st_lookup(RCLASS_IV_TBL(obj), (st_data_t)id, 0)) -+ if (sa_lookup(RCLASS_IV_TBL(obj), (sa_index_t)id, 0)) - return Qtrue; - break; - default: -@@ -1137,40 +1113,26 @@ rb_ivar_defined(VALUE obj, ID id) - return Qfalse; - } - --struct obj_ivar_tag { -- VALUE obj; -- int (*func)(ID key, VALUE val, st_data_t arg); -- st_data_t arg; --}; -- --static int --obj_ivar_i(st_data_t key, st_data_t index, st_data_t arg) --{ -- struct obj_ivar_tag *data = (struct obj_ivar_tag *)arg; -- if ((long)index < ROBJECT_NUMIV(data->obj)) { -- VALUE val = ROBJECT_IVPTR(data->obj)[(long)index]; -- if (val != Qundef) { -- return (data->func)((ID)key, val, data->arg); -- } -- } -- return ST_CONTINUE; --} -- - static void - obj_ivar_each(VALUE obj, int (*func)(ANYARGS), st_data_t arg) - { -- st_table *tbl; -- struct obj_ivar_tag data; -+ sa_table *tbl; -+ long numiv = ROBJECT_NUMIV(obj); -+ VALUE *vars = ROBJECT_IVPTR(obj); - - tbl = ROBJECT_IV_INDEX_TBL(obj); -- if (!tbl) -+ if (!tbl || !numiv) - return; - -- data.obj = obj; -- data.func = (int (*)(ID key, VALUE val, st_data_t arg))func; -- data.arg = arg; -- -- st_foreach_safe(tbl, obj_ivar_i, (st_data_t)&data); -+ SA_FOREACH_START(tbl); -+ if ((long)value < numiv) { -+ VALUE val = vars[value]; -+ if (val != Qundef) { -+ if (((sa_iter_func)func)(entry->key, val, arg) == SA_STOP) -+ break; -+ } -+ } -+ SA_FOREACH_END(); - } - - void -@@ -1182,9 +1144,7 @@ rb_ivar_foreach(VALUE obj, int (*func)(ANYARGS), st_data_t arg) - break; - case T_CLASS: - case T_MODULE: -- if (RCLASS_IV_TBL(obj)) { -- st_foreach_safe(RCLASS_IV_TBL(obj), func, arg); -- } -+ sa_foreach(RCLASS_IV_TBL(obj), func, arg); - break; - default: - if (!generic_iv_tbl) break; -@@ -1192,7 +1152,7 @@ rb_ivar_foreach(VALUE obj, int (*func)(ANYARGS), st_data_t arg) - st_data_t tbl; - - if (st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) { -- st_foreach_safe((st_table *)tbl, func, arg); -+ sa_foreach((sa_table *)tbl, func, arg); - } - } - break; -@@ -1202,11 +1162,11 @@ rb_ivar_foreach(VALUE obj, int (*func)(ANYARGS), st_data_t arg) - st_index_t - rb_ivar_count(VALUE obj) - { -- st_table *tbl; -+ sa_table *tbl; - switch (TYPE(obj)) { - case T_OBJECT: - if ((tbl = ROBJECT_IV_INDEX_TBL(obj)) != 0) { -- st_index_t i, count, num = tbl->num_entries; -+ sa_index_t i, count, num = tbl->num_entries; - const VALUE *const ivptr = ROBJECT_IVPTR(obj); - for (i = count = 0; i < num; ++i) { - if (ivptr[i] != Qundef) { -@@ -1228,7 +1188,7 @@ rb_ivar_count(VALUE obj) - st_data_t data; - - if (st_lookup(generic_iv_tbl, (st_data_t)obj, &data) && -- (tbl = (st_table *)data) != 0) { -+ (tbl = (sa_table *)data) != 0) { - return tbl->num_entries; - } - } -@@ -1238,7 +1198,7 @@ rb_ivar_count(VALUE obj) - } - - static int --ivar_i(ID key, VALUE val, VALUE ary) -+ivar_i(sa_index_t key, VALUE val, VALUE ary) - { - if (rb_is_instance_id(key)) { - rb_ary_push(ary, ID2SYM(key)); -@@ -1301,7 +1261,7 @@ rb_obj_remove_instance_variable(VALUE obj, VALUE name) - VALUE val = Qnil; - const ID id = rb_to_id(name); - st_data_t n, v; -- struct st_table *iv_index_tbl; -+ struct sa_table *iv_index_tbl; - st_data_t index; - - if (!OBJ_UNTRUSTED(obj) && rb_safe_level() >= 4) -@@ -1315,7 +1275,7 @@ rb_obj_remove_instance_variable(VALUE obj, VALUE name) - case T_OBJECT: - iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); - if (!iv_index_tbl) break; -- if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break; -+ if (!sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) break; - if (ROBJECT_NUMIV(obj) <= (long)index) break; - val = ROBJECT_IVPTR(obj)[index]; - if (val != Qundef) { -@@ -1326,14 +1286,14 @@ rb_obj_remove_instance_variable(VALUE obj, VALUE name) - case T_CLASS: - case T_MODULE: - n = id; -- if (RCLASS_IV_TBL(obj) && st_delete(RCLASS_IV_TBL(obj), &n, &v)) { -+ if (sa_delete(RCLASS_IV_TBL(obj), (sa_index_t)id, &v)) { - return (VALUE)v; - } - break; - default: - if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) { - v = val; -- if (generic_ivar_remove(obj, (st_data_t)id, &v)) { -+ if (generic_ivar_remove(obj, id, &v)) { - return (VALUE)v; - } - } -@@ -1410,20 +1370,20 @@ rb_mod_const_missing(VALUE klass, VALUE name) - static void - autoload_mark(void *ptr) - { -- rb_mark_tbl((st_table *)ptr); -+ rb_mark_sa_tbl((sa_table *)ptr); - } - - static void - autoload_free(void *ptr) - { -- st_free_table((st_table *)ptr); -+ sa_free_table((sa_table *)ptr); - } - - static size_t - autoload_memsize(const void *ptr) - { -- const st_table *tbl = ptr; -- return st_memsize(tbl); -+ const sa_table *tbl = ptr; -+ return sa_memsize(tbl); - } - - static const rb_data_type_t autoload_data_type = { -@@ -1432,14 +1392,14 @@ static const rb_data_type_t autoload_data_type = { - }; - - #define check_autoload_table(av) \ -- (struct st_table *)rb_check_typeddata((av), &autoload_data_type) -+ (struct sa_table *)rb_check_typeddata((av), &autoload_data_type) - - void - rb_autoload(VALUE mod, ID id, const char *file) - { - st_data_t av; - VALUE fn; -- struct st_table *tbl; -+ struct sa_table *tbl; - - if (!rb_is_const_id(id)) { - rb_raise(rb_eNameError, "autoload must be constant name: %s", rb_id2name(id)); -@@ -1448,43 +1408,41 @@ rb_autoload(VALUE mod, ID id, const char *file) - rb_raise(rb_eArgError, "empty file name"); - } - -- if ((tbl = RCLASS_CONST_TBL(mod)) && st_lookup(tbl, (st_data_t)id, &av) && ((rb_const_entry_t*)av)->value != Qundef) -+ if (sa_lookup(RCLASS_CONST_TBL(mod), (sa_index_t)id, &av) && ((rb_const_entry_t*)av)->value != Qundef) - return; - - rb_const_set(mod, id, Qundef); - tbl = RCLASS_IV_TBL(mod); -- if (tbl && st_lookup(tbl, (st_data_t)autoload, &av)) { -+ if (sa_lookup(tbl, (sa_index_t)autoload, &av)) { - tbl = check_autoload_table((VALUE)av); - } - else { -- if (!tbl) tbl = RCLASS_IV_TBL(mod) = st_init_numtable(); - av = (st_data_t)TypedData_Wrap_Struct(0, &autoload_data_type, 0); -- st_add_direct(tbl, (st_data_t)autoload, av); -- DATA_PTR(av) = tbl = st_init_numtable(); -+ sa_insert(tbl, (sa_index_t)autoload, av); -+ DATA_PTR(av) = tbl = sa_new_table(); - } - fn = rb_str_new2(file); - FL_UNSET(fn, FL_TAINT); - OBJ_FREEZE(fn); -- st_insert(tbl, (st_data_t)id, (st_data_t)rb_node_newnode(NODE_MEMO, fn, rb_safe_level(), 0)); -+ sa_insert(tbl, (sa_index_t)id, (st_data_t)rb_node_newnode(NODE_MEMO, fn, rb_safe_level(), 0)); - } - - static NODE* - autoload_delete(VALUE mod, ID id) - { -- st_data_t val, load = 0, n = id; -+ st_data_t val, load = 0; - rb_const_entry_t *ce; - -- st_delete(RCLASS_CONST_TBL(mod), &n, &val); -+ sa_delete(RCLASS_CONST_TBL(mod), (sa_index_t)id, &val); - ce = (rb_const_entry_t*)val; - if (ce) xfree(ce); -- if (st_lookup(RCLASS_IV_TBL(mod), (st_data_t)autoload, &val)) { -- struct st_table *tbl = check_autoload_table((VALUE)val); -+ if (sa_lookup(RCLASS_IV_TBL(mod), (sa_index_t)autoload, &val)) { -+ struct sa_table *tbl = check_autoload_table((VALUE)val); - -- st_delete(tbl, &n, &load); -+ sa_delete(tbl, (sa_index_t)id, &load); - - if (tbl->num_entries == 0) { -- n = autoload; -- st_delete(RCLASS_IV_TBL(mod), &n, &val); -+ sa_delete(RCLASS_IV_TBL(mod), (sa_index_t)autoload, &val); - } - } - -@@ -1509,14 +1467,14 @@ static NODE * - autoload_node(VALUE mod, ID id, const char **loadingpath) - { - VALUE file; -- struct st_table *tbl; -+ struct sa_table *tbl; - st_data_t val; - NODE *load; - const char *loading; - int safe; - -- if (!st_lookup(RCLASS_IV_TBL(mod), autoload, &val) || -- !(tbl = check_autoload_table((VALUE)val)) || !st_lookup(tbl, (st_data_t)id, &val)) { -+ if (!sa_lookup(RCLASS_IV_TBL(mod), (sa_index_t)autoload, &val) || -+ !(tbl = check_autoload_table((VALUE)val)) || !sa_lookup(tbl, (sa_index_t)id, &val)) { - return 0; - } - load = (NODE *)val; -@@ -1541,10 +1499,10 @@ autoload_node(VALUE mod, ID id, const char **loadingpath) - static int - autoload_node_id(VALUE mod, ID id) - { -- struct st_table *tbl = RCLASS_CONST_TBL(mod); -+ struct sa_table *tbl = RCLASS_CONST_TBL(mod); - st_data_t val; - -- if (!tbl || !st_lookup(tbl, (st_data_t)id, &val) || ((rb_const_entry_t*)val)->value != Qundef) { -+ if (!tbl || !sa_lookup(tbl, (sa_index_t)id, &val) || ((rb_const_entry_t*)val)->value != Qundef) { - return 0; - } - return 1; -@@ -1593,7 +1551,7 @@ rb_const_get_0(VALUE klass, ID id, int exclude, int recurse, int visibility) - while (RTEST(tmp)) { - VALUE am = 0; - st_data_t data; -- while (RCLASS_CONST_TBL(tmp) && st_lookup(RCLASS_CONST_TBL(tmp), (st_data_t)id, &data)) { -+ while (sa_lookup(RCLASS_CONST_TBL(tmp), (sa_index_t)id, &data)) { - rb_const_entry_t *ce = (rb_const_entry_t *)data; - if (visibility && ce->flag == CONST_PRIVATE) { - rb_name_error(id, "private constant %s::%s referenced", rb_class2name(klass), rb_id2name(id)); -@@ -1686,12 +1644,12 @@ VALUE - rb_const_remove(VALUE mod, ID id) - { - VALUE val; -- st_data_t v, n = id; -+ st_data_t v; - - if (!OBJ_UNTRUSTED(mod) && rb_safe_level() >= 4) - rb_raise(rb_eSecurityError, "Insecure: can't remove constant"); - rb_check_frozen(mod); -- if (!RCLASS_CONST_TBL(mod) || !st_delete(RCLASS_CONST_TBL(mod), &n, &v)) { -+ if (!sa_delete(RCLASS_CONST_TBL(mod), (sa_index_t)id, &v)) { - if (rb_const_defined_at(mod, id)) { - rb_name_error(id, "cannot remove %s::%s", - rb_class2name(mod), rb_id2name(id)); -@@ -1711,27 +1669,20 @@ rb_const_remove(VALUE mod, ID id) - return val; - } - --static int --sv_i(ID key, rb_const_entry_t *ce, st_table *tbl) --{ -- if (rb_is_const_id(key)) { -- if (!st_lookup(tbl, (st_data_t)key, 0)) { -- st_insert(tbl, (st_data_t)key, (st_data_t)ce); -- } -- } -- return ST_CONTINUE; --} -- - void* - rb_mod_const_at(VALUE mod, void *data) - { -- st_table *tbl = data; -+ sa_table *tbl = data; - if (!tbl) { -- tbl = st_init_numtable(); -+ tbl = sa_new_table(); - } -- if (RCLASS_CONST_TBL(mod)) { -- st_foreach_safe(RCLASS_CONST_TBL(mod), sv_i, (st_data_t)tbl); -+ SA_FOREACH_START(RCLASS_CONST_TBL(mod)); -+ if (rb_is_const_id(entry->key)) { -+ if (!sa_lookup(tbl, entry->key, 0)) { -+ sa_insert(tbl, entry->key, value); -+ } - } -+ SA_FOREACH_END(); - return tbl; - } - -@@ -1748,25 +1699,21 @@ rb_mod_const_of(VALUE mod, void *data) - return data; - } - --static int --list_i(st_data_t key, st_data_t value, VALUE ary) --{ -- ID sym = (ID)key; -- rb_const_entry_t *ce = (rb_const_entry_t *)value; -- if (ce->flag != CONST_PRIVATE) rb_ary_push(ary, ID2SYM(sym)); -- return ST_CONTINUE; --} -- - VALUE - rb_const_list(void *data) - { -- st_table *tbl = data; -+ sa_table *tbl = data; - VALUE ary; - - if (!tbl) return rb_ary_new2(0); - ary = rb_ary_new2(tbl->num_entries); -- st_foreach_safe(tbl, list_i, ary); -- st_free_table(tbl); -+ -+ SA_FOREACH_START(tbl); -+ rb_const_entry_t *ce = (rb_const_entry_t *)value; -+ if (ce->flag != CONST_PRIVATE) rb_ary_push(ary, ID2SYM(entry->key)); -+ SA_FOREACH_END(); -+ -+ sa_free_table(tbl); - - return ary; - } -@@ -1790,7 +1737,7 @@ VALUE - rb_mod_constants(int argc, VALUE *argv, VALUE mod) - { - VALUE inherit; -- st_table *tbl; -+ sa_table *tbl; - - if (argc == 0) { - inherit = Qtrue; -@@ -1817,7 +1764,7 @@ rb_const_defined_0(VALUE klass, ID id, int exclude, int recurse, int visibility) - tmp = klass; - retry: - while (tmp) { -- if (RCLASS_CONST_TBL(tmp) && st_lookup(RCLASS_CONST_TBL(tmp), (st_data_t)id, &value)) { -+ if (sa_lookup(RCLASS_CONST_TBL(tmp), (sa_index_t)id, &value)) { - rb_const_entry_t *ce = (rb_const_entry_t *)value; - if (visibility && ce->flag == CONST_PRIVATE) { - return (int)Qfalse; -@@ -1885,6 +1832,7 @@ void - rb_const_set(VALUE klass, ID id, VALUE val) - { - rb_const_entry_t *ce; -+ st_data_t value; - VALUE visibility = CONST_PUBLIC; - - if (NIL_P(klass)) { -@@ -1893,21 +1841,14 @@ rb_const_set(VALUE klass, ID id, VALUE val) - } - - check_before_mod_set(klass, id, val, "constant"); -- if (!RCLASS_CONST_TBL(klass)) { -- RCLASS_CONST_TBL(klass) = st_init_numtable(); -- } -- else { -- st_data_t value; -- -- if (st_lookup(RCLASS_CONST_TBL(klass), (st_data_t)id, &value)) { -- rb_const_entry_t *ce = (rb_const_entry_t*)value; -- if (ce->value == Qundef) -- autoload_delete(klass, id); -- else { -- visibility = ce->flag; -- rb_warn("already initialized constant %s", rb_id2name(id)); -- } -- } -+ if (sa_lookup(RCLASS_CONST_TBL(klass), (sa_index_t)id, &value)) { -+ rb_const_entry_t *ce = (rb_const_entry_t*)value; -+ if (ce->value == Qundef) -+ autoload_delete(klass, id); -+ else { -+ visibility = ce->flag; -+ rb_warn("already initialized constant %s", rb_id2name(id)); -+ } - } - - rb_vm_change_state(); -@@ -1916,7 +1857,7 @@ rb_const_set(VALUE klass, ID id, VALUE val) - ce->flag = (rb_const_flag_t)visibility; - ce->value = val; - -- st_insert(RCLASS_CONST_TBL(klass), (st_data_t)id, (st_data_t)ce); -+ sa_insert(RCLASS_CONST_TBL(klass), (sa_index_t)id, (st_data_t)ce); - } - - void -@@ -1958,8 +1899,7 @@ set_const_visibility(VALUE mod, int argc, VALUE *argv, rb_const_flag_t flag) - for (i = 0; i < argc; i++) { - VALUE val = argv[i]; - id = rb_to_id(val); -- if (RCLASS_CONST_TBL(mod) && -- st_lookup(RCLASS_CONST_TBL(mod), (st_data_t)id, &v)) { -+ if (sa_lookup(RCLASS_CONST_TBL(mod), (sa_index_t)id, &v)) { - ((rb_const_entry_t*)v)->flag = flag; - } - else { -@@ -2008,7 +1948,7 @@ original_module(VALUE c) - } - - #define CVAR_LOOKUP(v,r) do {\ -- if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass),(st_data_t)id,(v))) {\ -+ if (sa_lookup(RCLASS_IV_TBL(klass),(sa_index_t)id,(v))) {\ - r;\ - }\ - if (FL_TEST(klass, FL_SINGLETON) ) {\ -@@ -2027,7 +1967,7 @@ original_module(VALUE c) - klass = RCLASS_SUPER(klass);\ - }\ - while (klass) {\ -- if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass),(st_data_t)id,(v))) {\ -+ if (sa_lookup(RCLASS_IV_TBL(klass),(sa_index_t)id,(v))) {\ - r;\ - }\ - klass = RCLASS_SUPER(klass);\ -@@ -2043,15 +1983,13 @@ rb_cvar_set(VALUE klass, ID id, VALUE val) - CVAR_LOOKUP(0, {if (!front) front = klass; target = klass;}); - if (target) { - if (front && target != front) { -- st_data_t did = id; -- - if (RTEST(ruby_verbose)) { - rb_warning("class variable %s of %s is overtaken by %s", - rb_id2name(id), rb_class2name(original_module(front)), - rb_class2name(original_module(target))); - } - if (BUILTIN_TYPE(front) == T_CLASS) { -- st_delete(RCLASS_IV_TBL(front),&did,0); -+ sa_delete(RCLASS_IV_TBL(front),(sa_index_t)id,0); - } - } - } -@@ -2060,11 +1998,7 @@ rb_cvar_set(VALUE klass, ID id, VALUE val) - } - - check_before_mod_set(target, id, val, "class variable"); -- if (!RCLASS_IV_TBL(target)) { -- RCLASS_IV_TBL(target) = st_init_numtable(); -- } -- -- st_insert(RCLASS_IV_TBL(target), (st_data_t)id, (st_data_t)val); -+ sa_insert(RCLASS_IV_TBL(target), (sa_index_t)id, (st_data_t)val); - } - - VALUE -@@ -2080,15 +2014,13 @@ rb_cvar_get(VALUE klass, ID id) - rb_id2name(id), rb_class2name(tmp)); - } - if (front && target != front) { -- st_data_t did = id; -- - if (RTEST(ruby_verbose)) { - rb_warning("class variable %s of %s is overtaken by %s", - rb_id2name(id), rb_class2name(original_module(front)), - rb_class2name(original_module(target))); - } - if (BUILTIN_TYPE(front) == T_CLASS) { -- st_delete(RCLASS_IV_TBL(front),&did,0); -+ sa_delete(RCLASS_IV_TBL(front),(sa_index_t)id,0); - } - } - return (VALUE)value; -@@ -2134,7 +2066,7 @@ rb_define_class_variable(VALUE klass, const char *name, VALUE val) - } - - static int --cv_i(ID key, VALUE value, VALUE ary) -+cv_i(sa_index_t key, VALUE value, VALUE ary) - { - if (rb_is_class_id(key)) { - VALUE kval = ID2SYM(key); -@@ -2167,7 +2099,7 @@ rb_mod_class_variables(VALUE obj) - VALUE ary = rb_ary_new(); - - if (RCLASS_IV_TBL(obj)) { -- st_foreach_safe(RCLASS_IV_TBL(obj), cv_i, ary); -+ sa_foreach(RCLASS_IV_TBL(obj), cv_i, ary); - } - return ary; - } -@@ -2196,7 +2128,7 @@ VALUE - rb_mod_remove_cvar(VALUE mod, VALUE name) - { - const ID id = rb_to_id(name); -- st_data_t val, n = id; -+ st_data_t val; - - if (!rb_is_class_id(id)) { - rb_name_error(id, "wrong class variable name %s", rb_id2name(id)); -@@ -2204,7 +2136,7 @@ rb_mod_remove_cvar(VALUE mod, VALUE name) - if (!OBJ_UNTRUSTED(mod) && rb_safe_level() >= 4) - rb_raise(rb_eSecurityError, "Insecure: can't remove class variable"); - rb_check_frozen(mod); -- if (RCLASS_IV_TBL(mod) && st_delete(RCLASS_IV_TBL(mod), &n, &val)) { -+ if (RCLASS_IV_TBL(mod) && sa_delete(RCLASS_IV_TBL(mod), (sa_index_t)id, &val)) { - return (VALUE)val; - } - if (rb_cvar_defined(mod, id)) { -diff --git a/vm.c b/vm.c -index 04ef956..6edabf6 100644 ---- a/vm.c -+++ b/vm.c -@@ -1055,7 +1055,7 @@ static void - add_opt_method(VALUE klass, ID mid, VALUE bop) - { - rb_method_entry_t *me; -- if (st_lookup(RCLASS_M_TBL(klass), mid, (void *)&me) && me->def && -+ if (sa_lookup(RCLASS_M_TBL(klass), (sa_index_t)mid, (void *)&me) && me->def && - me->def->type == VM_METHOD_TYPE_CFUNC) { - st_insert(vm_opt_method_table, (st_data_t)me, (st_data_t)bop); - } -diff --git a/vm_insnhelper.c b/vm_insnhelper.c -index 4f709e6..1bfd131 100644 ---- a/vm_insnhelper.c -+++ b/vm_insnhelper.c -@@ -1183,7 +1183,7 @@ vm_get_ev_const(rb_thread_t *th, const rb_iseq_t *iseq, - st_data_t data; - search_continue: - if (RCLASS_CONST_TBL(klass) && -- st_lookup(RCLASS_CONST_TBL(klass), id, &data)) { -+ sa_lookup(RCLASS_CONST_TBL(klass), (sa_index_t)id, &data)) { - val = ((rb_const_entry_t*)data)->value; - if (val == Qundef) { - if (am == klass) break; -@@ -1293,10 +1293,10 @@ vm_getivar(VALUE obj, ID id, IC ic) - st_data_t index; - long len = ROBJECT_NUMIV(obj); - VALUE *ptr = ROBJECT_IVPTR(obj); -- struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); -+ struct sa_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); - - if (iv_index_tbl) { -- if (st_lookup(iv_index_tbl, id, &index)) { -+ if (sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) { - if ((long)index < len) { - val = ptr[index]; - } -@@ -1346,9 +1346,9 @@ vm_setivar(VALUE obj, ID id, VALUE val, IC ic) - } - } - else { -- struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); -+ struct sa_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); - -- if (iv_index_tbl && st_lookup(iv_index_tbl, (st_data_t)id, &index)) { -+ if (iv_index_tbl && sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) { - ic->ic_class = klass; - ic->ic_value.index = index; - ic->ic_vmstat = GET_VM_STATE_VERSION(); -diff --git a/vm_method.c b/vm_method.c -index 6e33603..f1d1774 100644 ---- a/vm_method.c -+++ b/vm_method.c -@@ -162,7 +162,7 @@ rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type, - rb_method_definition_t *def, rb_method_flag_t noex) - { - rb_method_entry_t *me; -- st_table *mtbl; -+ sa_table *mtbl; - st_data_t data; - - if (NIL_P(klass)) { -@@ -190,7 +190,7 @@ rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type, - mtbl = RCLASS_M_TBL(klass); - - /* check re-definition */ -- if (st_lookup(mtbl, mid, &data)) { -+ if (sa_lookup(mtbl, (sa_index_t)mid, &data)) { - rb_method_entry_t *old_me = (rb_method_entry_t *)data; - rb_method_definition_t *old_def = old_me->def; - -@@ -248,7 +248,7 @@ rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type, - } - } - -- st_insert(mtbl, mid, (st_data_t) me); -+ sa_insert(mtbl, (sa_index_t)mid, (st_data_t) me); - - return me; - } -@@ -371,7 +371,7 @@ search_method(VALUE klass, ID id) - return 0; - } - -- while (!st_lookup(RCLASS_M_TBL(klass), id, &body)) { -+ while (!sa_lookup(RCLASS_M_TBL(klass), (sa_index_t)id, &body)) { - klass = RCLASS_SUPER(klass); - if (!klass) { - return 0; -@@ -429,7 +429,7 @@ rb_method_entry(VALUE klass, ID id) - static void - remove_method(VALUE klass, ID mid) - { -- st_data_t key, data; -+ st_data_t data; - rb_method_entry_t *me = 0; - - if (klass == rb_cObject) { -@@ -443,14 +443,13 @@ remove_method(VALUE klass, ID mid) - rb_warn("removing `%s' may cause serious problems", rb_id2name(mid)); - } - -- if (!st_lookup(RCLASS_M_TBL(klass), mid, &data) || -+ if (!sa_lookup(RCLASS_M_TBL(klass), (sa_index_t)mid, &data) || - !(me = (rb_method_entry_t *)data) || - (!me->def || me->def->type == VM_METHOD_TYPE_UNDEF)) { - rb_name_error(mid, "method `%s' not defined in %s", - rb_id2name(mid), rb_class2name(klass)); - } -- key = (st_data_t)mid; -- st_delete(RCLASS_M_TBL(klass), &key, &data); -+ sa_delete(RCLASS_M_TBL(klass), (sa_index_t)mid, &data); - - rb_vm_check_redefinition_opt_method(me); - rb_clear_cache_for_undef(klass, mid); diff --git a/patches/ruby/1.9.3/p385/railsexpress/12-falcon-array-queue.patch b/patches/ruby/1.9.3/p385/railsexpress/12-falcon-array-queue.patch deleted file mode 100644 index cdd40e123c..0000000000 --- a/patches/ruby/1.9.3/p385/railsexpress/12-falcon-array-queue.patch +++ /dev/null @@ -1,301 +0,0 @@ -diff --git a/array.c b/array.c -index c33d106..747da0e 100644 ---- a/array.c -+++ b/array.c -@@ -255,15 +255,24 @@ rb_ary_modify(VALUE ary) - rb_ary_modify_check(ary); - if (ARY_SHARED_P(ary)) { - long len = RARRAY_LEN(ary); -+ VALUE shared = ARY_SHARED(ary); - if (len <= RARRAY_EMBED_LEN_MAX) { - VALUE *ptr = ARY_HEAP_PTR(ary); -- VALUE shared = ARY_SHARED(ary); - FL_UNSET_SHARED(ary); - FL_SET_EMBED(ary); - MEMCPY(ARY_EMBED_PTR(ary), ptr, VALUE, len); - rb_ary_decrement_share(shared); - ARY_SET_EMBED_LEN(ary, len); - } -+ else if (ARY_SHARED_NUM(shared) == 1 && len > RARRAY_LEN(shared)>>1) { -+ long shift = RARRAY_PTR(ary) - RARRAY_PTR(shared); -+ ARY_SET_PTR(ary, RARRAY_PTR(shared)); -+ ARY_SET_CAPA(ary, RARRAY_LEN(shared)); -+ MEMMOVE(RARRAY_PTR(ary), RARRAY_PTR(ary)+shift, VALUE, len); -+ FL_UNSET_SHARED(ary); -+ FL_SET_EMBED(shared); -+ rb_ary_decrement_share(shared); -+ } - else { - VALUE *ptr = ALLOC_N(VALUE, len); - MEMCPY(ptr, RARRAY_PTR(ary), VALUE, len); -@@ -274,6 +283,38 @@ rb_ary_modify(VALUE ary) - } - } - -+static void -+ary_ensure_room_for_push(VALUE ary, long add_len) -+{ -+ long new_len = RARRAY_LEN(ary) + add_len; -+ long capa; -+ -+ if (ARY_SHARED_P(ary)) { -+ if (new_len > RARRAY_EMBED_LEN_MAX) { -+ VALUE shared = ARY_SHARED(ary); -+ if (ARY_SHARED_NUM(shared) == 1) { -+ if (RARRAY_PTR(ary) - RARRAY_PTR(shared) + new_len <= RARRAY_LEN(shared)) { -+ rb_ary_modify_check(ary); -+ } -+ else { -+ /* if array is shared, than it is likely it participate in push/shift pattern */ -+ rb_ary_modify(ary); -+ capa = ARY_CAPA(ary); -+ if (new_len > capa - (capa >> 6)) { -+ ary_double_capa(ary, new_len); -+ } -+ } -+ return; -+ } -+ } -+ } -+ rb_ary_modify(ary); -+ capa = ARY_CAPA(ary); -+ if (new_len > capa) { -+ ary_double_capa(ary, new_len); -+ } -+} -+ - VALUE - rb_ary_freeze(VALUE ary) - { -@@ -446,8 +487,9 @@ ary_make_shared(VALUE ary) - OBJSETUP(shared, 0, T_ARRAY); - FL_UNSET_EMBED(shared); - -- ARY_SET_LEN((VALUE)shared, RARRAY_LEN(ary)); -+ ARY_SET_LEN((VALUE)shared, ARY_CAPA(ary)); - ARY_SET_PTR((VALUE)shared, RARRAY_PTR(ary)); -+ rb_mem_clear(RARRAY_PTR(shared) + RARRAY_LEN(ary), ARY_CAPA(ary) - RARRAY_LEN(ary)); - FL_SET_SHARED_ROOT(shared); - ARY_SET_SHARED_NUM((VALUE)shared, 1); - FL_SET_SHARED(ary); -@@ -737,8 +779,6 @@ ary_take_first_or_last(int argc, VALUE *argv, VALUE ary, enum ary_take_pos_flags - return ary_make_partial(ary, rb_cArray, offset, n); - } - --static VALUE rb_ary_push_1(VALUE ary, VALUE item); -- - /* - * call-seq: - * ary << obj -> ary -@@ -755,8 +795,12 @@ static VALUE rb_ary_push_1(VALUE ary, VALUE item); - VALUE - rb_ary_push(VALUE ary, VALUE item) - { -- rb_ary_modify(ary); -- return rb_ary_push_1(ary, item); -+ long idx = RARRAY_LEN(ary); -+ -+ ary_ensure_room_for_push(ary, 1); -+ RARRAY_PTR(ary)[idx] = item; -+ ARY_SET_LEN(ary, idx + 1); -+ return ary; - } - - static VALUE -@@ -772,6 +816,18 @@ rb_ary_push_1(VALUE ary, VALUE item) - return ary; - } - -+static VALUE -+rb_ary_cat(VALUE ary, const VALUE *ptr, long len) -+{ -+ long oldlen = RARRAY_LEN(ary); -+ -+ ary_ensure_room_for_push(ary, len); -+copy: -+ MEMCPY(RARRAY_PTR(ary) + oldlen, ptr, VALUE, len); -+ ARY_SET_LEN(ary, oldlen + len); -+ return ary; -+} -+ - /* - * call-seq: - * ary.push(obj, ... ) -> ary -@@ -788,11 +844,7 @@ rb_ary_push_1(VALUE ary, VALUE item) - static VALUE - rb_ary_push_m(int argc, VALUE *argv, VALUE ary) - { -- rb_ary_modify(ary); -- while (argc--) { -- rb_ary_push_1(ary, *argv++); -- } -- return ary; -+ return rb_ary_cat(ary, argv, argc); - } - - VALUE -@@ -920,6 +972,55 @@ rb_ary_shift_m(int argc, VALUE *argv, VALUE ary) - return result; - } - -+static void -+ary_ensure_room_for_unshift(VALUE ary, int argc) -+{ -+ long len = RARRAY_LEN(ary); -+ long new_len = len + argc; -+ long capa; -+ VALUE *head, *sharedp; -+ -+ if (ARY_SHARED_P(ary)) { -+ VALUE shared = ARY_SHARED(ary); -+ capa = RARRAY_LEN(shared); -+ if (ARY_SHARED_NUM(shared) == 1 && capa > new_len) { -+ head = RARRAY_PTR(ary); -+ sharedp = RARRAY_PTR(shared); -+ goto makeroom_if_need; -+ } -+ } -+ -+ rb_ary_modify(ary); -+ capa = ARY_CAPA(ary); -+ if (capa - (capa >> 6) <= new_len) { -+ ary_double_capa(ary, new_len); -+ } -+ -+ /* use shared array for big "queues" */ -+ if (new_len > ARY_DEFAULT_SIZE * 4) { -+ /* make a room for unshifted items */ -+ capa = ARY_CAPA(ary); -+ ary_make_shared(ary); -+ -+ head = sharedp = RARRAY_PTR(ary); -+ goto makeroom; -+makeroom_if_need: -+ if (head - sharedp < argc) { -+ long room; -+makeroom: -+ room = capa - new_len; -+ room -= room >> 4; -+ MEMMOVE(sharedp + argc + room, head, VALUE, len); -+ head = sharedp + argc + room; -+ } -+ ARY_SET_PTR(ary, head - argc); -+ } -+ else { -+ /* sliding items */ -+ MEMMOVE(RARRAY_PTR(ary) + argc, RARRAY_PTR(ary), VALUE, len); -+ } -+} -+ - /* - * call-seq: - * ary.unshift(obj, ...) -> ary -@@ -935,19 +1036,16 @@ rb_ary_shift_m(int argc, VALUE *argv, VALUE ary) - static VALUE - rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary) - { -- long len; -+ long len = RARRAY_LEN(ary); - -- rb_ary_modify(ary); -- if (argc == 0) return ary; -- if (ARY_CAPA(ary) <= (len = RARRAY_LEN(ary)) + argc) { -- ary_double_capa(ary, len + argc); -+ if (argc == 0) { -+ rb_ary_modify_check(ary); -+ return ary; - } - -- /* sliding items */ -- MEMMOVE(RARRAY_PTR(ary) + argc, RARRAY_PTR(ary), VALUE, len); -+ ary_ensure_room_for_unshift(ary, argc); - MEMCPY(RARRAY_PTR(ary), argv, VALUE, argc); -- ARY_INCREASE_LEN(ary, argc); -- -+ ARY_SET_LEN(ary, len + argc); - return ary; - } - -@@ -1309,15 +1407,12 @@ rb_ary_splice(VALUE ary, long beg, long len, VALUE rpl) - rpl = rb_ary_to_ary(rpl); - rlen = RARRAY_LEN(rpl); - } -- rb_ary_modify(ary); - if (beg >= RARRAY_LEN(ary)) { - if (beg > ARY_MAX_SIZE - rlen) { - rb_raise(rb_eIndexError, "index %ld too big", beg); - } -+ ary_ensure_room_for_push(ary, rlen-len); /* len is 0 or negative */ - len = beg + rlen; -- if (len >= ARY_CAPA(ary)) { -- ary_double_capa(ary, len); -- } - rb_mem_clear(RARRAY_PTR(ary) + RARRAY_LEN(ary), beg - RARRAY_LEN(ary)); - if (rlen > 0) { - MEMCPY(RARRAY_PTR(ary) + beg, RARRAY_PTR(rpl), VALUE, rlen); -@@ -1327,6 +1422,7 @@ rb_ary_splice(VALUE ary, long beg, long len, VALUE rpl) - else { - long alen; - -+ rb_ary_modify(ary); - alen = RARRAY_LEN(ary) + rlen - len; - if (alen >= ARY_CAPA(ary)) { - ary_double_capa(ary, alen); -@@ -2116,12 +2212,13 @@ rb_ary_sort_bang(VALUE ary) - if (RARRAY_LEN(ary) > 1) { - VALUE tmp = ary_make_substitution(ary); /* only ary refers tmp */ - struct ary_sort_data data; -+ long len = RARRAY_LEN(ary); - - RBASIC(tmp)->klass = 0; - data.ary = tmp; - data.opt_methods = 0; - data.opt_inited = 0; -- ruby_qsort(RARRAY_PTR(tmp), RARRAY_LEN(tmp), sizeof(VALUE), -+ ruby_qsort(RARRAY_PTR(tmp), len, sizeof(VALUE), - rb_block_given_p()?sort_1:sort_2, &data); - - if (ARY_EMBED_P(tmp)) { -@@ -2138,7 +2235,7 @@ rb_ary_sort_bang(VALUE ary) - if (ARY_HEAP_PTR(ary) == ARY_HEAP_PTR(tmp)) { - assert(!ARY_EMBED_P(ary)); - FL_UNSET_SHARED(ary); -- ARY_SET_CAPA(ary, ARY_CAPA(tmp)); -+ ARY_SET_CAPA(ary, RARRAY_LEN(tmp)); - } - else { - assert(!ARY_SHARED_P(tmp)); -@@ -2153,8 +2250,8 @@ rb_ary_sort_bang(VALUE ary) - xfree(ARY_HEAP_PTR(ary)); - } - ARY_SET_PTR(ary, RARRAY_PTR(tmp)); -- ARY_SET_HEAP_LEN(ary, RARRAY_LEN(tmp)); -- ARY_SET_CAPA(ary, ARY_CAPA(tmp)); -+ ARY_SET_HEAP_LEN(ary, len); -+ ARY_SET_CAPA(ary, RARRAY_LEN(tmp)); - } - /* tmp was lost ownership for the ptr */ - FL_UNSET(tmp, FL_FREEZE); -diff --git a/test/ruby/test_array.rb b/test/ruby/test_array.rb -index 28d3e41..bcad2c0 100644 ---- a/test/ruby/test_array.rb -+++ b/test/ruby/test_array.rb -@@ -414,6 +414,18 @@ class TestArray < Test::Unit::TestCase - a = @cls[1, 2, 3] - a[-1, 0] = a - assert_equal([1, 2, 1, 2, 3, 3], a) -+ -+ a = @cls[] -+ a[5,0] = [5] -+ assert_equal([nil, nil, nil, nil, nil, 5], a) -+ -+ a = @cls[1] -+ a[1,0] = [2] -+ assert_equal([1, 2], a) -+ -+ a = @cls[1] -+ a[1,1] = [2] -+ assert_equal([1, 2], a) - end - - def test_assoc diff --git a/patches/ruby/1.9.3/p392/railsexpress/01-fix-make-clean.patch b/patches/ruby/1.9.3/p392/railsexpress/01-fix-make-clean.patch deleted file mode 100644 index bd3b673664..0000000000 --- a/patches/ruby/1.9.3/p392/railsexpress/01-fix-make-clean.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/lib/mkmf.rb b/lib/mkmf.rb -index 7c706e8..c381a38 100644 ---- a/lib/mkmf.rb -+++ b/lib/mkmf.rb -@@ -2191,7 +2191,7 @@ def init_mkmf(config = CONFIG, rbconfig = RbConfig::CONFIG) - $LOCAL_LIBS = "" - - $cleanfiles = config_string('CLEANFILES') {|s| Shellwords.shellwords(s)} || [] -- $cleanfiles << "mkmf.log" -+ $cleanfiles << "mkmf.log .*.time" - $distcleanfiles = config_string('DISTCLEANFILES') {|s| Shellwords.shellwords(s)} || [] - $distcleandirs = config_string('DISTCLEANDIRS') {|s| Shellwords.shellwords(s)} || [] - diff --git a/patches/ruby/1.9.3/p392/railsexpress/02-railsbench-gc.patch b/patches/ruby/1.9.3/p392/railsexpress/02-railsbench-gc.patch deleted file mode 100644 index 2acfd53d57..0000000000 --- a/patches/ruby/1.9.3/p392/railsexpress/02-railsbench-gc.patch +++ /dev/null @@ -1,1235 +0,0 @@ -diff --git a/configure.in b/configure.in -index c64d981..6099a92 100644 ---- a/configure.in -+++ b/configure.in -@@ -2416,6 +2416,10 @@ if test "$EXEEXT" = .exe; then - AC_SUBST(EXECUTABLE_EXTS) - fi - -+dnl enable gc debugging -+AC_ARG_ENABLE(gcdebug, -+ AS_HELP_STRING([--enable-gcdebug], [build garbage collector with debugging enabled]), -+ [AC_DEFINE(GC_DEBUG,1)]) - dnl } - dnl build section { - -diff --git a/gc.c b/gc.c -index 0f84e22..feb54f1 100644 ---- a/gc.c -+++ b/gc.c -@@ -98,6 +98,15 @@ ruby_gc_params_t initial_params = { - #endif - }; - -+#ifndef HAVE_LONG_LONG -+#define LONG_LONG long -+#endif -+ -+static int heap_min_slots = 10000; -+static int heap_slots_increment = 10000; -+static int initial_heap_slots_increment = 10000; -+static double heap_slots_growth_factor = 1.8; -+ - #define nomem_error GET_VM()->special_exceptions[ruby_error_nomemory] - - #if SIZEOF_LONG == SIZEOF_VOIDP -@@ -302,7 +311,7 @@ typedef struct RVALUE { - struct RComplex complex; - } as; - #ifdef GC_DEBUG -- const char *file; -+ VALUE file; - int line; - #endif - } RVALUE; -@@ -372,11 +381,25 @@ typedef struct rb_objspace { - size_t free_min; - size_t final_num; - size_t do_heap_free; -+ unsigned long max_blocks_to_free; -+ unsigned long freed_blocks; - } heap; - struct { -+ unsigned long processed; -+ unsigned long freed_objects; -+ unsigned long freelist_size; -+ unsigned long zombies; -+ unsigned long free_counts[T_MASK+1]; -+ unsigned long live_counts[T_MASK+1]; -+ unsigned long gc_time_accumulator_before_gc; -+ unsigned long live_after_last_mark_phase; -+ } stats; -+ struct { - int dont_gc; - int dont_lazy_sweep; - int during_gc; -+ int gc_statistics; -+ int verbose_gc_stats; - } flags; - struct { - st_table *table; -@@ -393,6 +416,14 @@ typedef struct rb_objspace { - struct gc_list *global_list; - size_t count; - int gc_stress; -+ long heap_size; -+ unsigned LONG_LONG gc_time_accumulator; -+ FILE* gc_data_file; -+ long gc_collections; -+ unsigned LONG_LONG gc_allocated_size; -+ unsigned LONG_LONG gc_num_allocations; -+ unsigned long live_objects; -+ unsigned LONG_LONG allocated_objects; - } rb_objspace_t; - - #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE -@@ -415,6 +446,16 @@ int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress; - #define heaps_freed objspace->heap.freed - #define dont_gc objspace->flags.dont_gc - #define during_gc objspace->flags.during_gc -+#define gc_statistics objspace->flags.gc_statistics -+#define verbose_gc_stats objspace->flags.verbose_gc_stats -+#define heap_size objspace->heap_size -+#define gc_time_accumulator objspace->gc_time_accumulator -+#define gc_data_file objspace->gc_data_file -+#define gc_collections objspace->gc_collections -+#define gc_allocated_size objspace->gc_allocated_size -+#define gc_num_allocations objspace->gc_num_allocations -+#define live_objects objspace->live_objects -+#define allocated_objects objspace->allocated_objects - #define finalizer_table objspace->final.table - #define deferred_final_list objspace->final.deferred - #define global_List objspace->global_list -@@ -422,6 +463,14 @@ int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress; - #define initial_malloc_limit initial_params.initial_malloc_limit - #define initial_heap_min_slots initial_params.initial_heap_min_slots - #define initial_free_min initial_params.initial_free_min -+#define free_counts objspace->stats.free_counts -+#define live_counts objspace->stats.live_counts -+#define processed objspace->stats.processed -+#define zombies objspace->stats.zombies -+#define freelist_size objspace->stats.freelist_size -+#define freed_objects objspace->stats.freed_objects -+#define gc_time_accumulator_before_gc objspace->stats.gc_time_accumulator_before_gc -+#define live_after_last_mark_phase objspace->stats.live_after_last_mark_phase - - static void rb_objspace_call_finalizer(rb_objspace_t *objspace); - -@@ -444,24 +493,59 @@ static void init_mark_stack(mark_stack_t *stack); - void - rb_gc_set_params(void) - { -- char *malloc_limit_ptr, *heap_min_slots_ptr, *free_min_ptr; -+ char *envp; -+ -+ rb_objspace_t *objspace = &rb_objspace; -+ -+ gc_data_file = stderr; - - if (rb_safe_level() > 0) return; - -- malloc_limit_ptr = getenv("RUBY_GC_MALLOC_LIMIT"); -- if (malloc_limit_ptr != NULL) { -- int malloc_limit_i = atoi(malloc_limit_ptr); -+ envp = getenv("RUBY_GC_STATS"); -+ if (envp != NULL) { -+ int i = atoi(envp); -+ if (i > 0) { -+ verbose_gc_stats = 1; -+ fprintf(stderr, "RUBY_GC_STATS=%d\n", verbose_gc_stats); -+ } -+ /* child processes should not inherit RUBY_GC_STATS */ -+ ruby_unsetenv("RUBY_GC_STATS"); -+ } -+ -+ envp = getenv("RUBY_GC_DATA_FILE"); -+ if (envp != NULL) { -+ FILE* data_file = fopen(envp, "w"); -+ if (data_file != NULL) { -+ gc_data_file = data_file; -+ } -+ else { -+ fprintf(stderr, "can't open gc log file %s for writing, using default\n", envp); -+ } -+ /* child processes should not inherit RUBY_GC_DATA_FILE to avoid clobbering */ -+ ruby_unsetenv("RUBY_GC_DATA_FILE"); -+ } -+ -+ envp = getenv("RUBY_GC_MALLOC_LIMIT"); -+ if (envp != NULL) { -+ int malloc_limit_i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_GC_MALLOC_LIMIT=%s\n", envp); -+ } - if (RTEST(ruby_verbose)) - fprintf(stderr, "malloc_limit=%d (%d)\n", - malloc_limit_i, initial_malloc_limit); - if (malloc_limit_i > 0) { - initial_malloc_limit = malloc_limit_i; -+ // malloc_limit = initial_malloc_limit; - } - } - -- heap_min_slots_ptr = getenv("RUBY_HEAP_MIN_SLOTS"); -- if (heap_min_slots_ptr != NULL) { -- int heap_min_slots_i = atoi(heap_min_slots_ptr); -+ envp = getenv("RUBY_HEAP_MIN_SLOTS"); -+ if (envp != NULL) { -+ int heap_min_slots_i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_MIN_SLOTS=%s\n", envp); -+ } - if (RTEST(ruby_verbose)) - fprintf(stderr, "heap_min_slots=%d (%d)\n", - heap_min_slots_i, initial_heap_min_slots); -@@ -471,15 +555,42 @@ rb_gc_set_params(void) - } - } - -- free_min_ptr = getenv("RUBY_FREE_MIN"); -- if (free_min_ptr != NULL) { -- int free_min_i = atoi(free_min_ptr); -+ if (!(envp = getenv("RUBY_FREE_MIN"))) -+ envp = getenv("RUBY_HEAP_FREE_MIN"); -+ if (envp != NULL) { -+ int free_min_i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_FREE_MIN=%s\n", envp); -+ } - if (RTEST(ruby_verbose)) - fprintf(stderr, "free_min=%d (%d)\n", free_min_i, initial_free_min); - if (free_min_i > 0) { - initial_free_min = free_min_i; - } - } -+ -+ envp = getenv("RUBY_HEAP_SLOTS_INCREMENT"); -+ if (envp != NULL) { -+ int i = atoi(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_INCREMENT=%s\n", envp); -+ } -+ heap_slots_increment = i; -+ initial_heap_slots_increment = heap_slots_increment; -+ } -+ -+ envp = getenv("RUBY_HEAP_SLOTS_GROWTH_FACTOR"); -+ if (envp != NULL) { -+ double d = atof(envp); -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "RUBY_HEAP_SLOTS_GROWTH_FACTOR=%s\n", envp); -+ } -+ if (d > 0) { -+ heap_slots_growth_factor = d; -+ } -+ } -+ -+ fflush(gc_data_file); - } - - #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE -@@ -776,6 +887,11 @@ vm_malloc_fixup(rb_objspace_t *objspace, void *mem, size_t size) - mem = (size_t *)mem + 1; - #endif - -+ if (gc_statistics) { -+ gc_allocated_size += size; -+ gc_num_allocations += 1; -+ } -+ - return mem; - } - -@@ -836,6 +952,13 @@ vm_xrealloc(rb_objspace_t *objspace, void *ptr, size_t size) - mem = (size_t *)mem + 1; - #endif - -+ /* TODO: we can't count correctly unless we store old size on heap -+ if (gc_statistics) { -+ gc_allocated_size += size; -+ gc_num_allocations += 1; -+ } -+ */ -+ - return mem; - } - -@@ -917,7 +1040,6 @@ ruby_xfree(void *x) - vm_xfree(&rb_objspace, x); - } - -- - /* - * call-seq: - * GC.enable -> true or false -@@ -963,6 +1085,455 @@ rb_gc_disable(void) - return old ? Qtrue : Qfalse; - } - -+/* -+ * call-seq: -+ * GC.enable_stats => true or false -+ * -+ * Enables garbage collection statistics, returning true if garbage -+ * collection statistics was already enabled. -+ * -+ * GC.enable_stats #=> false or true -+ * GC.enable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = gc_statistics; -+ gc_statistics = 1; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_stats => true or false -+ * -+ * Disables garbage collection statistics, returning true if garbage -+ * collection statistics was already disabled. -+ * -+ * GC.disable_stats #=> false or true -+ * GC.disable_stats #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = gc_statistics; -+ gc_statistics = 0; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.stats_enabled? => true or false -+ * -+ * Check whether GC stats have been enabled. -+ * -+ * GC.stats_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_stats_enabled() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return gc_statistics ? Qtrue : Qfalse; -+} -+ -+ -+/* -+ * call-seq: -+ * GC.clear_stats => nil -+ * -+ * Clears garbage collection statistics, returning nil. This resets the number -+ * of collections (GC.collections) and the time used (GC.time) to 0. -+ * -+ * GC.clear_stats #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_clear_stats() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ gc_collections = 0; -+ gc_time_accumulator = 0; -+ gc_time_accumulator_before_gc = 0; -+ gc_allocated_size = 0; -+ gc_num_allocations = 0; -+ return Qnil; -+} -+ -+/* -+ * call-seq: -+ * GC.allocated_size => Integer -+ * -+ * Returns the size of memory (in bytes) allocated since GC statistics collection -+ * was enabled. -+ * -+ * GC.allocated_size #=> 35 -+ * -+ */ -+ -+VALUE -+rb_gc_allocated_size() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_allocated_size); -+#else -+ return ULONG2NUM(gc_allocated_size); -+#endif -+} -+ -+/* -+ * call-seq: -+ * GC.num_allocations => Integer -+ * -+ * Returns the number of memory allocations since GC statistics collection -+ * was enabled. -+ * -+ * GC.num_allocations #=> 150 -+ * -+ */ -+VALUE -+rb_gc_num_allocations() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return ULL2NUM(gc_num_allocations); -+#else -+ return ULONG2NUM(gc_num_allocations); -+#endif -+} -+ -+/* -+ * call-seq: -+ * GC.enable_trace => true or false -+ * -+ * Enables garbage collection tracing, returning true if garbage -+ * collection tracing was already enabled. -+ * -+ * GC.enable_trace #=> false or true -+ * GC.enable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_enable_trace() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = verbose_gc_stats; -+ verbose_gc_stats = 1; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.disable_trace => true or false -+ * -+ * Disables garbage collection tracing, returning true if garbage -+ * collection tracing was already disabled. -+ * -+ * GC.disable_trace #=> false or true -+ * GC.disable_trace #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_disable_trace() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ int old = verbose_gc_stats; -+ verbose_gc_stats = 0; -+ return old ? Qtrue : Qfalse; -+} -+ -+/* -+ * call-seq: -+ * GC.trace_enabled? => true or false -+ * -+ * Check whether GC tracing has been enabled. -+ * -+ * GC.trace_enabled? #=> false or true -+ * -+ */ -+ -+VALUE -+rb_gc_trace_enabled() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return verbose_gc_stats ? Qtrue : Qfalse; -+} -+ -+ -+const char* GC_LOGFILE_IVAR = "@gc_logfile_name"; -+ -+/* -+ * call-seq: -+ * GC.log_file(filename=nil, mode="w") => boolean -+ * -+ * Changes the GC data log file. Closes the currently open logfile. -+ * Returns true if the file was successfully opened for -+ * writing. Returns false if the file could not be opened for -+ * writing. Returns the name of the current logfile (or nil) if no -+ * parameter is given. Restores logging to stderr when given nil as -+ * an argument. -+ * -+ * GC.log_file #=> nil -+ * GC.log_file "/tmp/gc.log" #=> true -+ * GC.log_file #=> "/tmp/gc.log" -+ * GC.log_file nil #=> true -+ * -+ */ -+ -+VALUE -+rb_gc_log_file(int argc, VALUE *argv, VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ VALUE filename = Qnil; -+ VALUE mode_str = Qnil; -+ FILE* f = NULL; -+ const char* mode = "w"; -+ -+ VALUE current_logfile_name = rb_iv_get(rb_mGC, GC_LOGFILE_IVAR); -+ -+ if (argc==0) -+ return current_logfile_name; -+ -+ rb_scan_args(argc, argv, "02", &filename, &mode_str); -+ -+ if (filename == Qnil) { -+ /* close current logfile and reset logfile to stderr */ -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+ } -+ return Qtrue; -+ } -+ -+ /* we have a real logfile name */ -+ filename = StringValue(filename); -+ -+ if (rb_equal(current_logfile_name, filename) == Qtrue) { -+ /* do nothing if we get the file name we're already logging to */ -+ return Qtrue; -+ } -+ -+ /* get mode for file opening */ -+ if (mode_str != Qnil) -+ { -+ mode = RSTRING_PTR(StringValue(mode_str)); -+ } -+ -+ /* try to open file in given mode */ -+ if (f = fopen(RSTRING_PTR(filename), mode)) { -+ if (gc_data_file != stderr) { -+ fclose(gc_data_file); -+ } -+ gc_data_file = f; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, filename); -+ } else { -+ return Qfalse; -+ } -+ return Qtrue; -+} -+ -+/* -+ * call-seq: -+ * GC.log String => String -+ * -+ * Logs string to the GC data file and returns it. -+ * -+ * GC.log "manual GC call" #=> "manual GC call" -+ * -+ */ -+ -+VALUE -+rb_gc_log(self, original_str) -+ VALUE self, original_str; -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ if (original_str == Qnil) { -+ fprintf(gc_data_file, "\n"); -+ } -+ else { -+ VALUE str = StringValue(original_str); -+ char *p = RSTRING_PTR(str); -+ fprintf(gc_data_file, "%s\n", p); -+ } -+ return original_str; -+} -+ -+/* -+ * call-seq: -+ * GC.dump => nil -+ * -+ * dumps information about the current GC data structures to the GC log file -+ * -+ * GC.dump #=> nil -+ * -+ */ -+ -+VALUE -+rb_gc_dump() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ size_t i; -+ -+ for (i = 0; i < heaps_used; i++) { -+ size_t limit = objspace->heap.sorted[i].slot->limit; -+ fprintf(gc_data_file, "HEAP[%2lu]: size=%7lu\n", (unsigned long)i, (unsigned long)limit); -+ } -+ -+ return Qnil; -+} -+ -+static const char* obj_type(VALUE tp); -+ -+#ifdef GC_DEBUG -+/* -+ * call-seq: -+ * GC.dump_file_and_line_info(String, boolean) => nil -+ * -+ * dumps information on which currently allocated object was created by which file and on which line -+ * -+ * GC.dump_file_and_line_info(String, boolean) #=> nil -+ * -+ * The second parameter specifies whether class names should be included in the dump. -+ * Note that including class names will allocate additional string objects on the heap. -+ * -+ */ -+ -+VALUE -+rb_gc_dump_file_and_line_info(int argc, VALUE *argv) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ VALUE filename, str, include_classnames = Qnil; -+ char *fname = NULL; -+ char *klass = NULL; -+ FILE* f = NULL; -+ size_t i = 0; -+ -+ rb_scan_args(argc, argv, "11", &filename, &include_classnames); -+ -+ str = StringValue(filename); -+ fname = RSTRING_PTR(str); -+ f = fopen(fname, "w"); -+ -+ for (i = 0; i < heaps_used; i++) { -+ RVALUE *p, *pend; -+ -+ p = objspace->heap.sorted[i].start; pend = objspace->heap.sorted[i].end; -+ for (;p < pend; p++) { -+ if (p->as.basic.flags) { -+ const char *src_filename = (p->file && p->file != Qnil )? RSTRING_PTR(p->file) : ""; -+ fprintf(f, "%s:%s:%d", obj_type(p->as.basic.flags & T_MASK), src_filename, (int)p->line); -+ // rb_obj_classname will create objects on the heap, we need a better solution -+ if (include_classnames == Qtrue) { -+ /* write the class */ -+ fprintf(f, ":"); -+ switch (BUILTIN_TYPE(p)) { -+ case T_NONE: -+ fprintf(f, "__none__"); -+ break; -+ case T_UNDEF: -+ fprintf(f, "__undef__"); -+ break; -+ case T_NODE: -+ fprintf(f, "__node__"); -+ break; -+ default: -+ if (!p->as.basic.klass) { -+ fprintf(f, "__unknown__"); -+ } else { -+ fprintf(f, "%s", rb_obj_classname((VALUE)p)); -+ } -+ } -+ /* print object size for some known object types */ -+ switch (BUILTIN_TYPE(p)) { -+ case T_STRING: -+ fprintf(f, ":%lu", RSTRING_LEN(p)); -+ break; -+ case T_ARRAY: -+ fprintf(f, ":%lu", RARRAY_LEN(p)); -+ break; -+ case T_HASH: -+ fprintf(f, ":%lu", (long unsigned int)RHASH_SIZE(p)); -+ break; -+ } -+ } -+ fprintf(f, "\n"); -+ } -+ } -+ } -+ fclose(f); -+ return Qnil; -+} -+#endif -+ -+/* -+ * call-seq: -+ * GC.heap_slots => Integer -+ * -+ * Returns the number of heap slots available for object allocations. -+ * -+ * GC.heap_slots #=> 10000 -+ * -+ */ -+VALUE -+rb_gc_heap_slots() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return LONG2NUM(heap_size); -+} -+ -+ -+/* -+ * call-seq: -+ * GC.collections => Integer -+ * -+ * Returns the number of garbage collections performed while GC statistics collection -+ * was enabled. -+ * -+ * GC.collections #=> 35 -+ * -+ */ -+ -+VALUE -+rb_gc_collections() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return LONG2NUM(gc_collections); -+} -+ -+/* -+ * call-seq: -+ * GC.time => Integer -+ * -+ * Returns the time spent during garbage collection while GC statistics collection -+ * was enabled (in micro seconds). -+ * -+ * GC.time #=> 20000 -+ * -+ */ -+ -+VALUE -+rb_gc_time() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if HAVE_LONG_LONG -+ return LL2NUM(gc_time_accumulator); -+#else -+ return LONG2NUM(gc_time_accumulator); -+#endif -+} -+ - VALUE rb_mGC; - - void -@@ -1034,6 +1605,12 @@ allocate_sorted_heaps(rb_objspace_t *objspace, size_t next_heaps_length) - static void - assign_heap_slot(rb_objspace_t *objspace) - { -+ /* -+ if (gc_statistics & verbose_gc_stats) { -+ fprintf(gc_data_file, "assigning heap slot\n"); -+ } -+ */ -+ - RVALUE *p, *pend, *membase; - struct heaps_slot *slot; - size_t hi, lo, mid; -@@ -1095,6 +1672,7 @@ assign_heap_slot(rb_objspace_t *objspace) - if (lomem == 0 || lomem > p) lomem = p; - if (himem < pend) himem = pend; - heaps_used++; -+ heap_size += objs; - - while (p < pend) { - p->as.free.flags = 0; -@@ -1151,7 +1729,7 @@ initial_expand_heap(rb_objspace_t *objspace) - static void - set_heaps_increment(rb_objspace_t *objspace) - { -- size_t next_heaps_length = (size_t)(heaps_used * 1.8); -+ size_t next_heaps_length = (size_t)(heaps_used * heap_slots_growth_factor); - - if (next_heaps_length == heaps_used) { - next_heaps_length++; -@@ -1184,6 +1762,22 @@ rb_during_gc(void) - - #define RANY(o) ((RVALUE*)(o)) - -+#ifdef GC_DEBUG -+static VALUE -+_rb_sourcefile(void) -+{ -+ rb_thread_t *th = GET_THREAD(); -+ rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp); -+ -+ if (cfp) { -+ return cfp->iseq->filename; -+ } -+ else { -+ return Qnil; -+ } -+} -+#endif -+ - VALUE - rb_newobj(void) - { -@@ -1215,9 +1809,11 @@ rb_newobj(void) - - MEMZERO((void*)obj, RVALUE, 1); - #ifdef GC_DEBUG -- RANY(obj)->file = rb_sourcefile(); -+ RANY(obj)->file = _rb_sourcefile(); - RANY(obj)->line = rb_sourceline(); - #endif -+ live_objects++; -+ allocated_objects++; - GC_PROF_INC_LIVE_NUM; - - return obj; -@@ -1769,6 +2365,12 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr) - { - register RVALUE *obj = RANY(ptr); - -+#ifdef GC_DEBUG -+ if (obj->file && obj->file != Qnil && is_pointer_to_heap(objspace, (void*)obj->file)) { -+ gc_mark(objspace, obj->file, lev); -+ } -+#endif -+ - goto marking; /* skip */ - - again: -@@ -1779,6 +2381,12 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr) - obj->as.basic.flags |= FL_MARK; - objspace->heap.live_num++; - -+#ifdef GC_DEBUG -+ if (obj->file && obj->file != Qnil && is_pointer_to_heap(objspace, (void*)obj->file)) { -+ gc_mark(objspace, obj->file, lev); -+ } -+#endif -+ - marking: - if (FL_TEST(obj, FL_EXIVAR)) { - rb_mark_generic_ivar(ptr); -@@ -2121,6 +2729,25 @@ free_unused_heaps(rb_objspace_t *objspace) - } - } - -+static inline unsigned long -+elapsed_musecs(struct timeval since) -+{ -+ struct timeval now; -+ struct timeval temp; -+ -+ gettimeofday(&now, NULL); -+ -+ if ((now.tv_usec-since.tv_usec)<0) { -+ temp.tv_sec = now.tv_sec-since.tv_sec-1; -+ temp.tv_usec = 1000000+now.tv_usec-since.tv_usec; -+ } else { -+ temp.tv_sec = now.tv_sec-since.tv_sec; -+ temp.tv_usec = now.tv_usec-since.tv_usec; -+ } -+ -+ return temp.tv_sec*1000000 + temp.tv_usec; -+} -+ - static void - slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - { -@@ -2128,14 +2755,23 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - RVALUE *p, *pend; - RVALUE *free = freelist, *final = deferred_final_list; - int deferred; -+ int do_gc_stats = gc_statistics & verbose_gc_stats; -+ -+ struct timeval tv1; -+ if (gc_statistics) gettimeofday(&tv1, NULL); - - p = sweep_slot->slot; pend = p + sweep_slot->limit; - while (p < pend) { - if (!(p->as.basic.flags & FL_MARK)) { -+ if (do_gc_stats && !p->as.basic.flags) { -+ /* slot was free before GC */ -+ freelist_size++; -+ } - if (p->as.basic.flags && - ((deferred = obj_free(objspace, (VALUE)p)) || - (FL_TEST(p, FL_FINALIZE)))) { - if (!deferred) { -+ if (do_gc_stats) zombies++; - p->as.free.flags = T_ZOMBIE; - RDATA(p)->dfree = 0; - } -@@ -2145,6 +2781,10 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - final_num++; - } - else { -+ if (do_gc_stats) { -+ VALUE obt = p->as.basic.flags & T_MASK; -+ if (obt) free_counts[obt]++; -+ } - add_freelist(objspace, p); - free_num++; - } -@@ -2152,13 +2792,22 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - else if (BUILTIN_TYPE(p) == T_ZOMBIE) { - /* objects to be finalized */ - /* do nothing remain marked */ -+ if (do_gc_stats) zombies++; - } - else { - RBASIC(p)->flags &= ~FL_MARK; -+ if (do_gc_stats) { -+ live_counts[p->as.basic.flags & T_MASK]++; -+ } - } - p++; -+ processed++; - } -- if (final_num + free_num == sweep_slot->limit && -+ -+ freed_objects += free_num; -+ -+ if (objspace->heap.freed_blocks < objspace->heap.max_blocks_to_free && -+ final_num + free_num == sweep_slot->limit && - objspace->heap.free_num > objspace->heap.do_heap_free) { - RVALUE *pp; - -@@ -2169,6 +2818,8 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - sweep_slot->limit = final_num; - freelist = free; /* cancel this page from freelist */ - unlink_heap_slot(objspace, sweep_slot); -+ objspace->heap.freed_blocks += 1; -+ heap_size -= final_num + free_num; - } - else { - objspace->heap.free_num += free_num; -@@ -2181,6 +2832,10 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot) - RUBY_VM_SET_FINALIZER_INTERRUPT(th); - } - } -+ -+ if (gc_statistics) { -+ gc_time_accumulator += elapsed_musecs(tv1); -+ } - } - - static int -@@ -2201,6 +2856,21 @@ ready_to_gc(rb_objspace_t *objspace) - static void - before_gc_sweep(rb_objspace_t *objspace) - { -+ if (gc_statistics & verbose_gc_stats) { -+ /* -+ fprintf(gc_data_file, "Sweep started\n"); -+ */ -+ freed_objects = 0; -+ processed = 0; -+ zombies = 0; -+ freelist_size = 0; -+ MEMZERO((void*)free_counts, unsigned long, T_MASK+1); -+ MEMZERO((void*)live_counts, unsigned long, T_MASK+1); -+ } -+ -+ objspace->heap.max_blocks_to_free = heaps_used - (heap_min_slots / HEAP_OBJ_LIMIT); -+ objspace->heap.freed_blocks = 0; -+ - freelist = 0; - objspace->heap.do_heap_free = (size_t)((heaps_used * HEAP_OBJ_LIMIT) * 0.65); - objspace->heap.free_min = (size_t)((heaps_used * HEAP_OBJ_LIMIT) * 0.2); -@@ -2220,8 +2890,13 @@ before_gc_sweep(rb_objspace_t *objspace) - static void - after_gc_sweep(rb_objspace_t *objspace) - { -+ int i; -+ struct timeval tv1; -+ - GC_PROF_SET_MALLOC_INFO; - -+ if (gc_statistics) gettimeofday(&tv1, NULL); -+ - if (objspace->heap.free_num < objspace->heap.free_min) { - set_heaps_increment(objspace); - heaps_increment(objspace); -@@ -2234,6 +2909,29 @@ after_gc_sweep(rb_objspace_t *objspace) - malloc_increase = 0; - - free_unused_heaps(objspace); -+ -+ if (gc_statistics) { -+ gc_time_accumulator += elapsed_musecs(tv1); -+ -+ if (verbose_gc_stats) { -+ /* log gc stats if requested */ -+ fprintf(gc_data_file, "GC time: %lu musec\n", (unsigned long)(gc_time_accumulator-gc_time_accumulator_before_gc)); -+ fprintf(gc_data_file, "objects processed: %7lu\n", (unsigned long)processed); -+ fprintf(gc_data_file, "live objects : %7lu\n", (unsigned long)live_after_last_mark_phase); -+ fprintf(gc_data_file, "freelist objects : %7lu\n", (unsigned long)freelist_size); -+ fprintf(gc_data_file, "freed objects : %7lu\n", (unsigned long)freed_objects); -+ fprintf(gc_data_file, "zombies : %7lu\n", (unsigned long)zombies); -+ for(i=0; i0 || live_counts[i]>0) { -+ fprintf(gc_data_file, -+ "kept %7lu / freed %7lu objects of type %s\n", -+ (unsigned long)live_counts[i], (unsigned long)free_counts[i], obj_type((int)i)); -+ } -+ } -+ rb_gc_dump(); -+ fflush(gc_data_file); -+ } -+ } - } - - static int -@@ -2267,9 +2965,11 @@ rest_sweep(rb_objspace_t *objspace) - - static void gc_marks(rb_objspace_t *objspace); - -+/* only called from rb_new_obj */ - static int - gc_lazy_sweep(rb_objspace_t *objspace) - { -+ struct timeval gctv1; - int res; - INIT_GC_PROF_PARAMS; - -@@ -2291,7 +2991,6 @@ gc_lazy_sweep(rb_objspace_t *objspace) - GC_PROF_TIMER_STOP(Qfalse); - return res; - } -- after_gc_sweep(objspace); - } - else { - if (heaps_increment(objspace)) { -@@ -2299,6 +2998,18 @@ gc_lazy_sweep(rb_objspace_t *objspace) - return TRUE; - } - } -+ after_gc_sweep(objspace); -+ -+ if (gc_statistics) { -+ gc_time_accumulator_before_gc = gc_time_accumulator; -+ gc_collections++; -+ gettimeofday(&gctv1, NULL); -+ /* -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "Garbage collection started (gc_lazy_sweep)\n"); -+ } -+ */ -+ } - - gc_marks(objspace); - -@@ -2307,6 +3018,10 @@ gc_lazy_sweep(rb_objspace_t *objspace) - set_heaps_increment(objspace); - } - -+ if (gc_statistics) { -+ gc_time_accumulator += elapsed_musecs(gctv1); -+ } -+ - GC_PROF_SWEEP_TIMER_START; - if(!(res = lazy_sweep(objspace))) { - after_gc_sweep(objspace); -@@ -2318,6 +3033,7 @@ gc_lazy_sweep(rb_objspace_t *objspace) - GC_PROF_SWEEP_TIMER_STOP; - - GC_PROF_TIMER_STOP(Qtrue); -+ - return res; - } - -@@ -2544,9 +3260,15 @@ gc_marks(rb_objspace_t *objspace) - rb_thread_t *th = GET_THREAD(); - GC_PROF_MARK_TIMER_START; - -+ /* -+ if (gc_statistics & verbose_gc_stats) { -+ fprintf(gc_data_file, "Marking objects\n"); -+ } -+ */ -+ - objspace->heap.live_num = 0; - objspace->count++; -- -+ live_objects = 0; - - SET_STACK_END; - -@@ -2578,11 +3300,15 @@ gc_marks(rb_objspace_t *objspace) - gc_mark_stacked_objects(objspace); - - GC_PROF_MARK_TIMER_STOP; -+ -+ live_after_last_mark_phase = objspace->heap.live_num; - } - - static int - garbage_collect(rb_objspace_t *objspace) - { -+ struct timeval gctv1; -+ - INIT_GC_PROF_PARAMS; - - if (GC_NOTIFY) printf("start garbage_collect()\n"); -@@ -2598,15 +3324,31 @@ garbage_collect(rb_objspace_t *objspace) - - rest_sweep(objspace); - -+ if (gc_statistics) { -+ gc_time_accumulator_before_gc = gc_time_accumulator; -+ gc_collections++; -+ gettimeofday(&gctv1, NULL); -+ /* -+ if (verbose_gc_stats) { -+ fprintf(gc_data_file, "Garbage collection started (garbage_collect)\n"); -+ } -+ */ -+ } -+ - during_gc++; - gc_marks(objspace); - -+ if (gc_statistics) { -+ gc_time_accumulator += elapsed_musecs(gctv1); -+ } -+ - GC_PROF_SWEEP_TIMER_START; - gc_sweep(objspace); - GC_PROF_SWEEP_TIMER_STOP; - - GC_PROF_TIMER_STOP(Qtrue); - if (GC_NOTIFY) printf("end garbage_collect()\n"); -+ - return TRUE; - } - -@@ -3080,6 +3822,39 @@ rb_gc_call_finalizer_at_exit(void) - rb_objspace_call_finalizer(&rb_objspace); - } - -+static const char* obj_type(VALUE type) -+{ -+ switch (type) { -+ case T_NIL : return "NIL"; -+ case T_OBJECT : return "OBJECT"; -+ case T_CLASS : return "CLASS"; -+ case T_ICLASS : return "ICLASS"; -+ case T_MODULE : return "MODULE"; -+ case T_FLOAT : return "FLOAT"; -+ case T_COMPLEX: return "COMPLEX"; -+ case T_RATIONAL: return "RATIONAL"; -+ case T_STRING : return "STRING"; -+ case T_REGEXP : return "REGEXP"; -+ case T_ARRAY : return "ARRAY"; -+ case T_FIXNUM : return "FIXNUM"; -+ case T_HASH : return "HASH"; -+ case T_STRUCT : return "STRUCT"; -+ case T_BIGNUM : return "BIGNUM"; -+ case T_FILE : return "FILE"; -+ -+ case T_TRUE : return "TRUE"; -+ case T_FALSE : return "FALSE"; -+ case T_DATA : return "DATA"; -+ case T_MATCH : return "MATCH"; -+ case T_SYMBOL : return "SYMBOL"; -+ case T_ZOMBIE : return "ZOMBIE"; -+ -+ case T_UNDEF : return "UNDEF"; -+ case T_NODE : return "NODE"; -+ default: return "____"; -+ } -+} -+ - static void - rb_objspace_call_finalizer(rb_objspace_t *objspace) - { -@@ -3388,6 +4163,49 @@ count_objects(int argc, VALUE *argv, VALUE os) - return hash; - } - -+/* call-seq: -+ * ObjectSpace.live_objects => number -+ * -+ * Returns the count of objects currently allocated in the system. This goes -+ * down after the garbage collector runs. -+ */ -+static -+VALUE os_live_objects(VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return ULONG2NUM(live_objects); -+} -+ -+unsigned long rb_os_live_objects() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return live_objects; -+} -+ -+/* call-seq: -+ * ObjectSpace.allocated_objects => number -+ * -+ * Returns the count of objects allocated since the Ruby interpreter has -+ * started. This number can only increase. To know how many objects are -+ * currently allocated, use ObjectSpace::live_objects -+ */ -+static -+VALUE os_allocated_objects(VALUE self) -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+#if defined(HAVE_LONG_LONG) -+ return ULL2NUM(allocated_objects); -+#else -+ return ULONG2NUM(allocated_objects); -+#endif -+} -+ -+unsigned LONG_LONG rb_os_allocated_objects() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return allocated_objects; -+} -+ - /* - * call-seq: - * GC.count -> Integer -@@ -3680,6 +4498,28 @@ Init_GC(void) - rb_define_singleton_method(rb_mGC, "stat", gc_stat, -1); - rb_define_method(rb_mGC, "garbage_collect", rb_gc_start, 0); - -+ rb_define_singleton_method(rb_mGC, "enable_stats", rb_gc_enable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "disable_stats", rb_gc_disable_stats, 0); -+ rb_define_singleton_method(rb_mGC, "stats_enabled?", rb_gc_stats_enabled, 0); -+ rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0); -+ rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); -+ rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); -+ -+ rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); -+ rb_define_singleton_method(rb_mGC, "log_file", rb_gc_log_file, -1); -+ rb_define_singleton_method(rb_mGC, "enable_trace", rb_gc_enable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "disable_trace", rb_gc_disable_trace, 0); -+ rb_define_singleton_method(rb_mGC, "trace_enabled?", rb_gc_trace_enabled, 0); -+ -+ rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0); -+ rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0); -+ rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0); -+#ifdef GC_DEBUG -+ rb_define_singleton_method(rb_mGC, "dump_file_and_line_info", rb_gc_dump_file_and_line_info, -1); -+#endif -+ - 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); -@@ -3693,6 +4533,9 @@ Init_GC(void) - rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1); - rb_define_module_function(rb_mObSpace, "garbage_collect", rb_gc_start, 0); - -+ rb_define_module_function(rb_mObSpace, "live_objects", os_live_objects, 0); -+ rb_define_module_function(rb_mObSpace, "allocated_objects", os_allocated_objects, 0); -+ - rb_define_module_function(rb_mObSpace, "define_finalizer", define_final, -1); - rb_define_module_function(rb_mObSpace, "undefine_finalizer", undefine_final, 1); - diff --git a/patches/ruby/1.9.3/p392/railsexpress/03-display-more-detailed-stack-trace.patch b/patches/ruby/1.9.3/p392/railsexpress/03-display-more-detailed-stack-trace.patch deleted file mode 100644 index 5c7ad30352..0000000000 --- a/patches/ruby/1.9.3/p392/railsexpress/03-display-more-detailed-stack-trace.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/eval_error.c b/eval_error.c -index fd06adf..69c3b48 100644 ---- a/eval_error.c -+++ b/eval_error.c -@@ -164,8 +164,8 @@ error_print(void) - int skip = eclass == rb_eSysStackError; - - #define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5) --#define TRACE_HEAD 8 --#define TRACE_TAIL 5 -+#define TRACE_HEAD 100 -+#define TRACE_TAIL 100 - - for (i = 1; i < len; i++) { - if (TYPE(ptr[i]) == T_STRING) { diff --git a/patches/ruby/1.9.3/p392/railsexpress/04-fork-support-for-gc-logging.patch b/patches/ruby/1.9.3/p392/railsexpress/04-fork-support-for-gc-logging.patch deleted file mode 100644 index 92bbf6f179..0000000000 --- a/patches/ruby/1.9.3/p392/railsexpress/04-fork-support-for-gc-logging.patch +++ /dev/null @@ -1,68 +0,0 @@ -diff --git a/gc.c b/gc.c -index feb54f1..7f65b98 100644 ---- a/gc.c -+++ b/gc.c -@@ -1345,6 +1345,34 @@ rb_gc_log_file(int argc, VALUE *argv, VALUE self) - } - - /* -+ * Called from process.c before a fork. Flushes the gc log file to -+ * avoid writing the buffered output twice (once in the parent, and -+ * once in the child). -+ */ -+void -+rb_gc_before_fork() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ fflush(gc_data_file); -+} -+ -+/* -+ * Called from process.c after a fork in the child process. Turns off -+ * logging, disables GC stats and resets all gc counters and timing -+ * information. -+ */ -+void -+rb_gc_after_fork() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ rb_gc_disable_stats(); -+ rb_gc_clear_stats(); -+ rb_gc_disable_trace(); -+ gc_data_file = stderr; -+ rb_iv_set(rb_mGC, GC_LOGFILE_IVAR, Qnil); -+} -+ -+/* - * call-seq: - * GC.log String => String - * -diff --git a/include/ruby/intern.h b/include/ruby/intern.h -index 9745afd..7c3d970 100644 ---- a/include/ruby/intern.h -+++ b/include/ruby/intern.h -@@ -426,6 +426,8 @@ void rb_gc_call_finalizer_at_exit(void); - VALUE rb_gc_enable(void); - VALUE rb_gc_disable(void); - VALUE rb_gc_start(void); -+void rb_gc_before_fork _((void)); -+void rb_gc_after_fork _((void)); - #define Init_stack(addr) ruby_init_stack(addr) - void rb_gc_set_params(void); - /* hash.c */ -diff --git a/process.c b/process.c -index 99cfc69..8bee602 100644 ---- a/process.c -+++ b/process.c -@@ -2804,9 +2804,11 @@ rb_f_fork(VALUE obj) - rb_pid_t pid; - - rb_secure(2); -+ rb_gc_before_fork(); - - switch (pid = rb_fork(0, 0, 0, Qnil)) { - case 0: -+ rb_gc_after_fork(); - rb_thread_atfork(); - if (rb_block_given_p()) { - int status; diff --git a/patches/ruby/1.9.3/p392/railsexpress/05-track-live-dataset-size.patch b/patches/ruby/1.9.3/p392/railsexpress/05-track-live-dataset-size.patch deleted file mode 100644 index 3cfc64abac..0000000000 --- a/patches/ruby/1.9.3/p392/railsexpress/05-track-live-dataset-size.patch +++ /dev/null @@ -1,45 +0,0 @@ -diff --git a/gc.c b/gc.c -index 7f65b98..8498fe4 100644 ---- a/gc.c -+++ b/gc.c -@@ -281,7 +281,6 @@ getrusage_time(void) - #define GC_PROF_DEC_LIVE_NUM - #endif - -- - #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__) - #pragma pack(push, 1) /* magic for reducing sizeof(RVALUE): 24 -> 20 */ - #endif -@@ -1562,6 +1561,24 @@ rb_gc_time() - #endif - } - -+/* -+ * call-seq: -+ * GC.heap_slots_live_after_last_gc => Integer -+ * -+ * Returns the number of heap slots which were live after the last garbage collection. -+ * -+ * GC.heap_slots_live_after_last_gc #=> 231223 -+ * -+ */ -+VALUE -+rb_gc_heap_slots_live_after_last_gc() -+{ -+ rb_objspace_t *objspace = &rb_objspace; -+ return ULONG2NUM(live_after_last_mark_phase); -+} -+ -+ -+ - VALUE rb_mGC; - - void -@@ -4533,6 +4550,7 @@ Init_GC(void) - rb_define_singleton_method(rb_mGC, "allocated_size", rb_gc_allocated_size, 0); - rb_define_singleton_method(rb_mGC, "num_allocations", rb_gc_num_allocations, 0); - rb_define_singleton_method(rb_mGC, "heap_slots", rb_gc_heap_slots, 0); -+ rb_define_singleton_method(rb_mGC, "heap_slots_live_after_last_gc", rb_gc_heap_slots_live_after_last_gc, 0); - rb_define_const(rb_mGC, "HEAP_SLOT_SIZE", INT2FIX(sizeof(RVALUE))); - - rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1); diff --git a/patches/ruby/1.9.3/p392/railsexpress/06-webrick_204_304_keep_alive_fix.patch b/patches/ruby/1.9.3/p392/railsexpress/06-webrick_204_304_keep_alive_fix.patch deleted file mode 100644 index 34d9b78133..0000000000 --- a/patches/ruby/1.9.3/p392/railsexpress/06-webrick_204_304_keep_alive_fix.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/lib/webrick/httpresponse.rb b/lib/webrick/httpresponse.rb -index 0d36c07..ce72b3f 100644 ---- a/lib/webrick/httpresponse.rb -+++ b/lib/webrick/httpresponse.rb -@@ -202,7 +202,7 @@ module WEBrick - if @header['connection'] == "close" - @keep_alive = false - elsif keep_alive? -- if chunked? || @header['content-length'] -+ if chunked? || @header['content-length'] || @status == 304 || @status == 204 - @header['connection'] = "Keep-Alive" - else - msg = "Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true" diff --git a/patches/ruby/1.9.3/p392/railsexpress/07-export-a-few-more-symbols-for-ruby-prof.patch b/patches/ruby/1.9.3/p392/railsexpress/07-export-a-few-more-symbols-for-ruby-prof.patch deleted file mode 100644 index 4473c341e6..0000000000 --- a/patches/ruby/1.9.3/p392/railsexpress/07-export-a-few-more-symbols-for-ruby-prof.patch +++ /dev/null @@ -1,140 +0,0 @@ -diff --git a/gc.c b/gc.c -index 8498fe4..b5fc83c 100644 ---- a/gc.c -+++ b/gc.c -@@ -1052,6 +1052,7 @@ ruby_xfree(void *x) - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_enable(void) - { -@@ -1074,6 +1075,7 @@ rb_gc_enable(void) - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_disable(void) - { -@@ -1096,6 +1098,7 @@ rb_gc_disable(void) - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_enable_stats() - { -@@ -1117,6 +1120,7 @@ rb_gc_enable_stats() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_disable_stats() - { -@@ -1136,6 +1140,7 @@ rb_gc_disable_stats() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_stats_enabled() - { -@@ -1155,6 +1160,7 @@ rb_gc_stats_enabled() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_clear_stats() - { -@@ -1178,6 +1184,7 @@ rb_gc_clear_stats() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_allocated_size() - { -@@ -1222,6 +1229,7 @@ rb_gc_num_allocations() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_enable_trace() - { -@@ -1243,6 +1251,7 @@ rb_gc_enable_trace() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_disable_trace() - { -@@ -1262,6 +1271,7 @@ rb_gc_disable_trace() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_trace_enabled() - { -@@ -1290,6 +1300,7 @@ const char* GC_LOGFILE_IVAR = "@gc_logfile_name"; - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_log_file(int argc, VALUE *argv, VALUE self) - { -@@ -1381,6 +1392,7 @@ rb_gc_after_fork() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_log(self, original_str) - VALUE self, original_str; -@@ -1407,6 +1419,7 @@ rb_gc_log(self, original_str) - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_dump() - { -@@ -1437,6 +1450,7 @@ static const char* obj_type(VALUE tp); - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_dump_file_and_line_info(int argc, VALUE *argv) - { -@@ -1532,6 +1546,7 @@ rb_gc_heap_slots() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_collections() - { -@@ -1550,6 +1565,7 @@ rb_gc_collections() - * - */ - -+RUBY_FUNC_EXPORTED - VALUE - rb_gc_time() - { -@@ -4245,6 +4261,7 @@ VALUE os_allocated_objects(VALUE self) - #endif - } - -+RUBY_FUNC_EXPORTED - unsigned LONG_LONG rb_os_allocated_objects() - { - rb_objspace_t *objspace = &rb_objspace; diff --git a/patches/ruby/1.9.3/p392/railsexpress/08-thread-variables.patch b/patches/ruby/1.9.3/p392/railsexpress/08-thread-variables.patch deleted file mode 100644 index 2ed965e8d8..0000000000 --- a/patches/ruby/1.9.3/p392/railsexpress/08-thread-variables.patch +++ /dev/null @@ -1,319 +0,0 @@ -diff --git a/NEWS b/NEWS -index 30fec33..9f6c172 100644 ---- a/NEWS -+++ b/NEWS -@@ -103,6 +103,16 @@ with all sufficient information, see the ChangeLog file. - * String#prepend - * String#byteslice - -+ * Thread -+ * added method: -+ * added Thread#thread_variable_get for getting thread local variables -+ (these are different than Fiber local variables). -+ * added Thread#thread_variable_set for setting thread local variables. -+ * added Thread#thread_variables for getting a list of the thread local -+ variable keys. -+ * added Thread#thread_variable? for testing to see if a particular thread -+ variable has been set. -+ - * Time - * extended method: - * Time#strftime supports %:z and %::z. -diff --git a/test/ruby/test_thread.rb b/test/ruby/test_thread.rb -index e8cb3b1..9ff491d 100644 ---- a/test/ruby/test_thread.rb -+++ b/test/ruby/test_thread.rb -@@ -27,6 +27,79 @@ class TestThread < Test::Unit::TestCase - end - end - -+ def test_main_thread_variable_in_enumerator -+ assert_equal Thread.main, Thread.current -+ -+ Thread.current.thread_variable_set :foo, "bar" -+ -+ thread, value = Fiber.new { -+ Fiber.yield [Thread.current, Thread.current.thread_variable_get(:foo)] -+ }.resume -+ -+ assert_equal Thread.current, thread -+ assert_equal Thread.current.thread_variable_get(:foo), value -+ end -+ -+ def test_thread_variable_in_enumerator -+ Thread.new { -+ Thread.current.thread_variable_set :foo, "bar" -+ -+ thread, value = Fiber.new { -+ Fiber.yield [Thread.current, Thread.current.thread_variable_get(:foo)] -+ }.resume -+ -+ assert_equal Thread.current, thread -+ assert_equal Thread.current.thread_variable_get(:foo), value -+ }.join -+ end -+ -+ def test_thread_variables -+ assert_equal [], Thread.new { Thread.current.thread_variables }.join.value -+ -+ t = Thread.new { -+ Thread.current.thread_variable_set(:foo, "bar") -+ Thread.current.thread_variables -+ } -+ assert_equal [:foo], t.join.value -+ end -+ -+ def test_thread_variable? -+ refute Thread.new { Thread.current.thread_variable?("foo") }.join.value -+ t = Thread.new { -+ Thread.current.thread_variable_set("foo", "bar") -+ }.join -+ -+ assert t.thread_variable?("foo") -+ assert t.thread_variable?(:foo) -+ refute t.thread_variable?(:bar) -+ end -+ -+ def test_thread_variable_strings_and_symbols_are_the_same_key -+ t = Thread.new {}.join -+ t.thread_variable_set("foo", "bar") -+ assert_equal "bar", t.thread_variable_get(:foo) -+ end -+ -+ def test_thread_variable_frozen -+ t = Thread.new { }.join -+ t.freeze -+ assert_raises(RuntimeError) do -+ t.thread_variable_set(:foo, "bar") -+ end -+ end -+ -+ def test_thread_variable_security -+ t = Thread.new { sleep } -+ -+ assert_raises(SecurityError) do -+ Thread.new { $SAFE = 4; t.thread_variable_get(:foo) }.join -+ end -+ -+ assert_raises(SecurityError) do -+ Thread.new { $SAFE = 4; t.thread_variable_set(:foo, :baz) }.join -+ end -+ end -+ - def test_mutex_synchronize - m = Mutex.new - r = 0 -diff --git a/thread.c b/thread.c -index c7da34b..ce1fa3f 100644 ---- a/thread.c -+++ b/thread.c -@@ -2112,7 +2112,9 @@ rb_thread_local_aset(VALUE thread, ID id, VALUE val) - * thr[sym] = obj -> obj - * - * Attribute Assignment---Sets or creates the value of a thread-local variable, -- * using either a symbol or a string. See also Thread#[]. -+ * using either a symbol or a string. See also Thread#[]. For -+ * thread-local variables, please see Thread#thread_variable_set -+ * and Thread#thread_variable_get. - */ - - static VALUE -@@ -2123,6 +2125,80 @@ rb_thread_aset(VALUE self, VALUE id, VALUE val) - - /* - * call-seq: -+ * thr.thread_variable_get(key) -> obj or nil -+ * -+ * Returns the value of a thread local variable that has been set. Note that -+ * these are different than fiber local values. For fiber local values, -+ * please see Thread#[] and Thread#[]=. -+ * -+ * Thread local values are carried along with threads, and do not respect -+ * fibers. For example: -+ * -+ * Thread.new { -+ * Thread.current.thread_variable_set("foo", "bar") # set a thread local -+ * Thread.current["foo"] = "bar" # set a fiber local -+ * -+ * Fiber.new { -+ * Fiber.yield [ -+ * Thread.current.thread_variable_get("foo"), # get the thread local -+ * Thread.current["foo"], # get the fiber local -+ * ] -+ * }.resume -+ * }.join.value # => ['bar', nil] -+ * -+ * The value "bar" is returned for the thread local, where nil is returned -+ * for the fiber local. The fiber is executed in the same thread, so the -+ * thread local values are available. -+ * -+ * See also Thread#[] -+ */ -+ -+static VALUE -+rb_thread_variable_get(VALUE thread, VALUE id) -+{ -+ VALUE locals; -+ rb_thread_t *th; -+ -+ GetThreadPtr(thread, th); -+ -+ if (rb_safe_level() >= 4 && th != GET_THREAD()) { -+ rb_raise(rb_eSecurityError, "Insecure: can't access thread locals"); -+ } -+ -+ locals = rb_iv_get(thread, "locals"); -+ return rb_hash_aref(locals, ID2SYM(rb_to_id(id))); -+} -+ -+/* -+ * call-seq: -+ * thr.thread_variable_set(key, value) -+ * -+ * Sets a thread local with +key+ to +value+. Note that these are local to -+ * threads, and not to fibers. Please see Thread#thread_variable_get and -+ * Thread#[] for more information. -+ */ -+ -+static VALUE -+rb_thread_variable_set(VALUE thread, VALUE id, VALUE val) -+{ -+ VALUE locals; -+ rb_thread_t *th; -+ -+ GetThreadPtr(thread, th); -+ -+ if (rb_safe_level() >= 4 && th != GET_THREAD()) { -+ rb_raise(rb_eSecurityError, "Insecure: can't modify thread locals"); -+ } -+ if (OBJ_FROZEN(thread)) { -+ rb_error_frozen("thread locals"); -+ } -+ -+ locals = rb_iv_get(thread, "locals"); -+ return rb_hash_aset(locals, ID2SYM(rb_to_id(id)), val); -+} -+ -+/* -+ * call-seq: - * thr.key?(sym) -> true or false - * - * Returns true if the given string (or symbol) exists as a -@@ -2993,6 +3069,9 @@ rb_gc_save_machine_context(rb_thread_t *th) - - /* - * -+ * For thread-local variables, please see Thread#thread_local_get -+ * and Thread#thread_local_set. -+ * - */ - - void -@@ -3195,6 +3274,76 @@ thgroup_list_i(st_data_t key, st_data_t val, st_data_t data) - return ST_CONTINUE; - } - -+static int -+keys_i(VALUE key, VALUE value, VALUE ary) -+{ -+ rb_ary_push(ary, key); -+ return ST_CONTINUE; -+} -+ -+/* -+ * call-seq: -+ * thr.thread_variables -> array -+ * -+ * Returns an an array of the names of the thread-local variables (as Symbols). -+ * -+ * thr = Thread.new do -+ * Thread.current.thread_variable_set(:cat, 'meow') -+ * Thread.current.thread_variable_set("dog", 'woof') -+ * end -+ * thr.join #=> # -+ * thr.thread_variables #=> [:dog, :cat] -+ * -+ * Note that these are not fiber local variables. Please see Thread#[] and -+ * Thread#thread_variable_get for more details. -+ */ -+ -+static VALUE -+rb_thread_variables(VALUE thread) -+{ -+ VALUE locals; -+ VALUE ary; -+ -+ locals = rb_iv_get(thread, "locals"); -+ ary = rb_ary_new(); -+ rb_hash_foreach(locals, keys_i, ary); -+ -+ return ary; -+} -+ -+/* -+ * call-seq: -+ * thr.thread_variable?(key) -> true or false -+ * -+ * Returns true if the given string (or symbol) exists as a -+ * thread-local variable. -+ * -+ * me = Thread.current -+ * me.thread_variable_set(:oliver, "a") -+ * me.thread_variable?(:oliver) #=> true -+ * me.thread_variable?(:stanley) #=> false -+ * -+ * Note that these are not fiber local variables. Please see Thread#[] and -+ * Thread#thread_variable_get for more details. -+ */ -+ -+static VALUE -+rb_thread_variable_p(VALUE thread, VALUE key) -+{ -+ VALUE locals; -+ -+ locals = rb_iv_get(thread, "locals"); -+ -+ if (!RHASH(locals)->ntbl) -+ return Qfalse; -+ -+ if (st_lookup(RHASH(locals)->ntbl, ID2SYM(rb_to_id(key)), 0)) { -+ return Qtrue; -+ } -+ -+ return Qfalse; -+} -+ - /* - * call-seq: - * thgrp.list -> array -@@ -4680,6 +4829,10 @@ Init_Thread(void) - rb_define_method(rb_cThread, "priority", rb_thread_priority, 0); - rb_define_method(rb_cThread, "priority=", rb_thread_priority_set, 1); - rb_define_method(rb_cThread, "status", rb_thread_status, 0); -+ rb_define_method(rb_cThread, "thread_variable_get", rb_thread_variable_get, 1); -+ rb_define_method(rb_cThread, "thread_variable_set", rb_thread_variable_set, 2); -+ rb_define_method(rb_cThread, "thread_variables", rb_thread_variables, 0); -+ rb_define_method(rb_cThread, "thread_variable?", rb_thread_variable_p, 1); - rb_define_method(rb_cThread, "alive?", rb_thread_alive_p, 0); - rb_define_method(rb_cThread, "stop?", rb_thread_stop_p, 0); - rb_define_method(rb_cThread, "abort_on_exception", rb_thread_abort_exc, 0); -diff --git a/vm.c b/vm.c -index 6b2bd90..b5fc485 100644 ---- a/vm.c -+++ b/vm.c -@@ -1910,6 +1910,7 @@ ruby_thread_init(VALUE self) - GetThreadPtr(self, th); - - th_init(th, self); -+ rb_iv_set(self, "locals", rb_hash_new()); - th->vm = vm; - - th->top_wrapper = 0; -@@ -2178,6 +2179,7 @@ Init_VM(void) - - /* create main thread */ - th_self = th->self = TypedData_Wrap_Struct(rb_cThread, &thread_data_type, th); -+ rb_iv_set(th_self, "locals", rb_hash_new()); - vm->main_thread = th; - vm->running_thread = th; - th->vm = vm; diff --git a/patches/ruby/1.9.3/p392/railsexpress/09-faster-loading.patch b/patches/ruby/1.9.3/p392/railsexpress/09-faster-loading.patch deleted file mode 100644 index bc2807f7cd..0000000000 --- a/patches/ruby/1.9.3/p392/railsexpress/09-faster-loading.patch +++ /dev/null @@ -1,747 +0,0 @@ -diff --git a/array.c b/array.c -index e427cb3..c33d106 100644 ---- a/array.c -+++ b/array.c -@@ -295,6 +295,22 @@ rb_ary_frozen_p(VALUE ary) - return Qfalse; - } - -+/* This can be used to take a snapshot of an array (with -+ e.g. rb_ary_replace) and check later whether the array has been -+ modified from the snapshot. The snapshot is cheap, though if -+ something does modify the array it will pay the cost of copying -+ it. */ -+VALUE -+rb_ary_shared_with_p(VALUE ary1, VALUE ary2) -+{ -+ if (!ARY_EMBED_P(ary1) && ARY_SHARED_P(ary1) -+ && !ARY_EMBED_P(ary2) && ARY_SHARED_P(ary2) -+ && RARRAY(ary1)->as.heap.aux.shared == RARRAY(ary2)->as.heap.aux.shared) { -+ return Qtrue; -+ } -+ return Qfalse; -+} -+ - static VALUE - ary_alloc(VALUE klass) - { -diff --git a/file.c b/file.c -index fd64116..1abf821 100644 ---- a/file.c -+++ b/file.c -@@ -149,23 +149,32 @@ file_path_convert(VALUE name) - return name; - } - --static VALUE --rb_get_path_check(VALUE obj, int level) -+VALUE -+rb_get_path_check_to_string(VALUE obj, int level) - { - VALUE tmp; - ID to_path; -- rb_encoding *enc; - - if (insecure_obj_p(obj, level)) { - rb_insecure_operation(); - } - -+ if (RB_TYPE_P(obj, T_STRING)) { -+ return obj; -+ } - CONST_ID(to_path, "to_path"); - tmp = rb_check_funcall(obj, to_path, 0, 0); - if (tmp == Qundef) { - tmp = obj; - } - StringValue(tmp); -+ return tmp; -+} -+ -+VALUE -+rb_get_path_check_convert(VALUE obj, VALUE tmp, int level) -+{ -+ rb_encoding *enc; - - tmp = file_path_convert(tmp); - if (obj != tmp && insecure_obj_p(tmp, level)) { -@@ -183,6 +192,13 @@ rb_get_path_check(VALUE obj, int level) - return rb_str_new4(tmp); - } - -+static VALUE -+rb_get_path_check(VALUE obj, int level) -+{ -+ VALUE tmp = rb_get_path_check_to_string(obj, level); -+ return rb_get_path_check_convert(obj, tmp, level); -+} -+ - VALUE - rb_get_path_no_checksafe(VALUE obj) - { -@@ -3250,7 +3266,6 @@ rb_file_expand_path(VALUE fname, VALUE dname) - VALUE - rb_file_expand_path_fast(VALUE fname, VALUE dname) - { -- check_expand_path_args(fname, dname); - return rb_file_expand_path_internal(fname, dname, 0, 0, EXPAND_PATH_BUFFER()); - } - -@@ -5241,7 +5256,7 @@ rb_find_file_ext_safe(VALUE *filep, const char *const *ext, int safe_level) - rb_raise(rb_eSecurityError, "loading from non-absolute path %s", f); - } - -- RB_GC_GUARD(load_path) = rb_get_load_path(); -+ RB_GC_GUARD(load_path) = rb_get_expanded_load_path(); - if (!load_path) return 0; - - fname = rb_str_dup(*filep); -@@ -5306,7 +5321,7 @@ rb_find_file_safe(VALUE path, int safe_level) - rb_raise(rb_eSecurityError, "loading from non-absolute path %s", f); - } - -- RB_GC_GUARD(load_path) = rb_get_load_path(); -+ RB_GC_GUARD(load_path) = rb_get_expanded_load_path(); - if (load_path) { - long i; - -diff --git a/hash.c b/hash.c -index fbd8237..8423558 100644 ---- a/hash.c -+++ b/hash.c -@@ -1087,7 +1087,7 @@ clear_i(VALUE key, VALUE value, VALUE dummy) - * - */ - --static VALUE -+VALUE - rb_hash_clear(VALUE hash) - { - rb_hash_modify_check(hash); -diff --git a/include/ruby/intern.h b/include/ruby/intern.h -index 7c3d970..ab1cc94 100644 ---- a/include/ruby/intern.h -+++ b/include/ruby/intern.h -@@ -56,6 +56,7 @@ VALUE rb_ary_tmp_new(long); - void rb_ary_free(VALUE); - void rb_ary_modify(VALUE); - VALUE rb_ary_freeze(VALUE); -+VALUE rb_ary_shared_with_p(VALUE, VALUE); - VALUE rb_ary_aref(int, VALUE*, VALUE); - VALUE rb_ary_subseq(VALUE, long, long); - void rb_ary_store(VALUE, long, VALUE); -@@ -443,6 +444,7 @@ VALUE rb_hash_lookup(VALUE, VALUE); - VALUE rb_hash_lookup2(VALUE, VALUE, VALUE); - VALUE rb_hash_fetch(VALUE, VALUE); - VALUE rb_hash_aset(VALUE, VALUE, VALUE); -+VALUE rb_hash_clear(VALUE); - VALUE rb_hash_delete_if(VALUE); - VALUE rb_hash_delete(VALUE,VALUE); - typedef VALUE rb_hash_update_func(VALUE newkey, VALUE oldkey, VALUE value); -diff --git a/internal.h b/internal.h -index 59c9284..f5af903 100644 ---- a/internal.h -+++ b/internal.h -@@ -94,6 +94,8 @@ VALUE rb_home_dir(const char *user, VALUE result); - VALUE rb_realpath_internal(VALUE basedir, VALUE path, int strict); - VALUE rb_file_expand_path_fast(VALUE, VALUE); - VALUE rb_file_expand_path_internal(VALUE, VALUE, int, int, VALUE); -+VALUE rb_get_path_check_to_string(VALUE, int); -+VALUE rb_get_path_check_convert(VALUE, VALUE, int); - void Init_File(void); - - #ifdef _WIN32 -@@ -119,6 +121,7 @@ VALUE rb_iseq_clone(VALUE iseqval, VALUE newcbase); - - /* load.c */ - VALUE rb_get_load_path(void); -+VALUE rb_get_expanded_load_path(void); - - /* math.c */ - VALUE rb_math_atan2(VALUE, VALUE); -diff --git a/load.c b/load.c -index 163ec4c..e766880 100644 ---- a/load.c -+++ b/load.c -@@ -18,7 +18,6 @@ VALUE ruby_dln_librefs; - #define IS_DLEXT(e) (strcmp((e), DLEXT) == 0) - #endif - -- - static const char *const loadable_ext[] = { - ".rb", DLEXT, - #ifdef DLEXT2 -@@ -34,21 +33,120 @@ rb_get_load_path(void) - return load_path; - } - --VALUE --rb_get_expanded_load_path(void) -+enum expand_type { -+ EXPAND_ALL, -+ EXPAND_RELATIVE, -+ EXPAND_HOME, -+ EXPAND_NON_CACHE -+}; -+ -+/* Construct expanded load path and store it to cache. -+ We rebuild load path partially if the cache is invalid. -+ We don't cache non string object and expand it every times. We ensure that -+ string objects in $LOAD_PATH are frozen. -+ */ -+static void -+rb_construct_expanded_load_path(int type, int *has_relative, int *has_non_cache) - { -- VALUE load_path = rb_get_load_path(); -+ rb_vm_t *vm = GET_VM(); -+ VALUE load_path = vm->load_path; -+ VALUE expanded_load_path = vm->expanded_load_path; - VALUE ary; - long i; -+ int level = rb_safe_level(); - - ary = rb_ary_new2(RARRAY_LEN(load_path)); - for (i = 0; i < RARRAY_LEN(load_path); ++i) { -- VALUE path = rb_file_expand_path_fast(RARRAY_PTR(load_path)[i], Qnil); -- rb_str_freeze(path); -- rb_ary_push(ary, path); -+ VALUE path, as_str, expanded_path; -+ int is_string, non_cache; -+ char *as_cstr; -+ as_str = path = RARRAY_PTR(load_path)[i]; -+ is_string = RB_TYPE_P(path, T_STRING) ? 1 : 0; -+ non_cache = !is_string ? 1 : 0; -+ as_str = rb_get_path_check_to_string(path, level); -+ as_cstr = RSTRING_PTR(as_str); -+ -+ if (!non_cache) { -+ if ((type == EXPAND_RELATIVE && -+ rb_is_absolute_path(as_cstr)) || -+ (type == EXPAND_HOME && -+ (!as_cstr[0] || as_cstr[0] != '~')) || -+ (type == EXPAND_NON_CACHE)) { -+ /* Use cached expanded path. */ -+ rb_ary_push(ary, RARRAY_PTR(expanded_load_path)[i]); -+ continue; -+ } -+ } -+ if (!*has_relative && !rb_is_absolute_path(as_cstr)) -+ *has_relative = 1; -+ if (!*has_non_cache && non_cache) -+ *has_non_cache = 1; -+ /* Freeze only string object. We expand other objects every times. */ -+ if (is_string) -+ rb_str_freeze(path); -+ as_str = rb_get_path_check_convert(path, as_str, level); -+ expanded_path = rb_file_expand_path_fast(as_str, Qnil); -+ rb_str_freeze(expanded_path); -+ rb_ary_push(ary, expanded_path); - } - rb_obj_freeze(ary); -- return ary; -+ vm->expanded_load_path = ary; -+ rb_ary_replace(vm->load_path_snapshot, vm->load_path); -+} -+ -+static VALUE -+load_path_getcwd(void) -+{ -+ char *cwd = my_getcwd(); -+ VALUE cwd_str = rb_filesystem_str_new_cstr(cwd); -+ xfree(cwd); -+ return cwd_str; -+} -+ -+VALUE -+rb_get_expanded_load_path(void) -+{ -+ rb_vm_t *vm = GET_VM(); -+ const VALUE non_cache = Qtrue; -+ -+ if (!rb_ary_shared_with_p(vm->load_path_snapshot, vm->load_path)) { -+ /* The load path was modified. Rebuild the expanded load path. */ -+ int has_relative = 0, has_non_cache = 0; -+ rb_construct_expanded_load_path(EXPAND_ALL, &has_relative, &has_non_cache); -+ if (has_relative) { -+ vm->load_path_check_cache = load_path_getcwd(); -+ } -+ else if (has_non_cache) { -+ /* Non string object. */ -+ vm->load_path_check_cache = non_cache; -+ } -+ else { -+ vm->load_path_check_cache = 0; -+ } -+ } -+ else if (vm->load_path_check_cache == non_cache) { -+ int has_relative = 1, has_non_cache = 1; -+ /* Expand only non-cacheable objects. */ -+ rb_construct_expanded_load_path(EXPAND_NON_CACHE, -+ &has_relative, &has_non_cache); -+ } -+ else if (vm->load_path_check_cache) { -+ int has_relative = 1, has_non_cache = 1; -+ VALUE cwd = load_path_getcwd(); -+ if (!rb_str_equal(vm->load_path_check_cache, cwd)) { -+ /* Current working directory or filesystem encoding was changed. -+ Expand relative load path and non-cacheable objects again. */ -+ vm->load_path_check_cache = cwd; -+ rb_construct_expanded_load_path(EXPAND_RELATIVE, -+ &has_relative, &has_non_cache); -+ } -+ else { -+ /* Expand only tilde (User HOME) and non-cacheable objects. */ -+ rb_construct_expanded_load_path(EXPAND_HOME, -+ &has_relative, &has_non_cache); -+ } -+ } -+ return vm->expanded_load_path; - } - - static VALUE -@@ -63,12 +161,121 @@ get_loaded_features(void) - return GET_VM()->loaded_features; - } - -+static void -+reset_loaded_features_snapshot(void) -+{ -+ rb_vm_t *vm = GET_VM(); -+ rb_ary_replace(vm->loaded_features_snapshot, vm->loaded_features); -+} -+ -+static VALUE -+get_loaded_features_index_raw(void) -+{ -+ return GET_VM()->loaded_features_index; -+} -+ - static st_table * - get_loading_table(void) - { - return GET_VM()->loading_table; - } - -+static void -+features_index_add_single(VALUE short_feature, VALUE offset) -+{ -+ VALUE features_index, this_feature_index; -+ features_index = get_loaded_features_index_raw(); -+ if ((this_feature_index = rb_hash_lookup(features_index, short_feature)) == Qnil) { -+ this_feature_index = rb_ary_new(); -+ rb_hash_aset(features_index, short_feature, this_feature_index); -+ } -+ rb_ary_push(this_feature_index, offset); -+} -+ -+/* Add to the loaded-features index all the required entries for -+ `feature`, located at `offset` in $LOADED_FEATURES. We add an -+ index entry at each string `short_feature` for which -+ feature == "#{prefix}#{short_feature}#{e}" -+ where `e` is empty or matches %r{^\.[^./]*$}, and `prefix` is empty -+ or ends in '/'. This maintains the invariant that `rb_feature_p()` -+ relies on for its fast lookup. -+*/ -+static void -+features_index_add(VALUE feature, VALUE offset) -+{ -+ VALUE short_feature; -+ const char *feature_str, *feature_end, *ext, *p; -+ -+ feature_str = StringValuePtr(feature); -+ feature_end = feature_str + RSTRING_LEN(feature); -+ -+ for (ext = feature_end; ext > feature_str; ext--) -+ if (*ext == '.' || *ext == '/') -+ break; -+ if (*ext != '.') -+ ext = NULL; -+ /* Now `ext` points to the only string matching %r{^\.[^./]*$} that is -+ at the end of `feature`, or is NULL if there is no such string. */ -+ -+ p = ext ? ext : feature_end; -+ while (1) { -+ p--; -+ while (p >= feature_str && *p != '/') -+ p--; -+ if (p < feature_str) -+ break; -+ /* Now *p == '/'. We reach this point for every '/' in `feature`. */ -+ short_feature = rb_str_substr(feature, p + 1 - feature_str, feature_end - p - 1); -+ features_index_add_single(short_feature, offset); -+ if (ext) { -+ short_feature = rb_str_substr(feature, p + 1 - feature_str, ext - p - 1); -+ features_index_add_single(short_feature, offset); -+ } -+ } -+ features_index_add_single(feature, offset); -+ if (ext) { -+ short_feature = rb_str_substr(feature, 0, ext - feature_str); -+ features_index_add_single(short_feature, offset); -+ } -+} -+ -+static VALUE -+get_loaded_features_index(void) -+{ -+ VALUE features; -+ int i; -+ rb_vm_t *vm = GET_VM(); -+ -+ if (!rb_ary_shared_with_p(vm->loaded_features_snapshot, vm->loaded_features)) { -+ /* The sharing was broken; something (other than us in rb_provide_feature()) -+ modified loaded_features. Rebuild the index. */ -+ rb_hash_clear(vm->loaded_features_index); -+ features = vm->loaded_features; -+ for (i = 0; i < RARRAY_LEN(features); i++) { -+ VALUE entry, as_str; -+ as_str = entry = rb_ary_entry(features, i); -+ StringValue(as_str); -+ if (as_str != entry) -+ rb_ary_store(features, i, as_str); -+ rb_str_freeze(as_str); -+ features_index_add(as_str, INT2FIX(i)); -+ } -+ reset_loaded_features_snapshot(); -+ } -+ return vm->loaded_features_index; -+} -+ -+/* This searches `load_path` for a value such that -+ name == "#{load_path[i]}/#{feature}" -+ if `feature` is a suffix of `name`, or otherwise -+ name == "#{load_path[i]}/#{feature}#{ext}" -+ for an acceptable string `ext`. It returns -+ `load_path[i].to_str` if found, else 0. -+ -+ If type is 's', then `ext` is acceptable only if IS_DLEXT(ext); -+ if 'r', then only if IS_RBEXT(ext); otherwise `ext` may be absent -+ or have any value matching `%r{^\.[^./]*$}`. -+*/ - static VALUE - loaded_feature_path(const char *name, long vlen, const char *feature, long len, - int type, VALUE load_path) -@@ -77,7 +284,7 @@ loaded_feature_path(const char *name, long vlen, const char *feature, long len, - long plen; - const char *e; - -- if(vlen < len) return 0; -+ if (vlen < len+1) return 0; - if (!strncmp(name+(vlen-len),feature,len)){ - plen = vlen - len - 1; - } else { -@@ -88,23 +295,22 @@ loaded_feature_path(const char *name, long vlen, const char *feature, long len, - return 0; - plen = e - name - len - 1; - } -+ if (type == 's' && !IS_DLEXT(&name[plen+len+1]) -+ || type == 'r' && !IS_RBEXT(&name[plen+len+1]) -+ || name[plen] != '/') { -+ return 0; -+ } -+ /* Now name == "#{prefix}/#{feature}#{ext}" where ext is acceptable -+ (possibly empty) and prefix is some string of length plen. */ -+ - for (i = 0; i < RARRAY_LEN(load_path); ++i) { - VALUE p = RARRAY_PTR(load_path)[i]; - const char *s = StringValuePtr(p); - long n = RSTRING_LEN(p); - - if (n != plen ) continue; -- if (n && (strncmp(name, s, n) || name[n] != '/')) continue; -- switch (type) { -- case 's': -- if (IS_DLEXT(&name[n+len+1])) return p; -- break; -- case 'r': -- if (IS_RBEXT(&name[n+len+1])) return p; -- break; -- default: -- return p; -- } -+ if (n && strncmp(name, s, n)) continue; -+ return p; - } - return 0; - } -@@ -132,7 +338,7 @@ loaded_feature_path_i(st_data_t v, st_data_t b, st_data_t f) - static int - rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const char **fn) - { -- VALUE v, features, p, load_path = 0; -+ VALUE features, features_index, feature_val, this_feature_index, v, p, load_path = 0; - const char *f, *e; - long i, len, elen, n; - st_table *loading_tbl; -@@ -151,8 +357,39 @@ rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const c - type = 0; - } - features = get_loaded_features(); -- for (i = 0; i < RARRAY_LEN(features); ++i) { -- v = RARRAY_PTR(features)[i]; -+ features_index = get_loaded_features_index(); -+ -+ feature_val = rb_str_new(feature, len); -+ this_feature_index = rb_hash_lookup(features_index, feature_val); -+ /* We search `features` for an entry such that either -+ "#{features[i]}" == "#{load_path[j]}/#{feature}#{e}" -+ for some j, or -+ "#{features[i]}" == "#{feature}#{e}" -+ Here `e` is an "allowed" extension -- either empty or one -+ of the extensions accepted by IS_RBEXT, IS_SOEXT, or -+ IS_DLEXT. Further, if `ext && rb` then `IS_RBEXT(e)`, -+ and if `ext && !rb` then `IS_SOEXT(e) || IS_DLEXT(e)`. -+ -+ If `expanded`, then only the latter form (without load_path[j]) -+ is accepted. Otherwise either form is accepted, *unless* `ext` -+ is false and an otherwise-matching entry of the first form is -+ preceded by an entry of the form -+ "#{features[i2]}" == "#{load_path[j2]}/#{feature}#{e2}" -+ where `e2` matches %r{^\.[^./]*$} but is not an allowed extension. -+ After a "distractor" entry of this form, only entries of the -+ form "#{feature}#{e}" are accepted. -+ -+ In `rb_provide_feature()` and `get_loaded_features_index()` we -+ maintain an invariant that the array `this_feature_index` will -+ point to every entry in `features` which has the form -+ "#{prefix}#{feature}#{e}" -+ where `e` is empty or matches %r{^\.[^./]*$}, and `prefix` is empty -+ or ends in '/'. This includes both match forms above, as well -+ as any distractors, so we may ignore all other entries in `features`. -+ */ -+ for (i = 0; this_feature_index != Qnil && i < RARRAY_LEN(this_feature_index); i++) { -+ long index = FIX2LONG(rb_ary_entry(this_feature_index, i)); -+ v = RARRAY_PTR(features)[index]; - f = StringValuePtr(v); - if ((n = RSTRING_LEN(v)) < len) continue; - if (strncmp(f, feature, len) != 0) { -@@ -175,6 +412,7 @@ rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const c - return 'r'; - } - } -+ - loading_tbl = get_loading_table(); - if (loading_tbl) { - f = 0; -@@ -183,7 +421,7 @@ rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const c - fs.name = feature; - fs.len = len; - fs.type = type; -- fs.load_path = load_path ? load_path : rb_get_load_path(); -+ fs.load_path = load_path ? load_path : rb_get_expanded_load_path(); - fs.result = 0; - st_foreach(loading_tbl, loaded_feature_path_i, (st_data_t)&fs); - if ((f = fs.result) != 0) { -@@ -233,7 +471,7 @@ rb_feature_provided(const char *feature, const char **loading) - - if (*feature == '.' && - (feature[1] == '/' || strncmp(feature+1, "./", 2) == 0)) { -- fullpath = rb_file_expand_path_fast(rb_str_new2(feature), Qnil); -+ fullpath = rb_file_expand_path_fast(rb_get_path(rb_str_new2(feature)), Qnil); - feature = RSTRING_PTR(fullpath); - } - if (ext && !strchr(ext, '/')) { -@@ -254,11 +492,18 @@ rb_feature_provided(const char *feature, const char **loading) - static void - rb_provide_feature(VALUE feature) - { -- if (OBJ_FROZEN(get_loaded_features())) { -+ VALUE features; -+ -+ features = get_loaded_features(); -+ if (OBJ_FROZEN(features)) { - rb_raise(rb_eRuntimeError, - "$LOADED_FEATURES is frozen; cannot append feature"); - } -- rb_ary_push(get_loaded_features(), feature); -+ rb_str_freeze(feature); -+ -+ rb_ary_push(features, feature); -+ features_index_add(feature, INT2FIX(RARRAY_LEN(features)-1)); -+ reset_loaded_features_snapshot(); - } - - void -@@ -774,10 +1019,15 @@ Init_load() - rb_alias_variable(rb_intern("$-I"), id_load_path); - rb_alias_variable(rb_intern("$LOAD_PATH"), id_load_path); - vm->load_path = rb_ary_new(); -+ vm->expanded_load_path = rb_ary_new(); -+ vm->load_path_snapshot = rb_ary_new(); -+ vm->load_path_check_cache = 0; - - rb_define_virtual_variable("$\"", get_loaded_features, 0); - rb_define_virtual_variable("$LOADED_FEATURES", get_loaded_features, 0); - vm->loaded_features = rb_ary_new(); -+ vm->loaded_features_snapshot = rb_ary_new(); -+ vm->loaded_features_index = rb_hash_new(); - - rb_define_global_function("load", rb_f_load, -1); - rb_define_global_function("require", rb_f_require, 1); -diff --git a/ruby.c b/ruby.c -index 3ddd96c..7ffc78e 100644 ---- a/ruby.c -+++ b/ruby.c -@@ -1366,7 +1366,8 @@ process_options(int argc, char **argv, struct cmdline_options *opt) - long i; - VALUE load_path = GET_VM()->load_path; - for (i = 0; i < RARRAY_LEN(load_path); ++i) { -- rb_enc_associate(RARRAY_PTR(load_path)[i], lenc); -+ RARRAY_PTR(load_path)[i] = -+ rb_enc_associate(rb_str_dup(RARRAY_PTR(load_path)[i]), lenc); - } - } - if (!(opt->disable & DISABLE_BIT(gems))) { -diff --git a/test/ruby/test_require.rb b/test/ruby/test_require.rb -index 58a9ee2..ec75096 100644 ---- a/test/ruby/test_require.rb -+++ b/test/ruby/test_require.rb -@@ -356,4 +356,114 @@ class TestRequire < Test::Unit::TestCase - $:.replace(loadpath) - $".replace(features) - end -+ -+ def test_require_changed_current_dir -+ bug7158 = '[ruby-core:47970]' -+ Dir.mktmpdir {|tmp| -+ Dir.chdir(tmp) { -+ Dir.mkdir("a") -+ Dir.mkdir("b") -+ open(File.join("a", "foo.rb"), "w") {} -+ open(File.join("b", "bar.rb"), "w") {|f| -+ f.puts "p :ok" -+ } -+ assert_in_out_err([], <<-INPUT, %w(:ok), [], bug7158) -+ $: << "." -+ Dir.chdir("a") -+ require "foo" -+ Dir.chdir("../b") -+ p :ng unless require "bar" -+ Dir.chdir("..") -+ p :ng if require "b/bar" -+ INPUT -+ } -+ } -+ end -+ -+ def test_require_not_modified_load_path -+ bug7158 = '[ruby-core:47970]' -+ Dir.mktmpdir {|tmp| -+ Dir.chdir(tmp) { -+ open("foo.rb", "w") {} -+ assert_in_out_err([], <<-INPUT, %w(:ok), [], bug7158) -+ a = Object.new -+ def a.to_str -+ "#{tmp}" -+ end -+ $: << a -+ require "foo" -+ last_path = $:.pop -+ p :ok if last_path == a && last_path.class == Object -+ INPUT -+ } -+ } -+ end -+ -+ def test_require_changed_home -+ bug7158 = '[ruby-core:47970]' -+ Dir.mktmpdir {|tmp| -+ Dir.chdir(tmp) { -+ open("foo.rb", "w") {} -+ Dir.mkdir("a") -+ open(File.join("a", "bar.rb"), "w") {} -+ assert_in_out_err([], <<-INPUT, %w(:ok), [], bug7158) -+ $: << '~' -+ ENV['HOME'] = "#{tmp}" -+ require "foo" -+ ENV['HOME'] = "#{tmp}/a" -+ p :ok if require "bar" -+ INPUT -+ } -+ } -+ end -+ -+ def test_require_to_path_redefined_in_load_path -+ bug7158 = '[ruby-core:47970]' -+ Dir.mktmpdir {|tmp| -+ Dir.chdir(tmp) { -+ open("foo.rb", "w") {} -+ assert_in_out_err(["RUBYOPT"=>nil], <<-INPUT, %w(:ok), [], bug7158) -+ a = Object.new -+ def a.to_path -+ "bar" -+ end -+ $: << a -+ begin -+ require "foo" -+ p :ng -+ rescue LoadError -+ end -+ def a.to_path -+ "#{tmp}" -+ end -+ p :ok if require "foo" -+ INPUT -+ } -+ } -+ end -+ -+ def test_require_to_str_redefined_in_load_path -+ bug7158 = '[ruby-core:47970]' -+ Dir.mktmpdir {|tmp| -+ Dir.chdir(tmp) { -+ open("foo.rb", "w") {} -+ assert_in_out_err(["RUBYOPT"=>nil], <<-INPUT, %w(:ok), [], bug7158) -+ a = Object.new -+ def a.to_str -+ "foo" -+ end -+ $: << a -+ begin -+ require "foo" -+ p :ng -+ rescue LoadError -+ end -+ def a.to_str -+ "#{tmp}" -+ end -+ p :ok if require "foo" -+ INPUT -+ } -+ } -+ end - end -diff --git a/vm.c b/vm.c -index b5fc485..5a721d0 100644 ---- a/vm.c -+++ b/vm.c -@@ -1592,7 +1592,12 @@ rb_vm_mark(void *ptr) - RUBY_MARK_UNLESS_NULL(vm->thgroup_default); - RUBY_MARK_UNLESS_NULL(vm->mark_object_ary); - RUBY_MARK_UNLESS_NULL(vm->load_path); -+ RUBY_MARK_UNLESS_NULL(vm->load_path_snapshot); -+ RUBY_MARK_UNLESS_NULL(vm->load_path_check_cache); -+ RUBY_MARK_UNLESS_NULL(vm->expanded_load_path); - RUBY_MARK_UNLESS_NULL(vm->loaded_features); -+ RUBY_MARK_UNLESS_NULL(vm->loaded_features_snapshot); -+ RUBY_MARK_UNLESS_NULL(vm->loaded_features_index); - RUBY_MARK_UNLESS_NULL(vm->top_self); - RUBY_MARK_UNLESS_NULL(vm->coverages); - rb_gc_mark_locations(vm->special_exceptions, vm->special_exceptions + ruby_special_error_count); -diff --git a/vm_core.h b/vm_core.h -index dfc0e3c..70c5f5c 100644 ---- a/vm_core.h -+++ b/vm_core.h -@@ -299,7 +299,12 @@ typedef struct rb_vm_struct { - /* load */ - VALUE top_self; - VALUE load_path; -+ VALUE load_path_snapshot; -+ VALUE load_path_check_cache; -+ VALUE expanded_load_path; - VALUE loaded_features; -+ VALUE loaded_features_snapshot; -+ VALUE loaded_features_index; - struct st_table *loading_table; - - /* signal */ diff --git a/patches/ruby/1.9.3/p392/railsexpress/10-falcon-st-opt.patch b/patches/ruby/1.9.3/p392/railsexpress/10-falcon-st-opt.patch deleted file mode 100644 index de5d23c51b..0000000000 --- a/patches/ruby/1.9.3/p392/railsexpress/10-falcon-st-opt.patch +++ /dev/null @@ -1,2333 +0,0 @@ -diff --git a/common.mk b/common.mk -index ccc9647..1d8e442 100644 ---- a/common.mk -+++ b/common.mk -@@ -638,7 +638,8 @@ file.$(OBJEXT): {$(VPATH)}file.c $(RUBY_H_INCLUDES) {$(VPATH)}io.h \ - gc.$(OBJEXT): {$(VPATH)}gc.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \ - {$(VPATH)}regex.h $(ENCODING_H_INCLUDES) $(VM_CORE_H_INCLUDES) \ - {$(VPATH)}gc.h {$(VPATH)}io.h {$(VPATH)}eval_intern.h {$(VPATH)}util.h \ -- {$(VPATH)}debug.h {$(VPATH)}internal.h {$(VPATH)}constant.h -+ {$(VPATH)}debug.h {$(VPATH)}internal.h {$(VPATH)}constant.h \ -+ {$(VPATH)}pool_alloc.inc.h {$(VPATH)}pool_alloc.h - hash.$(OBJEXT): {$(VPATH)}hash.c $(RUBY_H_INCLUDES) {$(VPATH)}util.h \ - $(ENCODING_H_INCLUDES) - inits.$(OBJEXT): {$(VPATH)}inits.c $(RUBY_H_INCLUDES) \ -@@ -702,7 +703,7 @@ signal.$(OBJEXT): {$(VPATH)}signal.c $(RUBY_H_INCLUDES) \ - $(VM_CORE_H_INCLUDES) {$(VPATH)}debug.h - sprintf.$(OBJEXT): {$(VPATH)}sprintf.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \ - {$(VPATH)}regex.h {$(VPATH)}vsnprintf.c $(ENCODING_H_INCLUDES) --st.$(OBJEXT): {$(VPATH)}st.c $(RUBY_H_INCLUDES) -+st.$(OBJEXT): {$(VPATH)}st.c $(RUBY_H_INCLUDES) {$(VPATH)}pool_alloc.h - strftime.$(OBJEXT): {$(VPATH)}strftime.c $(RUBY_H_INCLUDES) \ - {$(VPATH)}timev.h - string.$(OBJEXT): {$(VPATH)}string.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \ -diff --git a/configure.in b/configure.in -index 6099a92..7b85cc9 100644 ---- a/configure.in -+++ b/configure.in -@@ -1268,6 +1268,30 @@ if test $rb_cv_stack_end_address != no; then - AC_DEFINE_UNQUOTED(STACK_END_ADDRESS, $rb_cv_stack_end_address) - fi - -+AS_CASE(["$target_os"], -+[openbsd*], [ -+ AC_CACHE_CHECK(for heap align log on openbsd, rb_cv_page_size_log, -+ [rb_cv_page_size_log=no -+ for page_log in 12 13; do -+ AC_TRY_RUN([ -+#include -+#include -+ -+int -+main() { -+ if ((int)log2((double)sysconf(_SC_PAGESIZE)) != $page_log) return 1; -+ return 0; -+} -+ ], -+ rb_cv_page_size_log="$page_log"; break) -+ done]) -+ if test $rb_cv_page_size_log != no; then -+ AC_DEFINE_UNQUOTED(HEAP_ALIGN_LOG, $rb_cv_page_size_log) -+ else -+ AC_DEFINE_UNQUOTED(HEAP_ALIGN_LOG, 12) -+ fi -+]) -+ - dnl Checks for library functions. - AC_TYPE_GETGROUPS - AC_TYPE_SIGNAL -@@ -1367,7 +1391,8 @@ AC_CHECK_FUNCS(fmod killpg wait4 waitpid fork spawnv syscall __syscall chroot ge - setsid telldir seekdir fchmod cosh sinh tanh log2 round\ - setuid setgid daemon select_large_fdset setenv unsetenv\ - mktime timegm gmtime_r clock_gettime gettimeofday poll ppoll\ -- pread sendfile shutdown sigaltstack dl_iterate_phdr) -+ pread sendfile shutdown sigaltstack dl_iterate_phdr\ -+ posix_memalign memalign) - - AC_CACHE_CHECK(for unsetenv returns a value, rb_cv_unsetenv_return_value, - [AC_TRY_COMPILE([ -diff --git a/ext/-test-/st/numhash/numhash.c b/ext/-test-/st/numhash/numhash.c -index e186cd4..53d9e1b 100644 ---- a/ext/-test-/st/numhash/numhash.c -+++ b/ext/-test-/st/numhash/numhash.c -@@ -54,7 +54,7 @@ numhash_i(st_data_t key, st_data_t value, st_data_t arg, int error) - static VALUE - numhash_each(VALUE self) - { -- return st_foreach((st_table *)DATA_PTR(self), numhash_i, self) ? Qtrue : Qfalse; -+ return st_foreach_check((st_table *)DATA_PTR(self), numhash_i, self, 0) ? Qtrue : Qfalse; - } - - void -diff --git a/gc.c b/gc.c -index b5fc83c..3110059 100644 ---- a/gc.c -+++ b/gc.c -@@ -20,6 +20,7 @@ - #include "vm_core.h" - #include "internal.h" - #include "gc.h" -+#include "pool_alloc.h" - #include "constant.h" - #include "ruby_atomic.h" - #include -@@ -37,7 +38,12 @@ - - #if defined _WIN32 || defined __CYGWIN__ - #include -+#elif defined(HAVE_POSIX_MEMALIGN) -+#elif defined(HAVE_MEMALIGN) -+#include - #endif -+static void aligned_free(void *); -+static void *aligned_malloc(size_t alignment, size_t size); - - #ifdef HAVE_VALGRIND_MEMCHECK_H - # include -@@ -356,6 +362,24 @@ typedef struct mark_stack { - - #define CALC_EXACT_MALLOC_SIZE 0 - -+#ifdef POOL_ALLOC_API -+/* POOL ALLOC API */ -+#define POOL_ALLOC_PART 1 -+#include "pool_alloc.inc.h" -+#undef POOL_ALLOC_PART -+ -+typedef struct pool_layout_t pool_layout_t; -+struct pool_layout_t { -+ pool_header -+ p6, /* st_table && st_table_entry */ -+ p11; /* st_table.bins init size */ -+} pool_layout = { -+ INIT_POOL(void*[6]), -+ INIT_POOL(void*[11]) -+}; -+static void pool_finalize_header(pool_header *header); -+#endif -+ - typedef struct rb_objspace { - struct { - size_t limit; -@@ -365,6 +389,9 @@ typedef struct rb_objspace { - size_t allocations; - #endif - } malloc_params; -+#ifdef POOL_ALLOC_API -+ pool_layout_t *pool_headers; -+#endif - struct { - size_t increment; - struct heaps_slot *ptr; -@@ -430,7 +457,11 @@ typedef struct rb_objspace { - #define ruby_initial_gc_stress initial_params.gc_stress - int *ruby_initial_gc_stress_ptr = &ruby_initial_gc_stress; - #else -+# ifdef POOL_ALLOC_API -+static rb_objspace_t rb_objspace = {{GC_MALLOC_LIMIT}, &pool_layout, {HEAP_MIN_SLOTS}}; -+# else - static rb_objspace_t rb_objspace = {{GC_MALLOC_LIMIT}, {HEAP_MIN_SLOTS}}; -+# endif - int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress; - #endif - #define malloc_limit objspace->malloc_params.limit -@@ -481,6 +512,10 @@ rb_objspace_alloc(void) - memset(objspace, 0, sizeof(*objspace)); - malloc_limit = initial_malloc_limit; - ruby_gc_stress = ruby_initial_gc_stress; -+#ifdef POOL_ALLOC_API -+ objspace->pool_headers = (pool_layout_t*) malloc(sizeof(pool_layout)); -+ memcpy(objspace->pool_headers, &pool_layout, sizeof(pool_layout)); -+#endif - - return objspace; - } -@@ -624,6 +659,13 @@ rb_objspace_free(rb_objspace_t *objspace) - heaps = 0; - } - free_stack_chunks(&objspace->mark_stack); -+#ifdef POOL_ALLOC_API -+ if (objspace->pool_headers) { -+ pool_finalize_header(&objspace->pool_headers->p6); -+ pool_finalize_header(&objspace->pool_headers->p11); -+ free(objspace->pool_headers); -+ } -+#endif - free(objspace); - } - #endif -@@ -1148,6 +1190,27 @@ rb_gc_stats_enabled() - return gc_statistics ? Qtrue : Qfalse; - } - -+#ifdef POOL_ALLOC_API -+/* POOL ALLOC API */ -+#define POOL_ALLOC_PART 2 -+#include "pool_alloc.inc.h" -+#undef POOL_ALLOC_PART -+ -+void -+ruby_xpool_free(void *ptr) -+{ -+ pool_free_entry((void**)ptr); -+} -+ -+#define CONCRET_POOL_MALLOC(pnts) \ -+void * ruby_xpool_malloc_##pnts##p () { \ -+ return pool_alloc_entry(&rb_objspace.pool_headers->p##pnts ); \ -+} -+CONCRET_POOL_MALLOC(6) -+CONCRET_POOL_MALLOC(11) -+#undef CONCRET_POOL_MALLOC -+ -+#endif - - /* - * call-seq: -@@ -1663,6 +1726,55 @@ allocate_sorted_heaps(rb_objspace_t *objspace, size_t next_heaps_length) - heaps_length = next_heaps_length; - } - -+static void * -+aligned_malloc(size_t alignment, size_t size) -+{ -+ void *res; -+ -+#if defined __MINGW32__ -+ res = __mingw_aligned_malloc(size, alignment); -+#elif defined _WIN32 && !defined __CYGWIN__ -+ 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 -+ -+#if defined(_DEBUG) || defined(GC_DEBUG) -+ /* alignment must be a power of 2 */ -+ assert((alignment - 1) & alignment == 0); -+ assert(alignment % sizeof(void*) == 0); -+#endif -+ return res; -+} -+ -+static void -+aligned_free(void *ptr) -+{ -+#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 -+} -+ - static void - assign_heap_slot(rb_objspace_t *objspace) - { -diff --git a/hash.c b/hash.c -index 8423558..4cb2e2d 100644 ---- a/hash.c -+++ b/hash.c -@@ -44,7 +44,7 @@ rb_any_cmp(VALUE a, VALUE b) - if (FIXNUM_P(a) && FIXNUM_P(b)) { - return a != b; - } -- if (TYPE(a) == T_STRING && RBASIC(a)->klass == rb_cString && -+ if (RB_TYPE_P(a, T_STRING) && RBASIC(a)->klass == rb_cString && - TYPE(b) == T_STRING && RBASIC(b)->klass == rb_cString) { - return rb_str_hash_cmp(a, b); - } -@@ -80,20 +80,14 @@ rb_any_hash(VALUE a) - VALUE hval; - st_index_t hnum; - -- switch (TYPE(a)) { -- case T_FIXNUM: -- case T_SYMBOL: -- case T_NIL: -- case T_FALSE: -- case T_TRUE: -- hnum = rb_hash_end(rb_hash_start((unsigned int)a)); -- break; -- -- case T_STRING: -+ if (SPECIAL_CONST_P(a)) { -+ if (a == Qundef) return 0; -+ hnum = rb_hash_end(rb_hash_start((st_index_t)a)); -+ } -+ else if (BUILTIN_TYPE(a) == T_STRING) { - hnum = rb_str_hash(a); -- break; -- -- default: -+ } -+ else { - hval = rb_hash(a); - hnum = FIX2LONG(hval); - } -@@ -106,10 +100,8 @@ static const struct st_hash_type objhash = { - rb_any_hash, - }; - --static const struct st_hash_type identhash = { -- st_numcmp, -- st_numhash, --}; -+extern const struct st_hash_type st_hashtype_num; -+#define identhash st_hashtype_num - - typedef int st_foreach_func(st_data_t, st_data_t, st_data_t); - -@@ -124,7 +116,6 @@ foreach_safe_i(st_data_t key, st_data_t value, struct foreach_safe_arg *arg) - { - int status; - -- if (key == Qundef) return ST_CONTINUE; - status = (*arg->func)(key, value, arg->arg); - if (status == ST_CONTINUE) { - return ST_CHECK; -@@ -140,7 +131,7 @@ st_foreach_safe(st_table *table, int (*func)(ANYARGS), st_data_t a) - arg.tbl = table; - arg.func = (st_foreach_func *)func; - arg.arg = a; -- if (st_foreach(table, foreach_safe_i, (st_data_t)&arg)) { -+ if (st_foreach_check(table, foreach_safe_i, (st_data_t)&arg, 0)) { - rb_raise(rb_eRuntimeError, "hash modified during iteration"); - } - } -@@ -154,21 +145,21 @@ struct hash_foreach_arg { - }; - - static int --hash_foreach_iter(st_data_t key, st_data_t value, struct hash_foreach_arg *arg) -+hash_foreach_iter(st_data_t key, st_data_t value, st_data_t argp) - { -+ struct hash_foreach_arg *arg = (struct hash_foreach_arg *)argp; - int status; - st_table *tbl; - - tbl = RHASH(arg->hash)->ntbl; -- if ((VALUE)key == Qundef) return ST_CONTINUE; - status = (*arg->func)((VALUE)key, (VALUE)value, arg->arg); - if (RHASH(arg->hash)->ntbl != tbl) { - rb_raise(rb_eRuntimeError, "rehash occurred during iteration"); - } - switch (status) { - case ST_DELETE: -- st_delete_safe(tbl, &key, 0, Qundef); - FL_SET(arg->hash, HASH_DELETED); -+ return ST_DELETE; - case ST_CONTINUE: - break; - case ST_STOP: -@@ -184,7 +175,7 @@ hash_foreach_ensure(VALUE hash) - - if (RHASH(hash)->iter_lev == 0) { - if (FL_TEST(hash, HASH_DELETED)) { -- st_cleanup_safe(RHASH(hash)->ntbl, Qundef); -+ st_cleanup_safe(RHASH(hash)->ntbl, (st_data_t)Qundef); - FL_UNSET(hash, HASH_DELETED); - } - } -@@ -192,9 +183,10 @@ hash_foreach_ensure(VALUE hash) - } - - static VALUE --hash_foreach_call(struct hash_foreach_arg *arg) -+hash_foreach_call(VALUE arg) - { -- if (st_foreach(RHASH(arg->hash)->ntbl, hash_foreach_iter, (st_data_t)arg)) { -+ VALUE hash = ((struct hash_foreach_arg *)arg)->hash; -+ if (st_foreach_check(RHASH(hash)->ntbl, hash_foreach_iter, (st_data_t)arg, (st_data_t)Qundef)) { - rb_raise(rb_eRuntimeError, "hash modified during iteration"); - } - return Qnil; -@@ -447,7 +439,7 @@ rb_hash_rehash_i(VALUE key, VALUE value, VALUE arg) - { - st_table *tbl = (st_table *)arg; - -- if (key != Qundef) st_insert(tbl, key, value); -+ st_insert(tbl, (st_data_t)key, (st_data_t)value); - return ST_CONTINUE; - } - -@@ -490,6 +482,20 @@ rb_hash_rehash(VALUE hash) - return hash; - } - -+static VALUE -+hash_default_value(VALUE hash, VALUE key) -+{ -+ if (rb_method_basic_definition_p(CLASS_OF(hash), id_default)) { -+ VALUE ifnone = RHASH_IFNONE(hash); -+ if (!FL_TEST(hash, HASH_PROC_DEFAULT)) return ifnone; -+ if (key == Qundef) return Qnil; -+ return rb_funcall(ifnone, id_yield, 2, hash, key); -+ } -+ else { -+ return rb_funcall(hash, id_default, 1, key); -+ } -+} -+ - /* - * call-seq: - * hsh[key] -> value -@@ -510,13 +516,7 @@ rb_hash_aref(VALUE hash, VALUE key) - st_data_t val; - - if (!RHASH(hash)->ntbl || !st_lookup(RHASH(hash)->ntbl, key, &val)) { -- if (!FL_TEST(hash, HASH_PROC_DEFAULT) && -- rb_method_basic_definition_p(CLASS_OF(hash), id_default)) { -- return RHASH_IFNONE(hash); -- } -- else { -- return rb_funcall(hash, id_default, 1, key); -- } -+ return hash_default_value(hash, key); - } - return (VALUE)val; - } -@@ -659,7 +659,7 @@ rb_hash_default(int argc, VALUE *argv, VALUE hash) - static VALUE - rb_hash_set_default(VALUE hash, VALUE ifnone) - { -- rb_hash_modify(hash); -+ rb_hash_modify_check(hash); - RHASH_IFNONE(hash) = ifnone; - FL_UNSET(hash, HASH_PROC_DEFAULT); - return ifnone; -@@ -707,7 +707,7 @@ rb_hash_set_default_proc(VALUE hash, VALUE proc) - { - VALUE b; - -- rb_hash_modify(hash); -+ rb_hash_modify_check(hash); - b = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc"); - if (NIL_P(b) || !rb_obj_is_proc(b)) { - rb_raise(rb_eTypeError, -@@ -776,7 +776,7 @@ rb_hash_delete_key(VALUE hash, VALUE key) - if (!RHASH(hash)->ntbl) - return Qundef; - if (RHASH(hash)->iter_lev > 0) { -- if (st_delete_safe(RHASH(hash)->ntbl, &ktmp, &val, Qundef)) { -+ if (st_delete_safe(RHASH(hash)->ntbl, &ktmp, &val, (st_data_t)Qundef)) { - FL_SET(hash, HASH_DELETED); - return (VALUE)val; - } -@@ -809,7 +809,7 @@ rb_hash_delete(VALUE hash, VALUE key) - { - VALUE val; - -- rb_hash_modify(hash); -+ rb_hash_modify_check(hash); - val = rb_hash_delete_key(hash, key); - if (val != Qundef) return val; - if (rb_block_given_p()) { -@@ -828,7 +828,6 @@ shift_i(VALUE key, VALUE value, VALUE arg) - { - struct shift_var *var = (struct shift_var *)arg; - -- if (key == Qundef) return ST_CONTINUE; - if (var->key != Qundef) return ST_STOP; - var->key = key; - var->val = value; -@@ -840,7 +839,6 @@ shift_i_safe(VALUE key, VALUE value, VALUE arg) - { - struct shift_var *var = (struct shift_var *)arg; - -- if (key == Qundef) return ST_CONTINUE; - var->key = key; - var->val = value; - return ST_STOP; -@@ -864,29 +862,25 @@ rb_hash_shift(VALUE hash) - { - struct shift_var var; - -- rb_hash_modify(hash); -- var.key = Qundef; -- rb_hash_foreach(hash, RHASH(hash)->iter_lev > 0 ? shift_i_safe : shift_i, -- (VALUE)&var); -- -- if (var.key != Qundef) { -- if (RHASH(hash)->iter_lev > 0) { -- rb_hash_delete_key(hash, var.key); -+ rb_hash_modify_check(hash); -+ if (RHASH(hash)->ntbl) { -+ var.key = Qundef; -+ rb_hash_foreach(hash, RHASH(hash)->iter_lev > 0 ? shift_i_safe : shift_i, -+ (VALUE)&var); -+ -+ if (var.key != Qundef) { -+ if (RHASH(hash)->iter_lev > 0) { -+ rb_hash_delete_key(hash, var.key); -+ } -+ return rb_assoc_new(var.key, var.val); - } -- return rb_assoc_new(var.key, var.val); -- } -- else if (FL_TEST(hash, HASH_PROC_DEFAULT)) { -- return rb_funcall(RHASH_IFNONE(hash), id_yield, 2, hash, Qnil); -- } -- else { -- return RHASH_IFNONE(hash); - } -+ return hash_default_value(hash, Qnil); - } - - static int - delete_if_i(VALUE key, VALUE value, VALUE hash) - { -- if (key == Qundef) return ST_CONTINUE; - if (RTEST(rb_yield_values(2, key, value))) { - rb_hash_delete_key(hash, key); - } -@@ -912,8 +906,9 @@ VALUE - rb_hash_delete_if(VALUE hash) - { - RETURN_ENUMERATOR(hash, 0, 0); -- rb_hash_modify(hash); -- rb_hash_foreach(hash, delete_if_i, hash); -+ rb_hash_modify_check(hash); -+ if (RHASH(hash)->ntbl) -+ rb_hash_foreach(hash, delete_if_i, hash); - return hash; - } - -@@ -984,7 +979,6 @@ rb_hash_values_at(int argc, VALUE *argv, VALUE hash) - static int - select_i(VALUE key, VALUE value, VALUE result) - { -- if (key == Qundef) return ST_CONTINUE; - if (RTEST(rb_yield_values(2, key, value))) - rb_hash_aset(result, key, value); - return ST_CONTINUE; -@@ -1018,7 +1012,6 @@ rb_hash_select(VALUE hash) - static int - keep_if_i(VALUE key, VALUE value, VALUE hash) - { -- if (key == Qundef) return ST_CONTINUE; - if (!RTEST(rb_yield_values(2, key, value))) { - return ST_DELETE; - } -@@ -1040,7 +1033,7 @@ rb_hash_select_bang(VALUE hash) - st_index_t n; - - RETURN_ENUMERATOR(hash, 0, 0); -- rb_hash_modify(hash); -+ rb_hash_modify_check(hash); - if (!RHASH(hash)->ntbl) - return Qnil; - n = RHASH(hash)->ntbl->num_entries; -@@ -1065,8 +1058,9 @@ VALUE - rb_hash_keep_if(VALUE hash) - { - RETURN_ENUMERATOR(hash, 0, 0); -- rb_hash_modify(hash); -- rb_hash_foreach(hash, keep_if_i, hash); -+ rb_hash_modify_check(hash); -+ if (RHASH(hash)->ntbl) -+ rb_hash_foreach(hash, keep_if_i, hash); - return hash; - } - -@@ -1144,9 +1138,7 @@ rb_hash_aset(VALUE hash, VALUE key, VALUE val) - static int - replace_i(VALUE key, VALUE val, VALUE hash) - { -- if (key != Qundef) { -- rb_hash_aset(hash, key, val); -- } -+ rb_hash_aset(hash, key, val); - - return ST_CONTINUE; - } -@@ -1227,7 +1219,6 @@ rb_hash_empty_p(VALUE hash) - static int - each_value_i(VALUE key, VALUE value) - { -- if (key == Qundef) return ST_CONTINUE; - rb_yield(value); - return ST_CONTINUE; - } -@@ -1262,7 +1253,6 @@ rb_hash_each_value(VALUE hash) - static int - each_key_i(VALUE key, VALUE value) - { -- if (key == Qundef) return ST_CONTINUE; - rb_yield(key); - return ST_CONTINUE; - } -@@ -1296,7 +1286,6 @@ rb_hash_each_key(VALUE hash) - static int - each_pair_i(VALUE key, VALUE value) - { -- if (key == Qundef) return ST_CONTINUE; - rb_yield(rb_assoc_new(key, value)); - return ST_CONTINUE; - } -@@ -1334,7 +1323,6 @@ rb_hash_each_pair(VALUE hash) - static int - to_a_i(VALUE key, VALUE value, VALUE ary) - { -- if (key == Qundef) return ST_CONTINUE; - rb_ary_push(ary, rb_assoc_new(key, value)); - return ST_CONTINUE; - } -@@ -1367,7 +1355,6 @@ inspect_i(VALUE key, VALUE value, VALUE str) - { - VALUE str2; - -- if (key == Qundef) return ST_CONTINUE; - str2 = rb_inspect(key); - if (RSTRING_LEN(str) > 1) { - rb_str_cat2(str, ", "); -@@ -1434,7 +1421,6 @@ rb_hash_to_hash(VALUE hash) - static int - keys_i(VALUE key, VALUE value, VALUE ary) - { -- if (key == Qundef) return ST_CONTINUE; - rb_ary_push(ary, key); - return ST_CONTINUE; - } -@@ -1465,7 +1451,6 @@ rb_hash_keys(VALUE hash) - static int - values_i(VALUE key, VALUE value, VALUE ary) - { -- if (key == Qundef) return ST_CONTINUE; - rb_ary_push(ary, value); - return ST_CONTINUE; - } -@@ -1524,7 +1509,6 @@ rb_hash_search_value(VALUE key, VALUE value, VALUE arg) - { - VALUE *data = (VALUE *)arg; - -- if (key == Qundef) return ST_CONTINUE; - if (rb_equal(value, data[1])) { - data[0] = Qtrue; - return ST_STOP; -@@ -1568,7 +1552,6 @@ eql_i(VALUE key, VALUE val1, VALUE arg) - struct equal_data *data = (struct equal_data *)arg; - st_data_t val2; - -- if (key == Qundef) return ST_CONTINUE; - if (!st_lookup(data->tbl, key, &val2)) { - data->result = Qfalse; - return ST_STOP; -@@ -1599,7 +1582,7 @@ hash_equal(VALUE hash1, VALUE hash2, int eql) - struct equal_data data; - - if (hash1 == hash2) return Qtrue; -- if (TYPE(hash2) != T_HASH) { -+ if (!RB_TYPE_P(hash2, T_HASH)) { - if (!rb_respond_to(hash2, rb_intern("to_hash"))) { - return Qfalse; - } -@@ -1670,7 +1653,6 @@ hash_i(VALUE key, VALUE val, VALUE arg) - st_index_t *hval = (st_index_t *)arg; - st_index_t hdata[2]; - -- if (key == Qundef) return ST_CONTINUE; - hdata[0] = rb_hash(key); - hdata[1] = rb_hash(val); - *hval ^= st_hash(hdata, sizeof(hdata), 0); -@@ -1711,7 +1693,6 @@ rb_hash_hash(VALUE hash) - static int - rb_hash_invert_i(VALUE key, VALUE value, VALUE hash) - { -- if (key == Qundef) return ST_CONTINUE; - rb_hash_aset(hash, value, key); - return ST_CONTINUE; - } -@@ -1740,7 +1721,6 @@ rb_hash_invert(VALUE hash) - static int - rb_hash_update_i(VALUE key, VALUE value, VALUE hash) - { -- if (key == Qundef) return ST_CONTINUE; - hash_update(hash, key); - st_insert(RHASH(hash)->ntbl, key, value); - return ST_CONTINUE; -@@ -1749,7 +1729,6 @@ rb_hash_update_i(VALUE key, VALUE value, VALUE hash) - static int - rb_hash_update_block_i(VALUE key, VALUE value, VALUE hash) - { -- if (key == Qundef) return ST_CONTINUE; - if (rb_hash_has_key(hash, key)) { - value = rb_yield_values(3, key, rb_hash_aref(hash, key), value); - } -@@ -1806,7 +1785,6 @@ rb_hash_update_func_i(VALUE key, VALUE value, VALUE arg0) - struct update_arg *arg = (struct update_arg *)arg0; - VALUE hash = arg->hash; - -- if (key == Qundef) return ST_CONTINUE; - if (rb_hash_has_key(hash, key)) { - value = (*arg->func)(key, rb_hash_aref(hash, key), value); - } -@@ -1863,7 +1841,6 @@ assoc_i(VALUE key, VALUE val, VALUE arg) - { - VALUE *args = (VALUE *)arg; - -- if (key == Qundef) return ST_CONTINUE; - if (RTEST(rb_equal(args[0], key))) { - args[1] = rb_assoc_new(key, val); - return ST_STOP; -@@ -1901,7 +1878,6 @@ rassoc_i(VALUE key, VALUE val, VALUE arg) - { - VALUE *args = (VALUE *)arg; - -- if (key == Qundef) return ST_CONTINUE; - if (RTEST(rb_equal(args[0], val))) { - args[1] = rb_assoc_new(key, val); - return ST_STOP; -@@ -2198,7 +2174,7 @@ rb_env_path_tainted(void) - } - - #if defined(_WIN32) || (defined(HAVE_SETENV) && defined(HAVE_UNSETENV)) --#elif defined __sun__ -+#elif defined __sun - static int - in_origenv(const char *str) - { -@@ -2286,7 +2262,7 @@ ruby_setenv(const char *name, const char *value) - rb_sys_fail("unsetenv"); - #endif - } --#elif defined __sun__ -+#elif defined __sun - size_t len; - char **env_ptr, *str; - if (strchr(name, '=')) { -@@ -3084,11 +3060,9 @@ env_invert(void) - static int - env_replace_i(VALUE key, VALUE val, VALUE keys) - { -- if (key != Qundef) { -- env_aset(Qnil, key, val); -- if (rb_ary_includes(keys, key)) { -- rb_ary_delete(keys, key); -- } -+ env_aset(Qnil, key, val); -+ if (rb_ary_includes(keys, key)) { -+ rb_ary_delete(keys, key); - } - return ST_CONTINUE; - } -@@ -3120,12 +3094,10 @@ env_replace(VALUE env, VALUE hash) - static int - env_update_i(VALUE key, VALUE val) - { -- if (key != Qundef) { -- if (rb_block_given_p()) { -- val = rb_yield_values(3, key, rb_f_getenv(Qnil, key), val); -- } -- env_aset(Qnil, key, val); -+ if (rb_block_given_p()) { -+ val = rb_yield_values(3, key, rb_f_getenv(Qnil, key), val); - } -+ env_aset(Qnil, key, val); - return ST_CONTINUE; - } - -@@ -3150,15 +3122,116 @@ env_update(VALUE env, VALUE hash) - } - - /* -- * A Hash is a collection of key-value pairs. It is -- * similar to an Array, except that indexing is done via -- * arbitrary keys of any object type, not an integer index. Hashes enumerate -- * their values in the order that the corresponding keys were inserted. -+ * A Hash is a dictionary-like collection of unique keys and their values. -+ * Also called associative arrays, they are similar to Arrays, but where an -+ * Array uses integers as its index, a Hash allows you to use any object -+ * type. -+ * -+ * Hashes enumerate their values in the order that the corresponding keys -+ * were inserted. -+ * -+ * A Hash can be easily created by using its implicit form: -+ * -+ * grades = { "Jane Doe" => 10, "Jim Doe" => 6 } -+ * -+ * Hashes allow an alternate syntax form when your keys are always symbols. -+ * Instead of -+ * -+ * options = { :font_size => 10, :font_family => "Arial" } -+ * -+ * You could write it as: -+ * -+ * options = { font_size: 10, font_family: "Arial" } -+ * -+ * Each named key is a symbol you can access in hash: -+ * -+ * options[:font_size] # => 10 -+ * -+ * A Hash can also be created through its ::new method: -+ * -+ * grades = Hash.new -+ * grades["Dorothy Doe"] = 9 - * - * Hashes have a default value that is returned when accessing -- * keys that do not exist in the hash. By default, that value is -- * nil. -+ * keys that do not exist in the hash. If no default is set +nil+ is used. -+ * You can set the default value by sending it as an argument to Hash.new: -+ * -+ * grades = Hash.new(0) -+ * -+ * Or by using the #default= method: -+ * -+ * grades = {"Timmy Doe" => 8} -+ * grades.default = 0 -+ * -+ * Accessing a value in a Hash requires using its key: -+ * -+ * puts grades["Jane Doe"] # => 10 -+ * -+ * === Common Uses -+ * -+ * Hashes are an easy way to represent data structures, such as -+ * -+ * books = {} -+ * books[:matz] = "The Ruby Language" -+ * books[:black] = "The Well-Grounded Rubyist" -+ * -+ * Hashes are also commonly used as a way to have named parameters in -+ * functions. Note that no brackets are used below. If a hash is the last -+ * argument on a method call, no braces are needed, thus creating a really -+ * clean interface: -+ * -+ * Person.create(name: "John Doe", age: 27) -+ * -+ * def self.create(params) -+ * @name = params[:name] -+ * @age = params[:age] -+ * end -+ * -+ * === Hash Keys -+ * -+ * Two objects refer to the same hash key when their hash value -+ * is identical and the two objects are eql? to each other. -+ * -+ * A user-defined class may be used as a hash key if the hash -+ * and eql? methods are overridden to provide meaningful -+ * behavior. By default, separate instances refer to separate hash keys. -+ * -+ * A typical implementation of hash is based on the -+ * object's data while eql? is usually aliased to the overridden -+ * == method: -+ * -+ * class Book -+ * attr_reader :author, :title -+ * -+ * def initialize(author, title) -+ * @author = author -+ * @title = title -+ * end -+ * -+ * def ==(other) -+ * self.class === other and -+ * other.author == @author and -+ * other.title == @title -+ * end -+ * -+ * alias eql? == -+ * -+ * def hash -+ * @author.hash ^ @title.hash # XOR -+ * end -+ * end -+ * -+ * book1 = Book.new 'matz', 'Ruby in a Nutshell' -+ * book2 = Book.new 'matz', 'Ruby in a Nutshell' -+ * -+ * reviews = {} -+ * -+ * reviews[book1] = 'Great reference!' -+ * reviews[book2] = 'Nice and compact!' -+ * -+ * reviews.length #=> 1 - * -+ * See also Object#hash and Object#eql? - */ - - void -diff --git a/include/ruby/st.h b/include/ruby/st.h -index 50f2a75..119dfde 100644 ---- a/include/ruby/st.h -+++ b/include/ruby/st.h -@@ -36,7 +36,7 @@ typedef unsigned long st_data_t; - #elif SIZEOF_LONG_LONG == SIZEOF_VOIDP - typedef unsigned LONG_LONG st_data_t; - #else --# error ---->> st.c requires sizeof(void*) == sizeof(long) to be compiled. <<---- -+# error ---->> st.c requires sizeof(void*) == sizeof(long) or sizeof(LONG_LONG) to be compiled. <<---- - #endif - #define ST_DATA_T_DEFINED - -@@ -74,6 +74,11 @@ struct st_hash_type { - - #define ST_INDEX_BITS (sizeof(st_index_t) * CHAR_BIT) - -+typedef struct st_packed_entry { -+ st_index_t hash; -+ st_data_t key, val; -+} st_packed_entry; -+ - struct st_table { - const struct st_hash_type *type; - st_index_t num_bins; -@@ -91,8 +96,17 @@ struct st_table { - __extension__ - #endif - st_index_t num_entries : ST_INDEX_BITS - 1; -- struct st_table_entry **bins; -- struct st_table_entry *head, *tail; -+ union { -+ struct { -+ struct st_table_entry **bins; -+ struct st_table_entry *head, *tail; -+ } big; -+ struct { -+ struct st_packed_entry *entries; -+ st_index_t real_entries; -+ } packed; -+ st_packed_entry upacked; -+ } as; - }; - - #define st_is_member(table,key) st_lookup((table),(key),(st_data_t *)0) -@@ -114,6 +128,7 @@ int st_insert2(st_table *, st_data_t, st_data_t, st_data_t (*)(st_data_t)); - int st_lookup(st_table *, st_data_t, st_data_t *); - int st_get_key(st_table *, st_data_t, st_data_t *); - int st_foreach(st_table *, int (*)(ANYARGS), st_data_t); -+int st_foreach_check(st_table *, int (*)(ANYARGS), st_data_t, st_data_t); - int st_reverse_foreach(st_table *, int (*)(ANYARGS), st_data_t); - void st_add_direct(st_table *, st_data_t, st_data_t); - void st_free_table(st_table *); -diff --git a/pool_alloc.h b/pool_alloc.h -new file mode 100644 -index 0000000..957708e ---- /dev/null -+++ b/pool_alloc.h -@@ -0,0 +1,11 @@ -+#ifndef POOL_ALLOC_H -+#define POOL_ALLOC_H -+ -+#define POOL_ALLOC_API -+#ifdef POOL_ALLOC_API -+void ruby_xpool_free(void *ptr); -+void *ruby_xpool_malloc_6p(); -+void *ruby_xpool_malloc_11p(); -+#endif -+ -+#endif -diff --git a/pool_alloc.inc.h b/pool_alloc.inc.h -new file mode 100644 -index 0000000..a7879ab ---- /dev/null -+++ b/pool_alloc.inc.h -@@ -0,0 +1,156 @@ -+/* -+ * this is generic pool allocator -+ * you should define following macroses: -+ * ITEM_NAME - unique identifier, which allows to hold functions in a namespace -+ * ITEM_TYPEDEF(name) - passed to typedef to localize item type -+ * free_entry - desired name of function for free entry -+ * alloc_entry - defired name of function for allocate entry -+ */ -+ -+#if POOL_ALLOC_PART == 1 -+#ifdef HEAP_ALIGN_LOG -+#define DEFAULT_POOL_SIZE (1 << HEAP_ALIGN_LOG) -+#else -+#define DEFAULT_POOL_SIZE (sizeof(void*) * 2048) -+#endif -+typedef unsigned int pool_holder_counter; -+ -+typedef struct pool_entry_list pool_entry_list; -+typedef struct pool_holder pool_holder; -+ -+typedef struct pool_header { -+ pool_holder *first; -+ pool_holder *_black_magick; -+ pool_holder_counter size; // size of entry in sizeof(void*) items -+ pool_holder_counter total; // size of entry in sizeof(void*) items -+} pool_header; -+ -+struct pool_holder { -+ pool_holder_counter free, total; -+ pool_header *header; -+ void *freep; -+ pool_holder *fore, *back; -+ void *data[1]; -+}; -+#define POOL_DATA_SIZE(pool_size) (((pool_size) - sizeof(void*) * 6 - offsetof(pool_holder, data)) / sizeof(void*)) -+#define POOL_ENTRY_SIZE(item_type) ((sizeof(item_type) - 1) / sizeof(void*) + 1) -+#define POOL_HOLDER_COUNT(pool_size, item_type) (POOL_DATA_SIZE(pool_size)/POOL_ENTRY_SIZE(item_type)) -+#define INIT_POOL(item_type) {NULL, NULL, POOL_ENTRY_SIZE(item_type), POOL_HOLDER_COUNT(DEFAULT_POOL_SIZE, item_type)} -+ -+#elif POOL_ALLOC_PART == 2 -+static pool_holder * -+pool_holder_alloc(pool_header *header) -+{ -+ pool_holder *holder; -+ pool_holder_counter i, size, count; -+ register void **ptr; -+ -+ size_t sz = offsetof(pool_holder, data) + -+ header->size * header->total * sizeof(void*); -+#define objspace (&rb_objspace) -+ vm_malloc_prepare(objspace, DEFAULT_POOL_SIZE); -+ if (header->first != NULL) return header->first; -+ TRY_WITH_GC(holder = (pool_holder*) aligned_malloc(DEFAULT_POOL_SIZE, sz)); -+ malloc_increase += DEFAULT_POOL_SIZE; -+#if CALC_EXACT_MALLOC_SIZE -+ objspace->malloc_params.allocated_size += DEFAULT_POOL_SIZE; -+ objspace->malloc_params.allocations++; -+#endif -+#undef objspace -+ -+ size = header->size; -+ count = header->total; -+ holder->free = count; -+ holder->total = count; -+ holder->header = header; -+ holder->fore = NULL; -+ holder->back = NULL; -+ holder->freep = &holder->data; -+ ptr = holder->data; -+ for(i = count - 1; i; i-- ) { -+ ptr = *ptr = ptr + size; -+ } -+ *ptr = NULL; -+ header->first = holder; -+ return holder; -+} -+ -+static inline void -+pool_holder_unchaing(pool_header *header, pool_holder *holder) -+{ -+ register pool_holder *fore = holder->fore, *back = holder->back; -+ holder->fore = NULL; -+ holder->back = NULL; -+ if (fore != NULL) fore->back = back; -+ else header->_black_magick = back; -+ if (back != NULL) back->fore = fore; -+ else header->first = fore; -+} -+ -+static inline pool_holder * -+entry_holder(void **entry) -+{ -+ return (pool_holder*)(((uintptr_t)entry) & ~(DEFAULT_POOL_SIZE - 1)); -+} -+ -+static inline void -+pool_free_entry(void **entry) -+{ -+ pool_holder *holder = entry_holder(entry); -+ pool_header *header = holder->header; -+ -+ if (holder->free++ == 0) { -+ register pool_holder *first = header->first; -+ if (first == NULL) { -+ header->first = holder; -+ } else { -+ holder->back = first; -+ holder->fore = first->fore; -+ first->fore = holder; -+ if (holder->fore) -+ holder->fore->back = holder; -+ else -+ header->_black_magick = holder; -+ } -+ } else if (holder->free == holder->total && header->first != holder ) { -+ pool_holder_unchaing(header, holder); -+ aligned_free(holder); -+#if CALC_EXACT_MALLOC_SIZE -+ rb_objspace.malloc_params.allocated_size -= DEFAULT_POOL_SIZE; -+ rb_objspace.malloc_params.allocations--; -+#endif -+ return; -+ } -+ -+ *entry = holder->freep; -+ holder->freep = entry; -+} -+ -+static inline void* -+pool_alloc_entry(pool_header *header) -+{ -+ pool_holder *holder = header->first; -+ void **result; -+ if (holder == NULL) { -+ holder = pool_holder_alloc(header); -+ } -+ -+ result = holder->freep; -+ holder->freep = *result; -+ -+ if (--holder->free == 0) { -+ pool_holder_unchaing(header, holder); -+ } -+ -+ return result; -+} -+ -+static void -+pool_finalize_header(pool_header *header) -+{ -+ if (header->first) { -+ aligned_free(header->first); -+ header->first = NULL; -+ } -+} -+#endif -diff --git a/st.c b/st.c -index fda5784..0194022 100644 ---- a/st.c -+++ b/st.c -@@ -7,6 +7,7 @@ - #include "st.h" - #else - #include "ruby/ruby.h" -+#include "pool_alloc.h" - #endif - - #include -@@ -25,8 +26,17 @@ struct st_table_entry { - st_table_entry *fore, *back; - }; - --#define ST_DEFAULT_MAX_DENSITY 5 -+#define STATIC_ASSERT(name, expr) typedef int static_assert_##name##_check[(expr) ? 1 : -1]; -+ -+#define ST_DEFAULT_MAX_DENSITY 2 - #define ST_DEFAULT_INIT_TABLE_SIZE 11 -+#define ST_DEFAULT_SECOND_TABLE_SIZE 19 -+#define ST_DEFAULT_PACKED_TABLE_SIZE 19 -+#define PACKED_UNIT (int)(sizeof(st_packed_entry) / sizeof(st_table_entry*)) -+#define MAX_PACKED_HASH (int)(ST_DEFAULT_PACKED_TABLE_SIZE * sizeof(st_table_entry*) / sizeof(st_packed_entry)) -+ -+STATIC_ASSERT(st_packed_entry, sizeof(st_packed_entry) == sizeof(st_table_entry*[PACKED_UNIT])) -+STATIC_ASSERT(st_packed_bins, sizeof(st_packed_entry[MAX_PACKED_HASH]) <= sizeof(st_table_entry*[ST_DEFAULT_PACKED_TABLE_SIZE])) - - /* - * DEFAULT_MAX_DENSITY is the default for the largest we allow the -@@ -38,7 +48,8 @@ struct st_table_entry { - * - */ - --static const struct st_hash_type type_numhash = { -+#define type_numhash st_hashtype_num -+const struct st_hash_type st_hashtype_num = { - st_numcmp, - st_numhash, - }; -@@ -61,20 +72,128 @@ static void rehash(st_table *); - #ifdef RUBY - #define malloc xmalloc - #define calloc xcalloc -+#define realloc xrealloc - #define free(x) xfree(x) - #endif - - #define numberof(array) (int)(sizeof(array) / sizeof((array)[0])) - --#define alloc(type) (type*)malloc((size_t)sizeof(type)) --#define Calloc(n,s) (char*)calloc((n),(s)) -- - #define EQUAL(table,x,y) ((x)==(y) || (*(table)->type->compare)((x),(y)) == 0) - --/* remove cast to unsigned int in the future */ --#define do_hash(key,table) (unsigned int)(st_index_t)(*(table)->type->hash)((key)) -+#define do_hash(key,table) (st_index_t)(*(table)->type->hash)((key)) - #define do_hash_bin(key,table) (do_hash((key), (table))%(table)->num_bins) - -+/* preparation for possible allocation improvements */ -+#ifdef POOL_ALLOC_API -+#define st_alloc_entry() (st_table_entry *)ruby_xpool_malloc_6p() -+#define st_free_entry(entry) ruby_xpool_free(entry) -+#define st_alloc_table() (st_table *)ruby_xpool_malloc_6p() -+#define st_dealloc_table(table) ruby_xpool_free(table) -+static inline st_table_entry ** -+st_alloc_bins(st_index_t size) -+{ -+ st_table_entry **result; -+ if (size == 11) { -+ result = (st_table_entry **) ruby_xpool_malloc_11p(); -+ memset(result, 0, 11 * sizeof(st_table_entry *)); -+ } -+ else -+ result = (st_table_entry **) ruby_xcalloc(size, sizeof(st_table_entry*)); -+ return result; -+} -+static inline void -+st_free_bins(st_table_entry **bins, st_index_t size) -+{ -+ if (size == 11) -+ ruby_xpool_free(bins); -+ else -+ ruby_xfree(bins); -+} -+static inline st_table_entry** -+st_realloc_bins(st_table_entry **bins, st_index_t newsize, st_index_t oldsize) -+{ -+ st_table_entry **new_bins = st_alloc_bins(newsize); -+ st_free_bins(bins, oldsize); -+ return new_bins; -+} -+#else -+#define st_alloc_entry() (st_table_entry *)malloc(sizeof(st_table_entry)) -+#define st_free_entry(entry) free(entry) -+#define st_alloc_table() (st_table *)malloc(sizeof(st_table)) -+#define st_dealloc_table(table) free(table) -+#define st_alloc_bins(size) (st_table_entry **)calloc(size, sizeof(st_table_entry *)) -+#define st_free_bins(bins, size) free(bins) -+static inline st_table_entry** -+st_realloc_bins(st_table_entry **bins, st_index_t newsize, st_index_t oldsize) -+{ -+ bins = (st_table_entry **)realloc(bins, newsize * sizeof(st_table_entry *)); -+ MEMZERO(bins, st_table_entry*, newsize); -+ return bins; -+} -+#endif -+ -+/* Shortage */ -+#define bins as.big.bins -+#define head as.big.head -+#define tail as.big.tail -+#define real_entries as.packed.real_entries -+ -+/* preparation for possible packing improvements */ -+#define PACKED_BINS(table) ((table)->as.packed.entries) -+#define PACKED_ENT(table, i) PACKED_BINS(table)[i] -+#define PKEY(table, i) PACKED_ENT((table), (i)).key -+#define PVAL(table, i) PACKED_ENT((table), (i)).val -+#define PHASH(table, i) PACKED_ENT((table), (i)).hash -+#define PKEY_SET(table, i, v) (PKEY((table), (i)) = (v)) -+#define PVAL_SET(table, i, v) (PVAL((table), (i)) = (v)) -+#define PHASH_SET(table, i, v) (PHASH((table), (i)) = (v)) -+ -+/* this function depends much on packed layout, so that it placed here */ -+static inline void -+remove_packed_entry(st_table *table, st_index_t i) -+{ -+ table->real_entries--; -+ table->num_entries--; -+ if (i < table->real_entries) { -+ MEMMOVE(&PACKED_ENT(table, i), &PACKED_ENT(table, i+1), -+ st_packed_entry, table->real_entries - i); -+ } -+} -+ -+static inline void -+remove_safe_packed_entry(st_table *table, st_index_t i, st_data_t never) -+{ -+ table->num_entries--; -+ PKEY_SET(table, i, never); -+ PVAL_SET(table, i, never); -+ PHASH_SET(table, i, 0); -+} -+ -+/* ultrapacking */ -+#define real_upacked num_bins -+#define MAX_UPACKED_HASH 1 -+#define ULTRAPACKED(table) ((table)->real_upacked <= 1) -+#define UPACKED_ENT(table) ((table)->as.upacked) -+#define UPKEY(table) UPACKED_ENT(table).key -+#define UPVAL(table) UPACKED_ENT(table).val -+#define UPHASH(table) UPACKED_ENT(table).hash -+#define UPKEY_SET(table, v) (UPACKED_ENT(table).key = (v)) -+#define UPVAL_SET(table, v) (UPACKED_ENT(table).val = (v)) -+#define UPHASH_SET(table, v) (UPACKED_ENT(table).hash = (v)) -+static inline void -+remove_upacked_entry(st_table *table) -+{ -+ table->real_upacked = table->num_entries = 0; -+} -+ -+static inline void -+remove_safe_upacked_entry(st_table *table, st_data_t never) -+{ -+ table->num_entries = 0; -+ UPKEY_SET(table, never); -+ UPVAL_SET(table, never); -+ UPHASH_SET(table, 0); -+} - /* - * MINSIZE is the minimum size of a dictionary. - */ -@@ -85,8 +204,8 @@ static void rehash(st_table *); - Table of prime numbers 2^n+a, 2<=n<=30. - */ - static const unsigned int primes[] = { -- 8 + 3, -- 16 + 3, -+ ST_DEFAULT_INIT_TABLE_SIZE, -+ ST_DEFAULT_SECOND_TABLE_SIZE, - 32 + 5, - 64 + 3, - 128 + 3, -@@ -161,8 +280,6 @@ stat_col(void) - } - #endif - --#define MAX_PACKED_NUMHASH (ST_DEFAULT_INIT_TABLE_SIZE/2) -- - st_table* - st_init_table_with_size(const struct st_hash_type *type, st_index_t size) - { -@@ -181,14 +298,19 @@ st_init_table_with_size(const struct st_hash_type *type, st_index_t size) - } - #endif - -- size = new_size(size); /* round up to prime number */ - -- tbl = alloc(st_table); -+ tbl = st_alloc_table(); - tbl->type = type; - tbl->num_entries = 0; -- tbl->entries_packed = type == &type_numhash && size/2 <= MAX_PACKED_NUMHASH; -+ tbl->entries_packed = size <= MAX_PACKED_HASH; -+ if (tbl->entries_packed) { -+ size = size <= MAX_UPACKED_HASH ? 0 : ST_DEFAULT_PACKED_TABLE_SIZE; -+ } -+ else { -+ size = new_size(size); /* round up to prime number */ -+ } - tbl->num_bins = size; -- tbl->bins = (st_table_entry **)Calloc(size, sizeof(st_table_entry*)); -+ tbl->bins = size ? st_alloc_bins(size) : 0; - tbl->head = 0; - tbl->tail = 0; - -@@ -243,17 +365,23 @@ st_clear(st_table *table) - register st_table_entry *ptr, *next; - st_index_t i; - -+ if (ULTRAPACKED(table)) { -+ remove_upacked_entry(table); -+ return; -+ } -+ - if (table->entries_packed) { - table->num_entries = 0; -+ table->real_entries = 0; - return; - } - -- for(i = 0; i < table->num_bins; i++) { -+ for (i = 0; i < table->num_bins; i++) { - ptr = table->bins[i]; - table->bins[i] = 0; - while (ptr != 0) { - next = ptr->next; -- free(ptr); -+ st_free_entry(ptr); - ptr = next; - } - } -@@ -266,14 +394,19 @@ void - st_free_table(st_table *table) - { - st_clear(table); -- free(table->bins); -- free(table); -+ if (!ULTRAPACKED(table)) { -+ st_free_bins(table->bins, table->num_bins); -+ } -+ st_dealloc_table(table); - } - - size_t - st_memsize(const st_table *table) - { -- if (table->entries_packed) { -+ if (ULTRAPACKED(table)) { -+ return sizeof(st_table); -+ } -+ else if (table->entries_packed) { - return table->num_bins * sizeof (void *) + sizeof(st_table); - } - else { -@@ -306,46 +439,77 @@ count_collision(const struct st_hash_type *type) - #define FOUND_ENTRY - #endif - --#define FIND_ENTRY(table, ptr, hash_val, bin_pos) do {\ -- (bin_pos) = (hash_val)%(table)->num_bins;\ -- (ptr) = (table)->bins[(bin_pos)];\ -- FOUND_ENTRY;\ -- if (PTR_NOT_EQUAL((table), (ptr), (hash_val), key)) {\ -- COLLISION;\ -- while (PTR_NOT_EQUAL((table), (ptr)->next, (hash_val), key)) {\ -- (ptr) = (ptr)->next;\ -- }\ -- (ptr) = (ptr)->next;\ -- }\ --} while (0) -+#define FIND_ENTRY(table, ptr, hash_val, bin_pos) \ -+ ((ptr) = find_entry((table), key, (hash_val), ((bin_pos) = (hash_val)%(table)->num_bins))) -+ -+static st_table_entry * -+find_entry(st_table *table, st_data_t key, st_index_t hash_val, st_index_t bin_pos) -+{ -+ register st_table_entry *ptr = table->bins[bin_pos]; -+ FOUND_ENTRY; -+ if (PTR_NOT_EQUAL(table, ptr, hash_val, key)) { -+ COLLISION; -+ while (PTR_NOT_EQUAL(table, ptr->next, hash_val, key)) { -+ ptr = ptr->next; -+ } -+ ptr = ptr->next; -+ } -+ return ptr; -+} -+ -+static inline st_index_t -+find_packed_index(st_table *table, st_index_t hash_val, st_data_t key) -+{ -+ st_index_t i = 0; -+ while (i < table->real_entries && -+ (PHASH(table, i) != hash_val || !EQUAL(table, key, PKEY(table, i)))) { -+ i++; -+ } -+ return i; -+} -+ -+static inline int -+check_upacked(st_table *table, st_index_t hash_val, st_data_t key) -+{ -+ return table->num_entries && -+ UPHASH(table) == hash_val && -+ EQUAL(table, key, UPKEY(table)); -+} - - #define collision_check 0 - - int - st_lookup(st_table *table, register st_data_t key, st_data_t *value) - { -- st_index_t hash_val, bin_pos; -+ st_index_t hash_val; - register st_table_entry *ptr; - -+ hash_val = do_hash(key, table); -+ -+ if (ULTRAPACKED(table)) { -+ if (check_upacked(table, hash_val, key)) { -+ if (value != 0) *value = UPVAL(table); -+ return 1; -+ } -+ return 0; -+ } -+ - if (table->entries_packed) { -- st_index_t i; -- for (i = 0; i < table->num_entries; i++) { -- if ((st_data_t)table->bins[i*2] == key) { -- if (value !=0) *value = (st_data_t)table->bins[i*2+1]; -- return 1; -- } -- } -+ st_index_t i = find_packed_index(table, hash_val, key); -+ if (i < table->real_entries) { -+ if (value != 0) *value = PVAL(table, i); -+ return 1; -+ } - return 0; - } - -- hash_val = do_hash(key, table); -- FIND_ENTRY(table, ptr, hash_val, bin_pos); -+ ptr = find_entry(table, key, hash_val, hash_val % table->num_bins); - - if (ptr == 0) { - return 0; - } - else { -- if (value != 0) *value = ptr->record; -+ if (value != 0) *value = ptr->record; - return 1; - } - } -@@ -353,22 +517,29 @@ st_lookup(st_table *table, register st_data_t key, st_data_t *value) - int - st_get_key(st_table *table, register st_data_t key, st_data_t *result) - { -- st_index_t hash_val, bin_pos; -+ st_index_t hash_val; - register st_table_entry *ptr; - -+ hash_val = do_hash(key, table); -+ -+ if (ULTRAPACKED(table)) { -+ if (check_upacked(table, hash_val, key)) { -+ if (result != 0) *result = UPKEY(table); -+ return 1; -+ } -+ return 0; -+ } -+ - if (table->entries_packed) { -- st_index_t i; -- for (i = 0; i < table->num_entries; i++) { -- if ((st_data_t)table->bins[i*2] == key) { -- if (result !=0) *result = (st_data_t)table->bins[i*2]; -- return 1; -- } -- } -+ st_index_t i = find_packed_index(table, hash_val, key); -+ if (i < table->real_entries) { -+ if (result != 0) *result = PKEY(table, i); -+ return 1; -+ } - return 0; - } - -- hash_val = do_hash(key, table); -- FIND_ENTRY(table, ptr, hash_val, bin_pos); -+ ptr = find_entry(table, key, hash_val, hash_val % table->num_bins); - - if (ptr == 0) { - return 0; -@@ -382,85 +553,151 @@ st_get_key(st_table *table, register st_data_t key, st_data_t *result) - #undef collision_check - #define collision_check 1 - --#define MORE_PACKABLE_P(table) \ -- ((st_index_t)((table)->num_entries+1) * 2 <= (table)->num_bins && \ -- (table)->num_entries+1 <= MAX_PACKED_NUMHASH) -- --#define ADD_DIRECT(table, key, value, hash_val, bin_pos)\ --do {\ -- st_table_entry *entry;\ -- if ((table)->num_entries > ST_DEFAULT_MAX_DENSITY * (table)->num_bins) {\ -- rehash(table);\ -- (bin_pos) = (hash_val) % (table)->num_bins;\ -- }\ -- \ -- entry = alloc(st_table_entry);\ -- \ -- entry->hash = (hash_val);\ -- entry->key = (key);\ -- entry->record = (value);\ -- entry->next = (table)->bins[(bin_pos)];\ -- if ((table)->head != 0) {\ -- entry->fore = 0;\ -- (entry->back = (table)->tail)->fore = entry;\ -- (table)->tail = entry;\ -- }\ -- else {\ -- (table)->head = (table)->tail = entry;\ -- entry->fore = entry->back = 0;\ -- }\ -- (table)->bins[(bin_pos)] = entry;\ -- (table)->num_entries++;\ --} while (0) -+static inline st_table_entry * -+new_entry(st_table * table, st_data_t key, st_data_t value, -+ st_index_t hash_val, register st_index_t bin_pos) -+{ -+ register st_table_entry *entry = st_alloc_entry(); -+ -+ entry->next = table->bins[bin_pos]; -+ table->bins[bin_pos] = entry; -+ entry->hash = hash_val; -+ entry->key = key; -+ entry->record = value; -+ -+ return entry; -+} -+ -+static inline void -+add_direct(st_table *table, st_data_t key, st_data_t value, -+ st_index_t hash_val, register st_index_t bin_pos) -+{ -+ register st_table_entry *entry; -+ if (table->num_entries > ST_DEFAULT_MAX_DENSITY * table->num_bins) { -+ rehash(table); -+ bin_pos = hash_val % table->num_bins; -+ } -+ -+ entry = new_entry(table, key, value, hash_val, bin_pos); -+ -+ if (table->head != 0) { -+ entry->fore = 0; -+ (entry->back = table->tail)->fore = entry; -+ table->tail = entry; -+ } -+ else { -+ table->head = table->tail = entry; -+ entry->fore = entry->back = 0; -+ } -+ table->num_entries++; -+} - - static void - unpack_entries(register st_table *table) - { - st_index_t i; -- struct st_table_entry *packed_bins[MAX_PACKED_NUMHASH*2]; -+ st_packed_entry packed_bins[MAX_PACKED_HASH]; -+ register st_table_entry *entry, *preventry = 0, **chain; - st_table tmp_table = *table; - -- memcpy(packed_bins, table->bins, sizeof(struct st_table_entry *) * table->num_entries*2); -- table->bins = packed_bins; -+ MEMCPY(packed_bins, PACKED_BINS(table), st_packed_entry, MAX_PACKED_HASH); -+ table->as.packed.entries = packed_bins; - tmp_table.entries_packed = 0; -- tmp_table.num_entries = 0; -- memset(tmp_table.bins, 0, sizeof(struct st_table_entry *) * tmp_table.num_bins); -- for (i = 0; i < table->num_entries; i++) { -- st_insert(&tmp_table, (st_data_t)packed_bins[i*2], (st_data_t)packed_bins[i*2+1]); -- } -+#if ST_DEFAULT_INIT_TABLE_SIZE == ST_DEFAULT_PACKED_TABLE_SIZE -+ MEMZERO(tmp_table.bins, st_table_entry*, tmp_table.num_bins); -+#else -+ tmp_table.bins = st_realloc_bins(tmp_table.bins, ST_DEFAULT_INIT_TABLE_SIZE, tmp_table.num_bins); -+ tmp_table.num_bins = ST_DEFAULT_INIT_TABLE_SIZE; -+#endif -+ i = 0; -+ chain = &tmp_table.head; -+ do { -+ st_data_t key = packed_bins[i].key; -+ st_data_t val = packed_bins[i].val; -+ st_index_t hash = packed_bins[i].hash; -+ entry = new_entry(&tmp_table, key, val, hash, -+ hash % ST_DEFAULT_INIT_TABLE_SIZE); -+ *chain = entry; -+ entry->back = preventry; -+ preventry = entry; -+ chain = &entry->fore; -+ } while (++i < MAX_PACKED_HASH); -+ *chain = NULL; -+ tmp_table.tail = entry; - *table = tmp_table; - } - -+static void -+add_packed_direct(st_table *table, st_data_t key, st_data_t value, st_index_t hash_val) -+{ -+ if (table->real_entries < MAX_PACKED_HASH) { -+ st_index_t i = table->real_entries++; -+ PKEY_SET(table, i, key); -+ PVAL_SET(table, i, value); -+ PHASH_SET(table, i, hash_val); -+ table->num_entries++; -+ } -+ else { -+ unpack_entries(table); -+ add_direct(table, key, value, hash_val, hash_val % table->num_bins); -+ } -+} -+ -+static void -+add_upacked_direct(register st_table *table, register st_data_t key, st_data_t value, st_index_t hash_val) -+{ -+ if (table->real_upacked) { -+ st_packed_entry *entries = (st_packed_entry *) st_alloc_bins(ST_DEFAULT_PACKED_TABLE_SIZE); -+ entries[0] = UPACKED_ENT(table); -+ entries[1].hash = hash_val; -+ entries[1].key = key; -+ entries[1].val = value; -+ table->num_bins = ST_DEFAULT_PACKED_TABLE_SIZE; -+ table->real_entries = 2; -+ table->num_entries++; -+ table->as.packed.entries = entries; -+ } -+ else { -+ table->real_upacked = 1; -+ table->num_entries = 1; -+ UPHASH_SET(table, hash_val); -+ UPKEY_SET(table, key); -+ UPVAL_SET(table, value); -+ } -+} -+ - int - st_insert(register st_table *table, register st_data_t key, st_data_t value) - { -- st_index_t hash_val, bin_pos; -+ st_index_t hash_val; -+ register st_index_t bin_pos; - register st_table_entry *ptr; - -+ hash_val = do_hash(key, table); -+ -+ if (ULTRAPACKED(table)) { -+ if (check_upacked(table, hash_val, key)) { -+ UPVAL_SET(table, value); -+ return 1; -+ } -+ add_upacked_direct(table, key, value, hash_val); -+ return 0; -+ } -+ - if (table->entries_packed) { -- st_index_t i; -- for (i = 0; i < table->num_entries; i++) { -- if ((st_data_t)table->bins[i*2] == key) { -- table->bins[i*2+1] = (struct st_table_entry*)value; -- return 1; -- } -- } -- if (MORE_PACKABLE_P(table)) { -- i = table->num_entries++; -- table->bins[i*2] = (struct st_table_entry*)key; -- table->bins[i*2+1] = (struct st_table_entry*)value; -- return 0; -- } -- else { -- unpack_entries(table); -+ st_index_t i = find_packed_index(table, hash_val, key); -+ if (i < table->real_entries) { -+ PVAL_SET(table, i, value); -+ return 1; - } -+ add_packed_direct(table, key, value, hash_val); -+ return 0; - } - -- hash_val = do_hash(key, table); - FIND_ENTRY(table, ptr, hash_val, bin_pos); - - if (ptr == 0) { -- ADD_DIRECT(table, key, value, hash_val, bin_pos); -+ add_direct(table, key, value, hash_val, bin_pos); - return 0; - } - else { -@@ -473,34 +710,38 @@ int - st_insert2(register st_table *table, register st_data_t key, st_data_t value, - st_data_t (*func)(st_data_t)) - { -- st_index_t hash_val, bin_pos; -+ st_index_t hash_val; -+ register st_index_t bin_pos; - register st_table_entry *ptr; - -+ hash_val = do_hash(key, table); -+ -+ if (ULTRAPACKED(table)) { -+ if (check_upacked(table, hash_val, key)) { -+ UPVAL_SET(table, value); -+ return 1; -+ } -+ key = (*func)(key); -+ add_upacked_direct(table, key, value, hash_val); -+ return 0; -+ } -+ - if (table->entries_packed) { -- st_index_t i; -- for (i = 0; i < table->num_entries; i++) { -- if ((st_data_t)table->bins[i*2] == key) { -- table->bins[i*2+1] = (struct st_table_entry*)value; -- return 1; -- } -- } -- if (MORE_PACKABLE_P(table)) { -- i = table->num_entries++; -- table->bins[i*2] = (struct st_table_entry*)key; -- table->bins[i*2+1] = (struct st_table_entry*)value; -- return 0; -- } -- else { -- unpack_entries(table); -- } -+ st_index_t i = find_packed_index(table, hash_val, key); -+ if (i < table->real_entries) { -+ PVAL_SET(table, i, value); -+ return 1; -+ } -+ key = (*func)(key); -+ add_packed_direct(table, key, value, hash_val); -+ return 0; - } - -- hash_val = do_hash(key, table); - FIND_ENTRY(table, ptr, hash_val, bin_pos); - - if (ptr == 0) { - key = (*func)(key); -- ADD_DIRECT(table, key, value, hash_val, bin_pos); -+ add_direct(table, key, value, hash_val, bin_pos); - return 0; - } - else { -@@ -512,36 +753,30 @@ st_insert2(register st_table *table, register st_data_t key, st_data_t value, - void - st_add_direct(st_table *table, st_data_t key, st_data_t value) - { -- st_index_t hash_val, bin_pos; -+ st_index_t hash_val; -+ -+ hash_val = do_hash(key, table); -+ if (ULTRAPACKED(table)) { -+ add_upacked_direct(table, key, value, hash_val); -+ return; -+ } - - if (table->entries_packed) { -- int i; -- if (MORE_PACKABLE_P(table)) { -- i = table->num_entries++; -- table->bins[i*2] = (struct st_table_entry*)key; -- table->bins[i*2+1] = (struct st_table_entry*)value; -- return; -- } -- else { -- unpack_entries(table); -- } -+ add_packed_direct(table, key, value, hash_val); -+ return; - } - -- hash_val = do_hash(key, table); -- bin_pos = hash_val % table->num_bins; -- ADD_DIRECT(table, key, value, hash_val, bin_pos); -+ add_direct(table, key, value, hash_val, hash_val % table->num_bins); - } - - static void - rehash(register st_table *table) - { - register st_table_entry *ptr, **new_bins; -- st_index_t i, new_num_bins, hash_val; -+ st_index_t new_num_bins, hash_val; - - new_num_bins = new_size(table->num_bins+1); -- new_bins = (st_table_entry**) -- xrealloc(table->bins, new_num_bins * sizeof(st_table_entry*)); -- for (i = 0; i < new_num_bins; ++i) new_bins[i] = 0; -+ new_bins = st_realloc_bins(table->bins, new_num_bins, table->num_bins); - table->num_bins = new_num_bins; - table->bins = new_bins; - -@@ -558,34 +793,37 @@ st_table* - st_copy(st_table *old_table) - { - st_table *new_table; -- st_table_entry *ptr, *entry, *prev, **tail; -+ st_table_entry *ptr, *entry, *prev, **tailp; - st_index_t num_bins = old_table->num_bins; - st_index_t hash_val; - -- new_table = alloc(st_table); -+ new_table = st_alloc_table(); - if (new_table == 0) { - return 0; - } - - *new_table = *old_table; -- new_table->bins = (st_table_entry**) -- Calloc((unsigned)num_bins, sizeof(st_table_entry*)); -+ if (ULTRAPACKED(old_table)) { -+ return new_table; -+ } -+ -+ new_table->bins = st_alloc_bins(num_bins); - - if (new_table->bins == 0) { -- free(new_table); -+ st_dealloc_table(new_table); - return 0; - } - - if (old_table->entries_packed) { -- memcpy(new_table->bins, old_table->bins, sizeof(struct st_table_entry *) * old_table->num_bins); -+ MEMCPY(new_table->bins, old_table->bins, st_table_entry*, old_table->num_bins); - return new_table; - } - - if ((ptr = old_table->head) != 0) { - prev = 0; -- tail = &new_table->head; -+ tailp = &new_table->head; - do { -- entry = alloc(st_table_entry); -+ entry = st_alloc_entry(); - if (entry == 0) { - st_free_table(new_table); - return 0; -@@ -595,8 +833,8 @@ st_copy(st_table *old_table) - entry->next = new_table->bins[hash_val]; - new_table->bins[hash_val] = entry; - entry->back = prev; -- *tail = prev = entry; -- tail = &entry->fore; -+ *tailp = prev = entry; -+ tailp = &entry->fore; - } while ((ptr = ptr->fore) != 0); - new_table->tail = prev; - } -@@ -604,21 +842,22 @@ st_copy(st_table *old_table) - return new_table; - } - --#define REMOVE_ENTRY(table, ptr) do \ -- { \ -- if ((ptr)->fore == 0 && (ptr)->back == 0) { \ -- (table)->head = 0; \ -- (table)->tail = 0; \ -- } \ -- else { \ -- st_table_entry *fore = (ptr)->fore, *back = (ptr)->back; \ -- if (fore) fore->back = back; \ -- if (back) back->fore = fore; \ -- if ((ptr) == (table)->head) (table)->head = fore; \ -- if ((ptr) == (table)->tail) (table)->tail = back; \ -- } \ -- (table)->num_entries--; \ -- } while (0) -+static inline void -+remove_entry(st_table *table, st_table_entry *ptr) -+{ -+ if (ptr->fore == 0 && ptr->back == 0) { -+ table->head = 0; -+ table->tail = 0; -+ } -+ else { -+ st_table_entry *fore = ptr->fore, *back = ptr->back; -+ if (fore) fore->back = back; -+ if (back) back->fore = fore; -+ if (ptr == table->head) table->head = fore; -+ if (ptr == table->tail) table->tail = back; -+ } -+ table->num_entries--; -+} - - int - st_delete(register st_table *table, register st_data_t *key, st_data_t *value) -@@ -627,30 +866,38 @@ st_delete(register st_table *table, register st_data_t *key, st_data_t *value) - st_table_entry **prev; - register st_table_entry *ptr; - -+ hash_val = do_hash(*key, table); -+ -+ if (ULTRAPACKED(table)) { -+ if (check_upacked(table, hash_val, *key)) { -+ if (value != 0) *value = UPVAL(table); -+ *key = UPKEY(table); -+ remove_upacked_entry(table); -+ return 1; -+ } -+ return 0; -+ } -+ - if (table->entries_packed) { -- st_index_t i; -- for (i = 0; i < table->num_entries; i++) { -- if ((st_data_t)table->bins[i*2] == *key) { -- if (value != 0) *value = (st_data_t)table->bins[i*2+1]; -- table->num_entries--; -- memmove(&table->bins[i*2], &table->bins[(i+1)*2], -- sizeof(struct st_table_entry*) * 2*(table->num_entries-i)); -- return 1; -- } -+ st_index_t i = find_packed_index(table, hash_val, *key); -+ if (i < table->real_entries) { -+ if (value != 0) *value = PVAL(table, i); -+ *key = PKEY(table, i); -+ remove_packed_entry(table, i); -+ return 1; - } - if (value != 0) *value = 0; - return 0; - } - -- hash_val = do_hash_bin(*key, table); -- -- for (prev = &table->bins[hash_val]; (ptr = *prev) != 0; prev = &ptr->next) { -+ prev = &table->bins[hash_val % table->num_bins]; -+ for (;(ptr = *prev) != 0; prev = &ptr->next) { - if (EQUAL(table, *key, ptr->key)) { - *prev = ptr->next; -- REMOVE_ENTRY(table, ptr); -+ remove_entry(table, ptr); - if (value != 0) *value = ptr->record; - *key = ptr->key; -- free(ptr); -+ st_free_entry(ptr); - return 1; - } - } -@@ -665,25 +912,36 @@ st_delete_safe(register st_table *table, register st_data_t *key, st_data_t *val - st_index_t hash_val; - register st_table_entry *ptr; - -+ hash_val = do_hash(*key, table); -+ -+ if (ULTRAPACKED(table)) { -+ if (check_upacked(table, hash_val, *key)) { -+ if (value != 0) *value = UPVAL(table); -+ *key = UPKEY(table); -+ remove_safe_upacked_entry(table, never); -+ return 1; -+ } -+ if (value != 0) *value = 0; -+ return 0; -+ } -+ - if (table->entries_packed) { -- st_index_t i; -- for (i = 0; i < table->num_entries; i++) { -- if ((st_data_t)table->bins[i*2] == *key) { -- if (value != 0) *value = (st_data_t)table->bins[i*2+1]; -- table->bins[i*2] = (void *)never; -- return 1; -- } -+ st_index_t i = find_packed_index(table, hash_val, *key); -+ if (i < table->real_entries) { -+ if (value != 0) *value = PVAL(table, i); -+ *key = PKEY(table, i); -+ remove_safe_packed_entry(table, i, never); -+ return 1; - } - if (value != 0) *value = 0; - return 0; - } - -- hash_val = do_hash_bin(*key, table); -- ptr = table->bins[hash_val]; -+ ptr = table->bins[hash_val % table->num_bins]; - - for (; ptr != 0; ptr = ptr->next) { - if ((ptr->key != never) && EQUAL(table, ptr->key, *key)) { -- REMOVE_ENTRY(table, ptr); -+ remove_entry(table, ptr); - *key = ptr->key; - if (value != 0) *value = ptr->record; - ptr->key = ptr->record = never; -@@ -701,17 +959,23 @@ st_cleanup_safe(st_table *table, st_data_t never) - st_table_entry *ptr, **last, *tmp; - st_index_t i; - -+ if (ULTRAPACKED(table)) { -+ table->real_upacked = table->num_entries; -+ return; -+ } -+ - if (table->entries_packed) { - st_index_t i = 0, j = 0; -- while ((st_data_t)table->bins[i*2] != never) { -- if (i++ == table->num_entries) return; -+ while (PKEY(table, i) != never) { -+ if (i++ == table->real_entries) return; - } -- for (j = i; ++i < table->num_entries;) { -- if ((st_data_t)table->bins[i*2] == never) continue; -- table->bins[j*2] = table->bins[i*2]; -- table->bins[j*2+1] = table->bins[i*2+1]; -+ for (j = i; ++i < table->real_entries;) { -+ if (PKEY(table, i) == never) continue; -+ PACKED_ENT(table, j) = PACKED_ENT(table, i); - j++; - } -+ table->real_entries = j; -+ /* table->num_entries really should be equal j at this moment, but let set it anyway */ - table->num_entries = j; - return; - } -@@ -722,7 +986,7 @@ st_cleanup_safe(st_table *table, st_data_t never) - if (ptr->key == never) { - tmp = ptr; - *last = ptr = ptr->next; -- free(tmp); -+ st_free_entry(tmp); - } - else { - ptr = *(last = &ptr->next); -@@ -732,50 +996,78 @@ st_cleanup_safe(st_table *table, st_data_t never) - } - - int --st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) -+st_foreach_check(st_table *table, int (*func)(ANYARGS), st_data_t arg, st_data_t never) - { - st_table_entry *ptr, **last, *tmp; - enum st_retval retval; -- st_index_t i; -+ st_data_t key, val; -+ st_index_t hash, i = 0; -+ -+ if (table->num_entries == 0) { -+ return 0; -+ } -+ -+ if (ULTRAPACKED(table)) { -+ key = UPKEY(table); -+ val = UPVAL(table); -+ hash = UPHASH(table); -+ if (key == never) return 0; -+ retval = (*func)(key, val, arg); -+ if (!ULTRAPACKED(table)) { -+ goto packed; -+ } -+ switch(retval) { -+ case ST_CHECK: -+ if (UPHASH(table) == 0 && UPKEY(table) == never) -+ break; -+ if (check_upacked(table, hash, key)) -+ break; -+ goto deleted; -+ case ST_DELETE: -+ remove_safe_upacked_entry(table, never); -+ case ST_CONTINUE: -+ case ST_STOP: -+ break; -+ } -+ return 0; -+ } - - if (table->entries_packed) { -- for (i = 0; i < table->num_entries; i++) { -- st_index_t j; -- st_data_t key, val; -- key = (st_data_t)table->bins[i*2]; -- val = (st_data_t)table->bins[i*2+1]; -- retval = (*func)(key, val, arg); -+ for (i = 0; i < table->real_entries; i++) { -+ key = PKEY(table, i); -+ val = PVAL(table, i); -+ hash = PHASH(table, i); -+ if (key == never) continue; -+ retval = (*func)(key, val, arg); -+ packed: - if (!table->entries_packed) { -- FIND_ENTRY(table, ptr, key, i); -+ FIND_ENTRY(table, ptr, hash, i); - if (retval == ST_CHECK) { - if (!ptr) goto deleted; - goto unpacked_continue; - } - goto unpacked; - } -- switch (retval) { -+ switch (retval) { - case ST_CHECK: /* check if hash is modified during iteration */ -- for (j = 0; j < table->num_entries; j++) { -- if ((st_data_t)table->bins[j*2] == key) -- break; -- } -- if (j == table->num_entries) { -+ if (PHASH(table, i) == 0 && PKEY(table, i) == never) { -+ break; -+ } -+ i = find_packed_index(table, hash, key); -+ if (i == table->real_entries) { - goto deleted; -- } -+ } - /* fall through */ - case ST_CONTINUE: - break; - case ST_STOP: - return 0; - case ST_DELETE: -- table->num_entries--; -- memmove(&table->bins[i*2], &table->bins[(i+1)*2], -- sizeof(struct st_table_entry*) * 2*(table->num_entries-i)); -- i--; -- break; -- } -- } -- return 0; -+ remove_safe_packed_entry(table, i, never); -+ break; -+ } -+ } -+ return 0; - } - else { - ptr = table->head; -@@ -783,6 +1075,8 @@ st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) - - if (ptr != 0) { - do { -+ if (ptr->key == never) -+ goto unpacked_continue; - i = ptr->hash % table->num_bins; - retval = (*func)(ptr->key, ptr->record, arg); - unpacked: -@@ -808,10 +1102,100 @@ st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) - for (; (tmp = *last) != 0; last = &tmp->next) { - if (ptr == tmp) { - tmp = ptr->fore; -+ remove_entry(table, ptr); -+ ptr->key = ptr->record = never; -+ ptr->hash = 0; -+ ptr = tmp; -+ break; -+ } -+ } -+ } -+ } while (ptr && table->head); -+ } -+ return 0; -+} -+ -+int -+st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) -+{ -+ st_table_entry *ptr, **last, *tmp; -+ enum st_retval retval; -+ st_data_t key, val; -+ st_index_t hash, i = 0; -+ -+ if (table->num_entries == 0) { -+ return 0; -+ } -+ -+ if (ULTRAPACKED(table)) { -+ key = UPKEY(table); -+ val = UPVAL(table); -+ hash = UPHASH(table); -+ retval = (*func)(key, val, arg); -+ if (!ULTRAPACKED(table)) { -+ goto packed; -+ } -+ switch (retval) { -+ case ST_DELETE: -+ remove_upacked_entry(table); -+ case ST_CONTINUE: -+ case ST_CHECK: -+ case ST_STOP: -+ break; -+ } -+ return 0; -+ } -+ -+ if (table->entries_packed) { -+ for (i = 0; i < table->real_entries; i++) { -+ key = PKEY(table, i); -+ val = PVAL(table, i); -+ hash = PHASH(table, i); -+ retval = (*func)(key, val, arg); -+ packed: -+ if (!table->entries_packed) { -+ FIND_ENTRY(table, ptr, hash, i); -+ if (!ptr) return 0; -+ goto unpacked; -+ } -+ switch (retval) { -+ case ST_CONTINUE: -+ break; -+ case ST_CHECK: -+ case ST_STOP: -+ return 0; -+ case ST_DELETE: -+ remove_packed_entry(table, i); -+ i--; -+ break; -+ } -+ } -+ return 0; -+ } -+ else { -+ ptr = table->head; -+ } -+ -+ if (ptr != 0) { -+ do { -+ i = ptr->hash % table->num_bins; -+ retval = (*func)(ptr->key, ptr->record, arg); -+ unpacked: -+ switch (retval) { -+ case ST_CONTINUE: -+ ptr = ptr->fore; -+ break; -+ case ST_CHECK: -+ case ST_STOP: -+ return 0; -+ case ST_DELETE: -+ last = &table->bins[ptr->hash % table->num_bins]; -+ for (; (tmp = *last) != 0; last = &tmp->next) { -+ if (ptr == tmp) { -+ tmp = ptr->fore; - *last = ptr->next; -- REMOVE_ENTRY(table, ptr); -- free(ptr); -- if (ptr == tmp) return 0; -+ remove_entry(table, ptr); -+ st_free_entry(ptr); - ptr = tmp; - break; - } -@@ -834,13 +1218,13 @@ st_reverse_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) - for (i = table->num_entries-1; 0 <= i; i--) { - int j; - st_data_t key, val; -- key = (st_data_t)table->bins[i*2]; -- val = (st_data_t)table->bins[i*2+1]; -+ key = PKEY(table, i); -+ val = PVAL(table, i); - retval = (*func)(key, val, arg); - switch (retval) { - case ST_CHECK: /* check if hash is modified during iteration */ - for (j = 0; j < table->num_entries; j++) { -- if ((st_data_t)table->bins[j*2] == key) -+ if (PKEY(table, j) == key) - break; - } - if (j == table->num_entries) { -@@ -854,9 +1238,7 @@ st_reverse_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) - case ST_STOP: - return 0; - case ST_DELETE: -- table->num_entries--; -- memmove(&table->bins[i*2], &table->bins[(i+1)*2], -- sizeof(struct st_table_entry*) * 2*(table->num_entries-i)); -+ remove_packed_entry(table, i); - break; - } - } -@@ -889,8 +1271,8 @@ st_reverse_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg) - if (ptr == tmp) { - tmp = ptr->back; - *last = ptr->next; -- REMOVE_ENTRY(table, ptr); -- free(ptr); -+ remove_entry(table, ptr); -+ st_free_entry(ptr); - ptr = tmp; - break; - } diff --git a/patches/ruby/1.9.3/p392/railsexpress/11-falcon-sparse-array.patch b/patches/ruby/1.9.3/p392/railsexpress/11-falcon-sparse-array.patch deleted file mode 100644 index 011cf15952..0000000000 --- a/patches/ruby/1.9.3/p392/railsexpress/11-falcon-sparse-array.patch +++ /dev/null @@ -1,2467 +0,0 @@ -diff --git a/class.c b/class.c -index 4fbdf18..f5cb4a1 100644 ---- a/class.c -+++ b/class.c -@@ -31,7 +31,7 @@ - #include "internal.h" - #include - --extern st_table *rb_class_tbl; -+extern sa_table rb_class_tbl; - static ID id_attached; - - /** -@@ -53,11 +53,15 @@ class_alloc(VALUE flags, VALUE klass) - NEWOBJ(obj, struct RClass); - OBJSETUP(obj, klass, flags); - obj->ptr = ext; -- RCLASS_IV_TBL(obj) = 0; -- RCLASS_CONST_TBL(obj) = 0; -- RCLASS_M_TBL(obj) = 0; -- RCLASS_SUPER(obj) = 0; -- RCLASS_IV_INDEX_TBL(obj) = 0; -+ MEMZERO(ext, struct rb_classext_struct, 1); -+ return (VALUE)obj; -+} -+ -+static VALUE -+iclass_alloc() -+{ -+ NEWOBJ(obj, struct RClass); -+ OBJSETUP(obj, rb_cClass, T_ICLASS); - return (VALUE)obj; - } - -@@ -77,7 +81,6 @@ rb_class_boot(VALUE super) - VALUE klass = class_alloc(T_CLASS, rb_cClass); - - RCLASS_SUPER(klass) = super; -- RCLASS_M_TBL(klass) = st_init_numtable(); - - OBJ_INFECT(klass, super); - return (VALUE)klass; -@@ -120,43 +123,30 @@ rb_class_new(VALUE super) - return rb_class_boot(super); - } - --struct clone_method_data { -- st_table *tbl; -- VALUE klass; --}; -- - VALUE rb_iseq_clone(VALUE iseqval, VALUE newcbase); - --static int --clone_method(ID mid, const rb_method_entry_t *me, struct clone_method_data *data) -+static void -+clone_method(ID mid, const rb_method_entry_t *me, VALUE klass) - { - VALUE newiseqval; - if (me->def && me->def->type == VM_METHOD_TYPE_ISEQ) { - rb_iseq_t *iseq; -- newiseqval = rb_iseq_clone(me->def->body.iseq->self, data->klass); -+ newiseqval = rb_iseq_clone(me->def->body.iseq->self, klass); - GetISeqPtr(newiseqval, iseq); -- rb_add_method(data->klass, mid, VM_METHOD_TYPE_ISEQ, iseq, me->flag); -+ rb_add_method(klass, mid, VM_METHOD_TYPE_ISEQ, iseq, me->flag); - RB_GC_GUARD(newiseqval); - } - else { -- rb_method_entry_set(data->klass, mid, me, me->flag); -+ rb_method_entry_set(klass, mid, me, me->flag); - } -- return ST_CONTINUE; - } - --static int --clone_const(ID key, const rb_const_entry_t *ce, st_table *tbl) -+static void -+clone_const(sa_index_t key, st_data_t ce, sa_table *tbl) - { - rb_const_entry_t *nce = ALLOC(rb_const_entry_t); -- *nce = *ce; -- st_insert(tbl, key, (st_data_t)nce); -- return ST_CONTINUE; --} -- --static int --clone_const_i(st_data_t key, st_data_t value, st_data_t data) --{ -- return clone_const((ID)key, (const rb_const_entry_t *)value, (st_table *)data); -+ *nce = *(const rb_const_entry_t*)ce; -+ sa_insert(tbl, (sa_index_t)key, (st_data_t)nce); - } - - static void -@@ -177,6 +167,7 @@ class_init_copy_check(VALUE clone, VALUE orig) - VALUE - rb_mod_init_copy(VALUE clone, VALUE orig) - { -+ ID id; - if (RB_TYPE_P(clone, T_CLASS)) { - class_init_copy_check(clone, orig); - } -@@ -186,36 +177,22 @@ rb_mod_init_copy(VALUE clone, VALUE orig) - rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone); - } - RCLASS_SUPER(clone) = RCLASS_SUPER(orig); -- if (RCLASS_IV_TBL(orig)) { -- st_data_t id; - -- if (RCLASS_IV_TBL(clone)) { -- st_free_table(RCLASS_IV_TBL(clone)); -- } -- RCLASS_IV_TBL(clone) = st_copy(RCLASS_IV_TBL(orig)); -- CONST_ID(id, "__classpath__"); -- st_delete(RCLASS_IV_TBL(clone), &id, 0); -- CONST_ID(id, "__classid__"); -- st_delete(RCLASS_IV_TBL(clone), &id, 0); -- } -- if (RCLASS_CONST_TBL(orig)) { -- if (RCLASS_CONST_TBL(clone)) { -- rb_free_const_table(RCLASS_CONST_TBL(clone)); -- } -- RCLASS_CONST_TBL(clone) = st_init_numtable(); -- st_foreach(RCLASS_CONST_TBL(orig), clone_const_i, (st_data_t)RCLASS_CONST_TBL(clone)); -- } -- if (RCLASS_M_TBL(orig)) { -- struct clone_method_data data; -+ sa_copy_to(RCLASS_IV_TBL(orig), RCLASS_IV_TBL(clone)); -+ CONST_ID(id, "__classpath__"); -+ sa_delete(RCLASS_IV_TBL(clone), (sa_index_t)id, 0); -+ CONST_ID(id, "__classid__"); -+ sa_delete(RCLASS_IV_TBL(clone), (sa_index_t)id, 0); - -- if (RCLASS_M_TBL(clone)) { -- rb_free_m_table(RCLASS_M_TBL(clone)); -- } -- data.tbl = RCLASS_M_TBL(clone) = st_init_numtable(); -- data.klass = clone; -- st_foreach(RCLASS_M_TBL(orig), clone_method, -- (st_data_t)&data); -- } -+ sa_clear(RCLASS_CONST_TBL(clone)); -+ SA_FOREACH_START(RCLASS_CONST_TBL(orig)); -+ clone_const(entry->key, value, RCLASS_CONST_TBL(clone)); -+ SA_FOREACH_END(); -+ -+ rb_free_m_table(RCLASS_M_TBL(clone)); -+ SA_FOREACH_START(RCLASS_M_TBL(orig)); -+ clone_method(entry->key, (const rb_method_entry_t *)value, clone); -+ SA_FOREACH_END(); - - return clone; - } -@@ -228,7 +205,6 @@ rb_singleton_class_clone(VALUE obj) - if (!FL_TEST(klass, FL_SINGLETON)) - return klass; - else { -- struct clone_method_data data; - /* copy singleton(unnamed) class */ - VALUE clone = class_alloc((RBASIC(klass)->flags & ~(FL_MARK)), 0); - -@@ -240,18 +216,16 @@ rb_singleton_class_clone(VALUE obj) - } - - RCLASS_SUPER(clone) = RCLASS_SUPER(klass); -- if (RCLASS_IV_TBL(klass)) { -- RCLASS_IV_TBL(clone) = st_copy(RCLASS_IV_TBL(klass)); -- } -- if (RCLASS_CONST_TBL(klass)) { -- RCLASS_CONST_TBL(clone) = st_init_numtable(); -- st_foreach(RCLASS_CONST_TBL(klass), clone_const_i, (st_data_t)RCLASS_CONST_TBL(clone)); -- } -- RCLASS_M_TBL(clone) = st_init_numtable(); -- data.tbl = RCLASS_M_TBL(clone); -- data.klass = (VALUE)clone; -- st_foreach(RCLASS_M_TBL(klass), clone_method, -- (st_data_t)&data); -+ sa_copy_to(RCLASS_IV_TBL(klass), RCLASS_IV_TBL(clone)); -+ -+ SA_FOREACH_START(RCLASS_CONST_TBL(klass)); -+ clone_const(entry->key, value, RCLASS_CONST_TBL(clone)); -+ SA_FOREACH_END(); -+ -+ SA_FOREACH_START(RCLASS_M_TBL(klass)); -+ clone_method(entry->key, (const rb_method_entry_t*)value, clone); -+ SA_FOREACH_END(); -+ - rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone); - FL_SET(clone, FL_SINGLETON); - return (VALUE)clone; -@@ -266,10 +240,7 @@ void - rb_singleton_class_attached(VALUE klass, VALUE obj) - { - if (FL_TEST(klass, FL_SINGLETON)) { -- if (!RCLASS_IV_TBL(klass)) { -- RCLASS_IV_TBL(klass) = st_init_numtable(); -- } -- st_insert(RCLASS_IV_TBL(klass), id_attached, obj); -+ sa_insert(RCLASS_IV_TBL(klass), (sa_index_t)id_attached, obj); - } - } - -@@ -356,12 +327,12 @@ make_singleton_class(VALUE obj) - static VALUE - boot_defclass(const char *name, VALUE super) - { -- extern st_table *rb_class_tbl; -+ extern sa_table rb_class_tbl; - VALUE obj = rb_class_boot(super); - ID id = rb_intern(name); - - rb_name_class(obj, id); -- st_add_direct(rb_class_tbl, id, obj); -+ sa_insert(&rb_class_tbl, (sa_index_t)id, obj); - rb_const_set((rb_cObject ? rb_cObject : obj), id, obj); - return obj; - } -@@ -485,7 +456,7 @@ rb_define_class(const char *name, VALUE super) - rb_warn("no super class for `%s', Object assumed", name); - } - klass = rb_define_class_id(id, super); -- st_add_direct(rb_class_tbl, id, klass); -+ sa_insert(&rb_class_tbl, (sa_index_t)id, klass); - rb_name_class(klass, id); - rb_const_set(rb_cObject, id, klass); - rb_class_inherited(super, klass); -@@ -566,8 +537,6 @@ rb_module_new(void) - { - VALUE mdl = class_alloc(T_MODULE, rb_cModule); - -- RCLASS_M_TBL(mdl) = st_init_numtable(); -- - return (VALUE)mdl; - } - -@@ -596,7 +565,7 @@ rb_define_module(const char *name) - rb_raise(rb_eTypeError, "%s is not a module", rb_obj_classname(module)); - } - module = rb_define_module_id(id); -- st_add_direct(rb_class_tbl, id, module); -+ sa_insert(&rb_class_tbl, (sa_index_t)id, module); - rb_const_set(rb_cObject, id, module); - - return module; -@@ -631,27 +600,15 @@ rb_define_module_id_under(VALUE outer, ID id) - static VALUE - include_class_new(VALUE module, VALUE super) - { -- VALUE klass = class_alloc(T_ICLASS, rb_cClass); -+ VALUE klass; - - if (BUILTIN_TYPE(module) == T_ICLASS) { - module = RBASIC(module)->klass; - } -- if (!RCLASS_IV_TBL(module)) { -- RCLASS_IV_TBL(module) = st_init_numtable(); -- } -- if (!RCLASS_CONST_TBL(module)) { -- RCLASS_CONST_TBL(module) = st_init_numtable(); -- } -- RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module); -- RCLASS_CONST_TBL(klass) = RCLASS_CONST_TBL(module); -- RCLASS_M_TBL(klass) = RCLASS_M_TBL(module); -+ klass = iclass_alloc(); -+ RBASIC(klass)->klass = module; -+ RCLASS_EXT(klass) = RCLASS_EXT(module); - RCLASS_SUPER(klass) = super; -- if (TYPE(module) == T_ICLASS) { -- RBASIC(klass)->klass = RBASIC(module)->klass; -- } -- else { -- RBASIC(klass)->klass = module; -- } - OBJ_INFECT(klass, module); - OBJ_INFECT(klass, super); - -@@ -678,13 +635,13 @@ rb_include_module(VALUE klass, VALUE module) - while (module) { - int superclass_seen = FALSE; - -- if (RCLASS_M_TBL(klass) == RCLASS_M_TBL(module)) -+ if (RCLASS_EXT(klass) == RCLASS_EXT(module)) - rb_raise(rb_eArgError, "cyclic include detected"); - /* ignore if the module included already in superclasses */ - for (p = RCLASS_SUPER(klass); p; p = RCLASS_SUPER(p)) { - switch (BUILTIN_TYPE(p)) { - case T_ICLASS: -- if (RCLASS_M_TBL(p) == RCLASS_M_TBL(module)) { -+ if (RCLASS_EXT(p) == RCLASS_EXT(module)) { - if (!superclass_seen) { - c = p; /* move insertion point */ - } -@@ -697,7 +654,7 @@ rb_include_module(VALUE klass, VALUE module) - } - } - c = RCLASS_SUPER(c) = include_class_new(module, RCLASS_SUPER(c)); -- if (RMODULE_M_TBL(module) && RMODULE_M_TBL(module)->num_entries) -+ if (RMODULE_M_TBL(module)->num_entries) - changed = 1; - skip: - module = RCLASS_SUPER(module); -@@ -828,58 +785,58 @@ ins_methods_push(ID name, long type, VALUE ary, long visi) - } - - static int --ins_methods_i(st_data_t name, st_data_t type, st_data_t ary) -+ins_methods_i(sa_index_t name, st_data_t type, st_data_t ary) - { - return ins_methods_push((ID)name, (long)type, (VALUE)ary, -1); /* everything but private */ - } - - static int --ins_methods_prot_i(st_data_t name, st_data_t type, st_data_t ary) -+ins_methods_prot_i(sa_index_t name, st_data_t type, st_data_t ary) - { - return ins_methods_push((ID)name, (long)type, (VALUE)ary, NOEX_PROTECTED); - } - - static int --ins_methods_priv_i(st_data_t name, st_data_t type, st_data_t ary) -+ins_methods_priv_i(sa_index_t name, st_data_t type, st_data_t ary) - { - return ins_methods_push((ID)name, (long)type, (VALUE)ary, NOEX_PRIVATE); - } - - static int --ins_methods_pub_i(st_data_t name, st_data_t type, st_data_t ary) -+ins_methods_pub_i(sa_index_t name, st_data_t type, st_data_t ary) - { - return ins_methods_push((ID)name, (long)type, (VALUE)ary, NOEX_PUBLIC); - } - - static int --method_entry_i(st_data_t key, st_data_t value, st_data_t data) -+method_entry_i(sa_index_t key, st_data_t value, st_data_t data) - { - const rb_method_entry_t *me = (const rb_method_entry_t *)value; -- st_table *list = (st_table *)data; -+ sa_table *list = (sa_table *)data; - long type; - - if ((ID)key == ID_ALLOCATOR) { - return ST_CONTINUE; - } - -- if (!st_lookup(list, key, 0)) { -+ if (!sa_lookup(list, key, 0)) { - if (UNDEFINED_METHOD_ENTRY_P(me)) { - type = -1; /* none */ - } - else { - type = VISI(me->flag); - } -- st_add_direct(list, key, type); -+ sa_insert(list, key, type); - } - return ST_CONTINUE; - } - - static VALUE --class_instance_method_list(int argc, VALUE *argv, VALUE mod, int obj, int (*func) (st_data_t, st_data_t, st_data_t)) -+class_instance_method_list(int argc, VALUE *argv, VALUE mod, int obj, int (*func) (sa_index_t, st_data_t, st_data_t)) - { - VALUE ary; - int recur; -- st_table *list; -+ sa_table list = SA_EMPTY_TABLE; - - if (argc == 0) { - recur = TRUE; -@@ -890,16 +847,15 @@ class_instance_method_list(int argc, VALUE *argv, VALUE mod, int obj, int (*func - recur = RTEST(r); - } - -- list = st_init_numtable(); - for (; mod; mod = RCLASS_SUPER(mod)) { -- st_foreach(RCLASS_M_TBL(mod), method_entry_i, (st_data_t)list); -+ sa_foreach(RCLASS_M_TBL(mod), method_entry_i, (st_data_t)&list); - if (BUILTIN_TYPE(mod) == T_ICLASS) continue; - if (obj && FL_TEST(mod, FL_SINGLETON)) continue; - if (!recur) break; - } - ary = rb_ary_new(); -- st_foreach(list, func, ary); -- st_free_table(list); -+ sa_foreach(&list, func, ary); -+ sa_clear(&list); - - return ary; - } -@@ -1113,7 +1069,7 @@ VALUE - rb_obj_singleton_methods(int argc, VALUE *argv, VALUE obj) - { - VALUE recur, ary, klass; -- st_table *list; -+ sa_table list = SA_EMPTY_TABLE; - - if (argc == 0) { - recur = Qtrue; -@@ -1122,20 +1078,19 @@ rb_obj_singleton_methods(int argc, VALUE *argv, VALUE obj) - rb_scan_args(argc, argv, "01", &recur); - } - klass = CLASS_OF(obj); -- list = st_init_numtable(); - if (klass && FL_TEST(klass, FL_SINGLETON)) { -- st_foreach(RCLASS_M_TBL(klass), method_entry_i, (st_data_t)list); -+ sa_foreach(RCLASS_M_TBL(klass), method_entry_i, (st_data_t)&list); - klass = RCLASS_SUPER(klass); - } - if (RTEST(recur)) { - while (klass && (FL_TEST(klass, FL_SINGLETON) || TYPE(klass) == T_ICLASS)) { -- st_foreach(RCLASS_M_TBL(klass), method_entry_i, (st_data_t)list); -+ sa_foreach(RCLASS_M_TBL(klass), method_entry_i, (st_data_t)&list); - klass = RCLASS_SUPER(klass); - } - } - ary = rb_ary_new(); -- st_foreach(list, ins_methods_i, ary); -- st_free_table(list); -+ sa_foreach(&list, ins_methods_i, ary); -+ sa_clear(&list); - - return ary; - } -diff --git a/common.mk b/common.mk -index 1d8e442..0d767ab 100644 ---- a/common.mk -+++ b/common.mk -@@ -79,6 +79,7 @@ COMMONOBJS = array.$(OBJEXT) \ - safe.$(OBJEXT) \ - signal.$(OBJEXT) \ - sprintf.$(OBJEXT) \ -+ sp_ar.$(OBJEXT) \ - st.$(OBJEXT) \ - strftime.$(OBJEXT) \ - string.$(OBJEXT) \ -@@ -703,6 +704,7 @@ signal.$(OBJEXT): {$(VPATH)}signal.c $(RUBY_H_INCLUDES) \ - $(VM_CORE_H_INCLUDES) {$(VPATH)}debug.h - sprintf.$(OBJEXT): {$(VPATH)}sprintf.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \ - {$(VPATH)}regex.h {$(VPATH)}vsnprintf.c $(ENCODING_H_INCLUDES) -+sp_ar.$(OBJEXT): {$(VPATH)}sp_ar.c $(RUBY_H_INCLUDES) - st.$(OBJEXT): {$(VPATH)}st.c $(RUBY_H_INCLUDES) {$(VPATH)}pool_alloc.h - strftime.$(OBJEXT): {$(VPATH)}strftime.c $(RUBY_H_INCLUDES) \ - {$(VPATH)}timev.h -diff --git a/constant.h b/constant.h -index 8232910..9106847 100644 ---- a/constant.h -+++ b/constant.h -@@ -23,7 +23,7 @@ typedef struct rb_const_entry_struct { - - VALUE rb_mod_private_constant(int argc, VALUE *argv, VALUE obj); - VALUE rb_mod_public_constant(int argc, VALUE *argv, VALUE obj); --void rb_free_const_table(st_table *tbl); -+void rb_free_const_table(sa_table *tbl); - VALUE rb_public_const_get(VALUE klass, ID id); - VALUE rb_public_const_get_at(VALUE klass, ID id); - VALUE rb_public_const_get_from(VALUE klass, ID id); -diff --git a/ext/objspace/objspace.c b/ext/objspace/objspace.c -index 66e33a3..4b31f92 100644 ---- a/ext/objspace/objspace.c -+++ b/ext/objspace/objspace.c -@@ -60,20 +60,10 @@ memsize_of(VALUE obj) - break; - case T_MODULE: - case T_CLASS: -- size += st_memsize(RCLASS_M_TBL(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); -+ size += sa_memsize(RCLASS_M_TBL(obj)); -+ size += sa_memsize(RCLASS_IV_TBL(obj)); -+ size += sa_memsize(RCLASS_IV_INDEX_TBL(obj)); -+ size += sa_memsize(RCLASS_CONST_TBL(obj)); - break; - case T_STRING: - size += rb_str_memsize(obj); -diff --git a/gc.c b/gc.c -index 3110059..56f0217 100644 ---- a/gc.c -+++ b/gc.c -@@ -688,7 +688,7 @@ rb_objspace_free(rb_objspace_t *objspace) - - #define HEAP_OBJ_LIMIT (unsigned int)(HEAP_SIZE / sizeof(struct RVALUE)) - --extern st_table *rb_class_tbl; -+extern sa_table rb_class_tbl; - - int ruby_disable_gc_stress = 0; - -@@ -2358,6 +2358,15 @@ mark_tbl(rb_objspace_t *objspace, st_table *tbl) - st_foreach(tbl, mark_entry, (st_data_t)&arg); - } - -+static void -+mark_sa_tbl(rb_objspace_t *objspace, sa_table *tbl) -+{ -+ if (!tbl) return; -+ SA_FOREACH_START(tbl); -+ gc_mark(objspace, (VALUE)value); -+ SA_FOREACH_END(); -+} -+ - static int - mark_key(VALUE key, VALUE value, st_data_t data) - { -@@ -2434,74 +2443,52 @@ rb_mark_method_entry(const rb_method_entry_t *me) - mark_method_entry(&rb_objspace, me); - } - --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; -- mark_method_entry(arg->objspace, me); -- return ST_CONTINUE; --} -- - static void --mark_m_tbl(rb_objspace_t *objspace, st_table *tbl) --{ -- struct mark_tbl_arg arg; -- if (!tbl) return; -- arg.objspace = objspace; -- st_foreach(tbl, mark_method_entry_i, (st_data_t)&arg); --} -- --static int --free_method_entry_i(ID key, rb_method_entry_t *me, st_data_t data) -+mark_m_tbl(rb_objspace_t *objspace, sa_table *tbl) - { -- if (!me->mark) { -- rb_free_method_entry(me); -- } -- return ST_CONTINUE; -+ SA_FOREACH_START(tbl); -+ mark_method_entry(objspace, (const rb_method_entry_t*)value); -+ SA_FOREACH_END(); - } - - void --rb_free_m_table(st_table *tbl) -+rb_free_m_table(sa_table *tbl) - { -- st_foreach(tbl, free_method_entry_i, 0); -- st_free_table(tbl); --} -- --static int --mark_const_entry_i(ID key, const rb_const_entry_t *ce, st_data_t data) --{ -- struct mark_tbl_arg *arg = (void*)data; -- gc_mark(arg->objspace, ce->value); -- return ST_CONTINUE; -+ SA_FOREACH_START(tbl); -+ if (!((rb_method_entry_t*)value)->mark) { -+ rb_free_method_entry((rb_method_entry_t*)value); -+ } -+ SA_FOREACH_END(); -+ sa_clear(tbl); - } - - static void --mark_const_tbl(rb_objspace_t *objspace, st_table *tbl) -+mark_const_tbl(rb_objspace_t *objspace, sa_table *tbl) - { -- struct mark_tbl_arg arg; -- if (!tbl) return; -- arg.objspace = objspace; -- st_foreach(tbl, mark_const_entry_i, (st_data_t)&arg); -+ SA_FOREACH_START(tbl); -+ gc_mark(objspace, ((const rb_const_entry_t*)value)->value); -+ SA_FOREACH_END(); - } - --static int --free_const_entry_i(ID key, rb_const_entry_t *ce, st_data_t data) -+void -+rb_free_const_table(sa_table *tbl) - { -- xfree(ce); -- return ST_CONTINUE; -+ SA_FOREACH_START(tbl); -+ xfree((rb_const_entry_t*)value); -+ SA_FOREACH_END(); -+ sa_clear(tbl); - } - - void --rb_free_const_table(st_table *tbl) -+rb_mark_tbl(st_table *tbl) - { -- st_foreach(tbl, free_const_entry_i, 0); -- st_free_table(tbl); -+ mark_tbl(&rb_objspace, tbl); - } - - void --rb_mark_tbl(st_table *tbl) -+rb_mark_sa_tbl(sa_table *tbl) - { -- mark_tbl(&rb_objspace, tbl); -+ mark_sa_tbl(&rb_objspace, tbl); - } - - void -@@ -2709,7 +2696,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr) - case T_CLASS: - case T_MODULE: - mark_m_tbl(objspace, RCLASS_M_TBL(obj)); -- mark_tbl(objspace, RCLASS_IV_TBL(obj)); -+ mark_sa_tbl(objspace, RCLASS_IV_TBL(obj)); - mark_const_tbl(objspace, RCLASS_CONST_TBL(obj)); - ptr = RCLASS_SUPER(obj); - goto again; -@@ -3284,15 +3271,9 @@ obj_free(rb_objspace_t *objspace, VALUE obj) - case T_CLASS: - rb_clear_cache_by_class((VALUE)obj); - rb_free_m_table(RCLASS_M_TBL(obj)); -- 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)); -- } -+ sa_clear(RCLASS_IV_TBL(obj)); -+ rb_free_const_table(RCLASS_CONST_TBL(obj)); -+ sa_clear(RCLASS_IV_INDEX_TBL(obj)); - xfree(RANY(obj)->as.klass.ptr); - break; - case T_STRING: -@@ -3345,7 +3326,6 @@ obj_free(rb_objspace_t *objspace, VALUE obj) - break; - case T_ICLASS: - /* iClass shares table with the module */ -- xfree(RANY(obj)->as.klass.ptr); - break; - - case T_FLOAT: -@@ -3460,7 +3440,7 @@ gc_marks(rb_objspace_t *objspace) - rb_mark_end_proc(); - rb_gc_mark_global_tbl(); - -- mark_tbl(objspace, rb_class_tbl); -+ mark_sa_tbl(objspace, &rb_class_tbl); - - /* mark generic instance variables for special constants */ - rb_mark_generic_ivar_tbl(); -diff --git a/include/ruby/intern.h b/include/ruby/intern.h -index ab1cc94..53ca8b0 100644 ---- a/include/ruby/intern.h -+++ b/include/ruby/intern.h -@@ -415,6 +415,7 @@ size_t ruby_stack_length(VALUE**); - int rb_during_gc(void); - void rb_gc_mark_locations(VALUE*, VALUE*); - void rb_mark_tbl(struct st_table*); -+void rb_mark_sa_tbl(sa_table*); - void rb_mark_set(struct st_table*); - void rb_mark_hash(struct st_table*); - void rb_gc_mark_maybe(VALUE); -@@ -848,7 +849,7 @@ VALUE rb_f_trace_var(int, VALUE*); - VALUE rb_f_untrace_var(int, VALUE*); - VALUE rb_f_global_variables(void); - void rb_alias_variable(ID, ID); --struct st_table* rb_generic_ivar_table(VALUE); -+sa_table* rb_generic_ivar_table(VALUE); - void rb_copy_generic_ivar(VALUE,VALUE); - void rb_mark_generic_ivar(VALUE); - void rb_mark_generic_ivar_tbl(void); -diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h -index 2f97b33..78a2286 100644 ---- a/include/ruby/ruby.h -+++ b/include/ruby/ruby.h -@@ -605,7 +605,7 @@ struct RObject { - struct { - long numiv; - VALUE *ivptr; -- struct st_table *iv_index_tbl; /* shortcut for RCLASS_IV_INDEX_TBL(rb_obj_class(obj)) */ -+ struct sa_table *iv_index_tbl; /* shortcut for RCLASS_IV_INDEX_TBL(rb_obj_class(obj)) */ - } heap; - VALUE ary[ROBJECT_EMBED_LEN_MAX]; - } as; -@@ -629,9 +629,8 @@ typedef struct rb_classext_struct rb_classext_t; - - struct RClass { - struct RBasic basic; -+ VALUE super; - rb_classext_t *ptr; -- struct st_table *m_tbl; -- struct st_table *iv_index_tbl; - }; - #define RCLASS_SUPER(c) rb_class_get_superclass(c) - #define RMODULE_IV_TBL(m) RCLASS_IV_TBL(m) -diff --git a/include/ruby/st.h b/include/ruby/st.h -index 119dfde..aff94fc 100644 ---- a/include/ruby/st.h -+++ b/include/ruby/st.h -@@ -151,6 +151,51 @@ st_index_t st_hash_start(st_index_t h); - #pragma GCC visibility pop - #endif - -+typedef unsigned int sa_index_t; -+#define SA_STOP ST_STOP -+#define SA_CONTINUE ST_CONTINUE -+ -+#define SA_EMPTY 0 -+ -+typedef struct sa_entry { -+ sa_index_t next; -+ sa_index_t key; -+ st_data_t value; -+} sa_entry; -+ -+typedef struct sa_table { -+ sa_index_t num_bins; -+ sa_index_t num_entries; -+ sa_index_t free_pos; -+ sa_entry *entries; -+} sa_table; -+ -+#define SA_EMPTY_TABLE {0, 0, 0, 0}; -+void sa_init_table(sa_table *, sa_index_t); -+sa_table *sa_new_table(); -+int sa_insert(sa_table *, sa_index_t, st_data_t); -+int sa_lookup(sa_table *, sa_index_t, st_data_t *); -+int sa_delete(sa_table *, sa_index_t, st_data_t *); -+void sa_clear(sa_table *); -+void sa_clear_no_free(sa_table *); -+void sa_free_table(sa_table *); -+int sa_foreach(sa_table *, int (*)(ANYARGS), st_data_t); -+size_t sa_memsize(const sa_table *); -+sa_table *sa_copy(sa_table*); -+void sa_copy_to(sa_table*, sa_table*); -+typedef int (*sa_iter_func)(sa_index_t key, st_data_t val, st_data_t arg); -+ -+#define SA_FOREACH_START_I(table, entry) do { \ -+ sa_table *T##entry = (table); \ -+ sa_index_t K##entry; \ -+ for(K##entry = 0; K##entry < T##entry->num_bins; K##entry++) { \ -+ sa_entry *entry = T##entry->entries + K##entry; \ -+ if (entry->next != SA_EMPTY) { \ -+ st_data_t value = entry->value -+#define SA_FOREACH_END() } } } while(0) -+ -+#define SA_FOREACH_START(table) SA_FOREACH_START_I(table, entry) -+ - #if defined(__cplusplus) - #if 0 - { /* satisfy cc-mode */ -diff --git a/internal.h b/internal.h -index f5af903..5927d93 100644 ---- a/internal.h -+++ b/internal.h -@@ -24,18 +24,19 @@ struct rb_deprecated_classext_struct { - }; - - struct rb_classext_struct { -- VALUE super; -- struct st_table *iv_tbl; -- struct st_table *const_tbl; -+ sa_table m_tbl; -+ sa_table iv_tbl; -+ sa_table const_tbl; -+ sa_table iv_index_tbl; - }; - - #undef RCLASS_SUPER - #define RCLASS_EXT(c) (RCLASS(c)->ptr) --#define RCLASS_SUPER(c) (RCLASS_EXT(c)->super) --#define RCLASS_IV_TBL(c) (RCLASS_EXT(c)->iv_tbl) --#define RCLASS_CONST_TBL(c) (RCLASS_EXT(c)->const_tbl) --#define RCLASS_M_TBL(c) (RCLASS(c)->m_tbl) --#define RCLASS_IV_INDEX_TBL(c) (RCLASS(c)->iv_index_tbl) -+#define RCLASS_SUPER(c) (RCLASS(c)->super) -+#define RCLASS_IV_TBL(c) (&RCLASS_EXT(c)->iv_tbl) -+#define RCLASS_CONST_TBL(c) (&RCLASS_EXT(c)->const_tbl) -+#define RCLASS_M_TBL(c) (&RCLASS_EXT(c)->m_tbl) -+#define RCLASS_IV_INDEX_TBL(c) (&RCLASS_EXT(c)->iv_index_tbl) - - struct vtm; /* defined by timev.h */ - -diff --git a/marshal.c b/marshal.c -index 6ae3a55..48d9d9b 100644 ---- a/marshal.c -+++ b/marshal.c -@@ -506,7 +506,7 @@ w_uclass(VALUE obj, VALUE super, struct dump_arg *arg) - } - - static int --w_obj_each(ID id, VALUE value, struct dump_call_arg *arg) -+w_obj_each(sa_index_t id, VALUE value, struct dump_call_arg *arg) - { - if (id == rb_id_encoding()) return ST_CONTINUE; - if (id == rb_intern("E")) return ST_CONTINUE; -@@ -553,13 +553,13 @@ w_encoding(VALUE obj, long num, struct dump_call_arg *arg) - } - - static void --w_ivar(VALUE obj, st_table *tbl, struct dump_call_arg *arg) -+w_ivar(VALUE obj, sa_table *tbl, struct dump_call_arg *arg) - { - long num = tbl ? tbl->num_entries : 0; - - w_encoding(obj, num, arg); - if (tbl) { -- st_foreach_safe(tbl, w_obj_each, (st_data_t)arg); -+ sa_foreach(tbl, w_obj_each, (st_data_t)arg); - } - } - -@@ -586,7 +586,7 @@ static void - w_object(VALUE obj, struct dump_arg *arg, int limit) - { - struct dump_call_arg c_arg; -- st_table *ivtbl = 0; -+ sa_table *ivtbl = 0; - st_data_t num; - int hasiv = 0; - #define has_ivars(obj, ivtbl) (((ivtbl) = rb_generic_ivar_table(obj)) != 0 || \ -@@ -651,7 +651,7 @@ w_object(VALUE obj, struct dump_arg *arg, int limit) - } - if (rb_respond_to(obj, s_dump)) { - VALUE v; -- st_table *ivtbl2 = 0; -+ sa_table *ivtbl2 = 0; - int hasiv2; - - v = rb_funcall(obj, s_dump, 1, INT2NUM(limit)); -diff --git a/method.h b/method.h -index 9229896..2fecd57 100644 ---- a/method.h -+++ b/method.h -@@ -100,6 +100,6 @@ int rb_method_entry_eq(const rb_method_entry_t *m1, const rb_method_entry_t *m2) - void rb_mark_method_entry(const rb_method_entry_t *me); - void rb_free_method_entry(rb_method_entry_t *me); - void rb_sweep_method_entry(void *vm); --void rb_free_m_table(st_table *tbl); -+void rb_free_m_table(sa_table *tbl); - - #endif /* METHOD_H */ -diff --git a/object.c b/object.c -index 59611fd..4522d08 100644 ---- a/object.c -+++ b/object.c -@@ -236,17 +236,8 @@ init_copy(VALUE dest, VALUE obj) - break; - case T_CLASS: - case T_MODULE: -- if (RCLASS_IV_TBL(dest)) { -- st_free_table(RCLASS_IV_TBL(dest)); -- RCLASS_IV_TBL(dest) = 0; -- } -- if (RCLASS_CONST_TBL(dest)) { -- rb_free_const_table(RCLASS_CONST_TBL(dest)); -- RCLASS_CONST_TBL(dest) = 0; -- } -- if (RCLASS_IV_TBL(obj)) { -- RCLASS_IV_TBL(dest) = st_copy(RCLASS_IV_TBL(obj)); -- } -+ rb_free_const_table(RCLASS_CONST_TBL(dest)); -+ sa_copy_to(RCLASS_IV_TBL(obj), RCLASS_IV_TBL(dest)); - break; - } - } -@@ -537,7 +528,7 @@ rb_obj_is_kind_of(VALUE obj, VALUE c) - } - - while (cl) { -- if (cl == c || RCLASS_M_TBL(cl) == RCLASS_M_TBL(c)) -+ if (cl == c || RCLASS_EXT(cl) == RCLASS_EXT(c)) - return Qtrue; - cl = RCLASS_SUPER(cl); - } -@@ -1362,13 +1353,13 @@ rb_class_inherited_p(VALUE mod, VALUE arg) - rb_raise(rb_eTypeError, "compared with non class/module"); - } - while (mod) { -- if (RCLASS_M_TBL(mod) == RCLASS_M_TBL(arg)) -+ if (RCLASS_EXT(mod) == RCLASS_EXT(arg)) - return Qtrue; - mod = RCLASS_SUPER(mod); - } - /* not mod < arg; check if mod > arg */ - while (arg) { -- if (RCLASS_M_TBL(arg) == RCLASS_M_TBL(start)) -+ if (RCLASS_EXT(arg) == RCLASS_EXT(start)) - return Qfalse; - arg = RCLASS_SUPER(arg); - } -diff --git a/sp_ar.c b/sp_ar.c -new file mode 100644 -index 0000000..2ed69bf ---- /dev/null -+++ b/sp_ar.c -@@ -0,0 +1,374 @@ -+/* -+ * sparse array lib -+ * inspired by Lua table -+ * written by Sokolov Yura aka funny_falcon -+ */ -+#ifdef NOT_RUBY -+#include "regint.h" -+#include "st.h" -+#else -+#include "ruby/ruby.h" -+#endif -+ -+#include -+#ifdef HAVE_STDLIB_H -+#include -+#endif -+#include -+ -+#ifdef RUBY -+#define malloc xmalloc -+#define calloc xcalloc -+#define realloc xrealloc -+#define free xfree -+#endif -+ -+#define sa_table_alloc() (sa_table*)malloc(sizeof(sa_table)) -+#define sa_table_xalloc() (sa_table*)calloc(1, sizeof(sa_table)) -+#define sa_table_dealloc(table) free(table) -+#define sa_entry_alloc(n) (sa_entry*)calloc((n), sizeof(sa_entry)) -+#define sa_entry_dealloc(entries) free(entries) -+ -+#define SA_LAST 1 -+#define SA_OFFSET 2 -+ -+#define SA_MIN_SIZE 4 -+ -+void -+sa_init_table(register sa_table *table, sa_index_t num_bins) -+{ -+ if (num_bins) { -+ table->num_entries = 0; -+ table->entries = sa_entry_alloc(num_bins); -+ table->num_bins = num_bins; -+ table->free_pos = num_bins; -+ } -+ else { -+ memset(table, 0, sizeof(sa_table)); -+ } -+} -+ -+sa_table* -+sa_new_table() -+{ -+ sa_table* table = sa_table_alloc(); -+ sa_init_table(table, 0); -+ return table; -+} -+ -+static inline sa_index_t -+calc_pos(register sa_table* table, sa_index_t key) -+{ -+ /* this formula is empirical */ -+ /* it has no good avalance, but works well in our case */ -+ key ^= key >> 16; -+ key *= 0x445229; -+ return (key + (key >> 16)) % table->num_bins; -+} -+ -+static void -+fix_empty(register sa_table* table) -+{ -+ while(--table->free_pos && -+ table->entries[table->free_pos-1].next != SA_EMPTY); -+} -+ -+#define FLOOR_TO_4 ((~((sa_index_t)0)) << 2) -+static sa_index_t -+find_empty(register sa_table* table, register sa_index_t pos) -+{ -+ sa_index_t new_pos = table->free_pos-1; -+ sa_entry *entry; -+ pos &= FLOOR_TO_4; -+ entry = table->entries+pos; -+ -+ if (entry->next == SA_EMPTY) { new_pos = pos; goto check; } -+ pos++; entry++; -+ if (entry->next == SA_EMPTY) { new_pos = pos; goto check; } -+ pos++; entry++; -+ if (entry->next == SA_EMPTY) { new_pos = pos; goto check; } -+ pos++; entry++; -+ if (entry->next == SA_EMPTY) { new_pos = pos; goto check; } -+ -+check: -+ if (new_pos+1 == table->free_pos) fix_empty(table); -+ return new_pos; -+} -+ -+static void resize(register sa_table* table); -+static int insert_into_chain(register sa_table*, register sa_index_t, st_data_t, sa_index_t pos); -+static int insert_into_main(register sa_table*, sa_index_t, st_data_t, sa_index_t pos, sa_index_t prev_pos); -+ -+int -+sa_insert(register sa_table* table, register sa_index_t key, st_data_t value) -+{ -+ sa_index_t pos, main_pos; -+ register sa_entry *entry; -+ -+ if (table->num_bins == 0) { -+ sa_init_table(table, SA_MIN_SIZE); -+ } -+ -+ pos = calc_pos(table, key); -+ entry = table->entries + pos; -+ -+ if (entry->next == SA_EMPTY) { -+ entry->next = SA_LAST; -+ entry->key = key; -+ entry->value = value; -+ table->num_entries++; -+ if (pos+1 == table->free_pos) fix_empty(table); -+ return 0; -+ } -+ -+ if (entry->key == key) { -+ entry->value = value; -+ return 1; -+ } -+ -+ if (table->num_entries + (table->num_entries >> 2) > table->num_bins) { -+ resize(table); -+ return sa_insert(table, key, value); -+ } -+ -+ main_pos = calc_pos(table, entry->key); -+ if (main_pos == pos) { -+ return insert_into_chain(table, key, value, pos); -+ } -+ else { -+ if (!table->free_pos) { -+ resize(table); -+ return sa_insert(table, key, value); -+ } -+ return insert_into_main(table, key, value, pos, main_pos); -+ } -+} -+ -+static int -+insert_into_chain(register sa_table* table, register sa_index_t key, st_data_t value, sa_index_t pos) -+{ -+ sa_entry *entry = table->entries + pos, *new_entry; -+ sa_index_t new_pos; -+ -+ while (entry->next != SA_LAST) { -+ pos = entry->next - SA_OFFSET; -+ entry = table->entries + pos; -+ if (entry->key == key) { -+ entry->value = value; -+ return 1; -+ } -+ } -+ -+ if (!table->free_pos) { -+ resize(table); -+ return sa_insert(table, key, value); -+ } -+ -+ new_pos = find_empty(table, pos); -+ new_entry = table->entries + new_pos; -+ entry->next = new_pos + SA_OFFSET; -+ -+ new_entry->next = SA_LAST; -+ new_entry->key = key; -+ new_entry->value = value; -+ table->num_entries++; -+ return 0; -+} -+ -+static int -+insert_into_main(register sa_table* table, sa_index_t key, st_data_t value, sa_index_t pos, sa_index_t prev_pos) -+{ -+ sa_entry *entry = table->entries + pos; -+ sa_index_t new_pos = find_empty(table, pos); -+ sa_entry *new_entry = table->entries + new_pos; -+ sa_index_t npos; -+ -+ *new_entry = *entry; -+ -+ while((npos = table->entries[prev_pos].next - SA_OFFSET) != pos) { -+ prev_pos = npos; -+ } -+ table->entries[prev_pos].next = new_pos + SA_OFFSET; -+ -+ entry->next = SA_LAST; -+ entry->key = key; -+ entry->value = value; -+ table->num_entries++; -+ return 0; -+} -+ -+static sa_index_t -+new_size(sa_index_t num_entries) -+{ -+ sa_index_t msb = num_entries; -+ msb |= msb >> 1; -+ msb |= msb >> 2; -+ msb |= msb >> 4; -+ msb |= msb >> 8; -+ msb |= msb >> 16; -+ msb = ((msb >> 4) + 1) << 3; -+ return (num_entries & (msb | (msb >> 1))) + (msb >> 1); -+} -+ -+static void -+resize(register sa_table *table) -+{ -+ sa_table tmp_table; -+ sa_entry *entry; -+ sa_index_t i; -+ -+ if (table->num_entries == 0) { -+ sa_entry_dealloc(table->entries); -+ memset(table, 0, sizeof(sa_table)); -+ return; -+ } -+ -+ sa_init_table(&tmp_table, new_size(table->num_entries + (table->num_entries >> 2))); -+ entry = table->entries; -+ -+ for(i = 0; i < table->num_bins; i++, entry++) { -+ if (entry->next != SA_EMPTY) { -+ sa_insert(&tmp_table, entry->key, entry->value); -+ } -+ } -+ sa_entry_dealloc(table->entries); -+ *table = tmp_table; -+} -+ -+int -+sa_lookup(register sa_table *table, register sa_index_t key, st_data_t *value) -+{ -+ register sa_entry *entry; -+ -+ if (table->num_entries == 0) return 0; -+ -+ entry = table->entries + calc_pos(table, key); -+ if (entry->next == SA_EMPTY) return 0; -+ -+ if (entry->key == key) goto found; -+ if (entry->next == SA_LAST) return 0; -+ -+ entry = table->entries + (entry->next - SA_OFFSET); -+ if (entry->key == key) goto found; -+ -+ while(entry->next != SA_LAST) { -+ entry = table->entries + (entry->next - SA_OFFSET); -+ if (entry->key == key) goto found; -+ } -+ return 0; -+found: -+ if (value) *value = entry->value; -+ return 1; -+} -+ -+void -+sa_clear(sa_table *table) -+{ -+ sa_entry_dealloc(table->entries); -+ memset(table, 0, sizeof(sa_table)); -+} -+ -+void -+sa_clear_no_free(sa_table *table) -+{ -+ memset(table->entries, 0, sizeof(sa_entry) * table->num_bins); -+ table->num_entries = 0; -+ table->free_pos = table->num_bins; -+} -+ -+void -+sa_free_table(sa_table *table) -+{ -+ sa_entry_dealloc(table->entries); -+ sa_table_dealloc(table); -+} -+ -+int -+sa_delete(sa_table *table, sa_index_t key, st_data_t *value) -+{ -+ sa_index_t pos, prev_pos = ~0; -+ sa_entry *entry; -+ -+ if (table->num_entries == 0) goto not_found; -+ -+ pos = calc_pos(table, key); -+ entry = table->entries + pos; -+ -+ if (entry->next == SA_EMPTY) goto not_found; -+ -+ do { -+ if (entry->key == key) { -+ if (value) *value = entry->value; -+ if (entry->next != SA_LAST) { -+ sa_index_t npos = entry->next - SA_OFFSET; -+ *entry = table->entries[npos]; -+ memset(table->entries + npos, 0, sizeof(sa_entry)); -+ } -+ else { -+ memset(table->entries + pos, 0, sizeof(sa_entry)); -+ if (~prev_pos) { -+ table->entries[prev_pos].next = SA_LAST; -+ } -+ } -+ table->num_entries--; -+ if (table->num_entries < table->num_bins / 4) { -+ resize(table); -+ } -+ return 1; -+ } -+ if (entry->next == SA_LAST) break; -+ prev_pos = pos; -+ pos = entry->next - SA_OFFSET; -+ entry = table->entries + pos; -+ } while(1); -+ -+not_found: -+ if (value) *value = 0; -+ return 0; -+} -+ -+int -+sa_foreach(register sa_table *table, int (*func)(), st_data_t arg) -+{ -+ sa_index_t i; -+ if (table->num_bins == 0) { -+ return 0; -+ } -+ for(i = 0; i < table->num_bins ; i++) { -+ if (table->entries[i].next != SA_EMPTY) { -+ sa_index_t key = table->entries[i].key; -+ st_data_t val = table->entries[i].value; -+ if ((*func)(key, val, arg) == SA_STOP) break; -+ } -+ } -+ return 0; -+} -+ -+size_t -+sa_memsize(const sa_table *table) -+{ -+ return sizeof(sa_table) + table->num_bins * sizeof(sa_entry); -+} -+ -+sa_table* -+sa_copy(sa_table *table) -+{ -+ sa_table *new_table = sa_table_alloc(); -+ *new_table = *table; -+ if (table->num_bins) { -+ new_table->entries = sa_entry_alloc(table->num_bins); -+ memcpy(new_table->entries, table->entries, table->num_bins*sizeof(sa_entry)); -+ } -+ return new_table; -+} -+ -+void -+sa_copy_to(sa_table *from, sa_table *to) -+{ -+ sa_entry_dealloc(to->entries); -+ *to = *from; -+ if (to->num_bins) { -+ to->entries = sa_entry_alloc(to->num_bins); -+ memcpy(to->entries, from->entries, from->num_bins*sizeof(sa_entry)); -+ } -+} -diff --git a/test/ruby/test_marshal.rb b/test/ruby/test_marshal.rb -index 0f3f794..5c2e502 100644 ---- a/test/ruby/test_marshal.rb -+++ b/test/ruby/test_marshal.rb -@@ -312,7 +312,7 @@ class TestMarshal < Test::Unit::TestCase - assert_equal(a.instance_variable_get(i), b.instance_variable_get(i), bug1932) - end - end -- a.__send__(a.methods(true).grep(/=\z/)[0], a) -+ a.__send__(a.methods(true).grep(/r.*=\z/)[0], a) - assert_nothing_raised(bug1932) do - b = Marshal.load(Marshal.dump(a)) - assert_equal(ClassISO8859_1, b.class, bug1932) -diff --git a/test/ruby/test_method.rb b/test/ruby/test_method.rb -index ea6c5f2..6ccd37c 100644 ---- a/test/ruby/test_method.rb -+++ b/test/ruby/test_method.rb -@@ -406,7 +406,7 @@ class TestMethod < Test::Unit::TestCase - obj = a.new - assert_equal([:a], obj.public_methods(false), bug) - obj.extend(m) -- assert_equal([:m1, :a], obj.public_methods(false), bug) -+ assert_equal([:a, :m1], obj.public_methods(false).sort, bug) - end - - def test_visibility -diff --git a/test/ruby/test_module.rb b/test/ruby/test_module.rb -index 6176f48..a67d845 100644 ---- a/test/ruby/test_module.rb -+++ b/test/ruby/test_module.rb -@@ -870,7 +870,7 @@ class TestModule < Test::Unit::TestCase - (class << self ; self ; end).class_eval do - define_method :method_added do |sym| - memo << sym -- memo << mod.instance_methods(false) -+ memo << mod.instance_methods(false).sort - memo << (mod.instance_method(sym) rescue nil) - end - end -@@ -887,10 +887,10 @@ class TestModule < Test::Unit::TestCase - assert_equal [:f, :g], memo.shift - assert_equal mod.instance_method(:f), memo.shift - assert_equal :a, memo.shift -- assert_equal [:f, :g, :a], memo.shift -+ assert_equal [:a, :f, :g], memo.shift - assert_equal mod.instance_method(:a), memo.shift - assert_equal :a=, memo.shift -- assert_equal [:f, :g, :a, :a=], memo.shift -+ assert_equal [:a, :a=, :f, :g], memo.shift - assert_equal mod.instance_method(:a=), memo.shift - end - -diff --git a/time.c b/time.c -index 755812f..83edc83 100644 ---- a/time.c -+++ b/time.c -@@ -4712,16 +4712,14 @@ time_mload(VALUE time, VALUE str) - long nsec; - VALUE submicro, nano_num, nano_den, offset; - wideval_t timew; -- st_data_t data; - - time_modify(time); - - #define get_attr(attr, iffound) \ - attr = rb_attr_get(str, id_##attr); \ - if (!NIL_P(attr)) { \ -- data = id_##attr; \ - iffound; \ -- st_delete(rb_generic_ivar_table(str), &data, 0); \ -+ sa_delete(rb_generic_ivar_table(str), (sa_index_t)id_##attr, 0); \ - } - - get_attr(nano_num, {}); -diff --git a/variable.c b/variable.c -index 3da500e..4a61453 100644 ---- a/variable.c -+++ b/variable.c -@@ -19,15 +19,15 @@ - #include "constant.h" - #include "internal.h" - --st_table *rb_global_tbl; --st_table *rb_class_tbl; -+sa_table rb_global_tbl; -+sa_table rb_class_tbl; - static ID autoload, classpath, tmp_classpath, classid; - - void - Init_var_tables(void) - { -- rb_global_tbl = st_init_numtable(); -- rb_class_tbl = st_init_numtable(); -+ sa_init_table(&rb_global_tbl, 0); -+ sa_init_table(&rb_class_tbl, 0); - CONST_ID(autoload, "__autoload__"); - CONST_ID(classpath, "__classpath__"); - CONST_ID(tmp_classpath, "__tmp_classpath__"); -@@ -43,7 +43,7 @@ struct fc_result { - }; - - static VALUE --fc_path(struct fc_result *fc, ID name) -+fc_path(struct fc_result *fc, sa_index_t name) - { - VALUE path, tmp; - -@@ -51,8 +51,7 @@ fc_path(struct fc_result *fc, ID name) - while (fc) { - st_data_t n; - if (fc->track == rb_cObject) break; -- if (RCLASS_IV_TBL(fc->track) && -- st_lookup(RCLASS_IV_TBL(fc->track), (st_data_t)classpath, &n)) { -+ if (sa_lookup(RCLASS_IV_TBL(fc->track), (sa_index_t)classpath, &n)) { - tmp = rb_str_dup((VALUE)n); - rb_str_cat2(tmp, "::"); - rb_str_append(tmp, path); -@@ -70,7 +69,7 @@ fc_path(struct fc_result *fc, ID name) - } - - static int --fc_i(ID key, rb_const_entry_t *ce, struct fc_result *res) -+fc_i(sa_index_t key, rb_const_entry_t *ce, struct fc_result *res) - { - VALUE value = ce->value; - if (!rb_is_const_id(key)) return ST_CONTINUE; -@@ -98,7 +97,7 @@ fc_i(ID key, rb_const_entry_t *ce, struct fc_result *res) - arg.klass = res->klass; - arg.track = value; - arg.prev = res; -- st_foreach(RCLASS_CONST_TBL(value), fc_i, (st_data_t)&arg); -+ sa_foreach(RCLASS_CONST_TBL(value), fc_i, (st_data_t)&arg); - if (arg.path) { - res->path = arg.path; - return ST_STOP; -@@ -123,18 +122,14 @@ find_class_path(VALUE klass) - arg.track = rb_cObject; - arg.prev = 0; - if (RCLASS_CONST_TBL(rb_cObject)) { -- st_foreach_safe(RCLASS_CONST_TBL(rb_cObject), fc_i, (st_data_t)&arg); -+ sa_foreach(RCLASS_CONST_TBL(rb_cObject), fc_i, (st_data_t)&arg); - } - if (arg.path == 0) { -- st_foreach_safe(rb_class_tbl, fc_i, (st_data_t)&arg); -+ sa_foreach(&rb_class_tbl, fc_i, (st_data_t)&arg); - } - if (arg.path) { -- st_data_t tmp = tmp_classpath; -- if (!RCLASS_IV_TBL(klass)) { -- RCLASS_IV_TBL(klass) = st_init_numtable(); -- } -- st_insert(RCLASS_IV_TBL(klass), (st_data_t)classpath, arg.path); -- st_delete(RCLASS_IV_TBL(klass), &tmp, 0); -+ sa_insert(RCLASS_IV_TBL(klass), (sa_index_t)classpath, arg.path); -+ sa_delete(RCLASS_IV_TBL(klass), (sa_index_t)tmp_classpath, 0); - return arg.path; - } - return Qnil; -@@ -147,16 +142,15 @@ classname(VALUE klass) - st_data_t n; - - if (!klass) klass = rb_cObject; -- if (RCLASS_IV_TBL(klass)) { -- if (!st_lookup(RCLASS_IV_TBL(klass), (st_data_t)classpath, &n)) { -- if (!st_lookup(RCLASS_IV_TBL(klass), (st_data_t)classid, &n)) { -+ if (RCLASS_IV_TBL(klass)->num_entries) { -+ if (!sa_lookup(RCLASS_IV_TBL(klass), (sa_index_t)classpath, &n)) { -+ if (!sa_lookup(RCLASS_IV_TBL(klass), (sa_index_t)classid, &n)) { - return find_class_path(klass); - } - path = rb_str_dup(rb_id2str(SYM2ID((VALUE)n))); - OBJ_FREEZE(path); -- st_insert(RCLASS_IV_TBL(klass), (st_data_t)classpath, (st_data_t)path); -- n = classid; -- st_delete(RCLASS_IV_TBL(klass), &n, 0); -+ sa_insert(RCLASS_IV_TBL(klass), (sa_index_t)classpath, (st_data_t)path); -+ sa_delete(RCLASS_IV_TBL(klass), (sa_index_t)classid, 0); - } - else { - path = (VALUE)n; -@@ -192,8 +186,7 @@ rb_class_path(VALUE klass) - st_data_t n = (st_data_t)path; - - if (!NIL_P(path)) return path; -- if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass), -- (st_data_t)tmp_classpath, &n)) { -+ if (sa_lookup(RCLASS_IV_TBL(klass), (sa_index_t)tmp_classpath, &n)) { - return (VALUE)n; - } - else { -@@ -364,7 +357,7 @@ rb_global_entry(ID id) - struct global_entry *entry; - st_data_t data; - -- if (!st_lookup(rb_global_tbl, (st_data_t)id, &data)) { -+ if (!sa_lookup(&rb_global_tbl, (sa_index_t)id, &data)) { - struct global_variable *var; - entry = ALLOC(struct global_entry); - var = ALLOC(struct global_variable); -@@ -378,7 +371,7 @@ rb_global_entry(ID id) - - var->block_trace = 0; - var->trace = 0; -- st_add_direct(rb_global_tbl, id, (st_data_t)entry); -+ sa_insert(&rb_global_tbl, (sa_index_t)id, (st_data_t)entry); - } - else { - entry = (struct global_entry *)data; -@@ -454,8 +447,8 @@ readonly_setter(VALUE val, ID id, void *data, struct global_variable *gvar) - rb_name_error(id, "%s is a read-only variable", rb_id2name(id)); - } - --static int --mark_global_entry(ID key, struct global_entry *entry) -+static void -+mark_global_entry(struct global_entry *entry) - { - struct trace_var *trace; - struct global_variable *var = entry->var; -@@ -466,14 +459,14 @@ mark_global_entry(ID key, struct global_entry *entry) - if (trace->data) rb_gc_mark_maybe(trace->data); - trace = trace->next; - } -- return ST_CONTINUE; - } - - void - rb_gc_mark_global_tbl(void) - { -- if (rb_global_tbl) -- st_foreach_safe(rb_global_tbl, mark_global_entry, 0); -+ SA_FOREACH_START(&rb_global_tbl); -+ mark_global_entry((struct global_entry*) value); -+ SA_FOREACH_END(); - } - - static ID -@@ -635,7 +628,7 @@ rb_f_untrace_var(int argc, VALUE *argv) - rb_secure(4); - rb_scan_args(argc, argv, "11", &var, &cmd); - id = rb_to_id(var); -- if (!st_lookup(rb_global_tbl, (st_data_t)id, &data)) { -+ if (!sa_lookup(&rb_global_tbl, (sa_index_t)id, &data)) { - rb_name_error(id, "undefined global variable %s", rb_id2name(id)); - } - -@@ -742,13 +735,6 @@ rb_gvar_defined(struct global_entry *entry) - return Qtrue; - } - --static int --gvar_i(ID key, struct global_entry *entry, VALUE ary) --{ -- rb_ary_push(ary, ID2SYM(key)); -- return ST_CONTINUE; --} -- - /* - * call-seq: - * global_variables -> array -@@ -765,7 +751,9 @@ rb_f_global_variables(void) - char buf[2]; - int i; - -- st_foreach_safe(rb_global_tbl, gvar_i, ary); -+ SA_FOREACH_START(&rb_global_tbl); -+ rb_ary_push(ary, ID2SYM(entry->key)); -+ SA_FOREACH_END(); - buf[0] = '$'; - for (i = 1; i <= 9; ++i) { - buf[1] = (char)(i + '0'); -@@ -784,10 +772,10 @@ rb_alias_variable(ID name1, ID name2) - rb_raise(rb_eSecurityError, "Insecure: can't alias global variable"); - - entry2 = rb_global_entry(name2); -- if (!st_lookup(rb_global_tbl, (st_data_t)name1, &data1)) { -+ if (!sa_lookup(&rb_global_tbl, (sa_index_t)name1, &data1)) { - entry1 = ALLOC(struct global_entry); - entry1->id = name1; -- st_add_direct(rb_global_tbl, name1, (st_data_t)entry1); -+ sa_insert(&rb_global_tbl, (sa_index_t)name1, (st_data_t)entry1); - } - else if ((entry1 = (struct global_entry *)data1)->var != entry2->var) { - struct global_variable *var = entry1->var; -@@ -815,7 +803,7 @@ rb_alias_variable(ID name1, ID name2) - static int special_generic_ivar = 0; - static st_table *generic_iv_tbl; - --st_table* -+sa_table* - rb_generic_ivar_table(VALUE obj) - { - st_data_t tbl; -@@ -823,7 +811,7 @@ rb_generic_ivar_table(VALUE obj) - if (!FL_TEST(obj, FL_EXIVAR)) return 0; - if (!generic_iv_tbl) return 0; - if (!st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) return 0; -- return (st_table *)tbl; -+ return (sa_table *)tbl; - } - - static VALUE -@@ -833,7 +821,7 @@ generic_ivar_get(VALUE obj, ID id, int warn) - - if (generic_iv_tbl) { - if (st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) { -- if (st_lookup((st_table *)tbl, (st_data_t)id, &val)) { -+ if (sa_lookup((sa_table *)tbl, (sa_index_t)id, &val)) { - return (VALUE)val; - } - } -@@ -847,7 +835,6 @@ generic_ivar_get(VALUE obj, ID id, int warn) - static void - generic_ivar_set(VALUE obj, ID id, VALUE val) - { -- st_table *tbl; - st_data_t data; - - if (rb_special_const_p(obj)) { -@@ -859,24 +846,22 @@ generic_ivar_set(VALUE obj, ID id, VALUE val) - } - if (!st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) { - FL_SET(obj, FL_EXIVAR); -- tbl = st_init_numtable(); -- st_add_direct(generic_iv_tbl, (st_data_t)obj, (st_data_t)tbl); -- st_add_direct(tbl, (st_data_t)id, (st_data_t)val); -- return; -+ data = (st_data_t)sa_new_table(); -+ st_add_direct(generic_iv_tbl, (st_data_t)obj, data); - } -- st_insert((st_table *)data, (st_data_t)id, (st_data_t)val); -+ sa_insert((sa_table *)data, (sa_index_t)id, (st_data_t)val); - } - - static VALUE - generic_ivar_defined(VALUE obj, ID id) - { -- st_table *tbl; -+ sa_table *tbl; - st_data_t data; - - if (!generic_iv_tbl) return Qfalse; - if (!st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) return Qfalse; -- tbl = (st_table *)data; -- if (st_lookup(tbl, (st_data_t)id, &data)) { -+ tbl = (sa_table *)data; -+ if (sa_lookup(tbl, (sa_index_t)id, &data)) { - return Qtrue; - } - return Qfalse; -@@ -885,18 +870,18 @@ generic_ivar_defined(VALUE obj, ID id) - static int - generic_ivar_remove(VALUE obj, ID id, st_data_t *valp) - { -- st_table *tbl; -+ sa_table *tbl; - st_data_t data, key = (st_data_t)id; - int status; - - if (!generic_iv_tbl) return 0; - if (!st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) return 0; -- tbl = (st_table *)data; -- status = st_delete(tbl, &key, valp); -+ tbl = (sa_table *)data; -+ status = sa_delete(tbl, (sa_index_t)id, valp); - if (tbl->num_entries == 0) { - key = (st_data_t)obj; - st_delete(generic_iv_tbl, &key, &data); -- st_free_table((st_table *)data); -+ sa_free_table(tbl); - } - return status; - } -@@ -908,22 +893,17 @@ rb_mark_generic_ivar(VALUE obj) - - if (!generic_iv_tbl) return; - if (st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) { -- rb_mark_tbl((st_table *)tbl); -+ rb_mark_sa_tbl((sa_table *)tbl); - } - } - - static int --givar_mark_i(ID key, VALUE value) --{ -- rb_gc_mark(value); -- return ST_CONTINUE; --} -- --static int --givar_i(VALUE obj, st_table *tbl) -+givar_i(VALUE obj, sa_table *tbl) - { - if (rb_special_const_p(obj)) { -- st_foreach_safe(tbl, givar_mark_i, 0); -+ SA_FOREACH_START(tbl); -+ rb_gc_mark((VALUE)value); -+ SA_FOREACH_END(); - } - return ST_CONTINUE; - } -@@ -943,7 +923,7 @@ rb_free_generic_ivar(VALUE obj) - - if (!generic_iv_tbl) return; - if (st_delete(generic_iv_tbl, &key, &tbl)) -- st_free_table((st_table *)tbl); -+ sa_free_table((sa_table *)tbl); - } - - RUBY_FUNC_EXPORTED size_t -@@ -951,7 +931,7 @@ rb_generic_ivar_memsize(VALUE obj) - { - st_data_t tbl; - if (st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) -- return st_memsize((st_table *)tbl); -+ return sa_memsize((sa_table *)tbl); - return 0; - } - -@@ -970,17 +950,17 @@ rb_copy_generic_ivar(VALUE clone, VALUE obj) - return; - } - if (st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) { -- st_table *tbl = (st_table *)data; -+ sa_table *tbl = (sa_table *)data; - - if (tbl->num_entries == 0) - goto clear; - - if (st_lookup(generic_iv_tbl, (st_data_t)clone, &data)) { -- st_free_table((st_table *)data); -- st_insert(generic_iv_tbl, (st_data_t)clone, (st_data_t)st_copy(tbl)); -+ sa_free_table((sa_table *)data); -+ st_insert(generic_iv_tbl, (st_data_t)clone, (st_data_t)sa_copy(tbl)); - } - else { -- st_add_direct(generic_iv_tbl, (st_data_t)clone, (st_data_t)st_copy(tbl)); -+ st_add_direct(generic_iv_tbl, (st_data_t)clone, (st_data_t)sa_copy(tbl)); - FL_SET(clone, FL_EXIVAR); - } - } -@@ -990,7 +970,7 @@ static VALUE - ivar_get(VALUE obj, ID id, int warn) - { - VALUE val, *ptr; -- struct st_table *iv_index_tbl; -+ sa_table *iv_index_tbl; - long len; - st_data_t index; - -@@ -1000,7 +980,7 @@ ivar_get(VALUE obj, ID id, int warn) - ptr = ROBJECT_IVPTR(obj); - iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); - if (!iv_index_tbl) break; -- if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break; -+ if (!sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) break; - if (len <= (long)index) break; - val = ptr[index]; - if (val != Qundef) -@@ -1008,7 +988,7 @@ ivar_get(VALUE obj, ID id, int warn) - break; - case T_CLASS: - case T_MODULE: -- if (RCLASS_IV_TBL(obj) && st_lookup(RCLASS_IV_TBL(obj), (st_data_t)id, &index)) -+ if (sa_lookup(RCLASS_IV_TBL(obj), (sa_index_t)id, &index)) - return (VALUE)index; - break; - default: -@@ -1037,7 +1017,7 @@ rb_attr_get(VALUE obj, ID id) - VALUE - rb_ivar_set(VALUE obj, ID id, VALUE val) - { -- struct st_table *iv_index_tbl; -+ struct sa_table *iv_index_tbl; - st_data_t index; - long i, len; - int ivar_extended; -@@ -1051,14 +1031,11 @@ rb_ivar_set(VALUE obj, ID id, VALUE val) - if (!iv_index_tbl) { - VALUE klass = rb_obj_class(obj); - iv_index_tbl = RCLASS_IV_INDEX_TBL(klass); -- if (!iv_index_tbl) { -- iv_index_tbl = RCLASS_IV_INDEX_TBL(klass) = st_init_numtable(); -- } - } - ivar_extended = 0; -- if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) { -+ if (!sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) { - index = iv_index_tbl->num_entries; -- st_add_direct(iv_index_tbl, (st_data_t)id, index); -+ sa_insert(iv_index_tbl, (sa_index_t)id, index); - ivar_extended = 1; - } - len = ROBJECT_NUMIV(obj); -@@ -1098,8 +1075,7 @@ rb_ivar_set(VALUE obj, ID id, VALUE val) - break; - case T_CLASS: - case T_MODULE: -- if (!RCLASS_IV_TBL(obj)) RCLASS_IV_TBL(obj) = st_init_numtable(); -- st_insert(RCLASS_IV_TBL(obj), (st_data_t)id, val); -+ sa_insert(RCLASS_IV_TBL(obj), (sa_index_t)id, val); - break; - default: - generic_ivar_set(obj, id, val); -@@ -1112,13 +1088,13 @@ VALUE - rb_ivar_defined(VALUE obj, ID id) - { - VALUE val; -- struct st_table *iv_index_tbl; -+ struct sa_table *iv_index_tbl; - st_data_t index; - switch (TYPE(obj)) { - case T_OBJECT: - iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); - if (!iv_index_tbl) break; -- if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break; -+ if (!sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) break; - if (ROBJECT_NUMIV(obj) <= (long)index) break; - val = ROBJECT_IVPTR(obj)[index]; - if (val != Qundef) -@@ -1126,7 +1102,7 @@ rb_ivar_defined(VALUE obj, ID id) - break; - case T_CLASS: - case T_MODULE: -- if (RCLASS_IV_TBL(obj) && st_lookup(RCLASS_IV_TBL(obj), (st_data_t)id, 0)) -+ if (sa_lookup(RCLASS_IV_TBL(obj), (sa_index_t)id, 0)) - return Qtrue; - break; - default: -@@ -1137,40 +1113,26 @@ rb_ivar_defined(VALUE obj, ID id) - return Qfalse; - } - --struct obj_ivar_tag { -- VALUE obj; -- int (*func)(ID key, VALUE val, st_data_t arg); -- st_data_t arg; --}; -- --static int --obj_ivar_i(st_data_t key, st_data_t index, st_data_t arg) --{ -- struct obj_ivar_tag *data = (struct obj_ivar_tag *)arg; -- if ((long)index < ROBJECT_NUMIV(data->obj)) { -- VALUE val = ROBJECT_IVPTR(data->obj)[(long)index]; -- if (val != Qundef) { -- return (data->func)((ID)key, val, data->arg); -- } -- } -- return ST_CONTINUE; --} -- - static void - obj_ivar_each(VALUE obj, int (*func)(ANYARGS), st_data_t arg) - { -- st_table *tbl; -- struct obj_ivar_tag data; -+ sa_table *tbl; -+ long numiv = ROBJECT_NUMIV(obj); -+ VALUE *vars = ROBJECT_IVPTR(obj); - - tbl = ROBJECT_IV_INDEX_TBL(obj); -- if (!tbl) -+ if (!tbl || !numiv) - return; - -- data.obj = obj; -- data.func = (int (*)(ID key, VALUE val, st_data_t arg))func; -- data.arg = arg; -- -- st_foreach_safe(tbl, obj_ivar_i, (st_data_t)&data); -+ SA_FOREACH_START(tbl); -+ if ((long)value < numiv) { -+ VALUE val = vars[value]; -+ if (val != Qundef) { -+ if (((sa_iter_func)func)(entry->key, val, arg) == SA_STOP) -+ break; -+ } -+ } -+ SA_FOREACH_END(); - } - - void -@@ -1182,9 +1144,7 @@ rb_ivar_foreach(VALUE obj, int (*func)(ANYARGS), st_data_t arg) - break; - case T_CLASS: - case T_MODULE: -- if (RCLASS_IV_TBL(obj)) { -- st_foreach_safe(RCLASS_IV_TBL(obj), func, arg); -- } -+ sa_foreach(RCLASS_IV_TBL(obj), func, arg); - break; - default: - if (!generic_iv_tbl) break; -@@ -1192,7 +1152,7 @@ rb_ivar_foreach(VALUE obj, int (*func)(ANYARGS), st_data_t arg) - st_data_t tbl; - - if (st_lookup(generic_iv_tbl, (st_data_t)obj, &tbl)) { -- st_foreach_safe((st_table *)tbl, func, arg); -+ sa_foreach((sa_table *)tbl, func, arg); - } - } - break; -@@ -1202,11 +1162,11 @@ rb_ivar_foreach(VALUE obj, int (*func)(ANYARGS), st_data_t arg) - st_index_t - rb_ivar_count(VALUE obj) - { -- st_table *tbl; -+ sa_table *tbl; - switch (TYPE(obj)) { - case T_OBJECT: - if ((tbl = ROBJECT_IV_INDEX_TBL(obj)) != 0) { -- st_index_t i, count, num = tbl->num_entries; -+ sa_index_t i, count, num = tbl->num_entries; - const VALUE *const ivptr = ROBJECT_IVPTR(obj); - for (i = count = 0; i < num; ++i) { - if (ivptr[i] != Qundef) { -@@ -1228,7 +1188,7 @@ rb_ivar_count(VALUE obj) - st_data_t data; - - if (st_lookup(generic_iv_tbl, (st_data_t)obj, &data) && -- (tbl = (st_table *)data) != 0) { -+ (tbl = (sa_table *)data) != 0) { - return tbl->num_entries; - } - } -@@ -1238,7 +1198,7 @@ rb_ivar_count(VALUE obj) - } - - static int --ivar_i(ID key, VALUE val, VALUE ary) -+ivar_i(sa_index_t key, VALUE val, VALUE ary) - { - if (rb_is_instance_id(key)) { - rb_ary_push(ary, ID2SYM(key)); -@@ -1301,7 +1261,7 @@ rb_obj_remove_instance_variable(VALUE obj, VALUE name) - VALUE val = Qnil; - const ID id = rb_to_id(name); - st_data_t n, v; -- struct st_table *iv_index_tbl; -+ struct sa_table *iv_index_tbl; - st_data_t index; - - if (!OBJ_UNTRUSTED(obj) && rb_safe_level() >= 4) -@@ -1315,7 +1275,7 @@ rb_obj_remove_instance_variable(VALUE obj, VALUE name) - case T_OBJECT: - iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); - if (!iv_index_tbl) break; -- if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break; -+ if (!sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) break; - if (ROBJECT_NUMIV(obj) <= (long)index) break; - val = ROBJECT_IVPTR(obj)[index]; - if (val != Qundef) { -@@ -1326,14 +1286,14 @@ rb_obj_remove_instance_variable(VALUE obj, VALUE name) - case T_CLASS: - case T_MODULE: - n = id; -- if (RCLASS_IV_TBL(obj) && st_delete(RCLASS_IV_TBL(obj), &n, &v)) { -+ if (sa_delete(RCLASS_IV_TBL(obj), (sa_index_t)id, &v)) { - return (VALUE)v; - } - break; - default: - if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) { - v = val; -- if (generic_ivar_remove(obj, (st_data_t)id, &v)) { -+ if (generic_ivar_remove(obj, id, &v)) { - return (VALUE)v; - } - } -@@ -1410,20 +1370,20 @@ rb_mod_const_missing(VALUE klass, VALUE name) - static void - autoload_mark(void *ptr) - { -- rb_mark_tbl((st_table *)ptr); -+ rb_mark_sa_tbl((sa_table *)ptr); - } - - static void - autoload_free(void *ptr) - { -- st_free_table((st_table *)ptr); -+ sa_free_table((sa_table *)ptr); - } - - static size_t - autoload_memsize(const void *ptr) - { -- const st_table *tbl = ptr; -- return st_memsize(tbl); -+ const sa_table *tbl = ptr; -+ return sa_memsize(tbl); - } - - static const rb_data_type_t autoload_data_type = { -@@ -1432,14 +1392,14 @@ static const rb_data_type_t autoload_data_type = { - }; - - #define check_autoload_table(av) \ -- (struct st_table *)rb_check_typeddata((av), &autoload_data_type) -+ (struct sa_table *)rb_check_typeddata((av), &autoload_data_type) - - void - rb_autoload(VALUE mod, ID id, const char *file) - { - st_data_t av; - VALUE fn; -- struct st_table *tbl; -+ struct sa_table *tbl; - - if (!rb_is_const_id(id)) { - rb_raise(rb_eNameError, "autoload must be constant name: %s", rb_id2name(id)); -@@ -1448,43 +1408,41 @@ rb_autoload(VALUE mod, ID id, const char *file) - rb_raise(rb_eArgError, "empty file name"); - } - -- if ((tbl = RCLASS_CONST_TBL(mod)) && st_lookup(tbl, (st_data_t)id, &av) && ((rb_const_entry_t*)av)->value != Qundef) -+ if (sa_lookup(RCLASS_CONST_TBL(mod), (sa_index_t)id, &av) && ((rb_const_entry_t*)av)->value != Qundef) - return; - - rb_const_set(mod, id, Qundef); - tbl = RCLASS_IV_TBL(mod); -- if (tbl && st_lookup(tbl, (st_data_t)autoload, &av)) { -+ if (sa_lookup(tbl, (sa_index_t)autoload, &av)) { - tbl = check_autoload_table((VALUE)av); - } - else { -- if (!tbl) tbl = RCLASS_IV_TBL(mod) = st_init_numtable(); - av = (st_data_t)TypedData_Wrap_Struct(0, &autoload_data_type, 0); -- st_add_direct(tbl, (st_data_t)autoload, av); -- DATA_PTR(av) = tbl = st_init_numtable(); -+ sa_insert(tbl, (sa_index_t)autoload, av); -+ DATA_PTR(av) = tbl = sa_new_table(); - } - fn = rb_str_new2(file); - FL_UNSET(fn, FL_TAINT); - OBJ_FREEZE(fn); -- st_insert(tbl, (st_data_t)id, (st_data_t)rb_node_newnode(NODE_MEMO, fn, rb_safe_level(), 0)); -+ sa_insert(tbl, (sa_index_t)id, (st_data_t)rb_node_newnode(NODE_MEMO, fn, rb_safe_level(), 0)); - } - - static NODE* - autoload_delete(VALUE mod, ID id) - { -- st_data_t val, load = 0, n = id; -+ st_data_t val, load = 0; - rb_const_entry_t *ce; - -- st_delete(RCLASS_CONST_TBL(mod), &n, &val); -+ sa_delete(RCLASS_CONST_TBL(mod), (sa_index_t)id, &val); - ce = (rb_const_entry_t*)val; - if (ce) xfree(ce); -- if (st_lookup(RCLASS_IV_TBL(mod), (st_data_t)autoload, &val)) { -- struct st_table *tbl = check_autoload_table((VALUE)val); -+ if (sa_lookup(RCLASS_IV_TBL(mod), (sa_index_t)autoload, &val)) { -+ struct sa_table *tbl = check_autoload_table((VALUE)val); - -- st_delete(tbl, &n, &load); -+ sa_delete(tbl, (sa_index_t)id, &load); - - if (tbl->num_entries == 0) { -- n = autoload; -- st_delete(RCLASS_IV_TBL(mod), &n, &val); -+ sa_delete(RCLASS_IV_TBL(mod), (sa_index_t)autoload, &val); - } - } - -@@ -1509,14 +1467,14 @@ static NODE * - autoload_node(VALUE mod, ID id, const char **loadingpath) - { - VALUE file; -- struct st_table *tbl; -+ struct sa_table *tbl; - st_data_t val; - NODE *load; - const char *loading; - int safe; - -- if (!st_lookup(RCLASS_IV_TBL(mod), autoload, &val) || -- !(tbl = check_autoload_table((VALUE)val)) || !st_lookup(tbl, (st_data_t)id, &val)) { -+ if (!sa_lookup(RCLASS_IV_TBL(mod), (sa_index_t)autoload, &val) || -+ !(tbl = check_autoload_table((VALUE)val)) || !sa_lookup(tbl, (sa_index_t)id, &val)) { - return 0; - } - load = (NODE *)val; -@@ -1541,10 +1499,10 @@ autoload_node(VALUE mod, ID id, const char **loadingpath) - static int - autoload_node_id(VALUE mod, ID id) - { -- struct st_table *tbl = RCLASS_CONST_TBL(mod); -+ struct sa_table *tbl = RCLASS_CONST_TBL(mod); - st_data_t val; - -- if (!tbl || !st_lookup(tbl, (st_data_t)id, &val) || ((rb_const_entry_t*)val)->value != Qundef) { -+ if (!tbl || !sa_lookup(tbl, (sa_index_t)id, &val) || ((rb_const_entry_t*)val)->value != Qundef) { - return 0; - } - return 1; -@@ -1593,7 +1551,7 @@ rb_const_get_0(VALUE klass, ID id, int exclude, int recurse, int visibility) - while (RTEST(tmp)) { - VALUE am = 0; - st_data_t data; -- while (RCLASS_CONST_TBL(tmp) && st_lookup(RCLASS_CONST_TBL(tmp), (st_data_t)id, &data)) { -+ while (sa_lookup(RCLASS_CONST_TBL(tmp), (sa_index_t)id, &data)) { - rb_const_entry_t *ce = (rb_const_entry_t *)data; - if (visibility && ce->flag == CONST_PRIVATE) { - rb_name_error(id, "private constant %s::%s referenced", rb_class2name(klass), rb_id2name(id)); -@@ -1686,12 +1644,12 @@ VALUE - rb_const_remove(VALUE mod, ID id) - { - VALUE val; -- st_data_t v, n = id; -+ st_data_t v; - - if (!OBJ_UNTRUSTED(mod) && rb_safe_level() >= 4) - rb_raise(rb_eSecurityError, "Insecure: can't remove constant"); - rb_check_frozen(mod); -- if (!RCLASS_CONST_TBL(mod) || !st_delete(RCLASS_CONST_TBL(mod), &n, &v)) { -+ if (!sa_delete(RCLASS_CONST_TBL(mod), (sa_index_t)id, &v)) { - if (rb_const_defined_at(mod, id)) { - rb_name_error(id, "cannot remove %s::%s", - rb_class2name(mod), rb_id2name(id)); -@@ -1711,27 +1669,20 @@ rb_const_remove(VALUE mod, ID id) - return val; - } - --static int --sv_i(ID key, rb_const_entry_t *ce, st_table *tbl) --{ -- if (rb_is_const_id(key)) { -- if (!st_lookup(tbl, (st_data_t)key, 0)) { -- st_insert(tbl, (st_data_t)key, (st_data_t)ce); -- } -- } -- return ST_CONTINUE; --} -- - void* - rb_mod_const_at(VALUE mod, void *data) - { -- st_table *tbl = data; -+ sa_table *tbl = data; - if (!tbl) { -- tbl = st_init_numtable(); -+ tbl = sa_new_table(); - } -- if (RCLASS_CONST_TBL(mod)) { -- st_foreach_safe(RCLASS_CONST_TBL(mod), sv_i, (st_data_t)tbl); -+ SA_FOREACH_START(RCLASS_CONST_TBL(mod)); -+ if (rb_is_const_id(entry->key)) { -+ if (!sa_lookup(tbl, entry->key, 0)) { -+ sa_insert(tbl, entry->key, value); -+ } - } -+ SA_FOREACH_END(); - return tbl; - } - -@@ -1748,25 +1699,21 @@ rb_mod_const_of(VALUE mod, void *data) - return data; - } - --static int --list_i(st_data_t key, st_data_t value, VALUE ary) --{ -- ID sym = (ID)key; -- rb_const_entry_t *ce = (rb_const_entry_t *)value; -- if (ce->flag != CONST_PRIVATE) rb_ary_push(ary, ID2SYM(sym)); -- return ST_CONTINUE; --} -- - VALUE - rb_const_list(void *data) - { -- st_table *tbl = data; -+ sa_table *tbl = data; - VALUE ary; - - if (!tbl) return rb_ary_new2(0); - ary = rb_ary_new2(tbl->num_entries); -- st_foreach_safe(tbl, list_i, ary); -- st_free_table(tbl); -+ -+ SA_FOREACH_START(tbl); -+ rb_const_entry_t *ce = (rb_const_entry_t *)value; -+ if (ce->flag != CONST_PRIVATE) rb_ary_push(ary, ID2SYM(entry->key)); -+ SA_FOREACH_END(); -+ -+ sa_free_table(tbl); - - return ary; - } -@@ -1790,7 +1737,7 @@ VALUE - rb_mod_constants(int argc, VALUE *argv, VALUE mod) - { - VALUE inherit; -- st_table *tbl; -+ sa_table *tbl; - - if (argc == 0) { - inherit = Qtrue; -@@ -1817,7 +1764,7 @@ rb_const_defined_0(VALUE klass, ID id, int exclude, int recurse, int visibility) - tmp = klass; - retry: - while (tmp) { -- if (RCLASS_CONST_TBL(tmp) && st_lookup(RCLASS_CONST_TBL(tmp), (st_data_t)id, &value)) { -+ if (sa_lookup(RCLASS_CONST_TBL(tmp), (sa_index_t)id, &value)) { - rb_const_entry_t *ce = (rb_const_entry_t *)value; - if (visibility && ce->flag == CONST_PRIVATE) { - return (int)Qfalse; -@@ -1885,6 +1832,7 @@ void - rb_const_set(VALUE klass, ID id, VALUE val) - { - rb_const_entry_t *ce; -+ st_data_t value; - VALUE visibility = CONST_PUBLIC; - - if (NIL_P(klass)) { -@@ -1893,21 +1841,14 @@ rb_const_set(VALUE klass, ID id, VALUE val) - } - - check_before_mod_set(klass, id, val, "constant"); -- if (!RCLASS_CONST_TBL(klass)) { -- RCLASS_CONST_TBL(klass) = st_init_numtable(); -- } -- else { -- st_data_t value; -- -- if (st_lookup(RCLASS_CONST_TBL(klass), (st_data_t)id, &value)) { -- rb_const_entry_t *ce = (rb_const_entry_t*)value; -- if (ce->value == Qundef) -- autoload_delete(klass, id); -- else { -- visibility = ce->flag; -- rb_warn("already initialized constant %s", rb_id2name(id)); -- } -- } -+ if (sa_lookup(RCLASS_CONST_TBL(klass), (sa_index_t)id, &value)) { -+ rb_const_entry_t *ce = (rb_const_entry_t*)value; -+ if (ce->value == Qundef) -+ autoload_delete(klass, id); -+ else { -+ visibility = ce->flag; -+ rb_warn("already initialized constant %s", rb_id2name(id)); -+ } - } - - rb_vm_change_state(); -@@ -1916,7 +1857,7 @@ rb_const_set(VALUE klass, ID id, VALUE val) - ce->flag = (rb_const_flag_t)visibility; - ce->value = val; - -- st_insert(RCLASS_CONST_TBL(klass), (st_data_t)id, (st_data_t)ce); -+ sa_insert(RCLASS_CONST_TBL(klass), (sa_index_t)id, (st_data_t)ce); - } - - void -@@ -1958,8 +1899,7 @@ set_const_visibility(VALUE mod, int argc, VALUE *argv, rb_const_flag_t flag) - for (i = 0; i < argc; i++) { - VALUE val = argv[i]; - id = rb_to_id(val); -- if (RCLASS_CONST_TBL(mod) && -- st_lookup(RCLASS_CONST_TBL(mod), (st_data_t)id, &v)) { -+ if (sa_lookup(RCLASS_CONST_TBL(mod), (sa_index_t)id, &v)) { - ((rb_const_entry_t*)v)->flag = flag; - } - else { -@@ -2008,7 +1948,7 @@ original_module(VALUE c) - } - - #define CVAR_LOOKUP(v,r) do {\ -- if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass),(st_data_t)id,(v))) {\ -+ if (sa_lookup(RCLASS_IV_TBL(klass),(sa_index_t)id,(v))) {\ - r;\ - }\ - if (FL_TEST(klass, FL_SINGLETON) ) {\ -@@ -2027,7 +1967,7 @@ original_module(VALUE c) - klass = RCLASS_SUPER(klass);\ - }\ - while (klass) {\ -- if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass),(st_data_t)id,(v))) {\ -+ if (sa_lookup(RCLASS_IV_TBL(klass),(sa_index_t)id,(v))) {\ - r;\ - }\ - klass = RCLASS_SUPER(klass);\ -@@ -2043,15 +1983,13 @@ rb_cvar_set(VALUE klass, ID id, VALUE val) - CVAR_LOOKUP(0, {if (!front) front = klass; target = klass;}); - if (target) { - if (front && target != front) { -- st_data_t did = id; -- - if (RTEST(ruby_verbose)) { - rb_warning("class variable %s of %s is overtaken by %s", - rb_id2name(id), rb_class2name(original_module(front)), - rb_class2name(original_module(target))); - } - if (BUILTIN_TYPE(front) == T_CLASS) { -- st_delete(RCLASS_IV_TBL(front),&did,0); -+ sa_delete(RCLASS_IV_TBL(front),(sa_index_t)id,0); - } - } - } -@@ -2060,11 +1998,7 @@ rb_cvar_set(VALUE klass, ID id, VALUE val) - } - - check_before_mod_set(target, id, val, "class variable"); -- if (!RCLASS_IV_TBL(target)) { -- RCLASS_IV_TBL(target) = st_init_numtable(); -- } -- -- st_insert(RCLASS_IV_TBL(target), (st_data_t)id, (st_data_t)val); -+ sa_insert(RCLASS_IV_TBL(target), (sa_index_t)id, (st_data_t)val); - } - - VALUE -@@ -2080,15 +2014,13 @@ rb_cvar_get(VALUE klass, ID id) - rb_id2name(id), rb_class2name(tmp)); - } - if (front && target != front) { -- st_data_t did = id; -- - if (RTEST(ruby_verbose)) { - rb_warning("class variable %s of %s is overtaken by %s", - rb_id2name(id), rb_class2name(original_module(front)), - rb_class2name(original_module(target))); - } - if (BUILTIN_TYPE(front) == T_CLASS) { -- st_delete(RCLASS_IV_TBL(front),&did,0); -+ sa_delete(RCLASS_IV_TBL(front),(sa_index_t)id,0); - } - } - return (VALUE)value; -@@ -2134,7 +2066,7 @@ rb_define_class_variable(VALUE klass, const char *name, VALUE val) - } - - static int --cv_i(ID key, VALUE value, VALUE ary) -+cv_i(sa_index_t key, VALUE value, VALUE ary) - { - if (rb_is_class_id(key)) { - VALUE kval = ID2SYM(key); -@@ -2167,7 +2099,7 @@ rb_mod_class_variables(VALUE obj) - VALUE ary = rb_ary_new(); - - if (RCLASS_IV_TBL(obj)) { -- st_foreach_safe(RCLASS_IV_TBL(obj), cv_i, ary); -+ sa_foreach(RCLASS_IV_TBL(obj), cv_i, ary); - } - return ary; - } -@@ -2196,7 +2128,7 @@ VALUE - rb_mod_remove_cvar(VALUE mod, VALUE name) - { - const ID id = rb_to_id(name); -- st_data_t val, n = id; -+ st_data_t val; - - if (!rb_is_class_id(id)) { - rb_name_error(id, "wrong class variable name %s", rb_id2name(id)); -@@ -2204,7 +2136,7 @@ rb_mod_remove_cvar(VALUE mod, VALUE name) - if (!OBJ_UNTRUSTED(mod) && rb_safe_level() >= 4) - rb_raise(rb_eSecurityError, "Insecure: can't remove class variable"); - rb_check_frozen(mod); -- if (RCLASS_IV_TBL(mod) && st_delete(RCLASS_IV_TBL(mod), &n, &val)) { -+ if (RCLASS_IV_TBL(mod) && sa_delete(RCLASS_IV_TBL(mod), (sa_index_t)id, &val)) { - return (VALUE)val; - } - if (rb_cvar_defined(mod, id)) { -diff --git a/vm.c b/vm.c -index 5a721d0..7bc007a 100644 ---- a/vm.c -+++ b/vm.c -@@ -1055,7 +1055,7 @@ static void - add_opt_method(VALUE klass, ID mid, VALUE bop) - { - rb_method_entry_t *me; -- if (st_lookup(RCLASS_M_TBL(klass), mid, (void *)&me) && me->def && -+ if (sa_lookup(RCLASS_M_TBL(klass), (sa_index_t)mid, (void *)&me) && me->def && - me->def->type == VM_METHOD_TYPE_CFUNC) { - st_insert(vm_opt_method_table, (st_data_t)me, (st_data_t)bop); - } -diff --git a/vm_insnhelper.c b/vm_insnhelper.c -index 5f7d1ee..ade417e 100644 ---- a/vm_insnhelper.c -+++ b/vm_insnhelper.c -@@ -1179,7 +1179,7 @@ vm_get_ev_const(rb_thread_t *th, const rb_iseq_t *iseq, - st_data_t data; - search_continue: - if (RCLASS_CONST_TBL(klass) && -- st_lookup(RCLASS_CONST_TBL(klass), id, &data)) { -+ sa_lookup(RCLASS_CONST_TBL(klass), (sa_index_t)id, &data)) { - val = ((rb_const_entry_t*)data)->value; - if (val == Qundef) { - if (am == klass) break; -@@ -1289,10 +1289,10 @@ vm_getivar(VALUE obj, ID id, IC ic) - st_data_t index; - long len = ROBJECT_NUMIV(obj); - VALUE *ptr = ROBJECT_IVPTR(obj); -- struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); -+ struct sa_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); - - if (iv_index_tbl) { -- if (st_lookup(iv_index_tbl, id, &index)) { -+ if (sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) { - if ((long)index < len) { - val = ptr[index]; - } -@@ -1342,9 +1342,9 @@ vm_setivar(VALUE obj, ID id, VALUE val, IC ic) - } - } - else { -- struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); -+ struct sa_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); - -- if (iv_index_tbl && st_lookup(iv_index_tbl, (st_data_t)id, &index)) { -+ if (iv_index_tbl && sa_lookup(iv_index_tbl, (sa_index_t)id, &index)) { - ic->ic_class = klass; - ic->ic_value.index = index; - ic->ic_vmstat = GET_VM_STATE_VERSION(); -diff --git a/vm_method.c b/vm_method.c -index 85cb30c..d45df81 100644 ---- a/vm_method.c -+++ b/vm_method.c -@@ -162,7 +162,7 @@ rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type, - rb_method_definition_t *def, rb_method_flag_t noex) - { - rb_method_entry_t *me; -- st_table *mtbl; -+ sa_table *mtbl; - st_data_t data; - - if (NIL_P(klass)) { -@@ -190,7 +190,7 @@ rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type, - mtbl = RCLASS_M_TBL(klass); - - /* check re-definition */ -- if (st_lookup(mtbl, mid, &data)) { -+ if (sa_lookup(mtbl, (sa_index_t)mid, &data)) { - rb_method_entry_t *old_me = (rb_method_entry_t *)data; - rb_method_definition_t *old_def = old_me->def; - -@@ -248,7 +248,7 @@ rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type, - } - } - -- st_insert(mtbl, mid, (st_data_t) me); -+ sa_insert(mtbl, (sa_index_t)mid, (st_data_t) me); - - return me; - } -@@ -371,7 +371,7 @@ search_method(VALUE klass, ID id) - return 0; - } - -- while (!st_lookup(RCLASS_M_TBL(klass), id, &body)) { -+ while (!sa_lookup(RCLASS_M_TBL(klass), (sa_index_t)id, &body)) { - klass = RCLASS_SUPER(klass); - if (!klass) { - return 0; -@@ -429,7 +429,7 @@ rb_method_entry(VALUE klass, ID id) - static void - remove_method(VALUE klass, ID mid) - { -- st_data_t key, data; -+ st_data_t data; - rb_method_entry_t *me = 0; - - if (klass == rb_cObject) { -@@ -443,14 +443,13 @@ remove_method(VALUE klass, ID mid) - rb_warn("removing `%s' may cause serious problems", rb_id2name(mid)); - } - -- if (!st_lookup(RCLASS_M_TBL(klass), mid, &data) || -+ if (!sa_lookup(RCLASS_M_TBL(klass), (sa_index_t)mid, &data) || - !(me = (rb_method_entry_t *)data) || - (!me->def || me->def->type == VM_METHOD_TYPE_UNDEF)) { - rb_name_error(mid, "method `%s' not defined in %s", - rb_id2name(mid), rb_class2name(klass)); - } -- key = (st_data_t)mid; -- st_delete(RCLASS_M_TBL(klass), &key, &data); -+ sa_delete(RCLASS_M_TBL(klass), (sa_index_t)mid, &data); - - rb_vm_check_redefinition_opt_method(me); - rb_clear_cache_for_undef(klass, mid); diff --git a/patches/ruby/1.9.3/p392/railsexpress/12-falcon-array-queue.patch b/patches/ruby/1.9.3/p392/railsexpress/12-falcon-array-queue.patch deleted file mode 100644 index cdd40e123c..0000000000 --- a/patches/ruby/1.9.3/p392/railsexpress/12-falcon-array-queue.patch +++ /dev/null @@ -1,301 +0,0 @@ -diff --git a/array.c b/array.c -index c33d106..747da0e 100644 ---- a/array.c -+++ b/array.c -@@ -255,15 +255,24 @@ rb_ary_modify(VALUE ary) - rb_ary_modify_check(ary); - if (ARY_SHARED_P(ary)) { - long len = RARRAY_LEN(ary); -+ VALUE shared = ARY_SHARED(ary); - if (len <= RARRAY_EMBED_LEN_MAX) { - VALUE *ptr = ARY_HEAP_PTR(ary); -- VALUE shared = ARY_SHARED(ary); - FL_UNSET_SHARED(ary); - FL_SET_EMBED(ary); - MEMCPY(ARY_EMBED_PTR(ary), ptr, VALUE, len); - rb_ary_decrement_share(shared); - ARY_SET_EMBED_LEN(ary, len); - } -+ else if (ARY_SHARED_NUM(shared) == 1 && len > RARRAY_LEN(shared)>>1) { -+ long shift = RARRAY_PTR(ary) - RARRAY_PTR(shared); -+ ARY_SET_PTR(ary, RARRAY_PTR(shared)); -+ ARY_SET_CAPA(ary, RARRAY_LEN(shared)); -+ MEMMOVE(RARRAY_PTR(ary), RARRAY_PTR(ary)+shift, VALUE, len); -+ FL_UNSET_SHARED(ary); -+ FL_SET_EMBED(shared); -+ rb_ary_decrement_share(shared); -+ } - else { - VALUE *ptr = ALLOC_N(VALUE, len); - MEMCPY(ptr, RARRAY_PTR(ary), VALUE, len); -@@ -274,6 +283,38 @@ rb_ary_modify(VALUE ary) - } - } - -+static void -+ary_ensure_room_for_push(VALUE ary, long add_len) -+{ -+ long new_len = RARRAY_LEN(ary) + add_len; -+ long capa; -+ -+ if (ARY_SHARED_P(ary)) { -+ if (new_len > RARRAY_EMBED_LEN_MAX) { -+ VALUE shared = ARY_SHARED(ary); -+ if (ARY_SHARED_NUM(shared) == 1) { -+ if (RARRAY_PTR(ary) - RARRAY_PTR(shared) + new_len <= RARRAY_LEN(shared)) { -+ rb_ary_modify_check(ary); -+ } -+ else { -+ /* if array is shared, than it is likely it participate in push/shift pattern */ -+ rb_ary_modify(ary); -+ capa = ARY_CAPA(ary); -+ if (new_len > capa - (capa >> 6)) { -+ ary_double_capa(ary, new_len); -+ } -+ } -+ return; -+ } -+ } -+ } -+ rb_ary_modify(ary); -+ capa = ARY_CAPA(ary); -+ if (new_len > capa) { -+ ary_double_capa(ary, new_len); -+ } -+} -+ - VALUE - rb_ary_freeze(VALUE ary) - { -@@ -446,8 +487,9 @@ ary_make_shared(VALUE ary) - OBJSETUP(shared, 0, T_ARRAY); - FL_UNSET_EMBED(shared); - -- ARY_SET_LEN((VALUE)shared, RARRAY_LEN(ary)); -+ ARY_SET_LEN((VALUE)shared, ARY_CAPA(ary)); - ARY_SET_PTR((VALUE)shared, RARRAY_PTR(ary)); -+ rb_mem_clear(RARRAY_PTR(shared) + RARRAY_LEN(ary), ARY_CAPA(ary) - RARRAY_LEN(ary)); - FL_SET_SHARED_ROOT(shared); - ARY_SET_SHARED_NUM((VALUE)shared, 1); - FL_SET_SHARED(ary); -@@ -737,8 +779,6 @@ ary_take_first_or_last(int argc, VALUE *argv, VALUE ary, enum ary_take_pos_flags - return ary_make_partial(ary, rb_cArray, offset, n); - } - --static VALUE rb_ary_push_1(VALUE ary, VALUE item); -- - /* - * call-seq: - * ary << obj -> ary -@@ -755,8 +795,12 @@ static VALUE rb_ary_push_1(VALUE ary, VALUE item); - VALUE - rb_ary_push(VALUE ary, VALUE item) - { -- rb_ary_modify(ary); -- return rb_ary_push_1(ary, item); -+ long idx = RARRAY_LEN(ary); -+ -+ ary_ensure_room_for_push(ary, 1); -+ RARRAY_PTR(ary)[idx] = item; -+ ARY_SET_LEN(ary, idx + 1); -+ return ary; - } - - static VALUE -@@ -772,6 +816,18 @@ rb_ary_push_1(VALUE ary, VALUE item) - return ary; - } - -+static VALUE -+rb_ary_cat(VALUE ary, const VALUE *ptr, long len) -+{ -+ long oldlen = RARRAY_LEN(ary); -+ -+ ary_ensure_room_for_push(ary, len); -+copy: -+ MEMCPY(RARRAY_PTR(ary) + oldlen, ptr, VALUE, len); -+ ARY_SET_LEN(ary, oldlen + len); -+ return ary; -+} -+ - /* - * call-seq: - * ary.push(obj, ... ) -> ary -@@ -788,11 +844,7 @@ rb_ary_push_1(VALUE ary, VALUE item) - static VALUE - rb_ary_push_m(int argc, VALUE *argv, VALUE ary) - { -- rb_ary_modify(ary); -- while (argc--) { -- rb_ary_push_1(ary, *argv++); -- } -- return ary; -+ return rb_ary_cat(ary, argv, argc); - } - - VALUE -@@ -920,6 +972,55 @@ rb_ary_shift_m(int argc, VALUE *argv, VALUE ary) - return result; - } - -+static void -+ary_ensure_room_for_unshift(VALUE ary, int argc) -+{ -+ long len = RARRAY_LEN(ary); -+ long new_len = len + argc; -+ long capa; -+ VALUE *head, *sharedp; -+ -+ if (ARY_SHARED_P(ary)) { -+ VALUE shared = ARY_SHARED(ary); -+ capa = RARRAY_LEN(shared); -+ if (ARY_SHARED_NUM(shared) == 1 && capa > new_len) { -+ head = RARRAY_PTR(ary); -+ sharedp = RARRAY_PTR(shared); -+ goto makeroom_if_need; -+ } -+ } -+ -+ rb_ary_modify(ary); -+ capa = ARY_CAPA(ary); -+ if (capa - (capa >> 6) <= new_len) { -+ ary_double_capa(ary, new_len); -+ } -+ -+ /* use shared array for big "queues" */ -+ if (new_len > ARY_DEFAULT_SIZE * 4) { -+ /* make a room for unshifted items */ -+ capa = ARY_CAPA(ary); -+ ary_make_shared(ary); -+ -+ head = sharedp = RARRAY_PTR(ary); -+ goto makeroom; -+makeroom_if_need: -+ if (head - sharedp < argc) { -+ long room; -+makeroom: -+ room = capa - new_len; -+ room -= room >> 4; -+ MEMMOVE(sharedp + argc + room, head, VALUE, len); -+ head = sharedp + argc + room; -+ } -+ ARY_SET_PTR(ary, head - argc); -+ } -+ else { -+ /* sliding items */ -+ MEMMOVE(RARRAY_PTR(ary) + argc, RARRAY_PTR(ary), VALUE, len); -+ } -+} -+ - /* - * call-seq: - * ary.unshift(obj, ...) -> ary -@@ -935,19 +1036,16 @@ rb_ary_shift_m(int argc, VALUE *argv, VALUE ary) - static VALUE - rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary) - { -- long len; -+ long len = RARRAY_LEN(ary); - -- rb_ary_modify(ary); -- if (argc == 0) return ary; -- if (ARY_CAPA(ary) <= (len = RARRAY_LEN(ary)) + argc) { -- ary_double_capa(ary, len + argc); -+ if (argc == 0) { -+ rb_ary_modify_check(ary); -+ return ary; - } - -- /* sliding items */ -- MEMMOVE(RARRAY_PTR(ary) + argc, RARRAY_PTR(ary), VALUE, len); -+ ary_ensure_room_for_unshift(ary, argc); - MEMCPY(RARRAY_PTR(ary), argv, VALUE, argc); -- ARY_INCREASE_LEN(ary, argc); -- -+ ARY_SET_LEN(ary, len + argc); - return ary; - } - -@@ -1309,15 +1407,12 @@ rb_ary_splice(VALUE ary, long beg, long len, VALUE rpl) - rpl = rb_ary_to_ary(rpl); - rlen = RARRAY_LEN(rpl); - } -- rb_ary_modify(ary); - if (beg >= RARRAY_LEN(ary)) { - if (beg > ARY_MAX_SIZE - rlen) { - rb_raise(rb_eIndexError, "index %ld too big", beg); - } -+ ary_ensure_room_for_push(ary, rlen-len); /* len is 0 or negative */ - len = beg + rlen; -- if (len >= ARY_CAPA(ary)) { -- ary_double_capa(ary, len); -- } - rb_mem_clear(RARRAY_PTR(ary) + RARRAY_LEN(ary), beg - RARRAY_LEN(ary)); - if (rlen > 0) { - MEMCPY(RARRAY_PTR(ary) + beg, RARRAY_PTR(rpl), VALUE, rlen); -@@ -1327,6 +1422,7 @@ rb_ary_splice(VALUE ary, long beg, long len, VALUE rpl) - else { - long alen; - -+ rb_ary_modify(ary); - alen = RARRAY_LEN(ary) + rlen - len; - if (alen >= ARY_CAPA(ary)) { - ary_double_capa(ary, alen); -@@ -2116,12 +2212,13 @@ rb_ary_sort_bang(VALUE ary) - if (RARRAY_LEN(ary) > 1) { - VALUE tmp = ary_make_substitution(ary); /* only ary refers tmp */ - struct ary_sort_data data; -+ long len = RARRAY_LEN(ary); - - RBASIC(tmp)->klass = 0; - data.ary = tmp; - data.opt_methods = 0; - data.opt_inited = 0; -- ruby_qsort(RARRAY_PTR(tmp), RARRAY_LEN(tmp), sizeof(VALUE), -+ ruby_qsort(RARRAY_PTR(tmp), len, sizeof(VALUE), - rb_block_given_p()?sort_1:sort_2, &data); - - if (ARY_EMBED_P(tmp)) { -@@ -2138,7 +2235,7 @@ rb_ary_sort_bang(VALUE ary) - if (ARY_HEAP_PTR(ary) == ARY_HEAP_PTR(tmp)) { - assert(!ARY_EMBED_P(ary)); - FL_UNSET_SHARED(ary); -- ARY_SET_CAPA(ary, ARY_CAPA(tmp)); -+ ARY_SET_CAPA(ary, RARRAY_LEN(tmp)); - } - else { - assert(!ARY_SHARED_P(tmp)); -@@ -2153,8 +2250,8 @@ rb_ary_sort_bang(VALUE ary) - xfree(ARY_HEAP_PTR(ary)); - } - ARY_SET_PTR(ary, RARRAY_PTR(tmp)); -- ARY_SET_HEAP_LEN(ary, RARRAY_LEN(tmp)); -- ARY_SET_CAPA(ary, ARY_CAPA(tmp)); -+ ARY_SET_HEAP_LEN(ary, len); -+ ARY_SET_CAPA(ary, RARRAY_LEN(tmp)); - } - /* tmp was lost ownership for the ptr */ - FL_UNSET(tmp, FL_FREEZE); -diff --git a/test/ruby/test_array.rb b/test/ruby/test_array.rb -index 28d3e41..bcad2c0 100644 ---- a/test/ruby/test_array.rb -+++ b/test/ruby/test_array.rb -@@ -414,6 +414,18 @@ class TestArray < Test::Unit::TestCase - a = @cls[1, 2, 3] - a[-1, 0] = a - assert_equal([1, 2, 1, 2, 3, 3], a) -+ -+ a = @cls[] -+ a[5,0] = [5] -+ assert_equal([nil, nil, nil, nil, nil, 5], a) -+ -+ a = @cls[1] -+ a[1,0] = [2] -+ assert_equal([1, 2], a) -+ -+ a = @cls[1] -+ a[1,1] = [2] -+ assert_equal([1, 2], a) - end - - def test_assoc diff --git a/patches/ruby/1.9.3/p392/railsexpress/13-railsbench-gc-fixes.patch b/patches/ruby/1.9.3/p392/railsexpress/13-railsbench-gc-fixes.patch deleted file mode 100644 index 0ff3abfe64..0000000000 --- a/patches/ruby/1.9.3/p392/railsexpress/13-railsbench-gc-fixes.patch +++ /dev/null @@ -1,257 +0,0 @@ -diff --git a/gc.c b/gc.c -index 56f0217..6e3714d 100644 ---- a/gc.c -+++ b/gc.c -@@ -108,11 +108,6 @@ ruby_gc_params_t initial_params = { - #define LONG_LONG long - #endif - --static int heap_min_slots = 10000; --static int heap_slots_increment = 10000; --static int initial_heap_slots_increment = 10000; --static double heap_slots_growth_factor = 1.8; -- - #define nomem_error GET_VM()->special_exceptions[ruby_error_nomemory] - - #if SIZEOF_LONG == SIZEOF_VOIDP -@@ -321,6 +316,28 @@ typedef struct RVALUE { - #endif - } RVALUE; - -+ -+/* tiny heap size */ -+/* 32KB */ -+/*#define HEAP_SIZE 0x8000 */ -+/* 128KB */ -+/*#define HEAP_SIZE 0x20000 */ -+/* 64KB */ -+/*#define HEAP_SIZE 0x10000 */ -+/* 16KB */ -+#define HEAP_SIZE 0x4000 -+/* 8KB */ -+/*#define HEAP_SIZE 0x2000 */ -+/* 4KB */ -+/*#define HEAP_SIZE 0x1000 */ -+/* 2KB */ -+/*#define HEAP_SIZE 0x800 */ -+ -+#define HEAP_OBJ_LIMIT (unsigned int)(HEAP_SIZE / sizeof(struct RVALUE)) -+ -+static int heap_slots_increment = 10000 / HEAP_OBJ_LIMIT; -+static double heap_slots_growth_factor = 1.8; -+ - #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__) - #pragma pack(pop) - #endif -@@ -535,17 +552,6 @@ rb_gc_set_params(void) - - if (rb_safe_level() > 0) return; - -- envp = getenv("RUBY_GC_STATS"); -- if (envp != NULL) { -- int i = atoi(envp); -- if (i > 0) { -- verbose_gc_stats = 1; -- fprintf(stderr, "RUBY_GC_STATS=%d\n", verbose_gc_stats); -- } -- /* child processes should not inherit RUBY_GC_STATS */ -- ruby_unsetenv("RUBY_GC_STATS"); -- } -- - envp = getenv("RUBY_GC_DATA_FILE"); - if (envp != NULL) { - FILE* data_file = fopen(envp, "w"); -@@ -559,6 +565,18 @@ rb_gc_set_params(void) - ruby_unsetenv("RUBY_GC_DATA_FILE"); - } - -+ envp = getenv("RUBY_GC_STATS"); -+ if (envp != NULL) { -+ int i = atoi(envp); -+ if (i > 0) { -+ /* gc_statistics = 1; */ -+ verbose_gc_stats = 1; -+ fprintf(gc_data_file, "RUBY_GC_STATS=%d\n", verbose_gc_stats); -+ } -+ /* child processes should not inherit RUBY_GC_STATS */ -+ ruby_unsetenv("RUBY_GC_STATS"); -+ } -+ - envp = getenv("RUBY_GC_MALLOC_LIMIT"); - if (envp != NULL) { - int malloc_limit_i = atoi(envp); -@@ -570,7 +588,7 @@ rb_gc_set_params(void) - malloc_limit_i, initial_malloc_limit); - if (malloc_limit_i > 0) { - initial_malloc_limit = malloc_limit_i; -- // malloc_limit = initial_malloc_limit; -+ malloc_limit = initial_malloc_limit; - } - } - -@@ -609,8 +627,7 @@ rb_gc_set_params(void) - if (verbose_gc_stats) { - fprintf(gc_data_file, "RUBY_HEAP_SLOTS_INCREMENT=%s\n", envp); - } -- heap_slots_increment = i; -- initial_heap_slots_increment = heap_slots_increment; -+ heap_slots_increment = i / HEAP_OBJ_LIMIT; - } - - envp = getenv("RUBY_HEAP_SLOTS_GROWTH_FACTOR"); -@@ -670,24 +687,6 @@ rb_objspace_free(rb_objspace_t *objspace) - } - #endif - --/* tiny heap size */ --/* 32KB */ --/*#define HEAP_SIZE 0x8000 */ --/* 128KB */ --/*#define HEAP_SIZE 0x20000 */ --/* 64KB */ --/*#define HEAP_SIZE 0x10000 */ --/* 16KB */ --#define HEAP_SIZE 0x4000 --/* 8KB */ --/*#define HEAP_SIZE 0x2000 */ --/* 4KB */ --/*#define HEAP_SIZE 0x1000 */ --/* 2KB */ --/*#define HEAP_SIZE 0x800 */ -- --#define HEAP_OBJ_LIMIT (unsigned int)(HEAP_SIZE / sizeof(struct RVALUE)) -- - extern sa_table rb_class_tbl; - - int ruby_disable_gc_stress = 0; -@@ -1520,7 +1519,6 @@ rb_gc_dump_file_and_line_info(int argc, VALUE *argv) - rb_objspace_t *objspace = &rb_objspace; - VALUE filename, str, include_classnames = Qnil; - char *fname = NULL; -- char *klass = NULL; - FILE* f = NULL; - size_t i = 0; - -@@ -1778,17 +1776,15 @@ aligned_free(void *ptr) - static void - assign_heap_slot(rb_objspace_t *objspace) - { -- /* -- if (gc_statistics & verbose_gc_stats) { -- fprintf(gc_data_file, "assigning heap slot\n"); -- } -- */ -- - RVALUE *p, *pend, *membase; - struct heaps_slot *slot; - size_t hi, lo, mid; - size_t objs; -- -+ /* -+ if (gc_statistics & verbose_gc_stats) { -+ fprintf(gc_data_file, "assigning heap slot: %d\n", heaps_inc); -+ } -+ */ - objs = HEAP_OBJ_LIMIT; - p = (RVALUE*)malloc(HEAP_SIZE); - if (p == 0) { -@@ -1903,13 +1899,17 @@ static void - set_heaps_increment(rb_objspace_t *objspace) - { - size_t next_heaps_length = (size_t)(heaps_used * heap_slots_growth_factor); -+ size_t next_heaps_length_alt = heaps_used + heap_slots_increment; - -- if (next_heaps_length == heaps_used) { -- next_heaps_length++; -+ if (next_heaps_length < next_heaps_length_alt) { -+ next_heaps_length = next_heaps_length_alt; - } - - heaps_inc = next_heaps_length - heaps_used; -- -+ /* -+ if (gc_statistics & verbose_gc_stats) -+ fprintf(gc_data_file, "heaps_inc:%lu, slots_inc: %lu\n", heaps_inc, heaps_inc * HEAP_OBJ_LIMIT); -+ */ - if (next_heaps_length > heaps_length) { - allocate_sorted_heaps(objspace, next_heaps_length); - } -@@ -2527,7 +2527,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr) - - #ifdef GC_DEBUG - if (obj->file && obj->file != Qnil && is_pointer_to_heap(objspace, (void*)obj->file)) { -- gc_mark(objspace, obj->file, lev); -+ gc_mark(objspace, obj->file); - } - #endif - -@@ -2543,7 +2543,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr) - - #ifdef GC_DEBUG - if (obj->file && obj->file != Qnil && is_pointer_to_heap(objspace, (void*)obj->file)) { -- gc_mark(objspace, obj->file, lev); -+ gc_mark(objspace, obj->file); - } - #endif - -@@ -3028,14 +3028,14 @@ before_gc_sweep(rb_objspace_t *objspace) - MEMZERO((void*)live_counts, unsigned long, T_MASK+1); - } - -- objspace->heap.max_blocks_to_free = heaps_used - (heap_min_slots / HEAP_OBJ_LIMIT); -+ objspace->heap.max_blocks_to_free = heaps_used - (initial_heap_min_slots / HEAP_OBJ_LIMIT); - objspace->heap.freed_blocks = 0; - - freelist = 0; - objspace->heap.do_heap_free = (size_t)((heaps_used * HEAP_OBJ_LIMIT) * 0.65); - objspace->heap.free_min = (size_t)((heaps_used * HEAP_OBJ_LIMIT) * 0.2); - if (objspace->heap.free_min < initial_free_min) { -- objspace->heap.do_heap_free = heaps_used * HEAP_OBJ_LIMIT; -+ /* objspace->heap.do_heap_free = heaps_used * HEAP_OBJ_LIMIT; */ - objspace->heap.free_min = initial_free_min; - } - objspace->heap.sweep_slots = heaps; -@@ -3067,7 +3067,11 @@ after_gc_sweep(rb_objspace_t *objspace) - if (malloc_limit < initial_malloc_limit) malloc_limit = initial_malloc_limit; - } - malloc_increase = 0; -- -+ /* -+ if (verbose_gc_stats) -+ fprintf(gc_data_file, "heap size before freeing unused heaps: %7lu\n", -+ (unsigned long)heaps_used*HEAP_OBJ_LIMIT); -+ */ - free_unused_heaps(objspace); - - if (gc_statistics) { -@@ -3076,6 +3080,7 @@ after_gc_sweep(rb_objspace_t *objspace) - if (verbose_gc_stats) { - /* log gc stats if requested */ - fprintf(gc_data_file, "GC time: %lu musec\n", (unsigned long)(gc_time_accumulator-gc_time_accumulator_before_gc)); -+ fprintf(gc_data_file, "heap size : %7lu\n", (unsigned long)heaps_used*HEAP_OBJ_LIMIT); - fprintf(gc_data_file, "objects processed: %7lu\n", (unsigned long)processed); - fprintf(gc_data_file, "live objects : %7lu\n", (unsigned long)live_after_last_mark_phase); - fprintf(gc_data_file, "freelist objects : %7lu\n", (unsigned long)freelist_size); -@@ -3125,7 +3130,7 @@ rest_sweep(rb_objspace_t *objspace) - - static void gc_marks(rb_objspace_t *objspace); - --/* only called from rb_new_obj */ -+/* only called from rb_newobj */ - static int - gc_lazy_sweep(rb_objspace_t *objspace) - { -@@ -3412,13 +3417,11 @@ gc_marks(rb_objspace_t *objspace) - struct gc_list *list; - rb_thread_t *th = GET_THREAD(); - GC_PROF_MARK_TIMER_START; -- - /* - if (gc_statistics & verbose_gc_stats) { - fprintf(gc_data_file, "Marking objects\n"); - } - */ -- - objspace->heap.live_num = 0; - objspace->count++; - live_objects = 0; diff --git a/patches/ruby/1.9.3/p392/railsexpress/14-show-full-backtrace-on-stack-overflow.patch b/patches/ruby/1.9.3/p392/railsexpress/14-show-full-backtrace-on-stack-overflow.patch deleted file mode 100644 index 897e1bd980..0000000000 --- a/patches/ruby/1.9.3/p392/railsexpress/14-show-full-backtrace-on-stack-overflow.patch +++ /dev/null @@ -1,14 +0,0 @@ -diff --git a/eval.c b/eval.c -index 9ceb833..fb5afc0 100644 ---- a/eval.c -+++ b/eval.c -@@ -380,8 +380,7 @@ setup_exception(rb_thread_t *th, int tag, volatile VALUE mesg) - if (file) line = rb_sourceline(); - if (file && !NIL_P(mesg)) { - if (mesg == sysstack_error) { -- at = rb_enc_sprintf(rb_usascii_encoding(), "%s:%d", file, line); -- at = rb_ary_new3(1, at); -+ at = rb_make_backtrace(); - rb_iv_set(mesg, "bt", at); - } - else { diff --git a/patchsets/ruby/1.8.7/head/railsexpress b/patchsets/ruby/1.8.7/head/railsexpress index 23a8bba83c..bcaf65bd76 100644 --- a/patchsets/ruby/1.8.7/head/railsexpress +++ b/patchsets/ruby/1.8.7/head/railsexpress @@ -1,17 +1,17 @@ -railsexpress/01-ignore-generated-files.patch -railsexpress/02-fix-tests-for-osx.patch -railsexpress/03-sigvtalrm-fix.patch -railsexpress/04-railsbench-gc-patch.patch -railsexpress/05-display-full-stack-trace.patch -railsexpress/06-better-source-file-tracing.patch -railsexpress/07-heap-dump-support.patch -railsexpress/08-fork-support-for-gc-logging.patch -railsexpress/09-track-malloc-size.patch -railsexpress/10-track-object-allocation.patch -railsexpress/11-expose-heap-slots.patch -railsexpress/12-fix-heap-size-growth-logic.patch -railsexpress/13-heap-slot-size.patch -railsexpress/14-add-trace-stats-enabled-methods.patch -railsexpress/15-track-live-dataset-size.patch -railsexpress/16-add-object-size-information-to-heap-dump.patch -railsexpress/17-caller-for-all-threads.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/head/railsexpress/01-ignore-generated-files.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/head/railsexpress/02-fix-tests-for-osx.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/head/railsexpress/03-sigvtalrm-fix.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/head/railsexpress/04-railsbench-gc-patch.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/head/railsexpress/05-display-full-stack-trace.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/head/railsexpress/06-better-source-file-tracing.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/head/railsexpress/07-heap-dump-support.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/head/railsexpress/08-fork-support-for-gc-logging.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/head/railsexpress/09-track-malloc-size.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/head/railsexpress/10-track-object-allocation.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/head/railsexpress/11-expose-heap-slots.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/head/railsexpress/12-fix-heap-size-growth-logic.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/head/railsexpress/13-heap-slot-size.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/head/railsexpress/14-add-trace-stats-enabled-methods.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/head/railsexpress/15-track-live-dataset-size.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/head/railsexpress/16-add-object-size-information-to-heap-dump.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/head/railsexpress/17-caller-for-all-threads.patch diff --git a/patchsets/ruby/1.8.7/p334/railsexpress b/patchsets/ruby/1.8.7/p334/railsexpress index 194ec26876..c160d6e827 100644 --- a/patchsets/ruby/1.8.7/p334/railsexpress +++ b/patchsets/ruby/1.8.7/p334/railsexpress @@ -1,17 +1,17 @@ -railsexpress/01-ignore-generated-files.patch -railsexpress/02-fix-rcs-keyword-idiom.patch -railsexpress/03-sigvtalrm-fix.patch -railsexpress/04-railsbench-gc-patch.patch -railsexpress/05-display-full-stack-trace.patch -railsexpress/06-better-source-file-tracing.patch -railsexpress/07-heap-dump-support.patch -railsexpress/08-fork-support-for-gc-logging.patch -railsexpress/09-track-malloc-size.patch -railsexpress/10-track-object-allocation.patch -railsexpress/11-expose-heap-slots.patch -railsexpress/12-fix-heap-size-growth-logic.patch -railsexpress/13-heap-slot-size.patch -railsexpress/14-add-trace-stats-enabled-methods.patch -railsexpress/15-track-live-dataset-size.patch -railsexpress/16-add-object-size-information-to-heap-dump.patch -railsexpress/17-caller-for-all-threads.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p334/railsexpress/01-ignore-generated-files.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p334/railsexpress/02-fix-rcs-keyword-idiom.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p334/railsexpress/03-sigvtalrm-fix.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p334/railsexpress/04-railsbench-gc-patch.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p334/railsexpress/05-display-full-stack-trace.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p334/railsexpress/06-better-source-file-tracing.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p334/railsexpress/07-heap-dump-support.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p334/railsexpress/08-fork-support-for-gc-logging.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p334/railsexpress/09-track-malloc-size.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p334/railsexpress/10-track-object-allocation.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p334/railsexpress/11-expose-heap-slots.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p334/railsexpress/12-fix-heap-size-growth-logic.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p334/railsexpress/13-heap-slot-size.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p334/railsexpress/14-add-trace-stats-enabled-methods.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p334/railsexpress/15-track-live-dataset-size.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p334/railsexpress/16-add-object-size-information-to-heap-dump.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p334/railsexpress/17-caller-for-all-threads.patch diff --git a/patchsets/ruby/1.8.7/p352/railsexpress b/patchsets/ruby/1.8.7/p352/railsexpress index a0d0929a99..44cee17dba 100644 --- a/patchsets/ruby/1.8.7/p352/railsexpress +++ b/patchsets/ruby/1.8.7/p352/railsexpress @@ -1,16 +1,16 @@ -railsexpress/01-ignore-generated-files.patch -railsexpress/02-sigvtalrm-fix.patch -railsexpress/03-railsbench-gc-patch.patch -railsexpress/04-display-full-stack-trace.patch -railsexpress/05-better-source-file-tracing.patch -railsexpress/06-heap-dump-support.patch -railsexpress/07-fork-support-for-gc-logging.patch -railsexpress/08-track-malloc-size.patch -railsexpress/09-track-object-allocation.patch -railsexpress/10-expose-heap-slots.patch -railsexpress/11-fix-heap-size-growth-logic.patch -railsexpress/12-heap-slot-size.patch -railsexpress/13-add-trace-stats-enabled-methods.patch -railsexpress/14-track-live-dataset-size.patch -railsexpress/15-add-object-size-information-to-heap-dump.patch -railsexpress/16-caller-for-all-threads.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p352/railsexpress/01-ignore-generated-files.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p352/railsexpress/02-sigvtalrm-fix.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p352/railsexpress/03-railsbench-gc-patch.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p352/railsexpress/04-display-full-stack-trace.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p352/railsexpress/05-better-source-file-tracing.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p352/railsexpress/06-heap-dump-support.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p352/railsexpress/07-fork-support-for-gc-logging.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p352/railsexpress/08-track-malloc-size.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p352/railsexpress/09-track-object-allocation.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p352/railsexpress/10-expose-heap-slots.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p352/railsexpress/11-fix-heap-size-growth-logic.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p352/railsexpress/12-heap-slot-size.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p352/railsexpress/13-add-trace-stats-enabled-methods.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p352/railsexpress/14-track-live-dataset-size.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p352/railsexpress/15-add-object-size-information-to-heap-dump.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p352/railsexpress/16-caller-for-all-threads.patch diff --git a/patchsets/ruby/1.8.7/p357/railsexpress b/patchsets/ruby/1.8.7/p357/railsexpress index a0d0929a99..6431981b17 100644 --- a/patchsets/ruby/1.8.7/p357/railsexpress +++ b/patchsets/ruby/1.8.7/p357/railsexpress @@ -1,16 +1,16 @@ -railsexpress/01-ignore-generated-files.patch -railsexpress/02-sigvtalrm-fix.patch -railsexpress/03-railsbench-gc-patch.patch -railsexpress/04-display-full-stack-trace.patch -railsexpress/05-better-source-file-tracing.patch -railsexpress/06-heap-dump-support.patch -railsexpress/07-fork-support-for-gc-logging.patch -railsexpress/08-track-malloc-size.patch -railsexpress/09-track-object-allocation.patch -railsexpress/10-expose-heap-slots.patch -railsexpress/11-fix-heap-size-growth-logic.patch -railsexpress/12-heap-slot-size.patch -railsexpress/13-add-trace-stats-enabled-methods.patch -railsexpress/14-track-live-dataset-size.patch -railsexpress/15-add-object-size-information-to-heap-dump.patch -railsexpress/16-caller-for-all-threads.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p357/railsexpress/01-ignore-generated-files.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p357/railsexpress/02-sigvtalrm-fix.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p357/railsexpress/03-railsbench-gc-patch.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p357/railsexpress/04-display-full-stack-trace.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p357/railsexpress/05-better-source-file-tracing.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p357/railsexpress/06-heap-dump-support.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p357/railsexpress/07-fork-support-for-gc-logging.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p357/railsexpress/08-track-malloc-size.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p357/railsexpress/09-track-object-allocation.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p357/railsexpress/10-expose-heap-slots.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p357/railsexpress/11-fix-heap-size-growth-logic.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p357/railsexpress/12-heap-slot-size.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p357/railsexpress/13-add-trace-stats-enabled-methods.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p357/railsexpress/14-track-live-dataset-size.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p357/railsexpress/15-add-object-size-information-to-heap-dump.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p357/railsexpress/16-caller-for-all-threads.patch diff --git a/patchsets/ruby/1.8.7/p358/railsexpress b/patchsets/ruby/1.8.7/p358/railsexpress index 23a8bba83c..e32c9675d7 100644 --- a/patchsets/ruby/1.8.7/p358/railsexpress +++ b/patchsets/ruby/1.8.7/p358/railsexpress @@ -1,17 +1,17 @@ -railsexpress/01-ignore-generated-files.patch -railsexpress/02-fix-tests-for-osx.patch -railsexpress/03-sigvtalrm-fix.patch -railsexpress/04-railsbench-gc-patch.patch -railsexpress/05-display-full-stack-trace.patch -railsexpress/06-better-source-file-tracing.patch -railsexpress/07-heap-dump-support.patch -railsexpress/08-fork-support-for-gc-logging.patch -railsexpress/09-track-malloc-size.patch -railsexpress/10-track-object-allocation.patch -railsexpress/11-expose-heap-slots.patch -railsexpress/12-fix-heap-size-growth-logic.patch -railsexpress/13-heap-slot-size.patch -railsexpress/14-add-trace-stats-enabled-methods.patch -railsexpress/15-track-live-dataset-size.patch -railsexpress/16-add-object-size-information-to-heap-dump.patch -railsexpress/17-caller-for-all-threads.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p358/railsexpress/01-ignore-generated-files.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p358/railsexpress/02-fix-tests-for-osx.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p358/railsexpress/03-sigvtalrm-fix.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p358/railsexpress/04-railsbench-gc-patch.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p358/railsexpress/05-display-full-stack-trace.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p358/railsexpress/06-better-source-file-tracing.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p358/railsexpress/07-heap-dump-support.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p358/railsexpress/08-fork-support-for-gc-logging.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p358/railsexpress/09-track-malloc-size.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p358/railsexpress/10-track-object-allocation.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p358/railsexpress/11-expose-heap-slots.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p358/railsexpress/12-fix-heap-size-growth-logic.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p358/railsexpress/13-heap-slot-size.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p358/railsexpress/14-add-trace-stats-enabled-methods.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p358/railsexpress/15-track-live-dataset-size.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p358/railsexpress/16-add-object-size-information-to-heap-dump.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p358/railsexpress/17-caller-for-all-threads.patch diff --git a/patchsets/ruby/1.8.7/p370/railsexpress b/patchsets/ruby/1.8.7/p370/railsexpress index 24413dd9a0..c2c23f6f59 100644 --- a/patchsets/ruby/1.8.7/p370/railsexpress +++ b/patchsets/ruby/1.8.7/p370/railsexpress @@ -1,19 +1,19 @@ -railsexpress/01-ignore-generated-files.patch -railsexpress/02-fix-tests-for-osx.patch -railsexpress/03-sigvtalrm-fix.patch -railsexpress/04-railsbench-gc-patch.patch -railsexpress/05-display-full-stack-trace.patch -railsexpress/06-better-source-file-tracing.patch -railsexpress/07-heap-dump-support.patch -railsexpress/08-fork-support-for-gc-logging.patch -railsexpress/09-track-malloc-size.patch -railsexpress/10-track-object-allocation.patch -railsexpress/11-expose-heap-slots.patch -railsexpress/12-fix-heap-size-growth-logic.patch -railsexpress/13-heap-slot-size.patch -railsexpress/14-add-trace-stats-enabled-methods.patch -railsexpress/15-track-live-dataset-size.patch -railsexpress/16-add-object-size-information-to-heap-dump.patch -railsexpress/17-caller-for-all-threads.patch -railsexpress/18-fix-zlib-deflate.patch -railsexpress/19-fix-broken-seek-on-osx.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p370/railsexpress/01-ignore-generated-files.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p370/railsexpress/02-fix-tests-for-osx.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p370/railsexpress/03-sigvtalrm-fix.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p370/railsexpress/04-railsbench-gc-patch.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p370/railsexpress/05-display-full-stack-trace.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p370/railsexpress/06-better-source-file-tracing.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p370/railsexpress/07-heap-dump-support.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p370/railsexpress/08-fork-support-for-gc-logging.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p370/railsexpress/09-track-malloc-size.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p370/railsexpress/10-track-object-allocation.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p370/railsexpress/11-expose-heap-slots.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p370/railsexpress/12-fix-heap-size-growth-logic.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p370/railsexpress/13-heap-slot-size.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p370/railsexpress/14-add-trace-stats-enabled-methods.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p370/railsexpress/15-track-live-dataset-size.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p370/railsexpress/16-add-object-size-information-to-heap-dump.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p370/railsexpress/17-caller-for-all-threads.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p370/railsexpress/18-fix-zlib-deflate.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.8.7/p370/railsexpress/19-fix-broken-seek-on-osx.patch diff --git a/patchsets/ruby/1.9.2/p180/railsexpress b/patchsets/ruby/1.9.2/p180/railsexpress index 0dae49b220..3f0d59280e 100644 --- a/patchsets/ruby/1.9.2/p180/railsexpress +++ b/patchsets/ruby/1.9.2/p180/railsexpress @@ -1,5 +1,5 @@ -railsexpress/01-railsbench-gc-patch.patch -railsexpress/02-display-more-detailed-stack-trace.patch -railsexpress/03-fork-support-for-gc-logging.patch -railsexpress/04-track-live-dataset-size.patch -railsexpress/05-load-performance-fix.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.2/p180/railsexpress/01-railsbench-gc-patch.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.2/p180/railsexpress/02-display-more-detailed-stack-trace.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.2/p180/railsexpress/03-fork-support-for-gc-logging.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.2/p180/railsexpress/04-track-live-dataset-size.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.2/p180/railsexpress/05-load-performance-fix.patch diff --git a/patchsets/ruby/1.9.2/p290/railsexpress b/patchsets/ruby/1.9.2/p290/railsexpress index 945f7c610b..64884530f0 100644 --- a/patchsets/ruby/1.9.2/p290/railsexpress +++ b/patchsets/ruby/1.9.2/p290/railsexpress @@ -1,6 +1,6 @@ -railsexpress/01-railsbench-gc-patch.patch -railsexpress/02-display-more-detailed-stack-trace.patch -railsexpress/03-fork-support-for-gc-logging.patch -railsexpress/04-track-live-dataset-size.patch -railsexpress/05-load-performance-fix.patch -railsexpress/06-trace-bmethods.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.2/p290/railsexpress/01-railsbench-gc-patch.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.2/p290/railsexpress/02-display-more-detailed-stack-trace.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.2/p290/railsexpress/03-fork-support-for-gc-logging.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.2/p290/railsexpress/04-track-live-dataset-size.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.2/p290/railsexpress/05-load-performance-fix.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.2/p290/railsexpress/06-trace-bmethods.patch diff --git a/patchsets/ruby/1.9.2/p318/railsexpress b/patchsets/ruby/1.9.2/p318/railsexpress index 3e7ae4d7ca..662f341e87 100644 --- a/patchsets/ruby/1.9.2/p318/railsexpress +++ b/patchsets/ruby/1.9.2/p318/railsexpress @@ -1,4 +1,4 @@ -railsexpress/01-railsbench-gc-patch.patch -railsexpress/02-display-more-detailed-stack-trace.patch -railsexpress/03-fork-support-for-gc-logging.patch -railsexpress/04-track-live-dataset-size.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.2/p318/railsexpress/01-railsbench-gc-patch.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.2/p318/railsexpress/02-display-more-detailed-stack-trace.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.2/p318/railsexpress/03-fork-support-for-gc-logging.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.2/p318/railsexpress/04-track-live-dataset-size.patch diff --git a/patchsets/ruby/1.9.2/p320/railsexpress b/patchsets/ruby/1.9.2/p320/railsexpress index 3e7ae4d7ca..d9e2da9b7f 100644 --- a/patchsets/ruby/1.9.2/p320/railsexpress +++ b/patchsets/ruby/1.9.2/p320/railsexpress @@ -1,4 +1,4 @@ -railsexpress/01-railsbench-gc-patch.patch -railsexpress/02-display-more-detailed-stack-trace.patch -railsexpress/03-fork-support-for-gc-logging.patch -railsexpress/04-track-live-dataset-size.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.2/p320/railsexpress/01-railsbench-gc-patch.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.2/p320/railsexpress/02-display-more-detailed-stack-trace.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.2/p320/railsexpress/03-fork-support-for-gc-logging.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.2/p320/railsexpress/04-track-live-dataset-size.patch diff --git a/patchsets/ruby/1.9.3/head/railsexpress b/patchsets/ruby/1.9.3/head/railsexpress index 590c5c520a..e8e208662c 100644 --- a/patchsets/ruby/1.9.3/head/railsexpress +++ b/patchsets/ruby/1.9.3/head/railsexpress @@ -1,14 +1,14 @@ -railsexpress/01-fix-make-clean.patch -railsexpress/02-railsbench-gc.patch -railsexpress/03-display-more-detailed-stack-trace.patch -railsexpress/04-fork-support-for-gc-logging.patch -railsexpress/05-track-live-dataset-size.patch -railsexpress/06-webrick_204_304_keep_alive_fix.patch -railsexpress/07-export-a-few-more-symbols-for-ruby-prof.patch -railsexpress/08-thread-variables.patch -railsexpress/09-faster-loading.patch -railsexpress/10-falcon-st-opt.patch -railsexpress/11-falcon-sparse-array.patch -railsexpress/12-falcon-array-queue.patch -railsexpress/13-railsbench-gc-fixes.patch -railsexpress/14-show-full-backtrace-on-stack-overflow.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/head/railsexpress/01-fix-make-clean.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/head/railsexpress/02-railsbench-gc.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/head/railsexpress/03-display-more-detailed-stack-trace.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/head/railsexpress/04-fork-support-for-gc-logging.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/head/railsexpress/05-track-live-dataset-size.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/head/railsexpress/06-webrick_204_304_keep_alive_fix.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/head/railsexpress/07-export-a-few-more-symbols-for-ruby-prof.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/head/railsexpress/08-thread-variables.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/head/railsexpress/09-faster-loading.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/head/railsexpress/10-falcon-st-opt.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/head/railsexpress/11-falcon-sparse-array.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/head/railsexpress/12-falcon-array-queue.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/head/railsexpress/13-railsbench-gc-fixes.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/head/railsexpress/14-show-full-backtrace-on-stack-overflow.patch diff --git a/patchsets/ruby/1.9.3/p125/railsexpress b/patchsets/ruby/1.9.3/p125/railsexpress index fd0a2aef47..28cc02079f 100644 --- a/patchsets/ruby/1.9.3/p125/railsexpress +++ b/patchsets/ruby/1.9.3/p125/railsexpress @@ -1,9 +1,9 @@ -railsexpress/01-merge-revision-s-34719-34720-b.patch -railsexpress/02-railsbench-gc.patch -railsexpress/03-display-more-detailed-stack-trace.patch -railsexpress/04-fork-support-for-gc-logging.patch -railsexpress/05-track-live-dataset-size.patch -railsexpress/06-export-some-symbols-for-rubyprof.patch -railsexpress/07-revert-f6b49243eb0c21bea1c4198cdd52a549e6ead075.patch -railsexpress/08-backport-c2086cc7ff1142b14c95c.patch -railsexpress/09-webrick_204_304_keep_alive_fix.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p125/railsexpress/01-merge-revision-s-34719-34720-b.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p125/railsexpress/02-railsbench-gc.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p125/railsexpress/03-display-more-detailed-stack-trace.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p125/railsexpress/04-fork-support-for-gc-logging.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p125/railsexpress/05-track-live-dataset-size.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p125/railsexpress/06-export-some-symbols-for-rubyprof.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p125/railsexpress/07-revert-f6b49243eb0c21bea1c4198cdd52a549e6ead075.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p125/railsexpress/08-backport-c2086cc7ff1142b14c95c.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p125/railsexpress/09-webrick_204_304_keep_alive_fix.patch diff --git a/patchsets/ruby/1.9.3/p194/railsexpress b/patchsets/ruby/1.9.3/p194/railsexpress index deb1016c35..1aa1dd16ed 100644 --- a/patchsets/ruby/1.9.3/p194/railsexpress +++ b/patchsets/ruby/1.9.3/p194/railsexpress @@ -1,9 +1,9 @@ -railsexpress/01-revert-f6b49243eb0c21bea1c4198cdd52a549e6ead075.patch -railsexpress/02-backport-c2086cc7ff1142b14c95c8758af24b8689b78ffc.patch -railsexpress/03-railsbench-gc.patch -railsexpress/04-display-more-detailed-stack-trace.patch -railsexpress/05-fork-support-for-gc-logging.patch -railsexpress/06-track-live-dataset-size.patch -railsexpress/07-webrick_204_304_keep_alive_fix.patch -railsexpress/08-export-a-few-more-symbols-for-ruby-prof.patch -railsexpress/09-avoid-using-broken-ffi-headers.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p194/railsexpress/01-revert-f6b49243eb0c21bea1c4198cdd52a549e6ead075.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p194/railsexpress/02-backport-c2086cc7ff1142b14c95c8758af24b8689b78ffc.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p194/railsexpress/03-railsbench-gc.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p194/railsexpress/04-display-more-detailed-stack-trace.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p194/railsexpress/05-fork-support-for-gc-logging.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p194/railsexpress/06-track-live-dataset-size.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p194/railsexpress/07-webrick_204_304_keep_alive_fix.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p194/railsexpress/08-export-a-few-more-symbols-for-ruby-prof.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p194/railsexpress/09-avoid-using-broken-ffi-headers.patch diff --git a/patchsets/ruby/1.9.3/p286/railsexpress b/patchsets/ruby/1.9.3/p286/railsexpress index d4504ec5a7..1e9eb231dd 100644 --- a/patchsets/ruby/1.9.3/p286/railsexpress +++ b/patchsets/ruby/1.9.3/p286/railsexpress @@ -1,7 +1,7 @@ -railsexpress/01-railsbench-gc.patch -railsexpress/02-display-more-detailed-stack-trace.patch -railsexpress/03-fork-support-for-gc-logging.patch -railsexpress/04-track-live-dataset-size.patch -railsexpress/05-webrick_204_304_keep_alive_fix.patch -railsexpress/06-export-a-few-more-symbols-for-ruby-prof.patch -railsexpress/07-thread-variables.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p286/railsexpress/01-railsbench-gc.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p286/railsexpress/02-display-more-detailed-stack-trace.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p286/railsexpress/03-fork-support-for-gc-logging.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p286/railsexpress/04-track-live-dataset-size.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p286/railsexpress/05-webrick_204_304_keep_alive_fix.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p286/railsexpress/06-export-a-few-more-symbols-for-ruby-prof.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p286/railsexpress/07-thread-variables.patch diff --git a/patchsets/ruby/1.9.3/p327/railsexpress b/patchsets/ruby/1.9.3/p327/railsexpress index aff80a3cf6..ad217ebf5e 100644 --- a/patchsets/ruby/1.9.3/p327/railsexpress +++ b/patchsets/ruby/1.9.3/p327/railsexpress @@ -1,12 +1,12 @@ -railsexpress/01-fix-make-clean.patch -railsexpress/02-railsbench-gc.patch -railsexpress/03-display-more-detailed-stack-trace.patch -railsexpress/04-fork-support-for-gc-logging.patch -railsexpress/05-track-live-dataset-size.patch -railsexpress/06-webrick_204_304_keep_alive_fix.patch -railsexpress/07-export-a-few-more-symbols-for-ruby-prof.patch -railsexpress/08-thread-variables.patch -railsexpress/09-faster-loading.patch -railsexpress/10-falcon-st-opt.patch -railsexpress/11-falcon-array-queue.patch -railsexpress/12-falcon-sparse-array.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p327/railsexpress/01-fix-make-clean.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p327/railsexpress/02-railsbench-gc.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p327/railsexpress/03-display-more-detailed-stack-trace.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p327/railsexpress/04-fork-support-for-gc-logging.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p327/railsexpress/05-track-live-dataset-size.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p327/railsexpress/06-webrick_204_304_keep_alive_fix.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p327/railsexpress/07-export-a-few-more-symbols-for-ruby-prof.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p327/railsexpress/08-thread-variables.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p327/railsexpress/09-faster-loading.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p327/railsexpress/10-falcon-st-opt.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p327/railsexpress/11-falcon-array-queue.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p327/railsexpress/12-falcon-sparse-array.patch diff --git a/patchsets/ruby/1.9.3/p362/railsexpress b/patchsets/ruby/1.9.3/p362/railsexpress index 931fe76c26..c05e57915b 100644 --- a/patchsets/ruby/1.9.3/p362/railsexpress +++ b/patchsets/ruby/1.9.3/p362/railsexpress @@ -1,12 +1,12 @@ -railsexpress/01-fix-make-clean.patch -railsexpress/02-railsbench-gc.patch -railsexpress/03-display-more-detailed-stack-trace.patch -railsexpress/04-fork-support-for-gc-logging.patch -railsexpress/05-track-live-dataset-size.patch -railsexpress/06-webrick_204_304_keep_alive_fix.patch -railsexpress/07-export-a-few-more-symbols-for-ruby-prof.patch -railsexpress/08-thread-variables.patch -railsexpress/09-faster-loading.patch -railsexpress/10-falcon-st-opt.patch -railsexpress/11-falcon-sparse-array.patch -railsexpress/12-falcon-array-queue.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p362/railsexpress/01-fix-make-clean.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p362/railsexpress/02-railsbench-gc.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p362/railsexpress/03-display-more-detailed-stack-trace.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p362/railsexpress/04-fork-support-for-gc-logging.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p362/railsexpress/05-track-live-dataset-size.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p362/railsexpress/06-webrick_204_304_keep_alive_fix.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p362/railsexpress/07-export-a-few-more-symbols-for-ruby-prof.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p362/railsexpress/08-thread-variables.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p362/railsexpress/09-faster-loading.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p362/railsexpress/10-falcon-st-opt.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p362/railsexpress/11-falcon-sparse-array.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p362/railsexpress/12-falcon-array-queue.patch diff --git a/patchsets/ruby/1.9.3/p374/railsexpress b/patchsets/ruby/1.9.3/p374/railsexpress index 931fe76c26..e4a2793c6f 100644 --- a/patchsets/ruby/1.9.3/p374/railsexpress +++ b/patchsets/ruby/1.9.3/p374/railsexpress @@ -1,12 +1,12 @@ -railsexpress/01-fix-make-clean.patch -railsexpress/02-railsbench-gc.patch -railsexpress/03-display-more-detailed-stack-trace.patch -railsexpress/04-fork-support-for-gc-logging.patch -railsexpress/05-track-live-dataset-size.patch -railsexpress/06-webrick_204_304_keep_alive_fix.patch -railsexpress/07-export-a-few-more-symbols-for-ruby-prof.patch -railsexpress/08-thread-variables.patch -railsexpress/09-faster-loading.patch -railsexpress/10-falcon-st-opt.patch -railsexpress/11-falcon-sparse-array.patch -railsexpress/12-falcon-array-queue.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p374/railsexpress/01-fix-make-clean.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p374/railsexpress/02-railsbench-gc.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p374/railsexpress/03-display-more-detailed-stack-trace.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p374/railsexpress/04-fork-support-for-gc-logging.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p374/railsexpress/05-track-live-dataset-size.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p374/railsexpress/06-webrick_204_304_keep_alive_fix.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p374/railsexpress/07-export-a-few-more-symbols-for-ruby-prof.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p374/railsexpress/08-thread-variables.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p374/railsexpress/09-faster-loading.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p374/railsexpress/10-falcon-st-opt.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p374/railsexpress/11-falcon-sparse-array.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p374/railsexpress/12-falcon-array-queue.patch diff --git a/patchsets/ruby/1.9.3/p385/railsexpress b/patchsets/ruby/1.9.3/p385/railsexpress index 931fe76c26..2d2cf19dcb 100644 --- a/patchsets/ruby/1.9.3/p385/railsexpress +++ b/patchsets/ruby/1.9.3/p385/railsexpress @@ -1,12 +1,12 @@ -railsexpress/01-fix-make-clean.patch -railsexpress/02-railsbench-gc.patch -railsexpress/03-display-more-detailed-stack-trace.patch -railsexpress/04-fork-support-for-gc-logging.patch -railsexpress/05-track-live-dataset-size.patch -railsexpress/06-webrick_204_304_keep_alive_fix.patch -railsexpress/07-export-a-few-more-symbols-for-ruby-prof.patch -railsexpress/08-thread-variables.patch -railsexpress/09-faster-loading.patch -railsexpress/10-falcon-st-opt.patch -railsexpress/11-falcon-sparse-array.patch -railsexpress/12-falcon-array-queue.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p385/railsexpress/01-fix-make-clean.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p385/railsexpress/02-railsbench-gc.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p385/railsexpress/03-display-more-detailed-stack-trace.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p385/railsexpress/04-fork-support-for-gc-logging.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p385/railsexpress/05-track-live-dataset-size.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p385/railsexpress/06-webrick_204_304_keep_alive_fix.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p385/railsexpress/07-export-a-few-more-symbols-for-ruby-prof.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p385/railsexpress/08-thread-variables.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p385/railsexpress/09-faster-loading.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p385/railsexpress/10-falcon-st-opt.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p385/railsexpress/11-falcon-sparse-array.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p385/railsexpress/12-falcon-array-queue.patch diff --git a/patchsets/ruby/1.9.3/p392/railsexpress b/patchsets/ruby/1.9.3/p392/railsexpress index 590c5c520a..4fdea2fe61 100644 --- a/patchsets/ruby/1.9.3/p392/railsexpress +++ b/patchsets/ruby/1.9.3/p392/railsexpress @@ -1,14 +1,14 @@ -railsexpress/01-fix-make-clean.patch -railsexpress/02-railsbench-gc.patch -railsexpress/03-display-more-detailed-stack-trace.patch -railsexpress/04-fork-support-for-gc-logging.patch -railsexpress/05-track-live-dataset-size.patch -railsexpress/06-webrick_204_304_keep_alive_fix.patch -railsexpress/07-export-a-few-more-symbols-for-ruby-prof.patch -railsexpress/08-thread-variables.patch -railsexpress/09-faster-loading.patch -railsexpress/10-falcon-st-opt.patch -railsexpress/11-falcon-sparse-array.patch -railsexpress/12-falcon-array-queue.patch -railsexpress/13-railsbench-gc-fixes.patch -railsexpress/14-show-full-backtrace-on-stack-overflow.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p392/railsexpress/01-fix-make-clean.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p392/railsexpress/02-railsbench-gc.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p392/railsexpress/03-display-more-detailed-stack-trace.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p392/railsexpress/04-fork-support-for-gc-logging.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p392/railsexpress/05-track-live-dataset-size.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p392/railsexpress/06-webrick_204_304_keep_alive_fix.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p392/railsexpress/07-export-a-few-more-symbols-for-ruby-prof.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p392/railsexpress/08-thread-variables.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p392/railsexpress/09-faster-loading.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p392/railsexpress/10-falcon-st-opt.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p392/railsexpress/11-falcon-sparse-array.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p392/railsexpress/12-falcon-array-queue.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p392/railsexpress/13-railsbench-gc-fixes.patch +https://raw.github.com/skaes/rvm-patchsets/master/patches/ruby/1.9.3/p392/railsexpress/14-show-full-backtrace-on-stack-overflow.patch