/spec/ruby/library/bigdecimal/

a>10
-rw-r--r--.github/dependabot.yml6
-rw-r--r--.github/workflows/baseruby.yml33
-rw-r--r--.github/workflows/bundled_gems.yml63
-rw-r--r--.github/workflows/check_dependencies.yml27
-rw-r--r--.github/workflows/check_misc.yml92
-rw-r--r--.github/workflows/codeql-analysis.yml48
-rw-r--r--.github/workflows/compilers.yml302
-rw-r--r--.github/workflows/macos.yml113
-rw-r--r--.github/workflows/mingw.yml67
-rw-r--r--.github/workflows/mjit-bindgen.yml104
-rw-r--r--.github/workflows/mjit.yml50
-rw-r--r--.github/workflows/publish.yml18
-rw-r--r--.github/workflows/scorecards.yml72
-rw-r--r--.github/workflows/spec_guards.yml52
-rw-r--r--.github/workflows/ubuntu.yml73
-rw-r--r--.github/workflows/wasm.yml146
-rw-r--r--.github/workflows/windows.yml104
-rw-r--r--.github/workflows/yjit-ubuntu.yml116
-rw-r--r--.github/workflows/yjit_asm_tests.yml38
-rw-r--r--.gitignore20
-rw-r--r--.indent.pro32
-rw-r--r--.rdoc_options4
-rw-r--r--.travis.yml234
-rw-r--r--CONTRIBUTING.md6
-rw-r--r--LEGAL10
-rw-r--r--NEWS.md1110
-rw-r--r--README.ja.md5
-rw-r--r--README.md141
-rw-r--r--addr2line.c457
-rw-r--r--array.c3299
-rw-r--r--ast.c75
-rw-r--r--ast.rb110
-rwxr-xr-xbasictest/test.rb3
-rw-r--r--benchmark/README.md8
-rw-r--r--benchmark/array_sort_int.yml15
-rw-r--r--benchmark/buffer_each.yml27
-rw-r--r--benchmark/buffer_get.yml32
-rw-r--r--benchmark/cgi_escape_html.yml37
-rw-r--r--benchmark/constant_invalidation.rb22
-rw-r--r--benchmark/enum_minmax.yml25
-rw-r--r--benchmark/enum_sort.yml15
-rw-r--r--benchmark/erb_escape_html.yml31
-rw-r--r--benchmark/io_write.rb22
-rw-r--r--benchmark/lib/benchmark_driver/runner/mjit.rb2
-rw-r--r--benchmark/lib/benchmark_driver/runner/mjit_exec.rb237
-rw-r--r--benchmark/marshal_dump_load_integer.yml22
-rw-r--r--benchmark/masgn.yml26
-rw-r--r--benchmark/mjit_exec_jt2jt.yml6
-rw-r--r--benchmark/mjit_exec_vm2jt.yml6
-rw-r--r--benchmark/mjit_exec_vm2vm.yml6
-rw-r--r--benchmark/module_eqq.yml27
-rw-r--r--benchmark/numeric_methods.yml16
-rw-r--r--benchmark/range_min.yml2
-rw-r--r--benchmark/so_nbody.rb58
-rw-r--r--benchmark/string_concat.yml45
-rw-r--r--benchmark/time_now.yml3
-rw-r--r--benchmark/time_parse.yml2
-rw-r--r--benchmark/vm_const.yml6
-rw-r--r--benchmark/vm_freezeobj.yml6
-rw-r--r--benchmark/vm_ivar_embedded_obj_init.yml14
-rw-r--r--benchmark/vm_ivar_extended_obj_init.yml (renamed from benchmark/vm_ivar_init.yml)8
-rw-r--r--benchmark/vm_ivar_generic_get.yml17
-rw-r--r--benchmark/vm_ivar_generic_set.yml14
-rw-r--r--benchmark/vm_ivar_get.yml37
-rw-r--r--benchmark/vm_ivar_get_unintialized.yml12
-rw-r--r--benchmark/vm_ivar_lazy_set.yml12
-rw-r--r--benchmark/vm_ivar_set_on_instance.yml35
-rw-r--r--benchmark/vm_ivar_set_subclass.yml9
-rw-r--r--benchmark/vm_lvar_cond_set.yml8
-rw-r--r--bignum.c1185
-rwxr-xr-xbin/gem19
-rwxr-xr-xbootstraptest/runner.rb823
-rw-r--r--bootstraptest/test_attr.rb16
-rw-r--r--bootstraptest/test_autoload.rb30
-rw-r--r--bootstraptest/test_constant_cache.rb187
-rw-r--r--bootstraptest/test_io.rb5
-rw-r--r--bootstraptest/test_literal.rb7
-rw-r--r--bootstraptest/test_method.rb2
-rw-r--r--bootstraptest/test_ractor.rb78
-rw-r--r--bootstraptest/test_thread.rb8
-rw-r--r--bootstraptest/test_yjit.rb819
-rw-r--r--bootstraptest/test_yjit_rust_port.rb422
-rw-r--r--builtin.h77
-rw-r--r--ccan/build_assert/build_assert.h12
-rw-r--r--ccan/check_type/check_type.h28
-rw-r--r--ccan/container_of/container_of.h52
-rw-r--r--ccan/list/list.h587
-rw-r--r--ccan/str/str.h9
-rw-r--r--class.c910
-rw-r--r--common.mk1493
-rw-r--r--compar.c38
-rw-r--r--compile.c7680
-rw-r--r--complex.c797
-rw-r--r--configure.ac806
-rw-r--r--cont.c866
-rw-r--r--coroutine/amd64/Context.h25
-rw-r--r--coroutine/arm64/Context.h25
-rw-r--r--coroutine/asyncify/Context.c10
-rw-r--r--coroutine/asyncify/Context.h93
-rw-r--r--coroutine/ppc/Context.S90
-rw-r--r--coroutine/ppc/Context.h58
-rw-r--r--coroutine/ppc64/Context.S89
-rw-r--r--coroutine/ppc64/Context.h57
-rw-r--r--coroutine/universal/Context.S6
-rw-r--r--coroutine/universal/Context.h6
-rw-r--r--cygwin/GNUmakefile.in35
-rw-r--r--darray.h107
-rw-r--r--debug.c373
-rw-r--r--debug_counter.c36
-rw-r--r--debug_counter.h45
-rw-r--r--defs/gmake.mk208
-rw-r--r--defs/id.def7
-rw-r--r--defs/keywords2
-rw-r--r--defs/lex.c.src2
-rw-r--r--dir.c1785
-rw-r--r--dir.rb102
-rw-r--r--dln.c451
-rw-r--r--dln_find.c246
-rw-r--r--dmyenc.c2
-rw-r--r--doc/.document7
-rw-r--r--doc/ChangeLog-0.60_to_1.12
-rw-r--r--doc/ChangeLog-1.9.32
-rw-r--r--doc/ChangeLog-2.0.08
-rw-r--r--doc/ChangeLog-2.3.015
-rw-r--r--doc/NEWS/NEWS-1.8.7 (renamed from doc/NEWS-1.8.7)0
-rw-r--r--doc/NEWS/NEWS-1.9.1 (renamed from doc/NEWS-1.9.1)0
-rw-r--r--doc/NEWS/NEWS-1.9.2 (renamed from doc/NEWS-1.9.2)0
-rw-r--r--doc/NEWS/NEWS-1.9.3 (renamed from doc/NEWS-1.9.3)0
-rw-r--r--doc/NEWS/NEWS-2.0.0 (renamed from doc/NEWS-2.0.0)0
-rw-r--r--doc/NEWS/NEWS-2.1.0 (renamed from doc/NEWS-2.1.0)0
-rw-r--r--doc/NEWS/NEWS-2.2.0 (renamed from doc/NEWS-2.2.0)0
-rw-r--r--doc/NEWS/NEWS-2.3.0 (renamed from doc/NEWS-2.3.0)0
-rw-r--r--doc/NEWS/NEWS-2.4.0 (renamed from doc/NEWS-2.4.0)0
-rw-r--r--doc/NEWS/NEWS-2.5.0 (renamed from doc/NEWS-2.5.0)0
-rw-r--r--doc/NEWS/NEWS-2.6.0 (renamed from doc/NEWS-2.6.0)0
-rw-r--r--doc/NEWS/NEWS-2.7.0 (renamed from doc/NEWS-2.7.0)10
-rw-r--r--doc/NEWS/NEWS-3.0.0.md (renamed from doc/NEWS-3.0.0.md)12
-rw-r--r--doc/NEWS/NEWS-3.1.0.md660
-rw-r--r--doc/case_mapping.rdoc4
-rw-r--r--doc/character_selectors.rdoc97
-rw-r--r--doc/command_injection.rdoc29
-rw-r--r--doc/contributing.md12
-rw-r--r--doc/contributing.rdoc402
-rw-r--r--doc/contributing/building_ruby.md172
-rw-r--r--doc/contributing/documentation_guide.md435
-rw-r--r--doc/contributing/making_changes_to_ruby.md28
-rw-r--r--doc/contributing/making_changes_to_stdlibs.md49
-rw-r--r--doc/contributing/reporting_issues.md91
-rw-r--r--doc/contributing/testing_ruby.md138
-rw-r--r--doc/date/calendars.rdoc62
-rw-r--r--doc/documentation_guide.rdoc281
-rw-r--r--doc/encodings.rdoc479
-rw-r--r--doc/examples/files.rdoc26
-rw-r--r--doc/extension.ja.rdoc40
-rw-r--r--doc/extension.rdoc79
-rw-r--r--doc/format_specifications.rdoc348
-rw-r--r--doc/hacking.md85
-rw-r--r--doc/implicit_conversion.rdoc23
-rw-r--r--doc/maintainers.rdoc10
-rw-r--r--doc/make_cheatsheet.md124
-rw-r--r--doc/matchdata/begin.rdoc30
-rw-r--r--doc/matchdata/end.rdoc30
-rw-r--r--doc/matchdata/offset.rdoc31
-rw-r--r--doc/math/math.rdoc117
-rw-r--r--doc/memory_view.md4
-rw-r--r--doc/mjit/mjit.md39
-rw-r--r--doc/net-http/examples.rdoc31
-rw-r--r--doc/net-http/included_getters.rdoc3
-rw-r--r--doc/optparse/.document1
-rw-r--r--doc/optparse/creates_option.rdoc4
-rw-r--r--doc/optparse/option_params.rdoc6
-rw-r--r--doc/optparse/tutorial.rdoc4
-rw-r--r--doc/packed_data.rdoc590
-rw-r--r--doc/ractor.md2
-rw-r--r--doc/rdoc/markup_reference.rb1257
-rw-r--r--doc/regexp.rdoc63
-rw-r--r--doc/standard_library.rdoc5
-rw-r--r--doc/strftime_formatting.rdoc527
-rw-r--r--doc/string/b.rdoc14
-rw-r--r--doc/string/bytes.rdoc6
-rw-r--r--doc/string/bytesize.rdoc11
-rw-r--r--doc/string/center.rdoc16
-rw-r--r--doc/string/chars.rdoc5
-rw-r--r--doc/string/chomp.rdoc29
-rw-r--r--doc/string/chop.rdoc16
-rw-r--r--doc/string/codepoints.rdoc6
-rw-r--r--doc/string/delete_prefix.rdoc8
-rw-r--r--doc/string/delete_suffix.rdoc8
-rw-r--r--doc/string/each_byte.rdoc17
-rw-r--r--doc/string/each_char.rdoc17
-rw-r--r--doc/string/each_codepoint.rdoc18
-rw-r--r--doc/string/each_grapheme_cluster.rdoc12
-rw-r--r--doc/string/each_line.rdoc60
-rw-r--r--doc/string/end_with_p.rdoc11
-rw-r--r--doc/string/force_encoding.rdoc20
-rw-r--r--doc/string/grapheme_clusters.rdoc6
-rw-r--r--doc/string/index.rdoc38
-rw-r--r--doc/string/length.rdoc13
-rw-r--r--doc/string/ljust.rdoc16
-rw-r--r--doc/string/new.rdoc51
-rw-r--r--doc/string/ord.rdoc6
-rw-r--r--doc/string/partition.rdoc24
-rw-r--r--doc/string/rjust.rdoc16
-rw-r--r--doc/string/rpartition.rdoc24
-rw-r--r--doc/string/scrub.rdoc25
-rw-r--r--doc/string/split.rdoc86
-rw-r--r--doc/string/start_with_p.rdoc18
-rw-r--r--doc/string/sum.rdoc11
-rw-r--r--doc/symbol/casecmp.rdoc27
-rw-r--r--doc/symbol/casecmp_p.rdoc26
-rw-r--r--doc/syntax/assignment.rdoc6
-rw-r--r--doc/syntax/control_expressions.rdoc26
-rw-r--r--doc/syntax/literals.rdoc83
-rw-r--r--doc/syntax/methods.rdoc14
-rw-r--r--doc/syntax/modules_and_classes.rdoc4
-rw-r--r--doc/syntax/precedence.rdoc2
-rw-r--r--doc/time/in.rdoc7
-rw-r--r--doc/time/mon-min.rdoc8
-rw-r--r--doc/time/msec.rdoc2
-rw-r--r--doc/time/nsec.rdoc2
-rw-r--r--doc/time/sec.rdoc2
-rw-r--r--doc/time/sec_i.rdoc1
-rw-r--r--doc/time/usec.rdoc2
-rw-r--r--doc/time/year.rdoc1
-rw-r--r--doc/time/zone_and_in.rdoc8
-rw-r--r--doc/timezones.rdoc108
-rw-r--r--doc/transcode.rdoc52
-rw-r--r--doc/yjit/yjit.md328
-rw-r--r--enc/Makefile.in4
-rw-r--r--enc/ascii.c6
-rw-r--r--enc/cesu_8.c23
-rw-r--r--enc/depend4219
-rw-r--r--enc/encdb.c2
-rw-r--r--enc/encinit.c.erb1
-rw-r--r--enc/jis/props.h.blt4
-rw-r--r--enc/jis/props.kwd2
-rw-r--r--enc/jis/props.src2
-rwxr-xr-xenc/make_encmake.rb2
-rw-r--r--enc/trans/newline.trans20
-rw-r--r--enc/trans/transdb.c2
-rw-r--r--enc/unicode/15.0.0/casefold.h (renamed from enc/unicode/13.0.0/casefold.h)6053
-rw-r--r--enc/unicode/15.0.0/name2ctype.h (renamed from enc/unicode/13.0.0/name2ctype.h)7239
-rw-r--r--enc/utf_16_32.h2
-rw-r--r--encindex.h6
-rw-r--r--encoding.c752
-rw-r--r--enum.c1051
-rw-r--r--enumerator.c983
-rw-r--r--error.c1025
-rw-r--r--eval.c946
-rw-r--r--eval_error.c561
-rw-r--r--eval_intern.h20
-rw-r--r--eval_jump.c38
-rw-r--r--ext/-test-/RUBY_ALIGNOF/depend1
-rw-r--r--ext/-test-/abi/abi.c11
-rw-r--r--ext/-test-/abi/extconf.rb4
-rw-r--r--ext/-test-/arith_seq/beg_len_step/beg_len_step.c19
-rw-r--r--ext/-test-/arith_seq/beg_len_step/depend161
-rw-r--r--ext/-test-/arith_seq/beg_len_step/extconf.rb2
-rw-r--r--ext/-test-/arith_seq/extract/depend1
-rw-r--r--ext/-test-/array/concat/depend1
-rw-r--r--ext/-test-/array/resize/depend1
-rw-r--r--ext/-test-/bignum/depend7
-rw-r--r--ext/-test-/bug-14834/depend1
-rw-r--r--ext/-test-/bug-3571/depend1
-rw-r--r--ext/-test-/bug-5832/depend1
-rw-r--r--ext/-test-/bug_reporter/depend1
-rw-r--r--ext/-test-/class/depend2
-rw-r--r--ext/-test-/debug/depend3
-rw-r--r--ext/-test-/debug/inspector.c14
-rw-r--r--ext/-test-/debug/profile_frames.c27
-rw-r--r--ext/-test-/dln/empty/depend159
-rw-r--r--ext/-test-/dln/empty/empty.c2
-rw-r--r--ext/-test-/econv/append.c15
-rw-r--r--ext/-test-/econv/extconf.rb3
-rw-r--r--ext/-test-/econv/init.c11
-rw-r--r--ext/-test-/enumerator_kw/depend1
-rw-r--r--ext/-test-/enumerator_kw/enumerator_kw.c3
-rw-r--r--ext/-test-/eval/eval.c13
-rw-r--r--ext/-test-/eval/extconf.rb2
-rw-r--r--ext/-test-/exception/depend4
-rw-r--r--ext/-test-/fatal/depend1
-rw-r--r--ext/-test-/file/depend3
-rw-r--r--ext/-test-/file/fs.c16
-rw-r--r--ext/-test-/float/depend2
-rw-r--r--ext/-test-/funcall/depend1
-rw-r--r--ext/-test-/funcall/funcall.c12
-rw-r--r--ext/-test-/gvl/call_without_gvl/call_without_gvl.c2
-rw-r--r--ext/-test-/gvl/call_without_gvl/depend1
-rw-r--r--ext/-test-/hash/depend2
-rw-r--r--ext/-test-/integer/depend3
-rw-r--r--ext/-test-/iseq_load/depend1
-rw-r--r--ext/-test-/iter/depend3
-rw-r--r--ext/-test-/load/dot.dot/depend159
-rw-r--r--ext/-test-/load/dot.dot/dot.dot.c2
-rw-r--r--ext/-test-/load/protect/depend1
-rw-r--r--ext/-test-/marshal/compat/depend1
-rw-r--r--ext/-test-/marshal/internal_ivar/depend1
-rw-r--r--ext/-test-/marshal/internal_ivar/internal_ivar.c5
-rw-r--r--ext/-test-/marshal/usr/depend1
-rw-r--r--ext/-test-/memory_status/depend1
-rw-r--r--ext/-test-/memory_status/memory_status.c12
-rw-r--r--ext/-test-/memory_view/depend1
-rw-r--r--ext/-test-/method/depend2
-rw-r--r--ext/-test-/notimplement/depend1
-rw-r--r--ext/-test-/num2int/depend1
-rw-r--r--ext/-test-/num2int/num2int.c26
-rw-r--r--ext/-test-/path_to_class/depend1
-rw-r--r--ext/-test-/popen_deadlock/depend27
-rw-r--r--ext/-test-/postponed_job/depend1
-rw-r--r--ext/-test-/printf/depend1
-rw-r--r--ext/-test-/printf/printf.c64
-rw-r--r--ext/-test-/proc/depend3
-rw-r--r--ext/-test-/proc/super.c2
-rw-r--r--ext/-test-/random/bad_version.c135
-rw-r--r--ext/-test-/random/depend162
-rw-r--r--ext/-test-/random/loop.c1
-rw-r--r--ext/-test-/rational/depend2
-rw-r--r--ext/-test-/rb_call_super_kw/depend1
-rw-r--r--ext/-test-/rb_call_super_kw/rb_call_super_kw.c3
-rw-r--r--ext/-test-/recursion/depend1
-rw-r--r--ext/-test-/regexp/depend2
-rw-r--r--ext/-test-/scan_args/depend1
-rw-r--r--ext/-test-/st/foreach/depend1
-rw-r--r--ext/-test-/st/foreach/foreach.c100
-rw-r--r--ext/-test-/st/numhash/depend1
-rw-r--r--ext/-test-/st/numhash/numhash.c16
-rw-r--r--ext/-test-/st/update/depend1
-rw-r--r--ext/-test-/st/update/update.c12
-rw-r--r--ext/-test-/string/coderange.c8
-rw-r--r--ext/-test-/string/cstr.c16
-rw-r--r--ext/-test-/string/depend16
-rw-r--r--ext/-test-/string/fstring.c4
-rw-r--r--ext/-test-/string/qsort.c14
-rw-r--r--ext/-test-/string/set_len.c10
-rw-r--r--ext/-test-/struct/depend4
-rw-r--r--ext/-test-/struct/member.c2
-rw-r--r--ext/-test-/symbol/depend2
-rw-r--r--ext/-test-/symbol/type.c6
-rw-r--r--ext/-test-/thread/instrumentation/depend164
-rw-r--r--ext/-test-/thread/instrumentation/extconf.rb2
-rw-r--r--ext/-test-/thread/instrumentation/instrumentation.c141
-rw-r--r--ext/-test-/thread_fd/depend1
-rw-r--r--ext/-test-/time/depend3
-rw-r--r--ext/-test-/tracepoint/depend2
-rw-r--r--ext/-test-/tracepoint/gc_hook.c26
-rw-r--r--ext/-test-/tracepoint/tracepoint.c54
-rw-r--r--ext/-test-/typeddata/depend1
-rw-r--r--ext/-test-/typeddata/typeddata.c2
-rw-r--r--ext/-test-/vm/at_exit.c12
-rw-r--r--ext/-test-/vm/depend1
-rw-r--r--ext/-test-/wait/depend1
-rw-r--r--ext/-test-/win32/console/attribute.c18
-rw-r--r--ext/-test-/win32/fd_setsize/fd_setsize.c10
-rw-r--r--ext/bigdecimal/bigdecimal.c2280
-rw-r--r--ext/bigdecimal/bigdecimal.gemspec6
-rw-r--r--ext/bigdecimal/bigdecimal.h48
-rw-r--r--ext/bigdecimal/depend2
-rw-r--r--ext/bigdecimal/extconf.rb9
-rw-r--r--ext/bigdecimal/lib/bigdecimal/jacobian.rb6
-rw-r--r--ext/bigdecimal/lib/bigdecimal/util.rb6
-rw-r--r--ext/bigdecimal/missing.h51
-rw-r--r--ext/cgi/escape/depend1
-rw-r--r--ext/cgi/escape/escape.c353
-rw-r--r--ext/continuation/depend1
-rw-r--r--ext/coverage/coverage.c216
-rw-r--r--ext/coverage/depend7
-rw-r--r--ext/date/date.gemspec24
-rw-r--r--ext/date/date_core.c2035
-rw-r--r--ext/date/date_parse.c131
-rw-r--r--ext/date/date_strptime.c105
-rw-r--r--ext/date/depend4
-rw-r--r--ext/date/extconf.rb1
-rw-r--r--ext/date/lib/date.rb6
-rw-r--r--ext/date/zonetab.h4
-rw-r--r--ext/date/zonetab.list2
-rw-r--r--ext/digest/bubblebabble/bubblebabble.c2
-rw-r--r--ext/digest/bubblebabble/depend1
-rw-r--r--ext/digest/depend1
-rw-r--r--ext/digest/digest.c12
-rw-r--r--ext/digest/digest.gemspec10
-rw-r--r--ext/digest/digest.h2
-rw-r--r--ext/digest/digest_conf.rb2
-rw-r--r--ext/digest/extconf.rb4
-rw-r--r--ext/digest/install_headers.rb13
-rw-r--r--ext/digest/lib/digest/version.rb2
-rw-r--r--ext/digest/md5/depend3
-rw-r--r--ext/digest/rmd160/depend2
-rw-r--r--ext/digest/sha1/depend3
-rw-r--r--ext/digest/sha2/depend3
-rw-r--r--ext/digest/sha2/sha2.c2
-rw-r--r--ext/digest/sha2/sha2init.c2
-rw-r--r--ext/erb/escape/escape.c95
-rw-r--r--ext/erb/escape/extconf.rb7
-rw-r--r--ext/etc/depend1
-rw-r--r--ext/etc/etc.c120
-rw-r--r--ext/etc/etc.gemspec13
-rw-r--r--ext/etc/extconf.rb1
-rwxr-xr-xext/extmk.rb137
-rw-r--r--ext/fcntl/depend1
-rw-r--r--ext/fcntl/fcntl.c17
-rw-r--r--ext/fcntl/fcntl.gemspec2
-rw-r--r--ext/fiddle/closure.c135
-rw-r--r--ext/fiddle/conversions.c20
-rw-r--r--ext/fiddle/depend8
-rw-r--r--ext/fiddle/extconf.rb28
-rw-r--r--ext/fiddle/extlibs13
-rw-r--r--ext/fiddle/fiddle.c214
-rw-r--r--ext/fiddle/fiddle.gemspec3
-rw-r--r--ext/fiddle/fiddle.h21
-rw-r--r--ext/fiddle/handle.c59
-rw-r--r--ext/fiddle/lib/fiddle.rb35
-rw-r--r--ext/fiddle/lib/fiddle/closure.rb25
-rw-r--r--ext/fiddle/lib/fiddle/cparser.rb18
-rw-r--r--ext/fiddle/lib/fiddle/pack.rb35
-rw-r--r--ext/fiddle/lib/fiddle/version.rb2
-rw-r--r--ext/io/console/console.c50
-rw-r--r--ext/io/console/depend3
-rw-r--r--ext/io/console/io-console.gemspec4
-rw-r--r--ext/io/console/win32_vk.inc327
-rw-r--r--ext/io/console/win32_vk.list2
-rw-r--r--ext/io/nonblock/depend1
-rw-r--r--ext/io/nonblock/io-nonblock.gemspec16
-rw-r--r--ext/io/nonblock/nonblock.c67
-rw-r--r--ext/io/wait/depend1
-rw-r--r--ext/io/wait/extconf.rb32
-rw-r--r--ext/io/wait/io-wait.gemspec23
-rw-r--r--ext/io/wait/wait.c212
-rw-r--r--ext/json/VERSION2
-rw-r--r--ext/json/generator/depend1
-rw-r--r--ext/json/generator/generator.c4
-rw-r--r--ext/json/lib/json/version.rb2
-rw-r--r--ext/json/parser/depend1
-rw-r--r--ext/json/parser/extconf.rb4
-rw-r--r--ext/json/parser/parser.c23
-rw-r--r--ext/json/parser/parser.rl23
-rw-r--r--ext/monitor/depend1
-rw-r--r--ext/nkf/depend1
-rw-r--r--ext/nkf/nkf-utf8/nkf.c14
-rw-r--r--ext/nkf/nkf.c88
-rw-r--r--ext/nkf/nkf.gemspec2
-rw-r--r--ext/objspace/depend27
-rw-r--r--ext/objspace/lib/objspace.rb97
-rw-r--r--ext/objspace/object_tracing.c167
-rw-r--r--ext/objspace/objspace.c420
-rw-r--r--ext/objspace/objspace_dump.c280
-rw-r--r--ext/openssl/History.md207
-rw-r--r--ext/openssl/depend32
-rw-r--r--ext/openssl/extconf.rb104
-rw-r--r--ext/openssl/lib/openssl/pkey.rb20
-rw-r--r--ext/openssl/lib/openssl/ssl.rb5
-rw-r--r--ext/openssl/lib/openssl/version.rb2
-rw-r--r--ext/openssl/openssl.gemspec2
-rw-r--r--ext/openssl/ossl.h10
-rw-r--r--ext/openssl/ossl_asn1.c21
-rw-r--r--ext/openssl/ossl_bn.c36
-rw-r--r--ext/openssl/ossl_cipher.c3
-rw-r--r--ext/openssl/ossl_hmac.c8
-rw-r--r--ext/openssl/ossl_kdf.c6
-rw-r--r--ext/openssl/ossl_ocsp.c4
-rw-r--r--ext/openssl/ossl_pkey.c52
-rw-r--r--ext/openssl/ossl_pkey.h2
-rw-r--r--ext/openssl/ossl_pkey_dh.c12
-rw-r--r--ext/openssl/ossl_pkey_dsa.c14
-rw-r--r--ext/openssl/ossl_pkey_ec.c68
-rw-r--r--ext/openssl/ossl_pkey_rsa.c12
-rw-r--r--ext/openssl/ossl_ssl.c261
-rw-r--r--ext/openssl/ossl_ssl_session.c4
-rw-r--r--ext/openssl/ossl_x509cert.c6
-rw-r--r--ext/openssl/ossl_x509crl.c6
-rw-r--r--ext/openssl/ossl_x509req.c6
-rw-r--r--ext/openssl/ossl_x509revoked.c6
-rw-r--r--ext/pathname/depend1
-rw-r--r--ext/pathname/lib/pathname.rb15
-rw-r--r--ext/pathname/pathname.c20
-rw-r--r--ext/pathname/pathname.gemspec4
-rw-r--r--ext/psych/.gitignore1
-rw-r--r--ext/psych/depend19
-rw-r--r--ext/psych/extconf.rb70
-rw-r--r--ext/psych/lib/psych.rb16
-rw-r--r--ext/psych/lib/psych/exception.rb14
-rw-r--r--ext/psych/lib/psych/nodes/node.rb4
-rw-r--r--ext/psych/lib/psych/parser.rb13
-rw-r--r--ext/psych/lib/psych/scalar_scanner.rb29
-rw-r--r--ext/psych/lib/psych/versions.rb4
-rw-r--r--ext/psych/lib/psych/visitors/to_ruby.rb12
-rw-r--r--ext/psych/lib/psych/visitors/yaml_tree.rb16
-rw-r--r--ext/psych/psych.gemspec3
-rw-r--r--ext/psych/psych_parser.c52
-rw-r--r--ext/psych/yaml/api.c1393
-rw-r--r--ext/psych/yaml/config.h80
-rw-r--r--ext/psych/yaml/dumper.c394
-rw-r--r--ext/psych/yaml/emitter.c2358
-rw-r--r--ext/psych/yaml/loader.c544
-rw-r--r--ext/psych/yaml/parser.c1375
-rw-r--r--ext/psych/yaml/reader.c469
-rw-r--r--ext/psych/yaml/scanner.c3598
-rw-r--r--ext/psych/yaml/writer.c141
-rw-r--r--ext/psych/yaml/yaml.h1985
-rw-r--r--ext/psych/yaml/yaml_private.h688
-rw-r--r--ext/pty/depend2
-rw-r--r--ext/pty/extconf.rb6
-rw-r--r--ext/pty/lib/expect.rb16
-rw-r--r--ext/pty/pty.c160
-rw-r--r--ext/racc/cparse/cparse.c4
-rw-r--r--ext/racc/cparse/depend1
-rw-r--r--ext/rbconfig/sizeof/depend2
-rw-r--r--ext/readline/depend1
-rw-r--r--ext/readline/readline-ext.gemspec6
-rw-r--r--ext/readline/readline.c4
-rw-r--r--ext/ripper/depend11
-rw-r--r--ext/ripper/eventids2.c19
-rw-r--r--ext/ripper/lib/ripper/lexer.rb9
-rw-r--r--ext/ripper/tools/preproc.rb2
-rw-r--r--ext/socket/addrinfo.h36
-rw-r--r--ext/socket/ancdata.c262
-rw-r--r--ext/socket/basicsocket.c76
-rw-r--r--ext/socket/constants.c6
-rw-r--r--ext/socket/depend30
-rw-r--r--ext/socket/extconf.rb23
-rw-r--r--ext/socket/getaddrinfo.c898
-rw-r--r--ext/socket/getnameinfo.c226
-rw-r--r--ext/socket/ifaddr.c8
-rw-r--r--ext/socket/init.c156
-rw-r--r--ext/socket/ipsocket.c190
-rw-r--r--ext/socket/lib/socket.rb9
-rw-r--r--ext/socket/mkconstants.rb7
-rw-r--r--ext/socket/option.c98
-rw-r--r--ext/socket/raddrinfo.c278
-rw-r--r--ext/socket/rubysocket.h24
-rw-r--r--ext/socket/socket.c461
-rw-r--r--ext/socket/sockssocket.c4
-rw-r--r--ext/socket/tcpserver.c2
-rw-r--r--ext/socket/tcpsocket.c18
-rw-r--r--ext/socket/udpsocket.c30
-rw-r--r--ext/socket/unixserver.c8
-rw-r--r--ext/socket/unixsocket.c148
-rw-r--r--ext/stringio/depend1
-rw-r--r--ext/stringio/stringio.c378
-rw-r--r--ext/stringio/stringio.gemspec17
-rw-r--r--ext/strscan/depend1
-rw-r--r--ext/strscan/extconf.rb11
-rw-r--r--ext/strscan/strscan.c178
-rw-r--r--ext/strscan/strscan.gemspec23
-rw-r--r--ext/syslog/depend1
-rw-r--r--ext/syslog/syslog.c22
-rw-r--r--ext/syslog/syslog.gemspec2
-rw-r--r--ext/win32/lib/win32/registry.rb13
-rw-r--r--ext/win32/resolv/resolv.c18
-rw-r--r--ext/win32ole/win32ole.c170
-rw-r--r--ext/win32ole/win32ole.gemspec2
-rw-r--r--ext/win32ole/win32ole_event.c21
-rw-r--r--ext/win32ole/win32ole_method.c3
-rw-r--r--ext/win32ole/win32ole_param.c3
-rw-r--r--ext/win32ole/win32ole_record.c3
-rw-r--r--ext/win32ole/win32ole_type.c3
-rw-r--r--ext/win32ole/win32ole_typelib.c19
-rw-r--r--ext/win32ole/win32ole_variable.c4
-rw-r--r--ext/win32ole/win32ole_variant.c3
-rw-r--r--ext/zlib/depend1
-rw-r--r--ext/zlib/extconf.rb2
-rw-r--r--ext/zlib/extlibs8
-rw-r--r--ext/zlib/win32/zlib-1.2.11-mswin.patch95
-rw-r--r--ext/zlib/zlib.c32
-rw-r--r--file.c3352
-rw-r--r--gc.c6624
-rw-r--r--gc.h30
-rw-r--r--gc.rb186
-rw-r--r--gem_prelude.rb7
-rw-r--r--gems/bundled_gems30
-rw-r--r--gems/lib/core_assertions.rb1
-rw-r--r--gems/lib/envutil.rb1
-rw-r--r--gems/lib/rake/extensiontask.rb (renamed from tool/dummy-rake-compiler/rake/extensiontask.rb)5
-rw-r--r--goruby.c32
-rw-r--r--hash.c1260
-rw-r--r--hrtime.h59
-rw-r--r--id_table.c161
-rw-r--r--id_table.h9
-rw-r--r--include/ruby/assert.h2
-rw-r--r--include/ruby/backward.h52
-rw-r--r--include/ruby/backward/2/assume.h2
-rw-r--r--include/ruby/debug.h35
-rw-r--r--include/ruby/fiber/scheduler.h106
-rw-r--r--include/ruby/internal/abi.h58
-rw-r--r--include/ruby/internal/anyargs.h37
-rw-r--r--include/ruby/internal/arithmetic.h3
-rw-r--r--include/ruby/internal/arithmetic/long.h2
-rw-r--r--include/ruby/internal/assume.h5
-rw-r--r--include/ruby/internal/attr/nodiscard.h2
-rw-r--r--include/ruby/internal/attr/nonstring.h32
-rw-r--r--include/ruby/internal/config.h4
-rw-r--r--include/ruby/internal/core/rarray.h45
-rw-r--r--include/ruby/internal/core/rclass.h49
-rw-r--r--include/ruby/internal/core/rdata.h24
-rw-r--r--include/ruby/internal/core/robject.h61
-rw-r--r--include/ruby/internal/core/rstring.h7
-rw-r--r--include/ruby/internal/encoding/ctype.h101
-rw-r--r--include/ruby/internal/encoding/encoding.h14
-rw-r--r--include/ruby/internal/encoding/transcode.h18
-rw-r--r--include/ruby/internal/eval.h33
-rw-r--r--include/ruby/internal/fl_type.h25
-rw-r--r--include/ruby/internal/gc.h13
-rw-r--r--include/ruby/internal/has/builtin.h8
-rw-r--r--include/ruby/internal/intern/array.h6
-rw-r--r--include/ruby/internal/intern/class.h12
-rw-r--r--include/ruby/internal/intern/cont.h22
-rw-r--r--include/ruby/internal/intern/error.h14
-rw-r--r--include/ruby/internal/intern/file.h4
-rw-r--r--include/ruby/internal/intern/gc.h4
-rw-r--r--include/ruby/internal/intern/hash.h20
-rw-r--r--include/ruby/internal/intern/object.h72
-rw-r--r--include/ruby/internal/intern/select/largesize.h3
-rw-r--r--include/ruby/internal/intern/select/posix.h2
-rw-r--r--include/ruby/internal/intern/string.h64
-rw-r--r--include/ruby/internal/intern/vm.h14
-rw-r--r--include/ruby/internal/memory.h12
-rw-r--r--include/ruby/internal/scan_args.h2
-rw-r--r--include/ruby/internal/special_consts.h87
-rw-r--r--include/ruby/internal/stdbool.h2
-rw-r--r--include/ruby/internal/variable.h2
-rw-r--r--include/ruby/io.h144
-rw-r--r--include/ruby/io/buffer.h50
-rw-r--r--include/ruby/memory_view.h2
-rw-r--r--include/ruby/missing.h113
-rw-r--r--include/ruby/onigmo.h15
-rw-r--r--include/ruby/random.h63
-rw-r--r--include/ruby/ruby.h39
-rw-r--r--include/ruby/st.h2
-rw-r--r--include/ruby/thread.h44
-rw-r--r--include/ruby/thread_native.h6
-rw-r--r--include/ruby/util.h4
-rw-r--r--include/ruby/version.h5
-rw-r--r--include/ruby/win32.h60
-rw-r--r--inits.c8
-rw-r--r--insns.def196
-rw-r--r--internal.h10
-rw-r--r--internal/array.h54
-rw-r--r--internal/basic_operators.h64
-rw-r--r--internal/class.h69
-rw-r--r--internal/cmdlineopt.h61
-rw-r--r--internal/compar.h32
-rw-r--r--internal/cont.h10
-rw-r--r--internal/encoding.h4
-rw-r--r--internal/eval.h1
-rw-r--r--internal/fixnum.h2
-rw-r--r--internal/gc.h10
-rw-r--r--internal/hash.h1
-rw-r--r--internal/imemo.h7
-rw-r--r--internal/numeric.h8
-rw-r--r--internal/object.h24
-rw-r--r--internal/parse.h2
-rw-r--r--internal/ractor.h6
-rw-r--r--internal/string.h8
-rw-r--r--internal/symbol.h1
-rw-r--r--internal/thread.h3
-rw-r--r--internal/time.h5
-rw-r--r--internal/variable.h15
-rw-r--r--internal/vm.h5
-rw-r--r--io.c9260
-rw-r--r--io_buffer.c3062
-rw-r--r--iseq.c2052
-rw-r--r--iseq.h102
-rw-r--r--lex.c.blt2
-rw-r--r--lib/English.gemspec2
-rw-r--r--lib/abbrev.gemspec2
-rw-r--r--lib/benchmark/version.rb2
-rw-r--r--lib/bundler.rb127
-rw-r--r--lib/bundler/build_metadata.rb2
-rw-r--r--lib/bundler/bundler.gemspec18
-rw-r--r--lib/bundler/cli.rb80
-rw-r--r--lib/bundler/cli/add.rb2
-rw-r--r--lib/bundler/cli/binstubs.rb8
-rw-r--r--lib/bundler/cli/check.rb2
-rw-r--r--lib/bundler/cli/common.rb6
-rw-r--r--lib/bundler/cli/config.rb11
-rw-r--r--lib/bundler/cli/console.rb4
-rw-r--r--lib/bundler/cli/doctor.rb8
-rw-r--r--lib/bundler/cli/gem.rb114
-rw-r--r--lib/bundler/cli/info.rb15
-rw-r--r--lib/bundler/cli/init.rb8
-rw-r--r--lib/bundler/cli/install.rb50
-rw-r--r--lib/bundler/cli/lock.rb13
-rw-r--r--lib/bundler/cli/open.rb10
-rw-r--r--lib/bundler/cli/outdated.rb21
-rw-r--r--lib/bundler/cli/platform.rb14
-rw-r--r--lib/bundler/cli/show.rb2
-rw-r--r--lib/bundler/cli/update.rb8
-rw-r--r--lib/bundler/cli/viz.rb2
-rw-r--r--lib/bundler/compact_index_client.rb6
-rw-r--r--lib/bundler/compact_index_client/cache.rb11
-rw-r--r--lib/bundler/compact_index_client/updater.rb92
-rw-r--r--lib/bundler/constants.rb2
-rw-r--r--lib/bundler/current_ruby.rb24
-rw-r--r--lib/bundler/definition.rb471
-rw-r--r--lib/bundler/dep_proxy.rb55
-rw-r--r--lib/bundler/dependency.rb87
-rw-r--r--lib/bundler/digest.rb2
-rw-r--r--lib/bundler/dsl.rb33
-rw-r--r--lib/bundler/endpoint_specification.rb20
-rw-r--r--lib/bundler/env.rb6
-rw-r--r--lib/bundler/environment_preserver.rb5
-rw-r--r--lib/bundler/errors.rb30
-rw-r--r--lib/bundler/feature_flag.rb2
-rw-r--r--lib/bundler/fetcher.rb59
-rw-r--r--lib/bundler/fetcher/base.rb14
-rw-r--r--lib/bundler/fetcher/compact_index.rb34
-rw-r--r--lib/bundler/fetcher/dependency.rb8
-rw-r--r--lib/bundler/fetcher/downloader.rb9
-rw-r--r--lib/bundler/fetcher/index.rb29
-rw-r--r--lib/bundler/force_platform.rb18
-rw-r--r--lib/bundler/friendly_errors.rb28
-rw-r--r--lib/bundler/gem_helper.rb11
-rw-r--r--lib/bundler/gem_helpers.rb11
-rw-r--r--lib/bundler/gem_version_promoter.rb151
-rw-r--r--lib/bundler/graph.rb6
-rw-r--r--lib/bundler/index.rb64
-rw-r--r--lib/bundler/injector.rb13
-rw-r--r--lib/bundler/inline.rb30
-rw-r--r--lib/bundler/installer.rb63
-rw-r--r--lib/bundler/installer/gem_installer.rb15
-rw-r--r--lib/bundler/installer/parallel_installer.rb38
-rw-r--r--lib/bundler/installer/standalone.rb53
-rw-r--r--lib/bundler/lazy_specification.rb109
-rw-r--r--lib/bundler/lockfile_generator.rb6
-rw-r--r--lib/bundler/lockfile_parser.rb56
-rw-r--r--lib/bundler/man/bundle-add.118
-rw-r--r--lib/bundler/man/bundle-add.1.ronn14
-rw-r--r--lib/bundler/man/bundle-binstubs.12
-rw-r--r--lib/bundler/man/bundle-cache.112
-rw-r--r--lib/bundler/man/bundle-cache.1.ronn11
-rw-r--r--lib/bundler/man/bundle-check.12
-rw-r--r--lib/bundler/man/bundle-clean.14
-rw-r--r--lib/bundler/man/bundle-clean.1.ronn2
-rw-r--r--lib/bundler/man/bundle-config.144
-rw-r--r--lib/bundler/man/bundle-config.1.ronn43
-rw-r--r--lib/bundler/man/bundle-console.153
-rw-r--r--lib/bundler/man/bundle-console.1.ronn44
-rw-r--r--lib/bundler/man/bundle-doctor.12
-rw-r--r--lib/bundler/man/bundle-exec.112
-rw-r--r--lib/bundler/man/bundle-exec.1.ronn12
-rw-r--r--lib/bundler/man/bundle-gem.164
-rw-r--r--lib/bundler/man/bundle-gem.1.ronn10
-rw-r--r--lib/bundler/man/bundle-help.113
-rw-r--r--lib/bundler/man/bundle-help.1.ronn12
-rw-r--r--lib/bundler/man/bundle-info.16
-rw-r--r--lib/bundler/man/bundle-info.1.ronn6
-rw-r--r--lib/bundler/man/bundle-init.16
-rw-r--r--lib/bundler/man/bundle-init.1.ronn2
-rw-r--r--lib/bundler/man/bundle-inject.17
-rw-r--r--lib/bundler/man/bundle-inject.1.ronn4
-rw-r--r--lib/bundler/man/bundle-install.135
-rw-r--r--lib/bundler/man/bundle-install.1.ronn35
-rw-r--r--lib/bundler/man/bundle-list.12
-rw-r--r--lib/bundler/man/bundle-lock.12
-rw-r--r--lib/bundler/man/bundle-open.124
-rw-r--r--lib/bundler/man/bundle-open.1.ronn10
-rw-r--r--lib/bundler/man/bundle-outdated.133
-rw-r--r--lib/bundler/man/bundle-outdated.1.ronn32
-rw-r--r--lib/bundler/man/bundle-platform.122
-rw-r--r--lib/bundler/man/bundle-platform.1.ronn21
-rw-r--r--lib/bundler/man/bundle-plugin.181
-rw-r--r--lib/bundler/man/bundle-plugin.1.ronn59
-rw-r--r--lib/bundler/man/bundle-pristine.12
-rw-r--r--lib/bundler/man/bundle-remove.12
-rw-r--r--lib/bundler/man/bundle-show.12
-rw-r--r--lib/bundler/man/bundle-update.12
-rw-r--r--lib/bundler/man/bundle-version.135
-rw-r--r--lib/bundler/man/bundle-version.1.ronn24
-rw-r--r--lib/bundler/man/bundle-viz.15
-rw-r--r--lib/bundler/man/bundle-viz.1.ronn2
-rw-r--r--lib/bundler/man/bundle.125
-rw-r--r--lib/bundler/man/bundle.1.ronn19
-rw-r--r--lib/bundler/man/gemfile.5188
-rw-r--r--lib/bundler/man/gemfile.5.ronn190
-rw-r--r--lib/bundler/man/index.txt4
-rw-r--r--lib/bundler/match_metadata.rb13
-rw-r--r--lib/bundler/match_platform.rb1
-rw-r--r--lib/bundler/match_remote_metadata.rb29
-rw-r--r--lib/bundler/mirror.rb12
-rw-r--r--lib/bundler/plugin.rb4
-rw-r--r--lib/bundler/plugin/api/source.rb12
-rw-r--r--lib/bundler/plugin/index.rb10
-rw-r--r--lib/bundler/plugin/installer.rb9
-rw-r--r--lib/bundler/plugin/installer/git.rb4
-rw-r--r--lib/bundler/plugin/installer/rubygems.rb8
-rw-r--r--lib/bundler/process_lock.rb2
-rw-r--r--lib/bundler/psyched_yaml.rb10
-rw-r--r--lib/bundler/remote_specification.rb12
-rw-r--r--lib/bundler/resolver.rb641
-rw-r--r--lib/bundler/resolver/base.rb107
-rw-r--r--lib/bundler/resolver/candidate.rb94
-rw-r--r--lib/bundler/resolver/incompatibility.rb15
-rw-r--r--lib/bundler/resolver/package.rb72
-rw-r--r--lib/bundler/resolver/root.rb25
-rw-r--r--lib/bundler/resolver/spec_group.rb114
-rw-r--r--lib/bundler/ruby_dsl.rb8
-rw-r--r--lib/bundler/ruby_version.rb29
-rw-r--r--lib/bundler/rubygems_ext.rb175
-rw-r--r--lib/bundler/rubygems_gem_installer.rb52
-rw-r--r--lib/bundler/rubygems_integration.rb97
-rw-r--r--lib/bundler/runtime.rb9
-rw-r--r--lib/bundler/safe_marshal.rb31
-rw-r--r--lib/bundler/self_manager.rb168
-rw-r--r--lib/bundler/settings.rb19
-rw-r--r--lib/bundler/setup.rb5
-rw-r--r--lib/bundler/shared_helpers.rb28
-rw-r--r--lib/bundler/source.rb9
-rw-r--r--lib/bundler/source/git.rb99
-rw-r--r--lib/bundler/source/git/git_proxy.rb316
-rw-r--r--lib/bundler/source/metadata.rb7
-rw-r--r--lib/bundler/source/path.rb14
-rw-r--r--lib/bundler/source/path/installer.rb23
-rw-r--r--lib/bundler/source/rubygems.rb213
-rw-r--r--lib/bundler/source_list.rb10
-rw-r--r--lib/bundler/source_map.rb17
-rw-r--r--lib/bundler/spec_set.rb96
-rw-r--r--lib/bundler/stub_specification.rb8
-rw-r--r--lib/bundler/templates/Executable8
-rw-r--r--lib/bundler/templates/Executable.bundler17
-rw-r--r--lib/bundler/templates/Executable.standalone8
-rw-r--r--lib/bundler/templates/gems.rb5
-rw-r--r--lib/bundler/templates/newgem/Cargo.toml.tt7
-rw-r--r--lib/bundler/templates/newgem/Gemfile.tt3
-rw-r--r--lib/bundler/templates/newgem/README.md.tt18
-rw-r--r--lib/bundler/templates/newgem/Rakefile.tt13
-rw-r--r--lib/bundler/templates/newgem/bin/console.tt4
-rw-r--r--lib/bundler/templates/newgem/circleci/config.yml.tt12
-rw-r--r--lib/bundler/templates/newgem/ext/newgem/Cargo.toml.tt15
-rw-r--r--lib/bundler/templates/newgem/ext/newgem/extconf-c.rb.tt10
-rw-r--r--lib/bundler/templates/newgem/ext/newgem/extconf-rust.rb.tt6
-rw-r--r--lib/bundler/templates/newgem/ext/newgem/extconf.rb.tt5
-rw-r--r--lib/bundler/templates/newgem/ext/newgem/newgem.c.tt2
-rw-r--r--lib/bundler/templates/newgem/ext/newgem/src/lib.rs.tt12
-rw-r--r--lib/bundler/templates/newgem/github/workflows/main.yml.tt12
-rw-r--r--lib/bundler/templates/newgem/gitignore.tt3
-rw-r--r--lib/bundler/templates/newgem/gitlab-ci.yml.tt17
-rw-r--r--lib/bundler/templates/newgem/newgem.gemspec.tt13
-rw-r--r--lib/bundler/templates/newgem/standard.yml.tt1
-rw-r--r--lib/bundler/templates/newgem/test/minitest/test_newgem.rb.tt2
-rw-r--r--lib/bundler/templates/newgem/travis.yml.tt6
-rw-r--r--lib/bundler/ui/rg_proxy.rb2
-rw-r--r--lib/bundler/ui/shell.rb47
-rw-r--r--lib/bundler/ui/silent.rb26
-rw-r--r--lib/bundler/uri_normalizer.rb23
-rw-r--r--lib/bundler/vendor/connection_pool/lib/connection_pool.rb4
-rw-r--r--lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb6
-rw-r--r--lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb1
-rw-r--r--lib/bundler/vendor/fileutils/lib/fileutils.rb1760
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo.rb11
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/delegates/resolution_state.rb57
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb88
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb255
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/action.rb36
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb66
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/add_vertex.rb62
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/delete_edge.rb63
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb61
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/log.rb126
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/set_payload.rb46
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb36
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb164
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/errors.rb143
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb6
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb112
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/modules/ui.rb67
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb839
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/resolver.rb46
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/state.rb58
-rw-r--r--lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb2
-rw-r--r--lib/bundler/vendor/pub_grub/lib/pub_grub.rb31
-rw-r--r--lib/bundler/vendor/pub_grub/lib/pub_grub/assignment.rb20
-rw-r--r--lib/bundler/vendor/pub_grub/lib/pub_grub/basic_package_source.rb189
-rw-r--r--lib/bundler/vendor/pub_grub/lib/pub_grub/failure_writer.rb182
-rw-r--r--lib/bundler/vendor/pub_grub/lib/pub_grub/incompatibility.rb150
-rw-r--r--lib/bundler/vendor/pub_grub/lib/pub_grub/package.rb43
-rw-r--r--lib/bundler/vendor/pub_grub/lib/pub_grub/partial_solution.rb121
-rw-r--r--lib/bundler/vendor/pub_grub/lib/pub_grub/rubygems.rb45
-rw-r--r--lib/bundler/vendor/pub_grub/lib/pub_grub/solve_failure.rb19
-rw-r--r--lib/bundler/vendor/pub_grub/lib/pub_grub/static_package_source.rb60
-rw-r--r--lib/bundler/vendor/pub_grub/lib/pub_grub/term.rb105
-rw-r--r--lib/bundler/vendor/pub_grub/lib/pub_grub/version.rb3
-rw-r--r--lib/bundler/vendor/pub_grub/lib/pub_grub/version_constraint.rb129
-rw-r--r--lib/bundler/vendor/pub_grub/lib/pub_grub/version_range.rb411
-rw-r--r--lib/bundler/vendor/pub_grub/lib/pub_grub/version_solver.rb248
-rw-r--r--lib/bundler/vendor/pub_grub/lib/pub_grub/version_union.rb178
-rw-r--r--lib/bundler/vendor/thor/lib/thor/actions.rb8
-rw-r--r--lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb12
-rw-r--r--lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb3
-rw-r--r--lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb6
-rw-r--r--lib/bundler/vendor/thor/lib/thor/error.rb13
-rw-r--r--lib/bundler/vendor/thor/lib/thor/parser/options.rb20
-rw-r--r--lib/bundler/vendor/thor/lib/thor/shell.rb2
-rw-r--r--lib/bundler/vendor/thor/lib/thor/shell/basic.rb28
-rw-r--r--lib/bundler/vendor/thor/lib/thor/util.rb2
-rw-r--r--lib/bundler/vendor/thor/lib/thor/version.rb2
-rw-r--r--lib/bundler/vendor/tmpdir/lib/tmpdir.rb154
-rw-r--r--lib/bundler/vendor/tsort/lib/tsort.rb637
-rw-r--r--lib/bundler/vendor/uri/lib/uri.rb5
-rw-r--r--lib/bundler/vendor/uri/lib/uri/common.rb80
-rw-r--r--lib/bundler/vendor/uri/lib/uri/file.rb8
-rw-r--r--lib/bundler/vendor/uri/lib/uri/ftp.rb3
-rw-r--r--lib/bundler/vendor/uri/lib/uri/generic.rb34
-rw-r--r--lib/bundler/vendor/uri/lib/uri/http.rb42
-rw-r--r--lib/bundler/vendor/uri/lib/uri/https.rb3
-rw-r--r--lib/bundler/vendor/uri/lib/uri/ldap.rb2
-rw-r--r--lib/bundler/vendor/uri/lib/uri/ldaps.rb3
-rw-r--r--lib/bundler/vendor/uri/lib/uri/mailto.rb4
-rw-r--r--lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb24
-rw-r--r--lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb17
-rw-r--r--lib/bundler/vendor/uri/lib/uri/version.rb2
-rw-r--r--lib/bundler/vendor/uri/lib/uri/ws.rb3
-rw-r--r--lib/bundler/vendor/uri/lib/uri/wss.rb3
-rw-r--r--lib/bundler/vendored_molinillo.rb4
-rw-r--r--lib/bundler/vendored_persistent.rb34
-rw-r--r--lib/bundler/vendored_pub_grub.rb (renamed from lib/bundler/vendored_tmpdir.rb)2
-rw-r--r--lib/bundler/version.rb6
-rw-r--r--lib/bundler/version_ranges.rb122
-rw-r--r--lib/bundler/worker.rb12
-rw-r--r--lib/cgi.rb4
-rw-r--r--lib/cgi/cgi.gemspec19
-rw-r--r--lib/cgi/cookie.rb49
-rw-r--r--lib/cgi/core.rb45
-rw-r--r--lib/cgi/util.rb53
-rw-r--r--lib/csv.rb502
-rw-r--r--lib/csv/fields_converter.rb5
-rw-r--r--lib/csv/input_record_separator.rb15
-rw-r--r--lib/csv/parser.rb329
-rw-r--r--lib/csv/row.rb231
-rw-r--r--lib/csv/table.rb626
-rw-r--r--lib/csv/version.rb2
-rw-r--r--lib/csv/writer.rb10
-rw-r--r--lib/delegate.rb4
-rw-r--r--lib/did_you_mean.rb55
-rw-r--r--lib/did_you_mean/core_ext/name_error.rb57
-rw-r--r--lib/did_you_mean/formatter.rb11
-rw-r--r--lib/did_you_mean/formatters/verbose_formatter.rb3
-rw-r--r--lib/did_you_mean/spell_checkers/method_name_checker.rb10
-rw-r--r--lib/did_you_mean/spell_checkers/name_error_checkers/variable_name_checker.rb5
-rw-r--r--lib/did_you_mean/spell_checkers/require_path_checker.rb5
-rw-r--r--lib/did_you_mean/version.rb2
-rw-r--r--lib/drb/drb.rb11
-rw-r--r--lib/drb/extserv.rb4
-rw-r--r--lib/drb/extservm.rb6
-rw-r--r--lib/drb/version.rb2
-rw-r--r--lib/erb.gemspec13
-rw-r--r--lib/erb.rb579
-rw-r--r--lib/erb/compiler.rb471
-rw-r--r--lib/erb/def_method.rb46
-rw-r--r--lib/erb/util.rb62
-rw-r--r--lib/erb/version.rb2
-rw-r--r--lib/error_highlight/base.rb67
-rw-r--r--lib/error_highlight/core_ext.rb71
-rw-r--r--lib/error_highlight/version.rb2
-rw-r--r--lib/fileutils.rb1705
-rw-r--r--lib/forwardable.rb4
-rw-r--r--lib/forwardable/impl.rb3
-rw-r--r--lib/getoptlong.rb573
-rw-r--r--lib/ipaddr.gemspec18
-rw-r--r--lib/ipaddr.rb11
-rw-r--r--lib/irb.rb156
-rw-r--r--lib/irb/cmd/backtrace.rb21
-rw-r--r--lib/irb/cmd/break.rb21
-rw-r--r--lib/irb/cmd/catch.rb21
-rw-r--r--lib/irb/cmd/chws.rb12
-rw-r--r--lib/irb/cmd/continue.rb17
-rw-r--r--lib/irb/cmd/debug.rb136
-rw-r--r--lib/irb/cmd/delete.rb17
-rw-r--r--lib/irb/cmd/edit.rb61
-rw-r--r--lib/irb/cmd/finish.rb17
-rw-r--r--lib/irb/cmd/fork.rb7
-rw-r--r--lib/irb/cmd/help.rb20
-rw-r--r--lib/irb/cmd/info.rb37
-rw-r--r--lib/irb/cmd/irb_info.rb37
-rw-r--r--lib/irb/cmd/load.rb39
-rw-r--r--lib/irb/cmd/ls.rb19
-rw-r--r--lib/irb/cmd/measure.rb9
-rw-r--r--lib/irb/cmd/next.rb17
-rw-r--r--lib/irb/cmd/nop.rb30
-rw-r--r--lib/irb/cmd/pushws.rb15
-rw-r--r--lib/irb/cmd/show_cmds.rb39
-rw-r--r--lib/irb/cmd/show_source.rb109
-rw-r--r--lib/irb/cmd/step.rb17
-rw-r--r--lib/irb/cmd/subirb.rb44
-rw-r--r--lib/irb/cmd/whereami.rb9
-rw-r--r--lib/irb/color.rb78
-rw-r--r--lib/irb/color_printer.rb5
-rw-r--r--lib/irb/completion.rb136
-rw-r--r--lib/irb/context.rb74
-rw-r--r--lib/irb/ext/multi-irb.rb1
-rw-r--r--lib/irb/ext/save-history.rb10
-rw-r--r--lib/irb/extend-command.rb171
-rw-r--r--lib/irb/init.rb48
-rw-r--r--lib/irb/input-method.rb34
-rw-r--r--lib/irb/inspector.rb14
-rw-r--r--lib/irb/irb.gemspec8
-rw-r--r--lib/irb/lc/error.rb11
-rw-r--r--lib/irb/lc/help-message96
-rw-r--r--lib/irb/lc/ja/encoding_aliases.rb6
-rw-r--r--lib/irb/lc/ja/error.rb11
-rw-r--r--lib/irb/lc/ja/help-message12
-rw-r--r--lib/irb/ruby-lex.rb125
-rw-r--r--lib/irb/version.rb4
-rw-r--r--lib/irb/workspace.rb19
-rw-r--r--lib/logger.rb773
-rw-r--r--lib/logger/errors.rb2
-rw-r--r--lib/logger/formatter.rb5
-rw-r--r--lib/logger/log_device.rb8
-rw-r--r--lib/logger/logger.gemspec1
-rw-r--r--lib/logger/version.rb2
-rw-r--r--lib/mkmf.rb129
-rw-r--r--lib/mutex_m.rb2
-rw-r--r--lib/net/http.rb2128
-rw-r--r--lib/net/http/backward.rb2
-rw-r--r--lib/net/http/exceptions.rb55
-rw-r--r--lib/net/http/generic_request.rb109
-rw-r--r--lib/net/http/header.rb791
-rw-r--r--lib/net/http/net-http.gemspec14
-rw-r--r--lib/net/http/proxy_delta.rb2
-rw-r--r--lib/net/http/request.rb79
-rw-r--r--lib/net/http/requests.rb352
-rw-r--r--lib/net/http/response.rb367
-rw-r--r--lib/net/http/responses.rb1313
-rw-r--r--lib/net/http/status.rb13
-rw-r--r--lib/net/https.rb2
-rw-r--r--lib/net/net-protocol.gemspec7
-rw-r--r--lib/net/protocol.rb75
-rw-r--r--lib/open-uri.gemspec4
-rw-r--r--lib/open-uri.rb37
-rw-r--r--lib/open3/version.rb2
-rw-r--r--lib/optparse.rb124
-rw-r--r--lib/optparse/ac.rb2
-rw-r--r--lib/optparse/date.rb2
-rw-r--r--lib/optparse/kwargs.rb2
-rw-r--r--lib/optparse/optparse.gemspec1
-rw-r--r--lib/optparse/shellwords.rb2
-rw-r--r--lib/optparse/time.rb2
-rw-r--r--lib/optparse/uri.rb2
-rw-r--r--lib/ostruct.rb19
-rw-r--r--lib/ostruct/ostruct.gemspec2
-rw-r--r--lib/pp.gemspec2
-rw-r--r--lib/pp.rb33
-rw-r--r--lib/pstore.rb578
-rw-r--r--lib/racc/info.rb2
-rw-r--r--lib/racc/parser-text.rb2
-rw-r--r--lib/racc/parser.rb2
-rw-r--r--lib/racc/racc.gemspec2
-rw-r--r--lib/racc/statetransitiontable.rb2
-rw-r--r--lib/random/formatter.rb62
-rw-r--r--lib/rdoc.rb92
-rw-r--r--lib/rdoc/any_method.rb4
-rw-r--r--lib/rdoc/code_objects.rb3
-rw-r--r--lib/rdoc/context.rb4
-rw-r--r--lib/rdoc/context/section.rb2
-rw-r--r--lib/rdoc/cross_reference.rb18
-rw-r--r--lib/rdoc/generator.rb10
-rw-r--r--lib/rdoc/generator/markup.rb2
-rw-r--r--lib/rdoc/generator/template/darkfish/_head.rhtml20
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_classes.rhtml30
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml24
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml29
-rw-r--r--lib/rdoc/generator/template/darkfish/class.rhtml42
-rw-r--r--lib/rdoc/generator/template/darkfish/css/rdoc.css25
-rw-r--r--lib/rdoc/generator/template/darkfish/index.rhtml2
-rw-r--r--lib/rdoc/generator/template/darkfish/js/darkfish.js2
-rw-r--r--lib/rdoc/generator/template/darkfish/js/search.js2
-rw-r--r--lib/rdoc/generator/template/darkfish/table_of_contents.rhtml4
-rw-r--r--lib/rdoc/i18n.rb2
-rw-r--r--lib/rdoc/known_classes.rb9
-rw-r--r--lib/rdoc/markdown.rb551
-rw-r--r--lib/rdoc/markdown/literals.rb107
-rw-r--r--lib/rdoc/markup.rb702
-rw-r--r--lib/rdoc/markup/attribute_manager.rb64
-rw-r--r--lib/rdoc/markup/parser.rb18
-rw-r--r--lib/rdoc/markup/to_html.rb32
-rw-r--r--lib/rdoc/markup/to_label.rb2
-rw-r--r--lib/rdoc/markup/to_rdoc.rb23
-rw-r--r--lib/rdoc/method_attr.rb2
-rw-r--r--lib/rdoc/normal_class.rb2
-rw-r--r--lib/rdoc/normal_module.rb2
-rw-r--r--lib/rdoc/options.rb51
-rw-r--r--lib/rdoc/parser.rb21
-rw-r--r--lib/rdoc/parser/c.rb190
-rw-r--r--lib/rdoc/parser/ruby.rb35
-rw-r--r--lib/rdoc/rd.rb7
-rw-r--r--lib/rdoc/rd/block_parser.rb22
-rw-r--r--lib/rdoc/rd/inline_parser.rb2
-rw-r--r--lib/rdoc/rdoc.gemspec18
-rw-r--r--lib/rdoc/rdoc.rb20
-rw-r--r--lib/rdoc/ri.rb9
-rw-r--r--lib/rdoc/ri/driver.rb89
-rw-r--r--lib/rdoc/rubygems_hook.rb2
-rw-r--r--lib/rdoc/servlet.rb2
-rw-r--r--lib/rdoc/single_class.rb5
-rw-r--r--lib/rdoc/stats.rb7
-rw-r--r--lib/rdoc/store.rb45
-rw-r--r--lib/rdoc/task.rb6
-rw-r--r--lib/rdoc/version.rb4
-rw-r--r--lib/readline.gemspec2
-rw-r--r--lib/reline.rb68
-rw-r--r--lib/reline/ansi.rb9
-rw-r--r--lib/reline/config.rb26
-rw-r--r--lib/reline/general_io.rb6
-rw-r--r--lib/reline/key_actor/emacs.rb2
-rw-r--r--lib/reline/line_editor.rb102
-rw-r--r--lib/reline/reline.gemspec2
-rw-r--r--lib/reline/terminfo.rb48
-rw-r--r--lib/reline/unicode.rb10
-rw-r--r--lib/reline/version.rb2
-rw-r--r--lib/reline/windows.rb10
-rw-r--r--lib/resolv-replace.gemspec2
-rw-r--r--lib/resolv.gemspec2
-rw-r--r--lib/resolv.rb10
-rw-r--r--lib/ruby_vm/mjit/c_pointer.rb329
-rw-r--r--lib/ruby_vm/mjit/c_type.rb91
-rw-r--r--lib/ruby_vm/mjit/compiler.rb952
-rw-r--r--lib/ruby_vm/mjit/hooks.rb32
-rw-r--r--lib/rubygems.rb235
-rw-r--r--lib/rubygems/available_set.rb7
-rw-r--r--lib/rubygems/basic_specification.rb25
-rw-r--r--lib/rubygems/bundler_version_finder.rb62
-rw-r--r--lib/rubygems/command.rb81
-rw-r--r--lib/rubygems/command_manager.rb52
-rw-r--r--lib/rubygems/commands/build_command.rb20
-rw-r--r--lib/rubygems/commands/cert_command.rb67
-rw-r--r--lib/rubygems/commands/check_command.rb41
-rw-r--r--lib/rubygems/commands/cleanup_command.rb47
-rw-r--r--lib/rubygems/commands/contents_command.rb27
-rw-r--r--lib/rubygems/commands/dependency_command.rb81
-rw-r--r--lib/rubygems/commands/environment_command.rb18
-rw-r--r--lib/rubygems/commands/exec_command.rb249
-rw-r--r--lib/rubygems/commands/fetch_command.rb44
-rw-r--r--lib/rubygems/commands/generate_index_command.rb35
-rw-r--r--lib/rubygems/commands/help_command.rb13
-rw-r--r--lib/rubygems/commands/info_command.rb6
-rw-r--r--lib/rubygems/commands/install_command.rb53
-rw-r--r--lib/rubygems/commands/list_command.rb9
-rw-r--r--lib/rubygems/commands/lock_command.rb9
-rw-r--r--lib/rubygems/commands/mirror_command.rb7
-rw-r--r--lib/rubygems/commands/open_command.rb19
-rw-r--r--lib/rubygems/commands/outdated_command.rb11
-rw-r--r--lib/rubygems/commands/owner_command.rb36
-rw-r--r--lib/rubygems/commands/pristine_command.rb108
-rw-r--r--lib/rubygems/commands/push_command.rb33
-rw-r--r--lib/rubygems/commands/query_command.rb19
-rw-r--r--lib/rubygems/commands/rdoc_command.rb52
-rw-r--r--lib/rubygems/commands/search_command.rb9
-rw-r--r--lib/rubygems/commands/server_command.rb7
-rw-r--r--lib/rubygems/commands/setup_command.rb224
-rw-r--r--lib/rubygems/commands/signin_command.rb19
-rw-r--r--lib/rubygems/commands/signout_command.rb15
-rw-r--r--lib/rubygems/commands/sources_command.rb45
-rw-r--r--lib/rubygems/commands/specification_command.rb37
-rw-r--r--lib/rubygems/commands/stale_command.rb5
-rw-r--r--lib/rubygems/commands/uninstall_command.rb84
-rw-r--r--lib/rubygems/commands/unpack_command.rb27
-rw-r--r--lib/rubygems/commands/update_command.rb123
-rw-r--r--lib/rubygems/commands/which_command.rb15
-rw-r--r--lib/rubygems/commands/yank_command.rb23
-rw-r--r--lib/rubygems/compatibility.rb6
-rw-r--r--lib/rubygems/config_file.rb84
-rw-r--r--lib/rubygems/core_ext/kernel_gem.rb7
-rw-r--r--lib/rubygems/core_ext/kernel_require.rb224
-rw-r--r--lib/rubygems/core_ext/kernel_warn.rb70
-rw-r--r--lib/rubygems/core_ext/tcpsocket_init.rb4
-rw-r--r--lib/rubygems/defaults.rb51
-rw-r--r--lib/rubygems/dependency.rb38
-rw-r--r--lib/rubygems/dependency_installer.rb75
-rw-r--r--lib/rubygems/dependency_list.rb13
-rw-r--r--lib/rubygems/deprecate.rb5
-rw-r--r--lib/rubygems/doctor.rb43
-rw-r--r--lib/rubygems/errors.rb10
-rw-r--r--lib/rubygems/exceptions.rb32
-rw-r--r--lib/rubygems/ext.rb14
-rw-r--r--lib/rubygems/ext/build_error.rb3
-rw-r--r--lib/rubygems/ext/builder.rb66
-rw-r--r--lib/rubygems/ext/cargo_builder.rb360
-rw-r--r--lib/rubygems/ext/cargo_builder/link_flag_converter.rb27
-rw-r--r--lib/rubygems/ext/cmake_builder.rb4
-rw-r--r--lib/rubygems/ext/configure_builder.rb3
-rw-r--r--lib/rubygems/ext/ext_conf_builder.rb97
-rw-r--r--lib/rubygems/ext/rake_builder.rb12
-rw-r--r--lib/rubygems/gem_runner.rb29
-rw-r--r--lib/rubygems/gemcutter_utilities.rb137
-rw-r--r--lib/rubygems/gemcutter_utilities/webauthn_listener.rb105
-rw-r--r--lib/rubygems/gemcutter_utilities/webauthn_listener/response.rb163
-rw-r--r--lib/rubygems/gemcutter_utilities/webauthn_poller.rb78
-rw-r--r--lib/rubygems/indexer.rb59
-rw-r--r--lib/rubygems/install_default_message.rb5
-rw-r--r--lib/rubygems/install_message.rb5
-rw-r--r--lib/rubygems/install_update_options.rb119
-rw-r--r--lib/rubygems/installer.rb169
-rw-r--r--lib/rubygems/installer_uninstaller_utils.rb4
-rw-r--r--lib/rubygems/local_remote_options.rb41
-rw-r--r--lib/rubygems/mock_gem_ui.rb5
-rw-r--r--lib/rubygems/name_tuple.rb9
-rw-r--r--lib/rubygems/optparse.rb2
-rw-r--r--lib/rubygems/optparse/lib/optparse.rb112
-rw-r--r--lib/rubygems/optparse/lib/optparse/ac.rb2
-rw-r--r--lib/rubygems/optparse/lib/optparse/date.rb2
-rw-r--r--lib/rubygems/optparse/lib/optparse/kwargs.rb2
-rw-r--r--lib/rubygems/optparse/lib/optparse/shellwords.rb2
-rw-r--r--lib/rubygems/optparse/lib/optparse/time.rb2
-rw-r--r--lib/rubygems/optparse/lib/optparse/uri.rb2
-rw-r--r--lib/rubygems/package.rb141
-rw-r--r--lib/rubygems/package/digest_io.rb1
-rw-r--r--lib/rubygems/package/file_source.rb5
-rw-r--r--lib/rubygems/package/io_source.rb1
-rw-r--r--lib/rubygems/package/old.rb19
-rw-r--r--lib/rubygems/package/source.rb1
-rw-r--r--lib/rubygems/package/tar_header.rb125
-rw-r--r--lib/rubygems/package/tar_reader.rb31
-rw-r--r--lib/rubygems/package/tar_reader/entry.rb100
-rw-r--r--lib/rubygems/package/tar_writer.rb15
-rw-r--r--lib/rubygems/package_task.rb9
-rw-r--r--lib/rubygems/path_support.rb1
-rw-r--r--lib/rubygems/platform.rb152
-rw-r--r--lib/rubygems/psych_additions.rb10
-rw-r--r--lib/rubygems/psych_tree.rb3
-rw-r--r--lib/rubygems/query_utils.rb100
-rw-r--r--lib/rubygems/rdoc.rb5
-rw-r--r--lib/rubygems/remote_fetcher.rb53
-rw-r--r--lib/rubygems/request.rb49
-rw-r--r--lib/rubygems/request/connection_pools.rb8
-rw-r--r--lib/rubygems/request/http_pool.rb3
-rw-r--r--lib/rubygems/request/https_pool.rb1
-rw-r--r--lib/rubygems/request_set.rb39
-rw-r--r--lib/rubygems/request_set/gem_dependency_api.rb246
-rw-r--r--lib/rubygems/request_set/lockfile.rb19
-rw-r--r--lib/rubygems/request_set/lockfile/parser.rb55
-rw-r--r--lib/rubygems/request_set/lockfile/tokenizer.rb8
-rw-r--r--lib/rubygems/requirement.rb29
-rw-r--r--lib/rubygems/resolver.rb81
-rw-r--r--lib/rubygems/resolver/activation_request.rb7
-rw-r--r--lib/rubygems/resolver/api_set.rb9
-rw-r--r--lib/rubygems/resolver/api_specification.rb13
-rw-r--r--lib/rubygems/resolver/best_set.rb11
-rw-r--r--lib/rubygems/resolver/composed_set.rb1
-rw-r--r--lib/rubygems/resolver/conflict.rb21
-rw-r--r--lib/rubygems/resolver/current_set.rb1
-rw-r--r--lib/rubygems/resolver/dependency_request.rb5
-rw-r--r--lib/rubygems/resolver/git_set.rb5
-rw-r--r--lib/rubygems/resolver/git_specification.rb13
-rw-r--r--lib/rubygems/resolver/index_set.rb7
-rw-r--r--lib/rubygems/resolver/index_specification.rb12
-rw-r--r--lib/rubygems/resolver/installed_specification.rb9
-rw-r--r--lib/rubygems/resolver/installer_set.rb50
-rw-r--r--lib/rubygems/resolver/local_specification.rb5
-rw-r--r--lib/rubygems/resolver/lock_set.rb9
-rw-r--r--lib/rubygems/resolver/lock_specification.rb9
-rw-r--r--lib/rubygems/resolver/molinillo.rb3
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb2
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/errors.rb58
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/gem_metadata.rb2
-rw-r--r--lib/rubygems/resolver/requirement_list.rb1
-rw-r--r--lib/rubygems/resolver/set.rb1
-rw-r--r--lib/rubygems/resolver/source_set.rb2
-rw-r--r--lib/rubygems/resolver/spec_specification.rb1
-rw-r--r--lib/rubygems/resolver/specification.rb3
-rw-r--r--lib/rubygems/resolver/stats.rb3
-rw-r--r--lib/rubygems/resolver/vendor_set.rb3
-rw-r--r--lib/rubygems/resolver/vendor_specification.rb7
-rw-r--r--lib/rubygems/s3_uri_signer.rb18
-rw-r--r--lib/rubygems/safe_yaml.rb22
-rw-r--r--lib/rubygems/security.rb74
-rw-r--r--lib/rubygems/security/policies.rb95
-rw-r--r--lib/rubygems/security/policy.rb41
-rw-r--r--lib/rubygems/security/signer.rb11
-rw-r--r--lib/rubygems/security/trust_dir.rb9
-rw-r--r--lib/rubygems/security_option.rb11
-rw-r--r--lib/rubygems/shellwords.rb3
-rw-r--r--lib/rubygems/source.rb55
-rw-r--r--lib/rubygems/source/git.rb49
-rw-r--r--lib/rubygems/source/installed.rb3
-rw-r--r--lib/rubygems/source/local.rb5
-rw-r--r--lib/rubygems/source/lock.rb1
-rw-r--r--lib/rubygems/source/specific_file.rb3
-rw-r--r--lib/rubygems/source/vendor.rb1
-rw-r--r--lib/rubygems/source_list.rb14
-rw-r--r--lib/rubygems/spec_fetcher.rb73
-rw-r--r--lib/rubygems/specification.rb404
-rw-r--r--lib/rubygems/specification_policy.rb81
-rw-r--r--lib/rubygems/stub_specification.rb55
-rw-r--r--lib/rubygems/text.rb4
-rw-r--r--lib/rubygems/tsort.rb2
-rw-r--r--lib/rubygems/tsort/lib/tsort.rb618
-rw-r--r--lib/rubygems/uninstaller.rb51
-rw-r--r--lib/rubygems/update_suggestion.rb69
-rw-r--r--lib/rubygems/uri.rb75
-rw-r--r--lib/rubygems/uri_formatter.rb2
-rw-r--r--lib/rubygems/user_interaction.rb76
-rw-r--r--lib/rubygems/util.rb29
-rw-r--r--lib/rubygems/util/licenses.rb7
-rw-r--r--lib/rubygems/util/list.rb1
-rw-r--r--lib/rubygems/validator.rb13
-rw-r--r--lib/rubygems/version.rb47
-rw-r--r--lib/rubygems/version_option.rb7
-rw-r--r--lib/securerandom.gemspec2
-rw-r--r--lib/securerandom.rb9
-rw-r--r--lib/set.rb88
-rw-r--r--lib/set/set.gemspec2
-rw-r--r--lib/syntax_suggest.rb3
-rw-r--r--lib/syntax_suggest/api.rb201
-rw-r--r--lib/syntax_suggest/around_block_scan.rb232
-rw-r--r--lib/syntax_suggest/block_expand.rb165
-rw-r--r--lib/syntax_suggest/capture/before_after_keyword_ends.rb85
-rw-r--r--lib/syntax_suggest/capture/falling_indent_lines.rb71
-rw-r--r--lib/syntax_suggest/capture_code_context.rb245
-rw-r--r--lib/syntax_suggest/clean_document.rb306
-rw-r--r--lib/syntax_suggest/cli.rb130
-rw-r--r--lib/syntax_suggest/code_block.rb100
-rw-r--r--lib/syntax_suggest/code_frontier.rb178
-rw-r--r--lib/syntax_suggest/code_line.rb237
-rw-r--r--lib/syntax_suggest/code_search.rb139
-rw-r--r--lib/syntax_suggest/core_ext.rb114
-rw-r--r--lib/syntax_suggest/display_code_with_line_numbers.rb70
-rw-r--r--lib/syntax_suggest/display_invalid_blocks.rb83
-rw-r--r--lib/syntax_suggest/explain_syntax.rb103
-rw-r--r--lib/syntax_suggest/left_right_lex_count.rb168
-rw-r--r--lib/syntax_suggest/lex_all.rb55
-rw-r--r--lib/syntax_suggest/lex_value.rb70
-rw-r--r--lib/syntax_suggest/parse_blocks_from_indent_line.rb60
-rw-r--r--lib/syntax_suggest/pathname_from_message.rb59
-rw-r--r--lib/syntax_suggest/priority_engulf_queue.rb63
-rw-r--r--lib/syntax_suggest/priority_queue.rb105
-rw-r--r--lib/syntax_suggest/ripper_errors.rb36
-rw-r--r--lib/syntax_suggest/scan_history.rb134
-rw-r--r--lib/syntax_suggest/syntax_suggest.gemspec32
-rw-r--r--lib/syntax_suggest/unvisited_lines.rb36
-rw-r--r--lib/syntax_suggest/version.rb5
-rw-r--r--lib/tempfile.gemspec4
-rw-r--r--lib/tempfile.rb145
-rw-r--r--lib/time.gemspec2
-rw-r--r--lib/time.rb6
-rw-r--r--lib/timeout.rb144
-rw-r--r--lib/timeout/timeout.gemspec8
-rw-r--r--lib/tmpdir.gemspec4
-rw-r--r--lib/tmpdir.rb24
-rw-r--r--lib/tsort.gemspec2
-rw-r--r--lib/tsort.rb20
-rw-r--r--lib/un.gemspec2
-rw-r--r--lib/un.rb8
-rw-r--r--lib/unicode_normalize/normalize.rb2
-rw-r--r--lib/unicode_normalize/tables.rb194
-rw-r--r--lib/uri.rb1
-rw-r--r--lib/uri/common.rb54
-rw-r--r--lib/uri/file.rb6
-rw-r--r--lib/uri/generic.rb29
-rw-r--r--lib/uri/mailto.rb2
-rw-r--r--lib/uri/rfc2396_parser.rb4
-rw-r--r--lib/uri/rfc3986_parser.rb7
-rw-r--r--lib/uri/version.rb2
-rw-r--r--lib/weakref.rb5
-rw-r--r--lib/yaml.rb14
-rw-r--r--lib/yaml/yaml.gemspec2
-rwxr-xr-xlibexec/bundle36
-rwxr-xr-xlibexec/bundler2
-rwxr-xr-xlibexec/erb12
-rwxr-xr-xlibexec/rdoc1
-rwxr-xr-xlibexec/syntax_suggest7
-rw-r--r--load.c887
-rw-r--r--localeinit.c12
-rw-r--r--main.c27
-rw-r--r--man/irb.125
-rw-r--r--man/ruby.140
-rw-r--r--marshal.c1805
-rw-r--r--marshal.rb23
-rw-r--r--math.c650
-rw-r--r--memory_view.c14
-rw-r--r--method.h15
-rw-r--r--mini_builtin.c2
-rwxr-xr-xmisc/lldb_cruby.py80
-rw-r--r--misc/lldb_disasm.py25
-rw-r--r--misc/lldb_rb/commands/command_template.py30
-rw-r--r--misc/lldb_rb/commands/heap_page_command.py26
-rw-r--r--misc/lldb_rb/commands/rclass_ext_command.py14
-rw-r--r--misc/lldb_rb/constants.py4
-rw-r--r--misc/lldb_rb/rb_base_command.py69
-rwxr-xr-xmisc/test_yjit_asm.sh10
-rw-r--r--misc/yjit_asm_tests.c443
-rw-r--r--missing/dtoa.c3
-rw-r--r--missing/flock.c9
-rw-r--r--mjit.c1814
-rw-r--r--mjit.h158
-rw-r--r--mjit.rb37
-rw-r--r--mjit_c.c43
-rw-r--r--mjit_c.h97
-rw-r--r--mjit_c.rb807
-rw-r--r--mjit_compile.c596
-rw-r--r--mjit_worker.c1522
-rw-r--r--node.c1440
-rw-r--r--node.h36
-rw-r--r--numeric.c1971
-rw-r--r--numeric.rb91
-rw-r--r--object.c1913
-rw-r--r--pack.c2268
-rw-r--r--pack.rb299
-rw-r--r--parse.y1255
-rw-r--r--prelude.rb9
-rw-r--r--probes_helper.h14
-rw-r--r--proc.c1086
-rw-r--r--process.c2020
-rw-r--r--ractor.c202
-rw-r--r--ractor.rb8
-rw-r--r--ractor_core.h116
-rw-r--r--random.c535
-rw-r--r--range.c814
-rw-r--r--rational.c799
-rw-r--r--re.c2823
-rw-r--r--regcomp.c19
-rw-r--r--regenc.c15
-rw-r--r--regenc.h15
-rw-r--r--regexec.c833
-rw-r--r--regint.h55
-rw-r--r--regparse.c13
-rw-r--r--ruby-runner.c56
-rw-r--r--ruby.c2320
-rw-r--r--rubystub.c29
-rw-r--r--sample/coverage.rb2
-rw-r--r--sample/drb/README.rdoc2
-rw-r--r--sample/from.rb2
-rw-r--r--sample/getoptlong/abbrev.rb9
-rw-r--r--sample/getoptlong/aliases.rb8
-rw-r--r--sample/getoptlong/argv.rb12
-rw-r--r--sample/getoptlong/each.rb12
-rw-r--r--sample/getoptlong/fibonacci.rb62
-rw-r--r--sample/getoptlong/permute.rb12
-rw-r--r--sample/getoptlong/require_order.rb13
-rw-r--r--sample/getoptlong/return_in_order.rb13
-rw-r--r--sample/getoptlong/simple.rb7
-rw-r--r--sample/getoptlong/types.rb10
-rwxr-xr-xsample/mine.rb8
-rw-r--r--sample/mpart.rb44
-rw-r--r--sample/trick2015/kinaba/entry.rb4
-rw-r--r--sample/trick2018/02-mame/entry.rb4
-rw-r--r--sample/trick2022/01-tompng/Gemfile2
-rw-r--r--sample/trick2022/01-tompng/Gemfile.lock13
-rw-r--r--sample/trick2022/01-tompng/authors.markdown3
-rw-r--r--sample/trick2022/01-tompng/entry.rb40
-rw-r--r--sample/trick2022/01-tompng/remarks.markdown51
-rw-r--r--sample/trick2022/02-tompng/authors.markdown3
-rw-r--r--sample/trick2022/02-tompng/entry.rb32
-rw-r--r--sample/trick2022/02-tompng/remarks.markdown32
-rw-r--r--sample/trick2022/03-mame/authors.markdown3
-rw-r--r--sample/trick2022/03-mame/entry.rb27
-rw-r--r--sample/trick2022/03-mame/remarks.markdown96
-rw-r--r--sample/trick2022/03-mame/test.txt13
-rw-r--r--sample/trick2022/README.md14
-rw-r--r--sample/uumerge.rb2
-rw-r--r--scheduler.c430
-rw-r--r--shape.c825
-rw-r--r--shape.h232
-rw-r--r--signal.c507
-rw-r--r--siphash.c90
-rw-r--r--sparc.c4
-rw-r--r--spec/README.md34
-rw-r--r--spec/bundler/bundler/bundler_spec.rb197
-rw-r--r--spec/bundler/bundler/cli_spec.rb50
-rw-r--r--spec/bundler/bundler/definition_spec.rb45
-rw-r--r--spec/bundler/bundler/dep_proxy_spec.rb32
-rw-r--r--spec/bundler/bundler/dependency_spec.rb157
-rw-r--r--spec/bundler/bundler/digest_spec.rb11
-rw-r--r--spec/bundler/bundler/dsl_spec.rb14
-rw-r--r--spec/bundler/bundler/endpoint_specification_spec.rb32
-rw-r--r--spec/bundler/bundler/env_spec.rb8
-rw-r--r--spec/bundler/bundler/fetcher/dependency_spec.rb18
-rw-r--r--spec/bundler/bundler/fetcher/downloader_spec.rb30
-rw-r--r--spec/bundler/bundler/fetcher/index_spec.rb23
-rw-r--r--spec/bundler/bundler/fetcher_spec.rb34
-rw-r--r--spec/bundler/bundler/friendly_errors_spec.rb14
-rw-r--r--spec/bundler/bundler/gem_helper_spec.rb20
-rw-r--r--spec/bundler/bundler/gem_version_promoter_spec.rb246
-rw-r--r--spec/bundler/bundler/installer/gem_installer_spec.rb18
-rw-r--r--spec/bundler/bundler/installer/parallel_installer_spec.rb38
-rw-r--r--spec/bundler/bundler/plugin/index_spec.rb10
-rw-r--r--spec/bundler/bundler/plugin/installer_spec.rb2
-rw-r--r--spec/bundler/bundler/plugin_spec.rb22
-rw-r--r--spec/bundler/bundler/remote_specification_spec.rb2
-rw-r--r--spec/bundler/bundler/resolver/candidate_spec.rb21
-rw-r--r--spec/bundler/bundler/ruby_dsl_spec.rb27
-rw-r--r--spec/bundler/bundler/ruby_version_spec.rb46
-rw-r--r--spec/bundler/bundler/rubygems_integration_spec.rb22
-rw-r--r--spec/bundler/bundler/settings_spec.rb2
-rw-r--r--spec/bundler/bundler/shared_helpers_spec.rb11
-rw-r--r--spec/bundler/bundler/source/git/git_proxy_spec.rb53
-rw-r--r--spec/bundler/bundler/source_spec.rb38
-rw-r--r--spec/bundler/bundler/vendored_persistent_spec.rb77
-rw-r--r--spec/bundler/bundler/version_ranges_spec.rb40
-rw-r--r--spec/bundler/cache/gems_spec.rb12
-rw-r--r--spec/bundler/cache/git_spec.rb77
-rw-r--r--spec/bundler/commands/add_spec.rb15
-rw-r--r--spec/bundler/commands/binstubs_spec.rb79
-rw-r--r--spec/bundler/commands/cache_spec.rb18
-rw-r--r--spec/bundler/commands/check_spec.rb73
-rw-r--r--spec/bundler/commands/clean_spec.rb12
-rw-r--r--spec/bundler/commands/config_spec.rb90
-rw-r--r--spec/bundler/commands/doctor_spec.rb8
-rw-r--r--spec/bundler/commands/exec_spec.rb45
-rw-r--r--spec/bundler/commands/fund_spec.rb16
-rw-r--r--spec/bundler/commands/help_spec.rb4
-rw-r--r--spec/bundler/commands/info_spec.rb43
-rw-r--r--spec/bundler/commands/init_spec.rb38
-rw-r--r--spec/bundler/commands/inject_spec.rb4
-rw-r--r--spec/bundler/commands/install_spec.rb195
-rw-r--r--spec/bundler/commands/lock_spec.rb749
-rw-r--r--spec/bundler/commands/newgem_spec.rb225
-rw-r--r--spec/bundler/commands/open_spec.rb60
-rw-r--r--spec/bundler/commands/outdated_spec.rb224
-rw-r--r--spec/bundler/commands/platform_spec.rb (renamed from spec/bundler/other/platform_spec.rb)107
-rw-r--r--spec/bundler/commands/pristine_spec.rb4
-rw-r--r--spec/bundler/commands/remove_spec.rb40
-rw-r--r--spec/bundler/commands/show_spec.rb6
-rw-r--r--spec/bundler/commands/update_spec.rb512
-rw-r--r--spec/bundler/commands/viz_spec.rb6
-rw-r--r--spec/bundler/install/allow_offline_install_spec.rb5
-rw-r--r--spec/bundler/install/binstubs_spec.rb4
-rw-r--r--spec/bundler/install/bundler_spec.rb83
-rw-r--r--spec/bundler/install/deploy_spec.rb125
-rw-r--r--spec/bundler/install/gemfile/force_ruby_platform_spec.rb118
-rw-r--r--spec/bundler/install/gemfile/gemspec_spec.rb222
-rw-r--r--spec/bundler/install/gemfile/git_spec.rb134
-rw-r--r--spec/bundler/install/gemfile/groups_spec.rb13
-rw-r--r--spec/bundler/install/gemfile/path_spec.rb111
-rw-r--r--spec/bundler/install/gemfile/platform_spec.rb135
-rw-r--r--spec/bundler/install/gemfile/ruby_spec.rb40
-rw-r--r--spec/bundler/install/gemfile/sources_spec.rb262
-rw-r--r--spec/bundler/install/gemfile/specific_platform_spec.rb735
-rw-r--r--spec/bundler/install/gemfile_spec.rb2
-rw-r--r--spec/bundler/install/gems/compact_index_spec.rb58
-rw-r--r--spec/bundler/install/gems/dependency_api_spec.rb53
-rw-r--r--spec/bundler/install/gems/flex_spec.rb71
-rw-r--r--spec/bundler/install/gems/fund_spec.rb43
-rw-r--r--spec/bundler/install/gems/native_extensions_spec.rb6
-rw-r--r--spec/bundler/install/gems/resolving_spec.rb331
-rw-r--r--spec/bundler/install/gems/standalone_spec.rb106
-rw-r--r--spec/bundler/install/gems/sudo_spec.rb205
-rw-r--r--spec/bundler/install/gemspecs_spec.rb3
-rw-r--r--spec/bundler/install/git_spec.rb80
-rw-r--r--spec/bundler/install/global_cache_spec.rb6
-rw-r--r--spec/bundler/install/path_spec.rb2
-rw-r--r--spec/bundler/install/process_lock_spec.rb22
-rw-r--r--spec/bundler/install/yanked_spec.rb143
-rw-r--r--spec/bundler/lock/git_spec.rb127
-rw-r--r--spec/bundler/lock/lockfile_spec.rb443
-rw-r--r--spec/bundler/other/ext_spec.rb4
-rw-r--r--spec/bundler/other/major_deprecation_spec.rb15
-rw-r--r--spec/bundler/plugins/install_spec.rb30
-rw-r--r--spec/bundler/plugins/source/example_spec.rb14
-rw-r--r--spec/bundler/quality_es_spec.rb4
-rw-r--r--spec/bundler/quality_spec.rb26
-rw-r--r--spec/bundler/realworld/dependency_api_spec.rb10
-rw-r--r--spec/bundler/realworld/edgecases_spec.rb369
-rw-r--r--spec/bundler/realworld/ffi_spec.rb2
-rw-r--r--spec/bundler/realworld/fixtures/warbler/Gemfile.lock2
-rw-r--r--spec/bundler/realworld/gemfile_source_header_spec.rb10
-rw-r--r--spec/bundler/realworld/git_spec.rb11
-rw-r--r--spec/bundler/realworld/mirror_probe_spec.rb43
-rw-r--r--spec/bundler/realworld/parallel_spec.rb2
-rw-r--r--spec/bundler/realworld/slow_perf_spec.rb19
-rw-r--r--spec/bundler/resolver/basic_spec.rb74
-rw-r--r--spec/bundler/resolver/platform_spec.rb161
-rw-r--r--spec/bundler/runtime/gem_tasks_spec.rb6
-rw-r--r--spec/bundler/runtime/inline_spec.rb220
-rw-r--r--spec/bundler/runtime/platform_spec.rb165
-rw-r--r--spec/bundler/runtime/require_spec.rb2
-rw-r--r--spec/bundler/runtime/self_management_spec.rb126
-rw-r--r--spec/bundler/runtime/setup_spec.rb117
-rw-r--r--spec/bundler/spec_helper.rb37
-rw-r--r--spec/bundler/support/api_request_limit_hax.rb16
-rw-r--r--spec/bundler/support/artifice/compact_index.rb118
-rw-r--r--spec/bundler/support/artifice/compact_index_api_missing.rb13
-rw-r--r--spec/bundler/support/artifice/compact_index_basic_authentication.rb6
-rw-r--r--spec/bundler/support/artifice/compact_index_checksum_mismatch.rb6
-rw-r--r--spec/bundler/support/artifice/compact_index_concurrent_download.rb6
-rw-r--r--spec/bundler/support/artifice/compact_index_creds_diff_host.rb6
-rw-r--r--spec/bundler/support/artifice/compact_index_extra.rb35
-rw-r--r--spec/bundler/support/artifice/compact_index_extra_api.rb50
-rw-r--r--spec/bundler/support/artifice/compact_index_extra_api_missing.rb6
-rw-r--r--spec/bundler/support/artifice/compact_index_extra_missing.rb6
-rw-r--r--spec/bundler/support/artifice/compact_index_forbidden.rb6
-rw-r--r--spec/bundler/support/artifice/compact_index_host_redirect.rb6
-rw-r--r--spec/bundler/support/artifice/compact_index_no_gem.rb6
-rw-r--r--spec/bundler/support/artifice/compact_index_partial_update.rb6
-rw-r--r--spec/bundler/support/artifice/compact_index_partial_update_no_etag_not_incremental.rb6
-rw-r--r--spec/bundler/support/artifice/compact_index_precompiled_before.rb25
-rw-r--r--spec/bundler/support/artifice/compact_index_range_not_satisfiable.rb6
-rw-r--r--spec/bundler/support/artifice/compact_index_rate_limited.rb6
-rw-r--r--spec/bundler/support/artifice/compact_index_redirects.rb6
-rw-r--r--spec/bundler/support/artifice/compact_index_strict_basic_authentication.rb8
-rw-r--r--spec/bundler/support/artifice/compact_index_wrong_dependencies.rb6
-rw-r--r--spec/bundler/support/artifice/compact_index_wrong_gem_checksum.rb6
-rw-r--r--spec/bundler/support/artifice/endpoint.rb113
-rw-r--r--spec/bundler/support/artifice/endpoint_500.rb7
-rw-r--r--spec/bundler/support/artifice/endpoint_api_forbidden.rb6
-rw-r--r--spec/bundler/support/artifice/endpoint_api_missing.rb18
-rw-r--r--spec/bundler/support/artifice/endpoint_basic_authentication.rb6
-rw-r--r--spec/bundler/support/artifice/endpoint_creds_diff_host.rb6
-rw-r--r--spec/bundler/support/artifice/endpoint_extra.rb6
-rw-r--r--spec/bundler/support/artifice/endpoint_extra_api.rb6
-rw-r--r--spec/bundler/support/artifice/endpoint_extra_missing.rb6
-rw-r--r--spec/bundler/support/artifice/endpoint_fallback.rb6
-rw-r--r--spec/bundler/support/artifice/endpoint_host_redirect.rb6
-rw-r--r--spec/bundler/support/artifice/endpoint_marshal_fail.rb11
-rw-r--r--spec/bundler/support/artifice/endpoint_marshal_fail_basic_authentication.rb6
-rw-r--r--spec/bundler/support/artifice/endpoint_mirror_source.rb4
-rw-r--r--spec/bundler/support/artifice/endpoint_redirect.rb6
-rw-r--r--spec/bundler/support/artifice/endpoint_strict_basic_authentication.rb8
-rw-r--r--spec/bundler/support/artifice/endpoint_timeout.rb6
-rw-r--r--spec/bundler/support/artifice/fail.rb11
-rw-r--r--spec/bundler/support/artifice/helpers/artifice.rb30
-rw-r--r--spec/bundler/support/artifice/helpers/compact_index.rb118
-rw-r--r--spec/bundler/support/artifice/helpers/compact_index_extra.rb33
-rw-r--r--spec/bundler/support/artifice/helpers/compact_index_extra_api.rb48
-rw-r--r--spec/bundler/support/artifice/helpers/endpoint.rb112
-rw-r--r--spec/bundler/support/artifice/helpers/endpoint_extra.rb29
-rw-r--r--spec/bundler/support/artifice/helpers/endpoint_fallback.rb15
-rw-r--r--spec/bundler/support/artifice/helpers/endpoint_marshal_fail.rb9
-rw-r--r--spec/bundler/support/artifice/helpers/rack_request.rb100
-rw-r--r--spec/bundler/support/artifice/used_cassettes.txt20908
-rw-r--r--spec/bundler/support/artifice/vcr.rb35
-rw-r--r--spec/bundler/support/artifice/windows.rb7
-rw-r--r--spec/bundler/support/builders.rb52
-rw-r--r--spec/bundler/support/bundle.rb2
-rw-r--r--spec/bundler/support/filters.rb10
-rw-r--r--spec/bundler/support/hax.rb41
-rw-r--r--spec/bundler/support/helpers.rb97
-rw-r--r--spec/bundler/support/indexes.rb37
-rw-r--r--spec/bundler/support/matchers.rb16
-rw-r--r--spec/bundler/support/path.rb54
-rw-r--r--spec/bundler/support/platforms.rb42
-rw-r--r--spec/bundler/support/rubygems_ext.rb33
-rw-r--r--spec/bundler/support/rubygems_version_manager.rb2
-rw-r--r--spec/bundler/support/sudo.rb18
-rw-r--r--spec/bundler/update/gems/fund_spec.rb16
-rw-r--r--spec/bundler/update/git_spec.rb14
-rw-r--r--spec/default.mspec2
-rwxr-xr-xspec/mspec/bin/mspec2
-rwxr-xr-xspec/mspec/lib/mspec/commands/mkspec.rb16
-rwxr-xr-xspec/mspec/lib/mspec/commands/mspec.rb6
-rw-r--r--spec/mspec/lib/mspec/expectations/expectations.rb4
-rw-r--r--spec/mspec/lib/mspec/guards/platform.rb4
-rw-r--r--spec/mspec/lib/mspec/guards/superuser.rb10
-rw-r--r--spec/mspec/lib/mspec/guards/version.rb28
-rw-r--r--spec/mspec/lib/mspec/helpers/datetime.rb1
-rw-r--r--spec/mspec/lib/mspec/helpers/numeric.rb4
-rw-r--r--spec/mspec/lib/mspec/helpers/ruby_exe.rb15
-rw-r--r--spec/mspec/lib/mspec/matchers/base.rb30
-rw-r--r--spec/mspec/lib/mspec/matchers/output.rb8
-rw-r--r--spec/mspec/lib/mspec/matchers/raise_error.rb6
-rw-r--r--spec/mspec/lib/mspec/runner/actions/leakchecker.rb3
-rw-r--r--spec/mspec/lib/mspec/runner/actions/timeout.rb37
-rw-r--r--spec/mspec/lib/mspec/runner/context.rb1
-rw-r--r--spec/mspec/lib/mspec/runner/exception.rb2
-rw-r--r--spec/mspec/lib/mspec/runner/formatters/base.rb26
-rw-r--r--spec/mspec/lib/mspec/runner/mspec.rb8
-rw-r--r--spec/mspec/lib/mspec/runner/shared.rb8
-rw-r--r--spec/mspec/lib/mspec/utils/name_map.rb7
-rw-r--r--spec/mspec/lib/mspec/utils/options.rb15
-rw-r--r--spec/mspec/lib/mspec/utils/script.rb16
-rw-r--r--spec/mspec/spec/commands/mkspec_spec.rb2
-rw-r--r--spec/mspec/spec/helpers/numeric_spec.rb10
-rw-r--r--spec/mspec/spec/helpers/ruby_exe_spec.rb12
-rw-r--r--spec/mspec/spec/utils/script_spec.rb5
-rw-r--r--spec/mspec/tool/remove_old_guards.rb12
-rw-r--r--spec/mspec/tool/sync/sync-rubyspec.rb2
-rwxr-xr-xspec/mspec/tool/tag_from_output.rb26
-rw-r--r--spec/ruby/.mspec.constants3
-rw-r--r--spec/ruby/.rubocop.yml55
-rw-r--r--spec/ruby/.rubocop_todo.yml11
-rw-r--r--spec/ruby/CONTRIBUTING.md21
-rw-r--r--spec/ruby/README.md21
-rw-r--r--spec/ruby/command_line/dash_upper_w_spec.rb33
-rw-r--r--spec/ruby/command_line/dash_w_spec.rb6
-rw-r--r--spec/ruby/command_line/feature_spec.rb4
-rw-r--r--spec/ruby/command_line/fixtures/freeze_flag_two_literals.rb2
-rw-r--r--spec/ruby/command_line/rubyopt_spec.rb30
-rw-r--r--spec/ruby/core/array/clear_spec.rb20
-rw-r--r--spec/ruby/core/array/compact_spec.rb30
-rw-r--r--spec/ruby/core/array/concat_spec.rb58
-rw-r--r--spec/ruby/core/array/deconstruct_spec.rb10
-rw-r--r--spec/ruby/core/array/delete_at_spec.rb22
-rw-r--r--spec/ruby/core/array/delete_if_spec.rb16
-rw-r--r--spec/ruby/core/array/delete_spec.rb22
-rw-r--r--spec/ruby/core/array/each_spec.rb35
-rw-r--r--spec/ruby/core/array/element_set_spec.rb76
-rw-r--r--spec/ruby/core/array/fill_spec.rb14
-rw-r--r--spec/ruby/core/array/fixtures/classes.rb62
-rw-r--r--spec/ruby/core/array/flatten_spec.rb10
-rw-r--r--spec/ruby/core/array/intersection_spec.rb16
-rw-r--r--spec/ruby/core/array/keep_if_spec.rb1
-rw-r--r--spec/ruby/core/array/multiply_spec.rb40
-rw-r--r--spec/ruby/core/array/pack/a_spec.rb11
-rw-r--r--spec/ruby/core/array/pack/b_spec.rb7
-rw-r--r--spec/ruby/core/array/pack/c_spec.rb14
-rw-r--r--spec/ruby/core/array/pack/h_spec.rb5
-rw-r--r--spec/ruby/core/array/pack/m_spec.rb10
-rw-r--r--spec/ruby/core/array/pack/p_spec.rb24
-rw-r--r--spec/ruby/core/array/pack/shared/basic.rb52
-rw-r--r--spec/ruby/core/array/pack/shared/float.rb74
-rw-r--r--spec/ruby/core/array/pack/shared/integer.rb96
-rw-r--r--spec/ruby/core/array/pack/shared/numeric_basic.rb10
-rw-r--r--spec/ruby/core/array/pack/shared/taint.rb33
-rw-r--r--spec/ruby/core/array/pack/shared/unicode.rb14
-rw-r--r--spec/ruby/core/array/pack/u_spec.rb10
-rw-r--r--spec/ruby/core/array/pack/w_spec.rb14
-rw-r--r--spec/ruby/core/array/pack/x_spec.rb1
-rw-r--r--spec/ruby/core/array/pack/z_spec.rb10
-rw-r--r--spec/ruby/core/array/plus_spec.rb16
-rw-r--r--spec/ruby/core/array/pop_spec.rb52
-rw-r--r--spec/ruby/core/array/sample_spec.rb26
-rw-r--r--spec/ruby/core/array/shared/clone.rb24
-rw-r--r--spec/ruby/core/array/shared/collect.rb31
-rw-r--r--spec/ruby/core/array/shared/inspect.rb26
-rw-r--r--spec/ruby/core/array/shared/join.rb86
-rw-r--r--spec/ruby/core/array/shared/slice.rb168
-rw-r--r--spec/ruby/core/array/shared/unshift.rb18
-rw-r--r--spec/ruby/core/array/shift_spec.rb16
-rw-r--r--spec/ruby/core/array/slice_spec.rb18
-rw-r--r--spec/ruby/core/array/uniq_spec.rb76
-rw-r--r--spec/ruby/core/array/values_at_spec.rb9
-rw-r--r--spec/ruby/core/array/zip_spec.rb6
-rw-r--r--spec/ruby/core/basicobject/instance_eval_spec.rb68
-rw-r--r--spec/ruby/core/builtin_constants/builtin_constants_spec.rb18
-rw-r--r--spec/ruby/core/class/attached_object_spec.rb31
-rw-r--r--spec/ruby/core/class/descendants_spec.rb38
-rw-r--r--spec/ruby/core/class/subclasses_spec.rb22
-rw-r--r--spec/ruby/core/comparable/clamp_spec.rb78
-rw-r--r--spec/ruby/core/complex/comparison_spec.rb36
-rw-r--r--spec/ruby/core/complex/polar_spec.rb16
-rw-r--r--spec/ruby/core/data/constants_spec.rb14
-rw-r--r--spec/ruby/core/dir/children_spec.rb8
-rw-r--r--spec/ruby/core/dir/each_child_spec.rb7
-rw-r--r--spec/ruby/core/dir/entries_spec.rb7
-rw-r--r--spec/ruby/core/dir/fixtures/common.rb20
-rw-r--r--spec/ruby/core/dir/foreach_spec.rb12
-rw-r--r--spec/ruby/core/dir/glob_spec.rb27
-rw-r--r--spec/ruby/core/dir/home_spec.rb45
-rw-r--r--spec/ruby/core/dir/mkdir_spec.rb18
-rw-r--r--spec/ruby/core/dir/read_spec.rb33
-rw-r--r--spec/ruby/core/dir/shared/chroot.rb9
-rw-r--r--spec/ruby/core/dir/shared/glob.rb20
-rw-r--r--spec/ruby/core/encoding/list_spec.rb6
-rw-r--r--spec/ruby/core/encoding/replicate_spec.rb108
-rw-r--r--spec/ruby/core/enumerable/all_spec.rb1
-rw-r--r--spec/ruby/core/enumerable/any_spec.rb1
-rw-r--r--spec/ruby/core/enumerable/compact_spec.rb11
-rw-r--r--spec/ruby/core/enumerable/each_cons_spec.rb6
-rw-r--r--spec/ruby/core/enumerable/each_slice_spec.rb6
-rw-r--r--spec/ruby/core/enumerable/filter_map_spec.rb34
-rw-r--r--spec/ruby/core/enumerable/group_by_spec.rb10
-rw-r--r--spec/ruby/core/enumerable/none_spec.rb1
-rw-r--r--spec/ruby/core/enumerable/one_spec.rb1
-rw-r--r--spec/ruby/core/enumerable/shared/entries.rb10
-rw-r--r--spec/ruby/core/enumerable/shared/inject.rb10
-rw-r--r--spec/ruby/core/enumerable/sum_spec.rb17
-rw-r--r--spec/ruby/core/enumerable/tally_spec.rb48
-rw-r--r--spec/ruby/core/enumerable/uniq_spec.rb76
-rw-r--r--spec/ruby/core/enumerable/zip_spec.rb5
-rw-r--r--spec/ruby/core/enumerator/arithmetic_sequence/begin_spec.rb10
-rw-r--r--spec/ruby/core/enumerator/lazy/compact_spec.rb11
-rw-r--r--spec/ruby/core/enumerator/lazy/eager_spec.rb38
-rw-r--r--spec/ruby/core/enumerator/lazy/filter_map_spec.rb14
-rw-r--r--spec/ruby/core/enumerator/lazy/lazy_spec.rb4
-rw-r--r--spec/ruby/core/enumerator/lazy/with_index_spec.rb44
-rw-r--r--spec/ruby/core/enumerator/new_spec.rb12
-rw-r--r--spec/ruby/core/enumerator/produce_spec.rb48
-rw-r--r--spec/ruby/core/enumerator/yielder/to_proc_spec.rb20
-rw-r--r--spec/ruby/core/env/merge_spec.rb6
-rw-r--r--spec/ruby/core/env/shared/update.rb38
-rw-r--r--spec/ruby/core/exception/frozen_error_spec.rb28
-rw-r--r--spec/ruby/core/exception/full_message_spec.rb40
-rw-r--r--spec/ruby/core/exception/interrupt_spec.rb9
-rw-r--r--spec/ruby/core/exception/signal_exception_spec.rb6
-rw-r--r--spec/ruby/core/exception/system_exit_spec.rb42
-rw-r--r--spec/ruby/core/false/case_compare_spec.rb14
-rw-r--r--spec/ruby/core/false/to_s_spec.rb12
-rw-r--r--spec/ruby/core/fiber/blocking_spec.rb17
-rw-r--r--spec/ruby/core/fiber/raise_spec.rb148
-rw-r--r--spec/ruby/core/fiber/storage_spec.rb117
-rw-r--r--spec/ruby/core/file/absolute_path_spec.rb74
-rw-r--r--spec/ruby/core/file/atime_spec.rb6
-rw-r--r--spec/ruby/core/file/ctime_spec.rb4
-rw-r--r--spec/ruby/core/file/extname_spec.rb4
-rw-r--r--spec/ruby/core/file/mtime_spec.rb20
-rw-r--r--spec/ruby/core/file/open_spec.rb8
-rw-r--r--spec/ruby/core/file/shared/fnmatch.rb16
-rw-r--r--spec/ruby/core/file/shared/path.rb14
-rw-r--r--spec/ruby/core/file/utime_spec.rb38
-rw-r--r--spec/ruby/core/float/coerce_spec.rb4
-rw-r--r--spec/ruby/core/float/comparison_spec.rb35
-rw-r--r--spec/ruby/core/float/divide_spec.rb4
-rw-r--r--spec/ruby/core/float/divmod_spec.rb4
-rw-r--r--spec/ruby/core/float/gt_spec.rb21
-rw-r--r--spec/ruby/core/float/gte_spec.rb21
-rw-r--r--spec/ruby/core/float/lt_spec.rb21
-rw-r--r--spec/ruby/core/float/lte_spec.rb21
-rw-r--r--spec/ruby/core/float/minus_spec.rb2
-rw-r--r--spec/ruby/core/float/multiply_spec.rb2
-rw-r--r--spec/ruby/core/float/plus_spec.rb2
-rw-r--r--spec/ruby/core/float/round_spec.rb64
-rw-r--r--spec/ruby/core/float/shared/equal.rb21
-rw-r--r--spec/ruby/core/float/shared/to_i.rb4
-rw-r--r--spec/ruby/core/hash/constructor_spec.rb27
-rw-r--r--spec/ruby/core/hash/deconstruct_keys_spec.rb32
-rw-r--r--spec/ruby/core/hash/hash_spec.rb9
-rw-r--r--spec/ruby/core/hash/reject_spec.rb7
-rw-r--r--spec/ruby/core/hash/ruby2_keywords_hash_spec.rb96
-rw-r--r--spec/ruby/core/hash/shared/eql.rb84
-rw-r--r--spec/ruby/core/hash/shared/to_s.rb17
-rw-r--r--spec/ruby/core/hash/shift_spec.rb42
-rw-r--r--spec/ruby/core/hash/to_a_spec.rb10
-rw-r--r--spec/ruby/core/hash/transform_keys_spec.rb5
-rw-r--r--spec/ruby/core/integer/bit_and_spec.rb14
-rw-r--r--spec/ruby/core/integer/bit_or_spec.rb33
-rw-r--r--spec/ruby/core/integer/bit_xor_spec.rb35
-rw-r--r--spec/ruby/core/integer/chr_spec.rb65
-rw-r--r--spec/ruby/core/integer/complement_spec.rb6
-rw-r--r--spec/ruby/core/integer/constants_spec.rb36
-rw-r--r--spec/ruby/core/integer/div_spec.rb10
-rw-r--r--spec/ruby/core/integer/divide_spec.rb12
-rw-r--r--spec/ruby/core/integer/divmod_spec.rb12
-rw-r--r--spec/ruby/core/integer/element_reference_spec.rb122
-rw-r--r--spec/ruby/core/integer/fdiv_spec.rb51
-rw-r--r--spec/ruby/core/integer/left_shift_spec.rb57
-rw-r--r--spec/ruby/core/integer/minus_spec.rb6
-rw-r--r--spec/ruby/core/integer/multiply_spec.rb6
-rw-r--r--spec/ruby/core/integer/plus_spec.rb8
-rw-r--r--spec/ruby/core/integer/remainder_spec.rb2
-rw-r--r--spec/ruby/core/integer/right_shift_spec.rb61
-rw-r--r--spec/ruby/core/integer/shared/abs.rb4
-rw-r--r--spec/ruby/core/integer/shared/exponent.rb11
-rw-r--r--spec/ruby/core/integer/shared/modulo.rb10
-rw-r--r--spec/ruby/core/integer/to_f_spec.rb6
-rw-r--r--spec/ruby/core/integer/to_s_spec.rb6
-rw-r--r--spec/ruby/core/integer/uminus_spec.rb8
-rw-r--r--spec/ruby/core/io/advise_spec.rb14
-rw-r--r--spec/ruby/core/io/close_spec.rb6
-rw-r--r--spec/ruby/core/io/fixtures/classes.rb26
-rw-r--r--spec/ruby/core/io/gets_spec.rb52
-rw-r--r--spec/ruby/core/io/lineno_spec.rb9
-rw-r--r--spec/ruby/core/io/new_spec.rb2
-rw-r--r--spec/ruby/core/io/path_spec.rb14
-rw-r--r--spec/ruby/core/io/pipe_spec.rb11
-rw-r--r--spec/ruby/core/io/print_spec.rb25
-rw-r--r--spec/ruby/core/io/read_nonblock_spec.rb49
-rw-r--r--spec/ruby/core/io/read_spec.rb25
-rw-r--r--spec/ruby/core/io/readchar_spec.rb66
-rw-r--r--spec/ruby/core/io/readline_spec.rb35
-rw-r--r--spec/ruby/core/io/readlines_spec.rb26
-rw-r--r--spec/ruby/core/io/readpartial_spec.rb17
-rw-r--r--spec/ruby/core/io/rewind_spec.rb15
-rw-r--r--spec/ruby/core/io/set_encoding_by_bom_spec.rb273
-rw-r--r--spec/ruby/core/io/set_encoding_spec.rb49
-rw-r--r--spec/ruby/core/io/shared/each.rb84
-rw-r--r--spec/ruby/core/io/shared/new.rb2
-rw-r--r--spec/ruby/core/io/shared/pos.rb8
-rw-r--r--spec/ruby/core/io/shared/readlines.rb142
-rw-r--r--spec/ruby/core/io/shared/write.rb10
-rw-r--r--spec/ruby/core/io/sysread_spec.rb31
-rw-r--r--spec/ruby/core/io/sysseek_spec.rb2
-rw-r--r--spec/ruby/core/io/syswrite_spec.rb10
-rw-r--r--spec/ruby/core/io/ungetbyte_spec.rb18
-rw-r--r--spec/ruby/core/io/ungetc_spec.rb2
-rw-r--r--spec/ruby/core/io/write_nonblock_spec.rb10
-rw-r--r--spec/ruby/core/io/write_spec.rb34
-rw-r--r--spec/ruby/core/kernel/Complex_spec.rb89
-rw-r--r--spec/ruby/core/kernel/caller_locations_spec.rb10
-rw-r--r--spec/ruby/core/kernel/caller_spec.rb10
-rw-r--r--spec/ruby/core/kernel/clone_spec.rb7
-rw-r--r--spec/ruby/core/kernel/define_singleton_method_spec.rb15
-rw-r--r--spec/ruby/core/kernel/fixtures/Complex.rb5
-rw-r--r--spec/ruby/core/kernel/fixtures/warn_core_method.rb2
-rw-r--r--spec/ruby/core/kernel/inspect_spec.rb10
-rw-r--r--spec/ruby/core/kernel/instance_variable_get_spec.rb6
-rw-r--r--spec/ruby/core/kernel/instance_variable_set_spec.rb12
-rw-r--r--spec/ruby/core/kernel/match_spec.rb34
-rw-r--r--spec/ruby/core/kernel/method_spec.rb24
-rw-r--r--spec/ruby/core/kernel/open_spec.rb2
-rw-r--r--spec/ruby/core/kernel/p_spec.rb6
-rw-r--r--spec/ruby/core/kernel/proc_spec.rb10
-rw-r--r--spec/ruby/core/kernel/remove_instance_variable_spec.rb13
-rw-r--r--spec/ruby/core/kernel/require_relative_spec.rb2
-rw-r--r--spec/ruby/core/kernel/shared/dup_clone.rb24
-rw-r--r--spec/ruby/core/kernel/shared/load.rb45
-rw-r--r--spec/ruby/core/kernel/shared/require.rb36
-rw-r--r--spec/ruby/core/kernel/shared/sprintf.rb85
-rw-r--r--spec/ruby/core/kernel/shared/sprintf_encoding.rb33
-rw-r--r--spec/ruby/core/kernel/singleton_class_spec.rb2
-rw-r--r--spec/ruby/core/kernel/taint_spec.rb45
-rw-r--r--spec/ruby/core/kernel/tainted_spec.rb12
-rw-r--r--spec/ruby/core/kernel/to_s_spec.rb10
-rw-r--r--spec/ruby/core/kernel/trust_spec.rb25
-rw-r--r--spec/ruby/core/kernel/untaint_spec.rb25
-rw-r--r--spec/ruby/core/kernel/untrust_spec.rb25
-rw-r--r--spec/ruby/core/kernel/untrusted_spec.rb28
-rw-r--r--spec/ruby/core/main/fixtures/using.rb1
-rw-r--r--spec/ruby/core/main/fixtures/using_in_main.rb5
-rw-r--r--spec/ruby/core/main/fixtures/using_in_method.rb5
-rw-r--r--spec/ruby/core/main/ruby2_keywords_spec.rb10
-rw-r--r--spec/ruby/core/main/using_spec.rb20
-rw-r--r--spec/ruby/core/marshal/dump_spec.rb71
-rw-r--r--spec/ruby/core/marshal/fixtures/classes.rb4
-rw-r--r--spec/ruby/core/marshal/shared/load.rb94
-rw-r--r--spec/ruby/core/matchdata/allocate_spec.rb8
-rw-r--r--spec/ruby/core/matchdata/element_reference_spec.rb21
-rw-r--r--spec/ruby/core/matchdata/post_match_spec.rb18
-rw-r--r--spec/ruby/core/matchdata/pre_match_spec.rb18
-rw-r--r--spec/ruby/core/matchdata/values_at_spec.rb73
-rw-r--r--spec/ruby/core/math/ldexp_spec.rb6
-rw-r--r--spec/ruby/core/math/log2_spec.rb2
-rw-r--r--spec/ruby/core/math/sqrt_spec.rb4
-rw-r--r--spec/ruby/core/method/fixtures/classes.rb30
-rw-r--r--spec/ruby/core/method/owner_spec.rb6
-rw-r--r--spec/ruby/core/method/parameters_spec.rb15
-rw-r--r--spec/ruby/core/method/private_spec.rb21
-rw-r--r--spec/ruby/core/method/protected_spec.rb21
-rw-r--r--spec/ruby/core/method/public_spec.rb21
-rw-r--r--spec/ruby/core/method/shared/to_s.rb32
-rw-r--r--spec/ruby/core/method/super_method_spec.rb21
-rw-r--r--spec/ruby/core/method/unbind_spec.rb12
-rw-r--r--spec/ruby/core/module/append_features_spec.rb14
-rw-r--r--spec/ruby/core/module/autoload_spec.rb50
-rw-r--r--spec/ruby/core/module/class_variables_spec.rb8
-rw-r--r--spec/ruby/core/module/const_added_spec.rb125
-rw-r--r--spec/ruby/core/module/const_defined_spec.rb7
-rw-r--r--spec/ruby/core/module/const_get_spec.rb14
-rw-r--r--spec/ruby/core/module/const_source_location_spec.rb333
-rw-r--r--spec/ruby/core/module/define_method_spec.rb43
-rw-r--r--spec/ruby/core/module/deprecate_constant_spec.rb20
-rw-r--r--spec/ruby/core/module/extend_object_spec.rb14
-rw-r--r--spec/ruby/core/module/fixtures/classes.rb13
-rw-r--r--spec/ruby/core/module/include_spec.rb25
-rw-r--r--spec/ruby/core/module/included_modules_spec.rb2
-rw-r--r--spec/ruby/core/module/instance_method_spec.rb42
-rw-r--r--spec/ruby/core/module/name_spec.rb26
-rw-r--r--spec/ruby/core/module/prepend_features_spec.rb14
-rw-r--r--spec/ruby/core/module/prepend_spec.rb14
-rw-r--r--spec/ruby/core/module/refine_spec.rb162
-rw-r--r--spec/ruby/core/module/ruby2_keywords_spec.rb343
-rw-r--r--spec/ruby/core/module/shared/class_eval.rb21
-rw-r--r--spec/ruby/core/nil/match_spec.rb2
-rw-r--r--spec/ruby/core/nil/to_s_spec.rb12
-rw-r--r--spec/ruby/core/numeric/quo_spec.rb2
-rw-r--r--spec/ruby/core/numeric/shared/step.rb1
-rw-r--r--spec/ruby/core/numeric/step_spec.rb2
-rw-r--r--spec/ruby/core/objectspace/define_finalizer_spec.rb22
-rw-r--r--spec/ruby/core/objectspace/weakmap/element_set_spec.rb53
-rw-r--r--spec/ruby/core/objectspace/weakmap/shared/include.rb16
-rw-r--r--spec/ruby/core/proc/block_pass_spec.rb22
-rw-r--r--spec/ruby/core/proc/compose_spec.rb8
-rw-r--r--spec/ruby/core/proc/eql_spec.rb2
-rw-r--r--spec/ruby/core/proc/equal_value_spec.rb2
-rw-r--r--spec/ruby/core/proc/new_spec.rb39
-rw-r--r--spec/ruby/core/proc/parameters_spec.rb27
-rw-r--r--spec/ruby/core/proc/ruby2_keywords_spec.rb104
-rw-r--r--spec/ruby/core/proc/shared/compose.rb51
-rw-r--r--spec/ruby/core/proc/shared/to_s.rb10
-rw-r--r--spec/ruby/core/process/_fork_spec.rb24
-rw-r--r--spec/ruby/core/process/clock_gettime_spec.rb101
-rw-r--r--spec/ruby/core/process/constants_spec.rb1
-rw-r--r--spec/ruby/core/process/daemon_spec.rb3
-rw-r--r--spec/ruby/core/process/detach_spec.rb29
-rw-r--r--spec/ruby/core/process/egid_spec.rb41
-rw-r--r--spec/ruby/core/process/euid_spec.rb12
-rw-r--r--spec/ruby/core/process/spawn_spec.rb30
-rw-r--r--spec/ruby/core/process/status/equal_value_spec.rb2
-rw-r--r--spec/ruby/core/process/status/exited_spec.rb2
-rw-r--r--spec/ruby/core/process/status/exitstatus_spec.rb2
-rw-r--r--spec/ruby/core/process/status/signaled_spec.rb2
-rw-r--r--spec/ruby/core/process/status/success_spec.rb2
-rw-r--r--spec/ruby/core/process/status/termsig_spec.rb4
-rw-r--r--spec/ruby/core/process/status/to_i_spec.rb2
-rw-r--r--spec/ruby/core/process/times_spec.rb14
-rw-r--r--spec/ruby/core/process/wait2_spec.rb9
-rw-r--r--spec/ruby/core/queue/initialize_spec.rb13
-rw-r--r--spec/ruby/core/random/bytes_spec.rb2
-rw-r--r--spec/ruby/core/random/default_spec.rb52
-rw-r--r--spec/ruby/core/random/rand_spec.rb5
-rw-r--r--spec/ruby/core/random/raw_seed_spec.rb6
-rw-r--r--spec/ruby/core/random/shared/urandom.rb23
-rw-r--r--spec/ruby/core/random/urandom_spec.rb25
-rw-r--r--spec/ruby/core/range/bsearch_spec.rb196
-rw-r--r--spec/ruby/core/range/case_compare_spec.rb10
-rw-r--r--spec/ruby/core/range/clone_spec.rb26
-rw-r--r--spec/ruby/core/range/count_spec.rb16
-rw-r--r--spec/ruby/core/range/dup_spec.rb10
-rw-r--r--spec/ruby/core/range/each_spec.rb6
-rw-r--r--spec/ruby/core/range/equal_value_spec.rb6
-rw-r--r--spec/ruby/core/range/first_spec.rb6
-rw-r--r--spec/ruby/core/range/frozen_spec.rb27
-rw-r--r--spec/ruby/core/range/inspect_spec.rb28
-rw-r--r--spec/ruby/core/range/last_spec.rb6
-rw-r--r--spec/ruby/core/range/max_spec.rb12
-rw-r--r--spec/ruby/core/range/min_spec.rb6
-rw-r--r--spec/ruby/core/range/minmax_spec.rb124
-rw-r--r--spec/ruby/core/range/new_spec.rb32
-rw-r--r--spec/ruby/core/range/shared/cover.rb56
-rw-r--r--spec/ruby/core/range/shared/cover_and_include.rb8
-rw-r--r--spec/ruby/core/range/size_spec.rb25
-rw-r--r--spec/ruby/core/range/step_spec.rb16
-rw-r--r--spec/ruby/core/range/to_a_spec.rb6
-rw-r--r--spec/ruby/core/range/to_s_spec.rb22
-rw-r--r--spec/ruby/core/rational/minus_spec.rb48
-rw-r--r--spec/ruby/core/refinement/append_features_spec.rb21
-rw-r--r--spec/ruby/core/refinement/extend_object_spec.rb21
-rw-r--r--spec/ruby/core/refinement/import_methods_spec.rb34
-rw-r--r--spec/ruby/core/refinement/include_spec.rb27
-rw-r--r--spec/ruby/core/refinement/prepend_features_spec.rb21
-rw-r--r--spec/ruby/core/refinement/prepend_spec.rb27
-rw-r--r--spec/ruby/core/regexp/compile_spec.rb4
-rw-r--r--spec/ruby/core/regexp/initialize_spec.rb2
-rw-r--r--spec/ruby/core/regexp/new_spec.rb14
-rw-r--r--spec/ruby/core/regexp/shared/new.rb192
-rw-r--r--spec/ruby/core/regexp/shared/quote.rb10
-rw-r--r--spec/ruby/core/regexp/source_spec.rb22
-rw-r--r--spec/ruby/core/regexp/timeout_spec.rb35
-rw-r--r--spec/ruby/core/signal/trap_spec.rb16
-rw-r--r--spec/ruby/core/string/allocate_spec.rb2
-rw-r--r--spec/ruby/core/string/append_spec.rb5
-rw-r--r--spec/ruby/core/string/b_spec.rb9
-rw-r--r--spec/ruby/core/string/byteindex_spec.rb16
-rw-r--r--spec/ruby/core/string/bytesize_spec.rb2
-rw-r--r--spec/ruby/core/string/byteslice_spec.rb6
-rw-r--r--spec/ruby/core/string/capitalize_spec.rb16
-rw-r--r--spec/ruby/core/string/center_spec.rb18
-rw-r--r--spec/ruby/core/string/chars_spec.rb7
-rw-r--r--spec/ruby/core/string/chomp_spec.rb62
-rw-r--r--spec/ruby/core/string/chop_spec.rb16
-rw-r--r--spec/ruby/core/string/clone_spec.rb4
-rw-r--r--spec/ruby/core/string/comparison_spec.rb4
-rw-r--r--spec/ruby/core/string/crypt_spec.rb30
-rw-r--r--spec/ruby/core/string/dedup_spec.rb8
-rw-r--r--spec/ruby/core/string/delete_prefix_spec.rb11
-rw-r--r--spec/ruby/core/string/delete_spec.rb13
-rw-r--r--spec/ruby/core/string/delete_suffix_spec.rb11
-rw-r--r--spec/ruby/core/string/downcase_spec.rb16
-rw-r--r--spec/ruby/core/string/dump_spec.rb22
-rw-r--r--spec/ruby/core/string/dup_spec.rb13
-rw-r--r--spec/ruby/core/string/element_set_spec.rb34
-rw-r--r--spec/ruby/core/string/encoding_spec.rb1
-rw-r--r--spec/ruby/core/string/fixtures/iso-8859-9-encoding.rb2
-rw-r--r--spec/ruby/core/string/fixtures/to_c.rb5
-rw-r--r--spec/ruby/core/string/gsub_spec.rb173
-rw-r--r--spec/ruby/core/string/include_spec.rb14
-rw-r--r--spec/ruby/core/string/index_spec.rb8
-rw-r--r--spec/ruby/core/string/insert_spec.rb21
-rw-r--r--spec/ruby/core/string/inspect_spec.rb32
-rw-r--r--spec/ruby/core/string/lines_spec.rb1
-rw-r--r--spec/ruby/core/string/ljust_spec.rb18
-rw-r--r--spec/ruby/core/string/lstrip_spec.rb50
-rw-r--r--spec/ruby/core/string/modulo_spec.rb62
-rw-r--r--spec/ruby/core/string/ord_spec.rb5
-rw-r--r--spec/ruby/core/string/partition_spec.rb22
-rw-r--r--spec/ruby/core/string/plus_spec.rb13
-rw-r--r--spec/ruby/core/string/prepend_spec.rb10
-rw-r--r--spec/ruby/core/string/reverse_spec.rb28
-rw-r--r--spec/ruby/core/string/rindex_spec.rb23
-rw-r--r--spec/ruby/core/string/rjust_spec.rb18
-rw-r--r--spec/ruby/core/string/rpartition_spec.rb22
-rw-r--r--spec/ruby/core/string/rstrip_spec.rb54
-rw-r--r--spec/ruby/core/string/scan_spec.rb46
-rw-r--r--spec/ruby/core/string/scrub_spec.rb15
-rw-r--r--spec/ruby/core/string/setbyte_spec.rb6
-rw-r--r--spec/ruby/core/string/shared/chars.rb14
-rw-r--r--spec/ruby/core/string/shared/concat.rb12
-rw-r--r--spec/ruby/core/string/shared/dedup.rb57
-rw-r--r--spec/ruby/core/string/shared/each_line.rb14
-rw-r--r--spec/ruby/core/string/shared/eql.rb4
-rw-r--r--spec/ruby/core/string/shared/length.rb24
-rw-r--r--spec/ruby/core/string/shared/partition.rb15
-rw-r--r--spec/ruby/core/string/shared/replace.rb30
-rw-r--r--spec/ruby/core/string/shared/slice.rb155
-rw-r--r--spec/ruby/core/string/shared/strip.rb4
-rw-r--r--spec/ruby/core/string/shared/succ.rb8
-rw-r--r--spec/ruby/core/string/shared/to_s.rb7
-rw-r--r--spec/ruby/core/string/shared/to_sym.rb9
-rw-r--r--spec/ruby/core/string/slice_spec.rb85
-rw-r--r--spec/ruby/core/string/split_spec.rb165
-rw-r--r--spec/ruby/core/string/squeeze_spec.rb15
-rw-r--r--spec/ruby/core/string/start_with_spec.rb10
-rw-r--r--spec/ruby/core/string/strip_spec.rb18
-rw-r--r--spec/ruby/core/string/sub_spec.rb136
-rw-r--r--spec/ruby/core/string/swapcase_spec.rb11
-rw-r--r--spec/ruby/core/string/to_c_spec.rb108
-rw-r--r--spec/ruby/core/string/tr_s_spec.rb13
-rw-r--r--spec/ruby/core/string/tr_spec.rb13
-rw-r--r--spec/ruby/core/string/uminus_spec.rb47
-rw-r--r--spec/ruby/core/string/undump_spec.rb12
-rw-r--r--spec/ruby/core/string/unpack/b_spec.rb34
-rw-r--r--spec/ruby/core/string/unpack/c_spec.rb14
-rw-r--r--spec/ruby/core/string/unpack/h_spec.rb28
-rw-r--r--spec/ruby/core/string/unpack/m_spec.rb5
-rw-r--r--spec/ruby/core/string/unpack/p_spec.rb12
-rw-r--r--spec/ruby/core/string/unpack/shared/basic.rb28
-rw-r--r--spec/ruby/core/string/unpack/shared/float.rb60
-rw-r--r--spec/ruby/core/string/unpack/shared/integer.rb88
-rw-r--r--spec/ruby/core/string/unpack/shared/taint.rb81
-rw-r--r--spec/ruby/core/string/unpack/shared/unicode.rb14
-rw-r--r--spec/ruby/core/string/unpack/w_spec.rb14
-rw-r--r--spec/ruby/core/string/unpack/z_spec.rb5
-rw-r--r--spec/ruby/core/string/unpack1_spec.rb12
-rw-r--r--spec/ruby/core/string/unpack_spec.rb34
-rw-r--r--spec/ruby/core/string/upcase_spec.rb16
-rw-r--r--spec/ruby/core/string/valid_encoding/utf_8_spec.rb214
-rw-r--r--spec/ruby/core/struct/deconstruct_keys_spec.rb146
-rw-r--r--spec/ruby/core/struct/deconstruct_spec.rb12
-rw-r--r--spec/ruby/core/struct/initialize_spec.rb8
-rw-r--r--spec/ruby/core/struct/keyword_init_spec.rb21
-rw-r--r--spec/ruby/core/struct/new_spec.rb16
-rw-r--r--spec/ruby/core/struct/values_at_spec.rb55
-rw-r--r--spec/ruby/core/symbol/end_with_spec.rb6
-rw-r--r--spec/ruby/core/symbol/shared/id2name.rb7
-rw-r--r--spec/ruby/core/symbol/shared/slice.rb20
-rw-r--r--spec/ruby/core/symbol/start_with_spec.rb6
-rw-r--r--spec/ruby/core/symbol/to_proc_spec.rb27
-rw-r--r--spec/ruby/core/thread/backtrace/limit_spec.rb15
-rw-r--r--spec/ruby/core/thread/backtrace/location/absolute_path_spec.rb9
-rw-r--r--spec/ruby/core/thread/backtrace/location/fixtures/subdir/absolute_path_main_chdir.rb11
-rw-r--r--spec/ruby/core/thread/backtrace/location/fixtures/subdir/sibling.rb1
-rw-r--r--spec/ruby/core/thread/backtrace_locations_spec.rb10
-rw-r--r--spec/ruby/core/thread/native_thread_id_spec.rb17
-rw-r--r--spec/ruby/core/thread/raise_spec.rb24
-rw-r--r--spec/ruby/core/thread/report_on_exception_spec.rb51
-rw-r--r--spec/ruby/core/thread/shared/exit.rb22
-rw-r--r--spec/ruby/core/thread/shared/to_s.rb4
-rw-r--r--spec/ruby/core/time/at_spec.rb21
-rw-r--r--spec/ruby/core/time/ceil_spec.rb64
-rw-r--r--spec/ruby/core/time/floor_spec.rb52
-rw-r--r--spec/ruby/core/time/inspect_spec.rb44
-rw-r--r--spec/ruby/core/time/localtime_spec.rb16
-rw-r--r--spec/ruby/core/time/new_spec.rb145
-rw-r--r--spec/ruby/core/time/now_spec.rb45
-rw-r--r--spec/ruby/core/time/shared/gmtime.rb4
-rw-r--r--spec/ruby/core/time/shared/local.rb11
-rw-r--r--spec/ruby/core/time/shared/time_params.rb11
-rw-r--r--spec/ruby/core/time/strftime_spec.rb41
-rw-r--r--spec/ruby/core/time/utc_spec.rb41
-rw-r--r--spec/ruby/core/time/zone_spec.rb20
-rw-r--r--spec/ruby/core/tracepoint/allow_reentry_spec.rb32
-rw-r--r--spec/ruby/core/tracepoint/enable_spec.rb55
-rw-r--r--spec/ruby/core/tracepoint/inspect_spec.rb13
-rw-r--r--spec/ruby/core/true/to_s_spec.rb12
-rw-r--r--spec/ruby/core/unboundmethod/bind_call_spec.rb74
-rw-r--r--spec/ruby/core/unboundmethod/equal_value_spec.rb76
-rw-r--r--spec/ruby/core/unboundmethod/fixtures/classes.rb16
-rw-r--r--spec/ruby/core/unboundmethod/hash_spec.rb7
-rw-r--r--spec/ruby/core/unboundmethod/owner_spec.rb7
-rw-r--r--spec/ruby/core/unboundmethod/private_spec.rb21
-rw-r--r--spec/ruby/core/unboundmethod/protected_spec.rb21
-rw-r--r--spec/ruby/core/unboundmethod/public_spec.rb21
-rw-r--r--spec/ruby/core/unboundmethod/shared/to_s.rb16
-rw-r--r--spec/ruby/core/unboundmethod/super_method_spec.rb23
-rw-r--r--spec/ruby/core/warning/element_reference_spec.rb28
-rw-r--r--spec/ruby/core/warning/element_set_spec.rb48
-rw-r--r--spec/ruby/fixtures/class.rb4
-rw-r--r--spec/ruby/fixtures/code/c/load_fixture.rb1
-rw-r--r--spec/ruby/fixtures/code/concurrent_require_fixture.rb4
-rw-r--r--spec/ruby/fixtures/code/load_wrap_fixture.rb (renamed from spec/ruby/fixtures/code/wrap_fixture.rb)3
-rw-r--r--spec/ruby/fixtures/constants.rb21
-rw-r--r--spec/ruby/language/alias_spec.rb13
-rw-r--r--spec/ruby/language/block_spec.rb182
-rw-r--r--spec/ruby/language/case_spec.rb13
-rw-r--r--spec/ruby/language/class_spec.rb13
-rw-r--r--spec/ruby/language/comment_spec.rb16
-rw-r--r--spec/ruby/language/constants_spec.rb48
-rw-r--r--spec/ruby/language/def_spec.rb33
-rw-r--r--spec/ruby/language/defined_spec.rb14
-rw-r--r--spec/ruby/language/delegation_spec.rb61
-rw-r--r--spec/ruby/language/file_spec.rb12
-rw-r--r--spec/ruby/language/fixtures/defined.rb3
-rw-r--r--spec/ruby/language/fixtures/freeze_magic_comment_two_literals.rb2
-rw-r--r--spec/ruby/language/hash_spec.rb15
-rw-r--r--spec/ruby/language/heredoc_spec.rb18
-rw-r--r--spec/ruby/language/keyword_arguments_spec.rb397
-rw-r--r--spec/ruby/language/lambda_spec.rb64
-rw-r--r--spec/ruby/language/method_spec.rb310
-rw-r--r--spec/ruby/language/module_spec.rb15
-rw-r--r--spec/ruby/language/numbered_parameters_spec.rb184
-rw-r--r--spec/ruby/language/numbers_spec.rb2
-rw-r--r--spec/ruby/language/optional_assignments_spec.rb38
-rw-r--r--spec/ruby/language/pattern_matching_spec.rb2151
-rw-r--r--spec/ruby/language/precedence_spec.rb78
-rw-r--r--spec/ruby/language/predefined_spec.rb439
-rw-r--r--spec/ruby/language/proc_spec.rb15
-rw-r--r--spec/ruby/language/range_spec.rb22
-rw-r--r--spec/ruby/language/regexp/character_classes_spec.rb5
-rw-r--r--spec/ruby/language/regexp/escapes_spec.rb84
-rw-r--r--spec/ruby/language/regexp_spec.rb23
-rw-r--r--spec/ruby/language/rescue_spec.rb22
-rw-r--r--spec/ruby/language/return_spec.rb61
-rw-r--r--spec/ruby/language/safe_spec.rb94
-rw-r--r--spec/ruby/language/send_spec.rb18
-rw-r--r--spec/ruby/language/string_spec.rb22
-rw-r--r--spec/ruby/language/variables_spec.rb39
-rw-r--r--spec/ruby/language/yield_spec.rb12
-rw-r--r--spec/ruby/library/bigdecimal/exponent_spec.rb11
-rw-r--r--spec/ruby/library/bigdecimal/round_spec.rb12
-rw-r--r--spec/ruby/library/bigdecimal/to_r_spec.rb12
-rw-r--r--spec/ruby/library/cgi/cookie/name_spec.rb12
-rw-r--r--spec/ruby/library/cgi/cookie/parse_spec.rb10
-rw-r--r--spec/ruby/library/cmath/math/acos_spec.rb18
-rw-r--r--spec/ruby/library/cmath/math/acosh_spec.rb18
-rw-r--r--spec/ruby/library/cmath/math/asin_spec.rb18
-rw-r--r--spec/ruby/library/cmath/math/asinh_spec.rb18
-rw-r--r--spec/ruby/library/cmath/math/atan2_spec.rb18
-rw-r--r--spec/ruby/library/cmath/math/atan_spec.rb18
-rw-r--r--spec/ruby/library/cmath/math/atanh_spec.rb20
-rw-r--r--spec/ruby/library/cmath/math/cos_spec.rb18
-rw-r--r--spec/ruby/library/cmath/math/cosh_spec.rb18
-rw-r--r--spec/ruby/library/cmath/math/exp_spec.rb18
-rw-r--r--spec/ruby/library/cmath/math/fixtures/classes.rb4
-rw-r--r--spec/ruby/library/cmath/math/log10_spec.rb18
-rw-r--r--spec/ruby/library/cmath/math/log_spec.rb18
-rw-r--r--spec/ruby/library/cmath/math/shared/acos.rb41
-rw-r--r--spec/ruby/library/cmath/math/shared/acosh.rb37
-rw-r--r--spec/ruby/library/cmath/math/shared/asin.rb47
-rw-r--r--spec/ruby/library/cmath/math/shared/asinh.rb32
-rw-r--r--spec/ruby/library/cmath/math/shared/atan.rb32
-rw-r--r--spec/ruby/library/cmath/math/shared/atan2.rb34
-rw-r--r--spec/ruby/library/cmath/math/shared/atanh.rb30
-rw-r--r--spec/ruby/library/cmath/math/shared/cos.rb30
-rw-r--r--spec/ruby/library/cmath/math/shared/cosh.rb28
-rw-r--r--spec/ruby/library/cmath/math/shared/exp.rb28
-rw-r--r--spec/ruby/library/cmath/math/shared/log.rb39
-rw-r--r--spec/ruby/library/cmath/math/shared/log10.rb41
-rw-r--r--spec/ruby/library/cmath/math/shared/sin.rb30
-rw-r--r--spec/ruby/library/cmath/math/shared/sinh.rb28
-rw-r--r--spec/ruby/library/cmath/math/shared/sqrt.rb34
-rw-r--r--spec/ruby/library/cmath/math/shared/tan.rb28
-rw-r--r--spec/ruby/library/cmath/math/shared/tanh.rb32
-rw-r--r--spec/ruby/library/cmath/math/sin_spec.rb18
-rw-r--r--spec/ruby/library/cmath/math/sinh_spec.rb18
-rw-r--r--spec/ruby/library/cmath/math/sqrt_spec.rb18
-rw-r--r--spec/ruby/library/cmath/math/tan_spec.rb18
-rw-r--r--spec/ruby/library/cmath/math/tanh_spec.rb18
-rw-r--r--spec/ruby/library/coverage/result_spec.rb54
-rw-r--r--spec/ruby/library/coverage/running_spec.rb20
-rw-r--r--spec/ruby/library/coverage/start_spec.rb8
-rw-r--r--spec/ruby/library/date/civil_spec.rb7
-rw-r--r--spec/ruby/library/date/iso8601_spec.rb9
-rw-r--r--spec/ruby/library/date/parse_spec.rb2
-rw-r--r--spec/ruby/library/date/shared/valid_jd.rb20
-rw-r--r--spec/ruby/library/datetime/to_time_spec.rb18
-rw-r--r--spec/ruby/library/delegate/delegator/taint_spec.rb17
-rw-r--r--spec/ruby/library/delegate/delegator/trust_spec.rb16
-rw-r--r--spec/ruby/library/delegate/delegator/untaint_spec.rb18
-rw-r--r--spec/ruby/library/delegate/delegator/untrust_spec.rb17
-rw-r--r--spec/ruby/library/erb/new_spec.rb16
-rw-r--r--spec/ruby/library/fiddle/handle/initialize_spec.rb10
-rw-r--r--spec/ruby/library/io-wait/wait_readable_spec.rb27
-rw-r--r--spec/ruby/library/io-wait/wait_writable_spec.rb20
-rw-r--r--spec/ruby/library/logger/device/close_spec.rb4
-rw-r--r--spec/ruby/library/logger/device/write_spec.rb4
-rw-r--r--spec/ruby/library/matrix/multiply_spec.rb4
-rw-r--r--spec/ruby/library/objectspace/fixtures/trace.rb5
-rw-r--r--spec/ruby/library/objectspace/trace_object_allocations_spec.rb18
-rw-r--r--spec/ruby/library/objectspace/trace_spec.rb15
-rw-r--r--spec/ruby/library/openssl/x509/name/verify_spec.rb78
-rw-r--r--spec/ruby/library/openstruct/method_missing_spec.rb8
-rw-r--r--spec/ruby/library/pathname/birthtime_spec.rb16
-rw-r--r--spec/ruby/library/pathname/glob_spec.rb53
-rw-r--r--spec/ruby/library/pathname/new_spec.rb7
-rw-r--r--spec/ruby/library/pathname/pathname_spec.rb19
-rw-r--r--spec/ruby/library/pp/pp_spec.rb7
-rw-r--r--spec/ruby/library/rbconfig/unicode_emoji_version_spec.rb25
-rw-r--r--spec/ruby/library/rbconfig/unicode_version_spec.rb25
-rw-r--r--spec/ruby/library/readline/history/delete_at_spec.rb9
-rw-r--r--spec/ruby/library/readline/history/each_spec.rb8
-rw-r--r--spec/ruby/library/readline/history/element_reference_spec.rb7
-rw-r--r--spec/ruby/library/readline/history/pop_spec.rb9
-rw-r--r--spec/ruby/library/readline/history/shift_spec.rb9
-rw-r--r--spec/ruby/library/readline/readline_spec.rb7
-rw-r--r--spec/ruby/library/scanf/io/block_scanf_spec.rb10
-rw-r--r--spec/ruby/library/scanf/io/fixtures/date.txt4
-rw-r--r--spec/ruby/library/scanf/io/fixtures/helloworld.txt1
-rw-r--r--spec/ruby/library/scanf/io/scanf_spec.rb38
-rw-r--r--spec/ruby/library/scanf/io/shared/block_scanf.rb28
-rw-r--r--spec/ruby/library/scanf/string/block_scanf_spec.rb10
-rw-r--r--spec/ruby/library/scanf/string/scanf_spec.rb56
-rw-r--r--spec/ruby/library/scanf/string/shared/block_scanf.rb25
-rw-r--r--spec/ruby/library/socket/addrinfo/initialize_spec.rb2
-rw-r--r--spec/ruby/library/socket/shared/pack_sockaddr.rb7
-rw-r--r--spec/ruby/library/socket/tcpsocket/shared/new.rb10
-rw-r--r--spec/ruby/library/stringio/append_spec.rb7
-rw-r--r--spec/ruby/library/stringio/each_line_spec.rb4
-rw-r--r--spec/ruby/library/stringio/each_spec.rb8
-rw-r--r--spec/ruby/library/stringio/gets_spec.rb4
-rw-r--r--spec/ruby/library/stringio/initialize_spec.rb85
-rw-r--r--spec/ruby/library/stringio/new_spec.rb8
-rw-r--r--spec/ruby/library/stringio/open_spec.rb12
-rw-r--r--spec/ruby/library/stringio/printf_spec.rb27
-rw-r--r--spec/ruby/library/stringio/putc_spec.rb15
-rw-r--r--spec/ruby/library/stringio/puts_spec.rb14
-rw-r--r--spec/ruby/library/stringio/read_nonblock_spec.rb11
-rw-r--r--spec/ruby/library/stringio/readline_spec.rb20
-rw-r--r--spec/ruby/library/stringio/readlines_spec.rb18
-rw-r--r--spec/ruby/library/stringio/reopen_spec.rb17
-rw-r--r--spec/ruby/library/stringio/shared/each.rb58
-rw-r--r--spec/ruby/library/stringio/shared/read.rb6
-rw-r--r--spec/ruby/library/stringio/shared/write.rb40
-rw-r--r--spec/ruby/library/stringio/truncate_spec.rb12
-rw-r--r--spec/ruby/library/stringio/write_nonblock_spec.rb6
-rw-r--r--spec/ruby/library/stringscanner/check_spec.rb14
-rw-r--r--spec/ruby/library/stringscanner/scan_spec.rb44
-rw-r--r--spec/ruby/library/stringscanner/shared/extract_range.rb13
-rw-r--r--spec/ruby/library/stringscanner/shared/extract_range_matched.rb11
-rw-r--r--spec/ruby/library/stringscanner/shared/peek.rb10
-rw-r--r--spec/ruby/library/time/to_datetime_spec.rb18
-rw-r--r--spec/ruby/library/yaml/to_yaml_spec.rb12
-rw-r--r--spec/ruby/library/zlib/crc_table_spec.rb143
-rw-r--r--spec/ruby/library/zlib/deflate/deflate_spec.rb5
-rw-r--r--spec/ruby/library/zlib/inflate/inflate_spec.rb7
-rw-r--r--spec/ruby/optional/capi/binding_spec.rb21
-rw-r--r--spec/ruby/optional/capi/class_spec.rb65
-rw-r--r--spec/ruby/optional/capi/encoding_spec.rb73
-rw-r--r--spec/ruby/optional/capi/ext/class_spec.c37
-rw-r--r--spec/ruby/optional/capi/ext/encoding_spec.c33
-rw-r--r--spec/ruby/optional/capi/ext/gc_spec.c35
-rw-r--r--spec/ruby/optional/capi/ext/globals_spec.c34
-rw-r--r--spec/ruby/optional/capi/ext/io_spec.c43
-rw-r--r--spec/ruby/optional/capi/ext/kernel_spec.c32
-rw-r--r--spec/ruby/optional/capi/ext/module_spec.c56
-rw-r--r--spec/ruby/optional/capi/ext/object_spec.c31
-rw-r--r--spec/ruby/optional/capi/ext/proc_spec.c59
-rw-r--r--spec/ruby/optional/capi/ext/regexp_spec.c7
-rw-r--r--spec/ruby/optional/capi/ext/rubyspec.h34
-rw-r--r--spec/ruby/optional/capi/ext/string_spec.c30
-rw-r--r--spec/ruby/optional/capi/ext/symbol_spec.c11
-rw-r--r--spec/ruby/optional/capi/ext/thread_spec.c38
-rw-r--r--spec/ruby/optional/capi/ext/util_spec.c21
-rw-r--r--spec/ruby/optional/capi/fixtures/class.rb10
-rw-r--r--spec/ruby/optional/capi/fixtures/object.rb29
-rw-r--r--spec/ruby/optional/capi/gc_spec.rb30
-rw-r--r--spec/ruby/optional/capi/globals_spec.rb54
-rw-r--r--spec/ruby/optional/capi/io_spec.rb15
-rw-r--r--spec/ruby/optional/capi/kernel_spec.rb94
-rw-r--r--spec/ruby/optional/capi/module_spec.rb30
-rw-r--r--spec/ruby/optional/capi/object_spec.rb141
-rw-r--r--spec/ruby/optional/capi/proc_spec.rb55
-rw-r--r--spec/ruby/optional/capi/rbasic_spec.rb1
-rw-r--r--spec/ruby/optional/capi/regexp_spec.rb16
-rw-r--r--spec/ruby/optional/capi/shared/rbasic.rb36
-rw-r--r--spec/ruby/optional/capi/spec_helper.rb8
-rw-r--r--spec/ruby/optional/capi/string_spec.rb168
-rw-r--r--spec/ruby/optional/capi/symbol_spec.rb8
-rw-r--r--spec/ruby/optional/capi/thread_spec.rb10
-rw-r--r--spec/ruby/optional/capi/util_spec.rb24
-rw-r--r--spec/ruby/security/cve_2018_16396_spec.rb14
-rw-r--r--spec/ruby/security/cve_2019_8323_spec.rb54
-rw-r--r--spec/ruby/security/cve_2019_8325_spec.rb62
-rw-r--r--spec/ruby/security/cve_2020_10663_spec.rb25
-rw-r--r--spec/ruby/shared/file/executable.rb35
-rw-r--r--spec/ruby/shared/file/executable_real.rb35
-rw-r--r--spec/ruby/shared/file/readable.rb16
-rw-r--r--spec/ruby/shared/file/readable_real.rb16
-rw-r--r--spec/ruby/shared/file/writable.rb16
-rw-r--r--spec/ruby/shared/file/writable_real.rb16
-rw-r--r--spec/ruby/shared/kernel/complex.rb133
-rw-r--r--spec/ruby/shared/kernel/raise.rb34
-rw-r--r--spec/ruby/shared/process/exit.rb6
-rw-r--r--spec/ruby/shared/queue/deque.rb62
-rw-r--r--spec/ruby/shared/rational/Rational.rb48
-rw-r--r--spec/ruby/shared/rational/divmod.rb4
-rw-r--r--spec/ruby/shared/rational/exponent.rb8
-rw-r--r--spec/ruby/shared/rational/minus.rb48
-rw-r--r--spec/ruby/shared/rational/to_f.rb6
-rw-r--r--spec/ruby/shared/sizedqueue/enque.rb63
-rw-r--r--spec/ruby/shared/sizedqueue/new.rb9
-rw-r--r--spec/ruby/shared/string/end_with.rb9
-rw-r--r--spec/ruby/shared/string/start_with.rb4
-rw-r--r--spec/ruby/shared/string/times.rb12
-rw-r--r--spec/ruby/spec_helper.rb10
-rw-r--r--spec/syntax_suggest/fixtures/derailed_require_tree.rb.txt74
-rwxr-xr-xspec/syntax_suggest/fixtures/rexe.rb.txt569
-rw-r--r--spec/syntax_suggest/fixtures/routes.rb.txt121
-rw-r--r--spec/syntax_suggest/fixtures/ruby_buildpack.rb.txt1344
-rw-r--r--spec/syntax_suggest/fixtures/syntax_tree.rb.txt9234
-rw-r--r--spec/syntax_suggest/fixtures/this_project_extra_def.rb.txt64
-rw-r--r--spec/syntax_suggest/fixtures/webmock.rb.txt35
-rw-r--r--spec/syntax_suggest/integration/exe_cli_spec.rb27
-rw-r--r--spec/syntax_suggest/integration/ruby_command_line_spec.rb193
-rw-r--r--spec/syntax_suggest/integration/syntax_suggest_spec.rb239
-rw-r--r--spec/syntax_suggest/spec_helper.rb104
-rw-r--r--spec/syntax_suggest/unit/api_spec.rb108
-rw-r--r--spec/syntax_suggest/unit/around_block_scan_spec.rb165
-rw-r--r--spec/syntax_suggest/unit/block_expand_spec.rb230
-rw-r--r--spec/syntax_suggest/unit/capture/before_after_keyword_ends_spec.rb47
-rw-r--r--spec/syntax_suggest/unit/capture/falling_indent_lines_spec.rb44
-rw-r--r--spec/syntax_suggest/unit/capture_code_context_spec.rb229
-rw-r--r--spec/syntax_suggest/unit/clean_document_spec.rb260
-rw-r--r--spec/syntax_suggest/unit/cli_spec.rb224
-rw-r--r--spec/syntax_suggest/unit/code_block_spec.rb77
-rw-r--r--spec/syntax_suggest/unit/code_frontier_spec.rb135
-rw-r--r--spec/syntax_suggest/unit/code_line_spec.rb165
-rw-r--r--spec/syntax_suggest/unit/code_search_spec.rb505
-rw-r--r--spec/syntax_suggest/unit/core_ext_spec.rb34
-rw-r--r--spec/syntax_suggest/unit/display_invalid_blocks_spec.rb174
-rw-r--r--spec/syntax_suggest/unit/explain_syntax_spec.rb255
-rw-r--r--spec/syntax_suggest/unit/lex_all_spec.rb29
-rw-r--r--spec/syntax_suggest/unit/pathname_from_message_spec.rb56
-rw-r--r--spec/syntax_suggest/unit/priority_queue_spec.rb95
-rw-r--r--spec/syntax_suggest/unit/scan_history_spec.rb114
-rw-r--r--sprintf.c1366
-rw-r--r--st.c717
-rw-r--r--strftime.c7
-rw-r--r--string.c8391
-rw-r--r--string.rb552
-rw-r--r--struct.c1168
-rw-r--r--symbol.c427
-rw-r--r--symbol.h20
-rw-r--r--symbol.rb15
-rw-r--r--template/Doxyfile.tmpl1
-rw-r--r--template/GNUmakefile.in15
-rw-r--r--template/Makefile.in100
-rw-r--r--template/configure-ext.mk.tmpl2
-rw-r--r--template/extinit.c.tmpl2
-rw-r--r--template/exts.mk.tmpl9
-rw-r--r--template/fake.rb.in39
-rw-r--r--template/id.c.tmpl5
-rw-r--r--template/id.h.tmpl10
-rw-r--r--template/prelude.c.tmpl107
-rw-r--r--test/-ext-/arith_seq/test_arith_seq_beg_len_step.rb52
-rw-r--r--test/-ext-/bignum/test_big2str.rb38
-rw-r--r--test/-ext-/bignum/test_bigzero.rb20
-rw-r--r--test/-ext-/bignum/test_div.rb38
-rw-r--r--test/-ext-/bignum/test_mul.rb260
-rw-r--r--test/-ext-/bignum/test_pack.rb653
-rw-r--r--test/-ext-/bignum/test_str2big.rb52
-rw-r--r--test/-ext-/bug_reporter/test_bug_reporter.rb16
-rw-r--r--test/-ext-/debug/test_profile_frames.rb24
-rw-r--r--test/-ext-/econv/test_append.rb23
-rw-r--r--test/-ext-/eval/test_eval.rb12
-rw-r--r--test/-ext-/float/test_nextafter.rb2
-rw-r--r--test/-ext-/funcall/test_funcall.rb11
-rw-r--r--test/-ext-/funcall/test_passing_block.rb5
-rw-r--r--test/-ext-/gvl/test_ubf_async_safe.rb2
-rw-r--r--test/-ext-/iseq_load/test_iseq_load.rb6
-rw-r--r--test/-ext-/string/test_capacity.rb11
-rw-r--r--test/-ext-/string/test_cstr.rb6
-rw-r--r--test/-ext-/string/test_fstring.rb22
-rw-r--r--test/-ext-/string/test_set_len.rb39
-rw-r--r--test/-ext-/symbol/test_type.rb14
-rw-r--r--test/-ext-/test_abi.rb47
-rw-r--r--test/-ext-/test_random.rb26
-rw-r--r--test/-ext-/thread/test_instrumentation_api.rb91
-rw-r--r--test/-ext-/thread_fd/test_thread_fd_close.rb1
-rw-r--r--test/bigdecimal/helper.rb11
-rw-r--r--test/bigdecimal/test_bigdecimal.rb197
-rw-r--r--test/bigdecimal/test_bigdecimal_util.rb15
-rw-r--r--test/cgi/test_cgi_cookie.rb85
-rw-r--r--test/cgi/test_cgi_header.rb8
-rw-r--r--test/cgi/test_cgi_util.rb68
-rw-r--r--test/coverage/autostart.rb2
-rw-r--r--test/coverage/main.rb1
-rw-r--r--test/coverage/test_coverage.rb71
-rw-r--r--test/csv/interface/test_read.rb18
-rw-r--r--test/csv/interface/test_write.rb9
-rw-r--r--test/csv/parse/test_convert.rb57
-rw-r--r--test/csv/parse/test_general.rb84
-rw-r--r--test/csv/parse/test_header.rb9
-rw-r--r--test/csv/parse/test_inputs_scanner.rb63
-rw-r--r--test/csv/parse/test_liberal_parsing.rb11
-rw-r--r--test/csv/parse/test_read.rb27
-rw-r--r--test/csv/parse/test_strip.rb29
-rw-r--r--test/csv/test_data_converters.rb84
-rw-r--r--test/csv/test_encodings.rb31
-rw-r--r--test/csv/test_patterns.rb27
-rw-r--r--test/csv/test_table.rb75
-rw-r--r--test/date/test_date.rb29
-rw-r--r--test/date/test_date_conv.rb17
-rw-r--r--test/date/test_date_parse.rb30
-rw-r--r--test/date/test_date_ractor.rb2
-rw-r--r--test/date/test_date_strftime.rb2
-rw-r--r--test/date/test_date_strptime.rb9
-rw-r--r--test/did_you_mean/core_ext/test_name_error_extension.rb23
-rw-r--r--test/did_you_mean/helper.rb14
-rw-r--r--test/did_you_mean/spell_checking/test_key_name_check.rb14
-rw-r--r--test/did_you_mean/spell_checking/test_method_name_check.rb38
-rw-r--r--test/did_you_mean/spell_checking/test_pattern_key_name_check.rb2
-rw-r--r--test/did_you_mean/spell_checking/test_require_path_check.rb6
-rw-r--r--test/did_you_mean/spell_checking/test_variable_name_check.rb36
-rw-r--r--test/did_you_mean/test_ractor_compatibility.rb117
-rw-r--r--test/digest/test_digest_extend.rb13
-rw-r--r--test/digest/test_ractor.rb6
-rw-r--r--test/drb/drbtest.rb2
-rw-r--r--test/drb/test_drb.rb5
-rw-r--r--test/drb/test_drbssl.rb8
-rw-r--r--test/dtrace/helper.rb2
-rw-r--r--test/erb/test_erb.rb30
-rw-r--r--test/erb/test_erb_command.rb18
-rw-r--r--test/error_highlight/test_error_highlight.rb133
-rw-r--r--test/excludes/TestGem.rb4
-rw-r--r--test/excludes/TestThread.rb12
-rw-r--r--test/excludes/TestThreadQueue.rb9
-rw-r--r--test/fiber/autoload.rb3
-rw-r--r--test/fiber/scheduler.rb111
-rw-r--r--test/fiber/test_address_resolve.rb2
-rw-r--r--test/fiber/test_enumerator.rb16
-rw-r--r--test/fiber/test_io.rb77
-rw-r--r--test/fiber/test_io_buffer.rb41
-rw-r--r--test/fiber/test_mutex.rb22
-rw-r--r--test/fiber/test_process.rb36
-rw-r--r--test/fiber/test_queue.rb54
-rw-r--r--test/fiber/test_ractor.rb2
-rw-r--r--test/fiber/test_scheduler.rb119
-rw-r--r--test/fiber/test_storage.rb115
-rw-r--r--test/fiber/test_thread.rb22
-rw-r--r--test/fiddle/helper.rb10
-rw-r--r--test/fiddle/test_closure.rb111
-rw-r--r--test/fiddle/test_fiddle.rb41
-rw-r--r--test/fiddle/test_func.rb36
-rw-r--r--test/fiddle/test_function.rb28
-rw-r--r--test/fiddle/test_handle.rb7
-rw-r--r--test/fiddle/test_import.rb23
-rw-r--r--test/fiddle/test_pack.rb37
-rw-r--r--test/fiddle/test_pointer.rb3
-rw-r--r--test/fileutils/clobber.rb5
-rw-r--r--test/fileutils/test_dryrun.rb2
-rw-r--r--test/fileutils/test_fileutils.rb91
-rw-r--r--test/fileutils/test_nowrite.rb2
-rw-r--r--test/fileutils/test_verbose.rb2
-rw-r--r--test/fileutils/visibility_tests.rb5
-rw-r--r--test/io/console/test_io_console.rb32
-rw-r--r--test/io/nonblock/test_flush.rb2
-rw-r--r--test/io/wait/test_io_wait.rb36
-rw-r--r--test/io/wait/test_io_wait_uncommon.rb3
-rw-r--r--test/io/wait/test_ractor.rb1
-rw-r--r--test/irb/helper.rb76
-rw-r--r--test/irb/test_cmd.rb862
-rw-r--r--test/irb/test_color.rb84
-rw-r--r--test/irb/test_color_printer.rb5
-rw-r--r--test/irb/test_completion.rb359
-rw-r--r--test/irb/test_context.rb331
-rw-r--r--test/irb/test_debug_cmd.rb303
-rw-r--r--test/irb/test_history.rb68
-rw-r--r--test/irb/test_init.rb81
-rw-r--r--test/irb/test_input_method.rb79
-rw-r--r--test/irb/test_option.rb4
-rw-r--r--test/irb/test_raise_no_backtrace_exception.rb10
-rw-r--r--test/irb/test_ruby_lex.rb130
-rw-r--r--test/irb/test_workspace.rb5
-rw-r--r--test/irb/yamatanooroti/test_rendering.rb23
-rw-r--r--test/json/json_addition_test.rb2
-rw-r--r--test/json/json_parser_test.rb5
-rw-r--r--test/lib/jit_support.rb36
-rw-r--r--test/logger/test_logdevice.rb3
-rw-r--r--test/mkmf/base.rb226
-rw-r--r--test/mkmf/test_config.rb16
-rw-r--r--test/mkmf/test_constant.rb60
-rw-r--r--test/mkmf/test_convertible.rb48
-rw-r--r--test/mkmf/test_egrep_cpp.rb14
-rw-r--r--test/mkmf/test_find_executable.rb82
-rw-r--r--test/mkmf/test_flags.rb92
-rw-r--r--test/mkmf/test_framework.rb70
-rw-r--r--test/mkmf/test_have_func.rb18
-rw-r--r--test/mkmf/test_have_library.rb84
-rw-r--r--test/mkmf/test_have_macro.rb46
-rw-r--r--test/mkmf/test_install.rb38
-rw-r--r--test/mkmf/test_libs.rb156
-rw-r--r--test/mkmf/test_mkmf.rb14
-rw-r--r--test/mkmf/test_pkg_config.rb66
-rw-r--r--test/mkmf/test_signedness.rb38
-rw-r--r--test/mkmf/test_sizeof.rb74
-rw-r--r--test/net/fixtures/Makefile6
-rw-r--r--test/net/fixtures/cacert.pem44
-rw-r--r--test/net/fixtures/server.crt99
-rw-r--r--test/net/fixtures/server.key55
-rw-r--r--test/net/http/test_http.rb116
-rw-r--r--test/net/http/test_httpheader.rb27
-rw-r--r--test/net/http/test_httpresponse.rb287
-rw-r--r--test/net/http/test_https.rb20
-rw-r--r--test/net/http/test_https_proxy.rb2
-rw-r--r--test/net/protocol/test_protocol.rb37
-rw-r--r--test/objspace/test_objspace.rb238
-rw-r--r--test/objspace/test_ractor.rb17
-rw-r--r--test/open-uri/test_open-uri.rb11
-rw-r--r--test/open-uri/test_ssl.rb19
-rw-r--r--test/openssl/fixtures/pkey/p256_too_large.pem5
-rw-r--r--test/openssl/fixtures/pkey/p384_invalid.pem6
-rw-r--r--test/openssl/test_asn1.rb22
-rw-r--r--test/openssl/test_bn.rb31
-rw-r--r--test/openssl/test_cipher.rb6
-rw-r--r--test/openssl/test_hmac.rb9
-rw-r--r--test/openssl/test_ns_spki.rb2
-rw-r--r--test/openssl/test_ocsp.rb2
-rw-r--r--test/openssl/test_pair.rb2
-rw-r--r--test/openssl/test_pkey.rb5
-rw-r--r--test/openssl/test_pkey_dsa.rb23
-rw-r--r--test/openssl/test_pkey_ec.rb36
-rw-r--r--test/openssl/test_pkey_rsa.rb23
-rw-r--r--test/openssl/test_ssl.rb190
-rw-r--r--test/openssl/test_ssl_session.rb2
-rw-r--r--test/openssl/test_x509cert.rb4
-rw-r--r--test/openssl/test_x509crl.rb20
-rw-r--r--test/openssl/test_x509req.rb30
-rw-r--r--test/optparse/test_acceptable.rb2
-rw-r--r--test/optparse/test_autoconf.rb4
-rw-r--r--test/optparse/test_bash_completion.rb4
-rw-r--r--test/optparse/test_cclass.rb2
-rw-r--r--test/optparse/test_did_you_mean.rb12
-rw-r--r--test/optparse/test_getopts.rb4
-rw-r--r--test/optparse/test_kwargs.rb4
-rw-r--r--test/optparse/test_load.rb141
-rw-r--r--test/optparse/test_noarg.rb6
-rw-r--r--test/optparse/test_optarg.rb2
-rw-r--r--test/optparse/test_optparse.rb15
-rw-r--r--test/optparse/test_placearg.rb8
-rw-r--r--test/optparse/test_reqarg.rb10
-rw-r--r--test/optparse/test_summary.rb25
-rw-r--r--test/optparse/test_zsh_completion.rb4
-rw-r--r--test/ostruct/test_ostruct.rb6
-rw-r--r--test/pathname/test_pathname.rb31
-rw-r--r--test/psych/helper.rb6
-rw-r--r--test/psych/test_array.rb16
-rw-r--r--test/psych/test_coder.rb6
-rw-r--r--test/psych/test_date_time.rb20
-rw-r--r--test/psych/test_encoding.rb7
-rw-r--r--test/psych/test_hash.rb64
-rw-r--r--test/psych/test_merge_keys.rb2
-rw-r--r--test/psych/test_numeric.rb11
-rw-r--r--test/psych/test_object.rb13
-rw-r--r--test/psych/test_parser.rb8
-rw-r--r--test/psych/test_safe_load.rb31
-rw-r--r--test/psych/test_scalar_scanner.rb25
-rw-r--r--test/psych/test_yaml.rb2
-rw-r--r--test/racc/case.rb5
-rw-r--r--test/rdoc/helper.rb6
-rw-r--r--test/rdoc/support/test_case.rb6
-rw-r--r--test/rdoc/test_rdoc_alias.rb3
-rw-r--r--test/rdoc/test_rdoc_any_method.rb16
-rw-r--r--test/rdoc/test_rdoc_class_module.rb3
-rw-r--r--test/rdoc/test_rdoc_code_object.rb2
-rw-r--r--test/rdoc/test_rdoc_constant.rb2
-rw-r--r--test/rdoc/test_rdoc_context.rb2
-rw-r--r--test/rdoc/test_rdoc_cross_reference.rb49
-rw-r--r--test/rdoc/test_rdoc_extend.rb3
-rw-r--r--test/rdoc/test_rdoc_generator_darkfish.rb92
-rw-r--r--test/rdoc/test_rdoc_generator_json_index.rb14
-rw-r--r--test/rdoc/test_rdoc_include.rb3
-rw-r--r--test/rdoc/test_rdoc_markdown.rb27
-rw-r--r--test/rdoc/test_rdoc_markdown_test.rb4
-rw-r--r--test/rdoc/test_rdoc_markup_attribute_manager.rb2
-rw-r--r--test/rdoc/test_rdoc_markup_to_html.rb101
-rw-r--r--test/rdoc/test_rdoc_markup_to_html_crossref.rb9
-rw-r--r--test/rdoc/test_rdoc_method_attr.rb3
-rw-r--r--test/rdoc/test_rdoc_normal_class.rb3
-rw-r--r--test/rdoc/test_rdoc_normal_module.rb3
-rw-r--r--test/rdoc/test_rdoc_options.rb65
-rw-r--r--test/rdoc/test_rdoc_parser_c.rb200
-rw-r--r--test/rdoc/test_rdoc_parser_ruby.rb23
-rw-r--r--test/rdoc/test_rdoc_rd_block_parser.rb21
-rw-r--r--test/rdoc/test_rdoc_rdoc.rb43
-rw-r--r--test/rdoc/test_rdoc_require.rb3
-rw-r--r--test/rdoc/test_rdoc_ri_driver.rb51
-rw-r--r--test/rdoc/test_rdoc_rubygems_hook.rb10
-rw-r--r--test/rdoc/test_rdoc_store.rb5
-rw-r--r--test/rdoc/test_rdoc_task.rb1
-rw-r--r--test/rdoc/test_rdoc_top_level.rb3
-rw-r--r--test/readline/test_readline.rb40
-rw-r--r--test/reline/helper.rb13
-rw-r--r--test/reline/test_config.rb23
-rw-r--r--test/reline/test_key_actor_emacs.rb60
-rw-r--r--test/reline/test_key_actor_vi.rb36
-rw-r--r--test/reline/test_reline.rb16
-rw-r--r--test/reline/test_terminfo.rb37
-rwxr-xr-xtest/reline/yamatanooroti/multiline_repl12
-rw-r--r--test/reline/yamatanooroti/termination_checker.rb6
-rw-r--r--test/reline/yamatanooroti/test_rendering.rb109
-rw-r--r--test/resolv/test_addr.rb4
-rw-r--r--test/resolv/test_dns.rb15
-rw-r--r--test/rinda/test_rinda.rb98
-rw-r--r--test/ripper/test_lexer.rb86
-rw-r--r--test/ripper/test_parser_events.rb55
-rw-r--r--test/ripper/test_ripper.rb22
-rw-r--r--test/ripper/test_scanner_events.rb13
-rw-r--r--test/ruby/enc/test_case_comprehensive.rb2
-rw-r--r--test/ruby/enc/test_cesu8.rb4
-rw-r--r--test/ruby/enc/test_emoji_breaks.rb208
-rw-r--r--test/ruby/enc/test_grapheme_breaks.rb117
-rw-r--r--test/ruby/enc/test_regex_casefold.rb2
-rw-r--r--test/ruby/test_alias.rb39
-rw-r--r--test/ruby/test_argf.rb16
-rw-r--r--test/ruby/test_arity.rb44
-rw-r--r--test/ruby/test_array.rb132
-rw-r--r--test/ruby/test_assignment.rb118
-rw-r--r--test/ruby/test_ast.rb525
-rw-r--r--test/ruby/test_autoload.rb104
-rw-r--r--test/ruby/test_backtrace.rb29
-rw-r--r--test/ruby/test_bignum.rb13
-rw-r--r--test/ruby/test_call.rb7
-rw-r--r--test/ruby/test_class.rb73
-rw-r--r--test/ruby/test_clone.rb53
-rw-r--r--test/ruby/test_complex.rb119
-rw-r--r--test/ruby/test_complex2.rb2
-rw-r--r--test/ruby/test_complexrational.rb4
-rw-r--r--test/ruby/test_data.rb249
-rw-r--r--test/ruby/test_default_gems.rb2
-rw-r--r--test/ruby/test_dir.rb73
-rw-r--r--test/ruby/test_dup.rb110
-rw-r--r--test/ruby/test_encoding.rb21
-rw-r--r--test/ruby/test_enum.rb13
-rw-r--r--test/ruby/test_enumerator.rb117
-rw-r--r--test/ruby/test_env.rb72
-rw-r--r--test/ruby/test_exception.rb165
-rw-r--r--test/ruby/test_fiber.rb15
-rw-r--r--test/ruby/test_file.rb54
-rw-r--r--test/ruby/test_file_exhaustive.rb54
-rw-r--r--test/ruby/test_float.rb35
-rw-r--r--test/ruby/test_frozen.rb30
-rw-r--r--test/ruby/test_gc.rb151
-rw-r--r--test/ruby/test_gc_compact.rb330
-rw-r--r--test/ruby/test_hash.rb129
-rw-r--r--test/ruby/test_inlinecache.rb2
-rw-r--r--test/ruby/test_integer.rb50
-rw-r--r--test/ruby/test_io.rb207
-rw-r--r--test/ruby/test_io_buffer.rb447
-rw-r--r--test/ruby/test_io_m17n.rb10
-rw-r--r--test/ruby/test_io_timeout.rb58
-rw-r--r--test/ruby/test_iseq.rb85
-rw-r--r--test/ruby/test_keyword.rb263
-rw-r--r--test/ruby/test_lazy_enumerator.rb20
-rw-r--r--test/ruby/test_m17n.rb56
-rw-r--r--test/ruby/test_marshal.rb30
-rw-r--r--test/ruby/test_method.rb235
-rw-r--r--test/ruby/test_mjit.rb (renamed from test/ruby/test_jit.rb)388
-rw-r--r--test/ruby/test_mjit_debug.rb (renamed from test/ruby/test_jit_debug.rb)8
-rw-r--r--test/ruby/test_module.rb197
-rw-r--r--test/ruby/test_numeric.rb3
-rw-r--r--test/ruby/test_object.rb31
-rw-r--r--test/ruby/test_objectspace.rb5
-rw-r--r--test/ruby/test_optimization.rb16
-rw-r--r--test/ruby/test_pack.rb60
-rw-r--r--test/ruby/test_parse.rb72
-rw-r--r--test/ruby/test_pattern_matching.rb50
-rw-r--r--test/ruby/test_proc.rb160
-rw-r--r--test/ruby/test_process.rb189
-rw-r--r--test/ruby/test_rand.rb14
-rw-r--r--test/ruby/test_range.rb108
-rw-r--r--test/ruby/test_rational.rb2
-rw-r--r--test/ruby/test_refinement.rb242
-rw-r--r--test/ruby/test_regexp.rb429
-rw-r--r--test/ruby/test_require.rb81
-rw-r--r--test/ruby/test_require_lib.rb2
-rw-r--r--test/ruby/test_rubyoptions.rb75
-rw-r--r--test/ruby/test_rubyvm.rb4
-rw-r--r--test/ruby/test_rubyvm_mjit.rb (renamed from test/ruby/test_rubyvm_jit.rb)40
-rw-r--r--test/ruby/test_settracefunc.rb353
-rw-r--r--test/ruby/test_shapes.rb441
-rw-r--r--test/ruby/test_signal.rb5
-rw-r--r--test/ruby/test_sprintf.rb29
-rw-r--r--test/ruby/test_string.rb827
-rw-r--r--test/ruby/test_struct.rb24
-rw-r--r--test/ruby/test_super.rb29
-rw-r--r--test/ruby/test_symbol.rb13
-rw-r--r--test/ruby/test_syntax.rb156
-rw-r--r--test/ruby/test_thread.rb107
-rw-r--r--test/ruby/test_thread_queue.rb59
-rw-r--r--test/ruby/test_time.rb146
-rw-r--r--test/ruby/test_time_tz.rb38
-rw-r--r--test/ruby/test_transcode.rb14
-rw-r--r--test/ruby/test_variable.rb25
-rw-r--r--test/ruby/test_vm_dump.rb4
-rw-r--r--test/ruby/test_weakmap.rb48
-rw-r--r--test/ruby/test_yjit.rb780
-rw-r--r--test/ruby/test_yjit_exit_locations.rb110
-rw-r--r--test/rubygems/alternate_cert.pem28
-rw-r--r--test/rubygems/alternate_cert_32.pem30
-rw-r--r--test/rubygems/alternate_key.pem50
-rw-r--r--test/rubygems/bad_rake.rb1
-rw-r--r--test/rubygems/bundler_test_gem.rb421
-rw-r--r--test/rubygems/child_cert.pem31
-rw-r--r--test/rubygems/child_cert_32.pem31
-rw-r--r--test/rubygems/child_key.pem50
-rw-r--r--test/rubygems/data/excon-0.7.7.gemspec.rzbin0 -> 388 bytes-rw-r--r--test/rubygems/data/null-type.gemspec.rzbin504 -> 0 bytes-rw-r--r--test/rubygems/data/pry-0.4.7.gemspec.rzbin0 -> 433 bytes-rw-r--r--test/rubygems/encrypted_private_key.pem52
-rw-r--r--test/rubygems/expired_cert.pem30
-rw-r--r--test/rubygems/fake_certlib/openssl.rb1
-rw-r--r--test/rubygems/future_cert.pem30
-rw-r--r--test/rubygems/future_cert_32.pem30
-rw-r--r--test/rubygems/good_rake.rb1
-rw-r--r--test/rubygems/grandchild_cert.pem31
-rw-r--r--test/rubygems/grandchild_cert_32.pem31
-rw-r--r--test/rubygems/grandchild_key.pem50
-rw-r--r--test/rubygems/helper.rb380
-rw-r--r--test/rubygems/installer_test_case.rb27
-rw-r--r--test/rubygems/invalid_issuer_cert.pem32
-rw-r--r--test/rubygems/invalid_issuer_cert_32.pem32
-rw-r--r--test/rubygems/invalid_key.pem50
-rw-r--r--test/rubygems/invalid_signer_cert.pem30
-rw-r--r--test/rubygems/invalid_signer_cert_32.pem30
-rw-r--r--test/rubygems/invalidchild_cert.pem31
-rw-r--r--test/rubygems/invalidchild_cert_32.pem31
-rw-r--r--test/rubygems/invalidchild_key.pem50
-rw-r--r--test/rubygems/multifactor_auth_utilities.rb111
-rw-r--r--test/rubygems/package/tar_test_case.rb70
-rw-r--r--test/rubygems/packages/Bluebie-legs-0.6.2.gembin0 -> 14336 bytes-rw-r--r--test/rubygems/plugin/exception/rubygems_plugin.rb3
-rw-r--r--test/rubygems/plugin/load/rubygems_plugin.rb1
-rw-r--r--test/rubygems/plugin/standarderror/rubygems_plugin.rb3
-rw-r--r--test/rubygems/private_key.pem50
-rw-r--r--test/rubygems/public_cert.pem32
-rw-r--r--test/rubygems/public_cert_32.pem30
-rw-r--r--test/rubygems/public_key.pem14
-rw-r--r--test/rubygems/rubygems/commands/crash_command.rb1
-rw-r--r--test/rubygems/rubygems_plugin.rb5
-rw-r--r--test/rubygems/simple_gem.rb3
-rw-r--r--test/rubygems/specifications/bar-0.0.2.gemspec2
-rw-r--r--test/rubygems/specifications/rubyforge-0.0.1.gemspec10
-rw-r--r--test/rubygems/test_bundled_ca.rb25
-rw-r--r--test/rubygems/test_config.rb9
-rw-r--r--test/rubygems/test_deprecate.rb9
-rw-r--r--test/rubygems/test_exit.rb12
-rw-r--r--test/rubygems/test_gem.rb1071
-rw-r--r--test/rubygems/test_gem_available_set.rb43
-rw-r--r--test/rubygems/test_gem_bundler_version_finder.rb75
-rw-r--r--test/rubygems/test_gem_command.rb89
-rw-r--r--test/rubygems/test_gem_command_manager.rb136
-rw-r--r--test/rubygems/test_gem_commands_build_command.rb137
-rw-r--r--test/rubygems/test_gem_commands_cert_command.rb197
-rw-r--r--test/rubygems/test_gem_commands_check_command.rb9
-rw-r--r--test/rubygems/test_gem_commands_cleanup_command.rb81
-rw-r--r--test/rubygems/test_gem_commands_contents_command.rb57
-rw-r--r--test/rubygems/test_gem_commands_dependency_command.rb73
-rw-r--r--test/rubygems/test_gem_commands_environment_command.rb53
-rw-r--r--test/rubygems/test_gem_commands_exec_command.rb853
-rw-r--r--test/rubygems/test_gem_commands_fetch_command.rb154
-rw-r--r--test/rubygems/test_gem_commands_generate_index_command.rb15
-rw-r--r--test/rubygems/test_gem_commands_help_command.rb27
-rw-r--r--test/rubygems/test_gem_commands_info_command.rb31
-rw-r--r--test/rubygems/test_gem_commands_install_command.rb333
-rw-r--r--test/rubygems/test_gem_commands_list_command.rb9
-rw-r--r--test/rubygems/test_gem_commands_lock_command.rb21
-rw-r--r--test/rubygems/test_gem_commands_mirror.rb5
-rw-r--r--test/rubygems/test_gem_commands_open_command.rb9
-rw-r--r--test/rubygems/test_gem_commands_outdated_command.rb19
-rw-r--r--test/rubygems/test_gem_commands_owner_command.rb277
-rw-r--r--test/rubygems/test_gem_commands_pristine_command.rb236
-rw-r--r--test/rubygems/test_gem_commands_push_command.rb256
-rw-r--r--test/rubygems/test_gem_commands_query_command.rb147
-rw-r--r--test/rubygems/test_gem_commands_search_command.rb5
-rw-r--r--test/rubygems/test_gem_commands_server_command.rb5
-rw-r--r--test/rubygems/test_gem_commands_setup_command.rb221
-rw-r--r--test/rubygems/test_gem_commands_signin_command.rb179
-rw-r--r--test/rubygems/test_gem_commands_signout_command.rb6
-rw-r--r--test/rubygems/test_gem_commands_sources_command.rb100
-rw-r--r--test/rubygems/test_gem_commands_specification_command.rb65
-rw-r--r--test/rubygems/test_gem_commands_stale_command.rb9
-rw-r--r--test/rubygems/test_gem_commands_uninstall_command.rb180
-rw-r--r--test/rubygems/test_gem_commands_unpack_command.rb63
-rw-r--r--test/rubygems/test_gem_commands_update_command.rb290
-rw-r--r--test/rubygems/test_gem_commands_which_command.rb13
-rw-r--r--test/rubygems/test_gem_commands_yank_command.rb205
-rw-r--r--test/rubygems/test_gem_config_file.rb175
-rw-r--r--test/rubygems/test_gem_dependency.rb159
-rw-r--r--test/rubygems/test_gem_dependency_installer.rb365
-rw-r--r--test/rubygems/test_gem_dependency_list.rb95
-rw-r--r--test/rubygems/test_gem_dependency_resolution_error.rb9
-rw-r--r--test/rubygems/test_gem_doctor.rb53
-rw-r--r--test/rubygems/test_gem_ext_builder.rb123
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder.rb167
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/custom_name/.gitignore1
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/custom_name/custom_name.gemspec10
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock233
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.toml10
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/src/lib.rs27
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/custom_name/lib/custom_name.rb3
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/.gitignore1
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock247
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml10
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/rust_ruby_example.gemspec10
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/src/lib.rs51
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder_link_flag_converter.rb34
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder_unit.rb60
-rw-r--r--test/rubygems/test_gem_ext_cmake_builder.rb35
-rw-r--r--test/rubygems/test_gem_ext_configure_builder.rb27
-rw-r--r--test/rubygems/test_gem_ext_ext_conf_builder.rb103
-rw-r--r--test/rubygems/test_gem_ext_rake_builder.rb31
-rw-r--r--test/rubygems/test_gem_gem_runner.rb24
-rw-r--r--test/rubygems/test_gem_gemcutter_utilities.rb252
-rw-r--r--test/rubygems/test_gem_impossible_dependencies_error.rb9
-rw-r--r--test/rubygems/test_gem_indexer.rb158
-rw-r--r--test/rubygems/test_gem_install_update_options.rb33
-rw-r--r--test/rubygems/test_gem_installer.rb907
-rw-r--r--test/rubygems/test_gem_local_remote_options.rb21
-rw-r--r--test/rubygems/test_gem_name_tuple.rb9
-rw-r--r--test/rubygems/test_gem_package.rb482
-rw-r--r--test/rubygems/test_gem_package_old.rb27
-rw-r--r--test/rubygems/test_gem_package_tar_header.rb95
-rw-r--r--test/rubygems/test_gem_package_tar_reader.rb64
-rw-r--r--test/rubygems/test_gem_package_tar_reader_entry.rb178
-rw-r--r--test/rubygems/test_gem_package_tar_writer.rb153
-rw-r--r--test/rubygems/test_gem_package_task.rb37
-rw-r--r--test/rubygems/test_gem_path_support.rb29
-rw-r--r--test/rubygems/test_gem_platform.rb550
-rw-r--r--test/rubygems/test_gem_rdoc.rb29
-rw-r--r--test/rubygems/test_gem_remote_fetcher.rb315
-rw-r--r--test/rubygems/test_gem_request.rb122
-rw-r--r--test/rubygems/test_gem_request_connection_pools.rb59
-rw-r--r--test/rubygems/test_gem_request_set.rb201
-rw-r--r--test/rubygems/test_gem_request_set_gem_dependency_api.rb421
-rw-r--r--test/rubygems/test_gem_request_set_lockfile.rb173
-rw-r--r--test/rubygems/test_gem_request_set_lockfile_parser.rb117
-rw-r--r--test/rubygems/test_gem_request_set_lockfile_tokenizer.rb125
-rw-r--r--test/rubygems/test_gem_requirement.rb89
-rw-r--r--test/rubygems/test_gem_resolver.rb266
-rw-r--r--test/rubygems/test_gem_resolver_activation_request.rb13
-rw-r--r--test/rubygems/test_gem_resolver_api_set.rb67
-rw-r--r--test/rubygems/test_gem_resolver_api_specification.rb95
-rw-r--r--test/rubygems/test_gem_resolver_best_set.rb45
-rw-r--r--test/rubygems/test_gem_resolver_composed_set.rb3
-rw-r--r--test/rubygems/test_gem_resolver_conflict.rb25
-rw-r--r--test/rubygems/test_gem_resolver_dependency_request.rb31
-rw-r--r--test/rubygems/test_gem_resolver_git_set.rb43
-rw-r--r--test/rubygems/test_gem_resolver_git_specification.rb43
-rw-r--r--test/rubygems/test_gem_resolver_index_set.rb25
-rw-r--r--test/rubygems/test_gem_resolver_index_specification.rb33
-rw-r--r--test/rubygems/test_gem_resolver_installed_specification.rb11
-rw-r--r--test/rubygems/test_gem_resolver_installer_set.rb115
-rw-r--r--test/rubygems/test_gem_resolver_local_specification.rb15
-rw-r--r--test/rubygems/test_gem_resolver_lock_set.rb25
-rw-r--r--test/rubygems/test_gem_resolver_lock_specification.rb35
-rw-r--r--test/rubygems/test_gem_resolver_requirement_list.rb3
-rw-r--r--test/rubygems/test_gem_resolver_specification.rb17
-rw-r--r--test/rubygems/test_gem_resolver_vendor_set.rb13
-rw-r--r--test/rubygems/test_gem_resolver_vendor_specification.rb21
-rw-r--r--test/rubygems/test_gem_security.rb137
-rw-r--r--test/rubygems/test_gem_security_policy.rb144
-rw-r--r--test/rubygems/test_gem_security_signer.rb69
-rw-r--r--test/rubygems/test_gem_security_trust_dir.rb13
-rw-r--r--test/rubygems/test_gem_silent_ui.rb71
-rw-r--r--test/rubygems/test_gem_source.rb89
-rw-r--r--test/rubygems/test_gem_source_fetch_problem.rb19
-rw-r--r--test/rubygems/test_gem_source_git.rb132
-rw-r--r--test/rubygems/test_gem_source_installed.rb33
-rw-r--r--test/rubygems/test_gem_source_list.rb11
-rw-r--r--test/rubygems/test_gem_source_local.rb29
-rw-r--r--test/rubygems/test_gem_source_lock.rb63
-rw-r--r--test/rubygems/test_gem_source_specific_file.rb35
-rw-r--r--test/rubygems/test_gem_source_subpath_problem.rb15
-rw-r--r--test/rubygems/test_gem_source_vendor.rb27
-rw-r--r--test/rubygems/test_gem_spec_fetcher.rb145
-rw-r--r--test/rubygems/test_gem_specification.rb1021
-rw-r--r--test/rubygems/test_gem_stream_ui.rb75
-rw-r--r--test/rubygems/test_gem_stub_specification.rb81
-rw-r--r--test/rubygems/test_gem_text.rb3
-rw-r--r--test/rubygems/test_gem_uninstaller.rb235
-rw-r--r--test/rubygems/test_gem_unsatisfiable_dependency_error.rb7
-rw-r--r--test/rubygems/test_gem_update_suggestion.rb209
-rw-r--r--test/rubygems/test_gem_uri.rb10
-rw-r--r--test/rubygems/test_gem_uri_formatter.rb29
-rw-r--r--test/rubygems/test_gem_util.rb47
-rw-r--r--test/rubygems/test_gem_validator.rb16
-rw-r--r--test/rubygems/test_gem_version.rb44
-rw-r--r--test/rubygems/test_gem_version_option.rb31
-rw-r--r--test/rubygems/test_kernel.rb105
-rw-r--r--test/rubygems/test_project_sanity.rb35
-rw-r--r--test/rubygems/test_remote_fetch_error.rb15
-rw-r--r--test/rubygems/test_require.rb274
-rw-r--r--test/rubygems/test_rubygems.rb37
-rw-r--r--test/rubygems/test_webauthn_listener.rb143
-rw-r--r--test/rubygems/test_webauthn_listener_response.rb93
-rw-r--r--test/rubygems/test_webauthn_poller.rb124
-rw-r--r--test/rubygems/utilities.rb140
-rw-r--r--test/rubygems/wrong_key_cert.pem30
-rw-r--r--test/rubygems/wrong_key_cert_32.pem30
-rw-r--r--test/runner.rb12
-rw-r--r--test/socket/test_addrinfo.rb6
-rw-r--r--test/socket/test_basicsocket.rb2
-rw-r--r--test/socket/test_nonblock.rb12
-rw-r--r--test/socket/test_socket.rb8
-rw-r--r--test/socket/test_sockopt.rb2
-rw-r--r--test/socket/test_tcp.rb2
-rw-r--r--test/socket/test_udp.rb2
-rw-r--r--test/socket/test_unix.rb147
-rw-r--r--test/stringio/test_stringio.rb75
-rw-r--r--test/strscan/test_ractor.rb2
-rw-r--r--test/strscan/test_stringscanner.rb63
-rw-r--r--test/test_extlibs.rb2
-rw-r--r--test/test_find.rb16
-rw-r--r--test/test_ipaddr.rb27
-rw-r--r--test/test_open3.rb2
-rw-r--r--test/test_pp.rb9
-rw-r--r--test/test_pstore.rb32
-rw-r--r--test/test_pty.rb30
-rw-r--r--test/test_rbconfig.rb9
-rw-r--r--test/test_set.rb39
-rw-r--r--test/test_time.rb9
-rw-r--r--test/test_timeout.rb46
-rw-r--r--test/test_tmpdir.rb20
-rw-r--r--test/test_trick.rb23
-rw-r--r--test/uri/test_common.rb103
-rw-r--r--test/uri/test_generic.rb27
-rw-r--r--test/uri/test_ldap.rb6
-rw-r--r--test/uri/test_parser.rb38
-rw-r--r--test/uri/test_wss.rb71
-rw-r--r--test/win32ole/test_err_in_callback.rb2
-rw-r--r--test/win32ole/test_win32ole_event.rb2
-rw-r--r--test/win32ole/test_win32ole_method_event.rb2
-rw-r--r--test/win32ole/test_win32ole_param_event.rb2
-rw-r--r--test/win32ole/test_win32ole_record.rb2
-rw-r--r--test/win32ole/test_win32ole_type_event.rb2
-rw-r--r--test/win32ole/test_win32ole_variable.rb4
-rw-r--r--test/win32ole/test_win32ole_variant.rb2
-rw-r--r--test/win32ole/test_win32ole_variant_outarg.rb2
-rw-r--r--test/win32ole/test_word.rb2
-rw-r--r--test/yaml/test_store.rb2
-rw-r--r--test/zlib/test_zlib.rb20
-rw-r--r--thread.c1604
-rw-r--r--thread_none.c284
-rw-r--r--thread_none.h20
-rw-r--r--thread_pthread.c966
-rw-r--r--thread_pthread.h92
-rw-r--r--thread_sync.c415
-rw-r--r--thread_sync.rb68
-rw-r--r--thread_win32.c401
-rw-r--r--thread_win32.h20
-rw-r--r--time.c2204
-rw-r--r--timev.h11
-rw-r--r--timev.rb300
-rw-r--r--tool/annocheck/Dockerfile4
-rw-r--r--tool/annocheck/Dockerfile-copy7
-rw-r--r--tool/bundler/dev_gems.rb19
-rw-r--r--tool/bundler/dev_gems.rb.lock57
-rw-r--r--tool/bundler/rubocop_gems.rb1
-rw-r--r--tool/bundler/rubocop_gems.rb.lock66
-rw-r--r--tool/bundler/standard_gems.rb1
-rw-r--r--tool/bundler/standard_gems.rb.lock76
-rw-r--r--tool/bundler/test_gems.rb2
-rw-r--r--tool/bundler/test_gems.rb.lock13
-rwxr-xr-xtool/checksum.rb4
-rw-r--r--tool/downloader.rb84
-rwxr-xr-x[-rw-r--r--]tool/enc-case-folding.rb (renamed from enc/unicode/case-folding.rb)10
-rw-r--r--tool/enc-emoji-citrus-gen.rb4
-rwxr-xr-xtool/enc-unicode.rb31
-rwxr-xr-xtool/expand-config.rb14
-rwxr-xr-xtool/extlibs.rb176
-rw-r--r--tool/fake.rb11
-rwxr-xr-xtool/fetch-bundled_gems.rb6
-rwxr-xr-xtool/file2lastrev.rb91
-rwxr-xr-xtool/format-release21
-rw-r--r--tool/gem-unpack.rb19
-rwxr-xr-xtool/gen-mailmap.rb4
-rw-r--r--tool/generic_erb.rb44
-rw-r--r--tool/gperf.sed1
-rwxr-xr-xtool/id2token.rb11
-rw-r--r--tool/lib/bundled_gem.rb68
-rw-r--r--tool/lib/colorize.rb4
-rw-r--r--tool/lib/core_assertions.rb96
-rw-r--r--tool/lib/envutil.rb25
-rw-r--r--tool/lib/leakchecker.rb9
-rw-r--r--tool/lib/output.rb57
-rw-r--r--tool/lib/test/unit.rb92
-rw-r--r--tool/lib/test/unit/assertions.rb28
-rw-r--r--tool/lib/vcs.rb156
-rw-r--r--tool/lib/vpath.rb7
-rw-r--r--tool/lib/webrick/httpserver.rb1
-rw-r--r--tool/lib/webrick/httputils.rb2
-rwxr-xr-xtool/ln_sr.rb131
-rw-r--r--tool/m4/ruby_default_arch.m41
-rw-r--r--tool/m4/ruby_prog_makedirs.m49
-rw-r--r--tool/m4/ruby_replace_funcs.m44
-rw-r--r--tool/m4/ruby_replace_type.m412
-rw-r--r--tool/m4/ruby_require_funcs.m413
-rw-r--r--tool/m4/ruby_thread.m455
-rw-r--r--tool/m4/ruby_try_cflags.m47
-rw-r--r--tool/m4/ruby_universal_arch.m46
-rw-r--r--tool/m4/ruby_wasm_tools.m424
-rwxr-xr-xtool/make-snapshot44
-rw-r--r--tool/make_hgraph.rb7
-rwxr-xr-xtool/merger.rb189
-rwxr-xr-xtool/mjit/bindgen.rb435
-rw-r--r--tool/mk_builtin_loader.rb67
-rwxr-xr-xtool/mkconfig.rb15
-rwxr-xr-xtool/mkrunnable.rb4
-rwxr-xr-xtool/outdate-bundled-gems.rb135
-rwxr-xr-xtool/pure_parser.rb24
-rwxr-xr-xtool/rbinstall.rb281
-rw-r--r--tool/rbs_skip_tests11
-rwxr-xr-xtool/redmine-backporter.rb158
-rwxr-xr-xtool/releng/gen-mail.rb13
-rw-r--r--tool/ruby_vm/controllers/application_controller.rb5
-rw-r--r--tool/ruby_vm/helpers/dumper.rb7
-rw-r--r--tool/ruby_vm/models/typemap.rb1
-rw-r--r--tool/ruby_vm/scripts/insns2vm.rb12
-rw-r--r--tool/ruby_vm/views/_insn_type_chars.erb19
-rw-r--r--tool/ruby_vm/views/_mjit_compile_getinlinecache.erb31
-rw-r--r--tool/ruby_vm/views/_mjit_compile_insn.erb92
-rw-r--r--tool/ruby_vm/views/_mjit_compile_insn_body.erb129
-rw-r--r--tool/ruby_vm/views/_mjit_compile_invokebuiltin.erb29
-rw-r--r--tool/ruby_vm/views/_mjit_compile_ivar.erb101
-rw-r--r--tool/ruby_vm/views/_mjit_compile_pc_and_sp.erb38
-rw-r--r--tool/ruby_vm/views/_mjit_compile_send.erb119
-rw-r--r--tool/ruby_vm/views/lib/ruby_vm/mjit/instruction.rb.erb40
-rw-r--r--tool/ruby_vm/views/mjit_compile.inc.erb110
-rw-r--r--tool/ruby_vm/views/mjit_sp_inc.inc.erb17
-rw-r--r--tool/ruby_vm/views/optinsn.inc.erb4
-rwxr-xr-xtool/runruby.rb15
-rwxr-xr-xtool/sync_default_gems.rb1247
-rwxr-xr-xtool/test-annocheck.sh33
-rw-r--r--tool/test-bundled-gems.rb86
-rwxr-xr-xtool/test/test_sync_default_gems.rb76
-rw-r--r--tool/test/testunit/test4test_hideskip.rb8
-rw-r--r--tool/test/testunit/test4test_sorting.rb2
-rw-r--r--tool/test/testunit/test_assertion.rb24
-rw-r--r--tool/test/testunit/test_hideskip.rb4
-rw-r--r--tool/test/testunit/test_minitest_unit.rb24
-rw-r--r--tool/test/webrick/test_filehandler.rb4
-rw-r--r--tool/test/webrick/test_httprequest.rb2
-rw-r--r--tool/transcode-tblgen.rb2
-rw-r--r--tool/transform_mjit_header.rb15
-rw-r--r--tool/update-NEWS-refs.rb37
-rwxr-xr-xtool/update-bundled_gems.rb5
-rwxr-xr-xtool/update-deps7
-rwxr-xr-xtool/wasm-clangw9
-rw-r--r--trace_point.rb62
-rw-r--r--transcode.c661
-rw-r--r--transcode_data.h32
-rw-r--r--transient_heap.c8
-rw-r--r--util.c172
-rw-r--r--variable.c2601
-rw-r--r--variable.h10
-rw-r--r--version.c62
-rw-r--r--version.h63
-rw-r--r--vm.c1754
-rw-r--r--vm_args.c639
-rw-r--r--vm_backtrace.c529
-rw-r--r--vm_callinfo.h103
-rw-r--r--vm_core.h559
-rw-r--r--vm_debug.h28
-rw-r--r--vm_dump.c1049
-rw-r--r--vm_eval.c679
-rw-r--r--vm_exec.c28
-rw-r--r--vm_exec.h6
-rw-r--r--vm_insnhelper.c2988
-rw-r--r--vm_insnhelper.h21
-rw-r--r--vm_method.c1162
-rw-r--r--vm_sync.c10
-rw-r--r--vm_trace.c540
-rw-r--r--vsnprintf.c13
-rw-r--r--wasm/GNUmakefile.in32
-rw-r--r--wasm/README.md70
-rw-r--r--wasm/asyncify.h23
-rw-r--r--wasm/fiber.c83
-rw-r--r--wasm/fiber.h43
-rw-r--r--wasm/machine.c62
-rw-r--r--wasm/machine.h25
-rw-r--r--wasm/machine_core.S25
-rw-r--r--wasm/missing.c199
-rw-r--r--wasm/runtime.c47
-rw-r--r--wasm/setjmp.c204
-rw-r--r--wasm/setjmp.h95
-rw-r--r--wasm/setjmp_core.S27
-rw-r--r--wasm/tests/fiber_test.c66
-rw-r--r--wasm/tests/machine_test.c115
-rw-r--r--wasm/tests/setjmp_test.c108
-rwxr-xr-xwasm/wasm-opt36
-rw-r--r--win32/Makefile.sub224
-rwxr-xr-xwin32/configure.bat29
-rw-r--r--win32/dir.h2
-rw-r--r--win32/file.c593
-rw-r--r--win32/file.h38
-rwxr-xr-xwin32/ifchange.bat1
-rwxr-xr-xwin32/mkexports.rb4
-rwxr-xr-xwin32/resource.rb2
-rw-r--r--win32/setup.mak83
-rw-r--r--win32/win32.c5986
-rw-r--r--win32/winmain.c4
-rw-r--r--yjit.c1254
-rw-r--r--yjit.h81
-rw-r--r--yjit.rb391
-rw-r--r--yjit/.gitignore2
-rw-r--r--yjit/Cargo.lock49
-rw-r--r--yjit/Cargo.toml47
-rw-r--r--yjit/bindgen/Cargo.lock311
-rw-r--r--yjit/bindgen/Cargo.toml10
-rw-r--r--yjit/bindgen/src/main.rs430
-rw-r--r--yjit/not_gmake.mk14
-rw-r--r--yjit/src/asm/arm64/README.md16
-rw-r--r--yjit/src/asm/arm64/arg/bitmask_imm.rs255
-rw-r--r--yjit/src/asm/arm64/arg/condition.rs52
-rw-r--r--yjit/src/asm/arm64/arg/inst_offset.rs47
-rw-r--r--yjit/src/asm/arm64/arg/mod.rs18
-rw-r--r--yjit/src/asm/arm64/arg/sf.rs19
-rw-r--r--yjit/src/asm/arm64/arg/shifted_imm.rs81
-rw-r--r--yjit/src/asm/arm64/arg/sys_reg.rs6
-rw-r--r--yjit/src/asm/arm64/arg/truncate.rs66
-rw-r--r--yjit/src/asm/arm64/inst/atomic.rs86
-rw-r--r--yjit/src/asm/arm64/inst/branch.rs100
-rw-r--r--yjit/src/asm/arm64/inst/branch_cond.rs78
-rw-r--r--yjit/src/asm/arm64/inst/breakpoint.rs55
-rw-r--r--yjit/src/asm/arm64/inst/call.rs104
-rw-r--r--yjit/src/asm/arm64/inst/conditional.rs73
-rw-r--r--yjit/src/asm/arm64/inst/data_imm.rs143
-rw-r--r--yjit/src/asm/arm64/inst/data_reg.rs192
-rw-r--r--yjit/src/asm/arm64/inst/halfword_imm.rs179
-rw-r--r--yjit/src/asm/arm64/inst/load_literal.rs89
-rw-r--r--yjit/src/asm/arm64/inst/load_register.rs108
-rw-r--r--yjit/src/asm/arm64/inst/load_store.rs249
-rw-r--r--yjit/src/asm/arm64/inst/load_store_exclusive.rs109
-rw-r--r--yjit/src/asm/arm64/inst/logical_imm.rs154
-rw-r--r--yjit/src/asm/arm64/inst/logical_reg.rs207
-rw-r--r--yjit/src/asm/arm64/inst/mod.rs50
-rw-r--r--yjit/src/asm/arm64/inst/mov.rs155
-rw-r--r--yjit/src/asm/arm64/inst/nop.rs44
-rw-r--r--yjit/src/asm/arm64/inst/pc_rel.rs107
-rw-r--r--yjit/src/asm/arm64/inst/reg_pair.rs212
-rw-r--r--yjit/src/asm/arm64/inst/sbfm.rs103
-rw-r--r--yjit/src/asm/arm64/inst/shift_imm.rs147
-rw-r--r--yjit/src/asm/arm64/inst/sys_reg.rs86
-rw-r--r--yjit/src/asm/arm64/inst/test_bit.rs133
-rw-r--r--yjit/src/asm/arm64/mod.rs1580
-rw-r--r--yjit/src/asm/arm64/opnd.rs195
-rw-r--r--yjit/src/asm/mod.rs792
-rw-r--r--yjit/src/asm/x86_64/mod.rs1415
-rw-r--r--yjit/src/asm/x86_64/tests.rs449
-rw-r--r--yjit/src/backend/arm64/mod.rs1491
-rw-r--r--yjit/src/backend/ir.rs1576
-rw-r--r--yjit/src/backend/mod.rs8
-rw-r--r--yjit/src/backend/tests.rs331
-rw-r--r--yjit/src/backend/x86_64/mod.rs895
-rw-r--r--yjit/src/codegen.rs7721
-rw-r--r--yjit/src/core.rs2400
-rw-r--r--yjit/src/cruby.rs715
-rw-r--r--yjit/src/cruby_bindings.inc.rs1310
-rw-r--r--yjit/src/disasm.rs269
-rw-r--r--yjit/src/invariants.rs567
-rw-r--r--yjit/src/lib.rs18
-rw-r--r--yjit/src/options.rs174
-rw-r--r--yjit/src/stats.rs640
-rw-r--r--yjit/src/utils.rs274
-rw-r--r--yjit/src/virtualmem.rs443
-rw-r--r--yjit/src/yjit.rs136
-rw-r--r--yjit/yjit.mk69
-rw-r--r--yjit_asm.c1835
-rw-r--r--yjit_asm.h408
-rw-r--r--yjit_codegen.c5059
-rw-r--r--yjit_codegen.h23
-rw-r--r--yjit_core.c1369
-rw-r--r--yjit_core.h307
-rw-r--r--yjit_iface.c1310
-rw-r--r--yjit_iface.h38
-rw-r--r--yjit_utils.c109
3248 files changed, 256834 insertions, 135438 deletions
diff --git a/.appveyor.yml b/.appveyor.yml
index 037c8d6df6..05ff204541 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -11,26 +11,29 @@ clone_depth: 10
platform:
- x64
skip_commits:
- message: /^\[DOC\]/
+ message: /\[DOC\]/
files:
- doc/*
- '**/*.md'
- '**/*.rdoc'
+ - '**/.document'
+ - '**/*.[1-8]'
+ - '**/*.ronn'
environment:
ruby_version: "24-%Platform%"
- zlib_version: "1.2.11"
matrix:
+ # Test only the oldest supported version because AppVeyor is unstable, its concurrency
+ # is limited, and compatibility issues that happen only in newer versions are rare.
+ # You may test some other stuff on GitHub Actions instead.
- build: vs
- vs: 120
- ssl: OpenSSL
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
- GEMS_FOR_TEST: ""
- - build: vs
- vs: 140
+ vs: 120 # Visual Studio 2013
ssl: OpenSSL-v111
+ # The worker image name. This is NOT the Visual Studio version we're using here.
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
GEMS_FOR_TEST: ""
- RELINE_TEST_ENCODING: "Windows-31J"
+ RELINE_TEST_ENCODING: "UTF-8"
+cache:
+ - c:\Tools\vcpkg\installed\
for:
-
matrix:
@@ -42,6 +45,12 @@ for:
- SET BITS=%Platform:x86=32%
- SET BITS=%BITS:x=%
- SET OPENSSL_DIR=C:\%ssl%-Win%BITS%
+ - cd C:\Tools\vcpkg
+ - git pull -q
+ - .\bootstrap-vcpkg.bat
+ - ps: Start-FileDownload 'https://github.com/microsoft/vcpkg-tool/releases/download/2023-08-09/vcpkg.exe' -FileName 'C:\Tools\vcpkg\vcpkg.exe'
+ - cd %APPVEYOR_BUILD_FOLDER%
+ - vcpkg --triplet %Platform%-windows install --x-use-aria2 libffi libyaml readline zlib
- CALL SET vcvars=%%^VS%VS%COMNTOOLS^%%..\..\VC\vcvarsall.bat
- SET vcvars
- '"%vcvars%" %Platform:x64=amd64%'
@@ -61,16 +70,20 @@ for:
- mkdir \usr\local\bin
- mkdir \usr\local\include
- mkdir \usr\local\lib
- - SET ZLIB_ZIP=.downloaded-cache\zlib%zlib_version:.=%.zip
- - if not exist %ZLIB_ZIP% curl -fsSL -o %ZLIB_ZIP% --retry 10 https://zlib.net/zlib%zlib_version:.=%.zip
- - 7z x -aos -o%APPVEYOR_BUILD_FOLDER%\ext\zlib %ZLIB_ZIP%
- for %%I in (%OPENSSL_DIR%\*.dll) do mklink /h \usr\local\bin\%%~nxI %%I
+ - for %%I in (c:\Tools\vcpkg\installed\%Platform%-windows\bin\*.dll) do (
+ if not %%~nI == readline mklink \usr\local\bin\%%~nxI %%I
+ )
- attrib +r /s /d
- mkdir %Platform%-mswin_%vs%
build_script:
+ - set HAVE_GIT=no
- cd %APPVEYOR_BUILD_FOLDER%
- cd %Platform%-mswin_%vs%
- - ..\win32\configure.bat --without-ext=+,dbm,gdbm,readline --with-opt-dir=/usr/local --with-openssl-dir=%OPENSSL_DIR:\=/%
+ - >-
+ ..\win32\configure.bat
+ --with-opt-dir="/usr/local;c:/Tools/vcpkg/installed/%Platform%-windows"
+ --with-openssl-dir=%OPENSSL_DIR:\=/%
- nmake -l
- nmake install-nodoc
- \usr\bin\ruby -v -e "p :locale => Encoding.find('locale'), :filesystem => Encoding.find('filesystem')"
@@ -80,9 +93,26 @@ for:
- set /a JOBS=%NUMBER_OF_PROCESSORS%
- nmake -l "TESTOPTS=-v -q" btest
- nmake -l "TESTOPTS=-v -q" test-basic
- - nmake -l "TESTOPTS=-v --timeout-scale=3.0 --excludes=../test/excludes/_appveyor -j%JOBS% --exclude readline --exclude win32ole --exclude test_bignum --exclude test_syntax --exclude test_open-uri --exclude test_bundled_ca" test-all
+ - >-
+ nmake -l "TESTOPTS=--timeout-scale=3.0
+ --excludes=../test/excludes/_appveyor -j%JOBS%
+ --exclude win32ole
+ --exclude test_bignum
+ --exclude test_syntax
+ --exclude test_open-uri
+ --exclude test_bundled_ca
+ " test-all
# separately execute tests without -j which may crash worker with -j.
- - nmake -l "TESTOPTS=-v --timeout-scale=3.0 --excludes=../test/excludes/_appveyor" test-all TESTS="../test/win32ole ../test/ruby/test_bignum.rb ../test/ruby/test_syntax.rb ../test/open-uri/test_open-uri.rb ../test/rubygems/test_bundled_ca.rb"
+ - >-
+ nmake -l
+ "TESTOPTS=--timeout-scale=3.0 --excludes=../test/excludes/_appveyor"
+ TESTS="
+ ../test/win32ole
+ ../test/ruby/test_bignum.rb
+ ../test/ruby/test_syntax.rb
+ ../test/open-uri/test_open-uri.rb
+ ../test/rubygems/test_bundled_ca.rb
+ " test-all
- nmake -l test-spec MSPECOPT=-fs # not using `-j` because sometimes `mspec -j` silently dies on Windows
notifications:
- provider: Webhook
@@ -93,7 +123,7 @@ notifications:
{{^isPullRequest}}
{
"ci": "AppVeyor CI",
- "env": "Visual Studio 2013 / 2015",
+ "env": "Visual Studio 2013",
"url": "{{buildUrl}}",
"commit": "{{commitId}}",
"branch": "{{branch}}"
diff --git a/.cirrus.yml b/.cirrus.yml
deleted file mode 100644
index c8fb326c89..0000000000
--- a/.cirrus.yml
+++ /dev/null
@@ -1,64 +0,0 @@
-# This CI is used to test Arm cases. We can set the maximum 16 tasks.
-# The entire testing design is inspired from .github/workflows/compilers.yml.
-
-# By default, Cirrus mounts an empty volume to `/tmp`
-# which triggers all sorts of warnings like "system temporary path is world-writable: /tmp".
-# Lets workaround it by specifying a custom volume mount point.
-env:
- CIRRUS_VOLUME: /cirrus-ci-volume
- LANG: C.UTF-8
-
-task:
- name: Arm64 Graviton2 / $CC
- skip: "changesIncludeOnly('doc/**', '**.{md,rdoc}')"
- arm_container:
- # We use the arm64 images at http://ghcr.io/ruby/ruby-ci-image .
- image: ghcr.io/ruby/ruby-ci-image:$CC
- # Define the used cpu core in each matrix task. We can use total 16 cpu
- # cores in entire matrix. [cpu] = [total cpu: 16] / [number of tasks]
- cpu: 8
- # We can request maximum 4 GB per cpu.
- # [memory per task] = [memory per cpu: 4 GB] * [cpu]
- memory: 32G
- env:
- CIRRUS_CLONE_DEPTH: 50
- optflags: '-O1'
- debugflags: '-ggdb3'
- RUBY_PREFIX: /tmp/ruby-prefix
- RUBY_DEBUG: ci rgengc
- RUBY_TESTOPTS: >-
- -q
- --color=always
- --tty=no
- matrix:
- CC: clang-12
- CC: gcc-11
- id_script: id
- set_env_script:
- # Set `GNUMAKEFLAGS`, because the flags are GNU make specific. Note using
- # the `make` environment variable used in compilers.yml causes some rubygems
- # tests to fail.
- # https://github.com/rubygems/rubygems/issues/4921
- - echo "GNUMAKEFLAGS=-s -j$((1 + $CIRRUS_CPU))" >> $CIRRUS_ENV
- print_env_script:
- - echo "GNUMAKEFLAGS=$GNUMAKEFLAGS"
- # Arm containers are executed in AWS's EKS, and it's not yet supporting IPv6
- # See https://github.com/aws/containers-roadmap/issues/835
- disable_ipv6_script: sudo ./tool/disable_ipv6.sh
- autogen_script: ./autogen.sh
- configure_script: >-
- ./configure -C
- --enable-debug-env
- --disable-install-doc
- --with-ext=-test-/cxxanyargs,+
- --prefix="$RUBY_PREFIX"
- make_extract-extlibs_script: make extract-extlibs
- make_incs_script: make incs
- make_script: make
- make_leaked-globals_script: make leaked-globals
- make_test_script: make test
- make_install_script: make install
- install_gems_for_test_script: $RUBY_PREFIX/bin/gem install --no-doc timezone tzinfo
- make_test-tool_script: make test-tool
- make_test-all_script: make test-all
- make_test-spec_script: make test-spec
diff --git a/.document b/.document
index 6e08f42698..3a6b0c238c 100644
--- a/.document
+++ b/.document
@@ -18,13 +18,18 @@ gc.rb
io.rb
kernel.rb
marshal.rb
+mjit.rb
numeric.rb
nilclass.rb
pack.rb
ractor.rb
+string.rb
+symbol.rb
timev.rb
+thread_sync.rb
trace_point.rb
warning.rb
+yjit.rb
# the lib/ directory (which has its own .document file)
lib
@@ -40,7 +45,6 @@ README.ja.md
COPYING
COPYING.ja
-CONTRIBUTING.md
LEGAL
diff --git a/.gdbinit b/.gdbinit
index 8979e8b47c..34d044caf6 100644
--- a/.gdbinit
+++ b/.gdbinit
@@ -544,13 +544,13 @@ end
define rp_class
printf "(struct RClass *) %p", (void*)$arg0
- if ((struct RClass *)($arg0))->ptr.origin_ != $arg0
- printf " -> %p", ((struct RClass *)($arg0))->ptr.origin_
+ if RCLASS_ORIGIN((struct RClass *)($arg0)) != $arg0
+ printf " -> %p", RCLASS_ORIGIN((struct RClass *)($arg0))
end
printf "\n"
rb_classname $arg0
print/x *(struct RClass *)($arg0)
- print *((struct RClass *)($arg0))->ptr
+ print *RCLASS_EXT((struct RClass *)($arg0))
end
document rp_class
Print the content of a Class/Module.
@@ -979,8 +979,8 @@ end
define rb_ps_vm
print $ps_vm = (rb_vm_t*)$arg0
- set $ps_thread_ln = $ps_vm->living_threads.n.next
- set $ps_thread_ln_last = $ps_vm->living_threads.n.prev
+ set $ps_thread_ln = $ps_vm->ractor.main_ractor.threads.set.n.next
+ set $ps_thread_ln_last = $ps_vm->ractor.main_ractor.threads.set.n.prev
while 1
set $ps_thread_th = (rb_thread_t *)$ps_thread_ln
set $ps_thread = (VALUE)($ps_thread_th->self)
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
new file mode 100644
index 0000000000..6c5eac5a0f
--- /dev/null
+++ b/.git-blame-ignore-revs
@@ -0,0 +1,23 @@
+# This is a file used by GitHub to ignore the following commits on `git blame`.
+#
+# You can also do the same thing in your local repository with:
+# $ git config --local blame.ignoreRevsFile .git-blame-ignore-revs
+
+# Expand tabs
+5b21e94bebed90180d8ff63dad03b8b948361089
+
+# Enable Style/StringLiterals cop for RubyGems/Bundler
+d7ffd3fea402239b16833cc434404a7af82d44f3
+
+# [ruby/digest] Revert tab-expansion in external files
+48b09aae7ec5632209229dcc294dd0d75a93a17f
+8a65cf3b61c60e4cb886f59a73ff6db44364bfa9
+39dc9f9093901d40d2998653948d5da38b18ee2c
+
+# [ruby/io-nonblock] Revert tab expansion
+f28287d34c03f472ffe90ea262bdde9affd4b965
+0d842fecb4f75ab3b1d4097ebdb8e88f51558041
+4ba2c66761d6a293abdfba409241d31063cefd62
+
+# Make benchmark indentation consistent
+fc4acf8cae82e5196186d3278d831f2438479d91
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
deleted file mode 100644
index 15abc79af6..0000000000
--- a/.github/CODEOWNERS
+++ /dev/null
@@ -1,10 +0,0 @@
-# Lines starting with '#' are comments.
-# Each line is a file pattern followed by one or more owners.
-# Code owners will be automatically tagged as reviewers when a pull request is opened
-
-# YJIT sources and tests
-yjit* @maximecb @xrxr @tenderlove
-doc/yjit/* @maximecb @xrxr @tenderlove
-bootstraptest/test_yjit* @maximecb @xrxr @tenderlove
-test/ruby/test_yjit* @maximecb @xrxr @tenderlove
-.github/workflows/yjit* @maximecb @xrxr @tenderlove
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000000..bc63aca35b
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,6 @@
+version: 2
+updates:
+ - package-ecosystem: 'github-actions'
+ directory: '/'
+ schedule:
+ interval: 'monthly'
diff --git a/.github/workflows/baseruby.yml b/.github/workflows/baseruby.yml
index cf86c2d7d7..ebaafe3bf0 100644
--- a/.github/workflows/baseruby.yml
+++ b/.github/workflows/baseruby.yml
@@ -4,23 +4,37 @@ on:
push:
paths-ignore:
- 'doc/**'
+ - '**/man'
- '**.md'
- '**.rdoc'
+ - '**/.document'
pull_request:
paths-ignore:
- 'doc/**'
+ - '**/man'
- '**.md'
- '**.rdoc'
+ - '**/.document'
+ merge_group:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
concurrency:
group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+permissions:
+ contents: read
+
jobs:
baseruby:
name: BASERUBY
- runs-on: ubuntu-20.04
- if: ${{ !startsWith(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
+ runs-on: ubuntu-22.04
+ if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
strategy:
matrix:
ruby:
@@ -29,28 +43,29 @@ jobs:
# - ruby-2.4
# - ruby-2.5
# - ruby-2.6
- - ruby-2.7
+# - ruby-2.7
- ruby-3.0
+ - ruby-3.1
steps:
- - uses: actions/checkout@v2
- - uses: actions/cache@v2
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: .downloaded-cache
key: downloaded-cache
- - uses: ruby/setup-ruby@v1
+ - uses: ruby/setup-ruby@13e7a03dc3ac6c3798f4570bfead2aed4d96abfb # v1.244.0
with:
ruby-version: ${{ matrix.ruby }}
bundler: none
- run: echo "GNUMAKEFLAGS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV
- - run: sudo apt-get install build-essential autoconf bison
+ - run: sudo apt-get install build-essential autoconf bison libyaml-dev
- run: ./autogen.sh
- run: ./configure --disable-install-doc
- run: make common-srcs
- run: make incs
- run: make all
- run: make test
- - uses: k0kubun/action-slack@v2.0.0
+ - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1
with:
payload: |
{
@@ -58,7 +73,7 @@ jobs:
"env": "${{ github.workflow }} / BASERUBY @ ${{ matrix.ruby }}",
"url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
"commit": "${{ github.sha }}",
- "branch": "${{ github.ref }}".split('/').reverse()[0]
+ "branch": "${{ github.ref_name }}"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
diff --git a/.github/workflows/bundled_gems.yml b/.github/workflows/bundled_gems.yml
index cc611d4579..070c0fa1dd 100644
--- a/.github/workflows/bundled_gems.yml
+++ b/.github/workflows/bundled_gems.yml
@@ -2,18 +2,31 @@ name: bundled_gems
on:
push:
+ branches: [ "master" ]
paths:
- '.github/workflows/bundled_gems.yml'
- 'gems/bundled_gems'
pull_request:
+ branches: [ "master" ]
+ paths:
+ - '.github/workflows/bundled_gems.yml'
+ - 'gems/bundled_gems'
+ merge_group:
+ branches: [ "master" ]
paths:
- '.github/workflows/bundled_gems.yml'
- 'gems/bundled_gems'
schedule:
- cron: '45 6 * * *'
+ workflow_dispatch:
+
+permissions: # added using https://github.com/step-security/secure-workflows
+ contents: read
jobs:
update:
+ permissions:
+ contents: write # for Git to git push
if: ${{ github.event_name != 'schedule' || github.repository == 'ruby/ruby' }}
name: update ${{ github.workflow }}
runs-on: ubuntu-latest
@@ -28,17 +41,21 @@ jobs:
echo "GNUMAKEFLAGS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV
echo "TODAY=$(date +%F)" >> $GITHUB_ENV
- - uses: actions/checkout@v2
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- - uses: actions/cache@v2
+ - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: .downloaded-cache
- key: downloaded-cache
+ key: downloaded-cache-${{ github.sha }}
+ restore-keys: |
+ downloaded-cache
- name: Download previous gems list
run: |
- curl -o .downloaded-cache/bundled_gems.json https://stdgems.org/bundled_gems.json
- ln -s .downloaded-cache/bundled_gems.json .
+ data=bundled_gems.json
+ mkdir -p .downloaded-cache
+ ln -s .downloaded-cache/$data .
+ curl -O -R -z ./$data https://stdgems.org/$data
- name: Update bundled gems list
run: |
@@ -46,6 +63,7 @@ jobs:
- name: Maintain updated gems list in NEWS
run: |
+ #!ruby
require 'json'
news = File.read("NEWS.md")
prev = news[/since the \*+(\d+\.\d+\.\d+)\*+/, 1]
@@ -63,12 +81,14 @@ jobs:
[g, v] unless last[g] == v
end
changed, added = changed.partition {|g, _| last[g]}
- news.sub!(/^\*\s+The following #{type} gems? are updated\.(\n\s+\*\s+)\K.*(?:\1.*)*/) do
- changed.map {|g, v|"#{g} #{v}"}.join($1)
- end or exit
- news.sub!(/^\*\s+The following default gems are now bundled.*(\n\s+\*\s+)\K.*(?:\1.*)*/) do
- added.map {|g, v|"#{g} #{v}"}.join($1)
- end if added
+ news.sub!(/^\*( +)The following #{type} gems? are updated\.\n+\K(?: \1\*( +).*\n)*/) do
+ mark = "#{$1} *#{$2}"
+ changed.map {|g, v|"#{mark}#{g} #{v}\n"}.join("")
+ end or next
+ news.sub!(/^\*( +)The following default gems are now bundled gems\.\n+\K(?: \1\*( +).*\n)*/) do
+ mark = "#{$1} *#{$2}"
+ added.map {|g, v|"#{mark}#{g} #{v}\n"}.join("")
+ end or next unless added.empty?
File.write("NEWS.md", news)
end
shell: ruby {0}
@@ -94,6 +114,11 @@ jobs:
make
if: ${{ steps.diff.outcome == 'failure' }}
+ - name: Prepare bundled gems
+ run: |
+ make -s prepare-gems
+ if: ${{ steps.diff.outcome == 'failure' }}
+
- name: Test bundled gems
run: |
make -s test-bundled-gems
@@ -124,4 +149,18 @@ jobs:
EMAIL: svn-admin@ruby-lang.org
GIT_AUTHOR_NAME: git
GIT_COMMITTER_NAME: git
- if: ${{ steps.show.outcome == 'failure' }}
+ if: ${{ github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull') && steps.show.outcome == 'failure' }}
+
+ - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1
+ with:
+ payload: |
+ {
+ "ci": "GitHub Actions",
+ "env": "${{ github.workflow }} / update",
+ "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
+ "commit": "${{ github.sha }}",
+ "branch": "${{ github.ref_name }}"
+ }
+ env:
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() && github.event_name == 'push' }}
diff --git a/.github/workflows/check_dependencies.yml b/.github/workflows/check_dependencies.yml
index 6c7e8e5787..79b2916feb 100644
--- a/.github/workflows/check_dependencies.yml
+++ b/.github/workflows/check_dependencies.yml
@@ -3,26 +3,40 @@ on:
push:
paths-ignore:
- 'doc/**'
+ - '**/man'
- '**.md'
- '**.rdoc'
+ - '**/.document'
pull_request:
paths-ignore:
- 'doc/**'
+ - '**/man'
- '**.md'
- '**.rdoc'
+ - '**/.document'
+ merge_group:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
concurrency:
group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+permissions:
+ contents: read
+
jobs:
update-deps:
strategy:
matrix:
- os: [ubuntu-20.04]
+ os: [ubuntu-22.04]
fail-fast: true
runs-on: ${{ matrix.os }}
- if: ${{ !startsWith(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
+ if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
steps:
- name: Install libraries
run: |
@@ -32,15 +46,14 @@ jobs:
if: ${{ contains(matrix.os, 'ubuntu') }}
- name: Install libraries
run: |
- brew upgrade
brew install gmp libffi openssl@1.1 zlib autoconf automake libtool readline
if: ${{ contains(matrix.os, 'macos') }}
- name: git config
run: |
git config --global advice.detachedHead 0
git config --global init.defaultBranch garbage
- - uses: actions/checkout@v2
- - uses: actions/cache@v2
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: .downloaded-cache
key: downloaded-cache
@@ -50,7 +63,7 @@ jobs:
- run: make all golf
- run: ruby tool/update-deps --fix
- run: git diff --no-ext-diff --ignore-submodules --exit-code
- - uses: k0kubun/action-slack@v2.0.0
+ - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1
with:
payload: |
{
@@ -58,7 +71,7 @@ jobs:
"env": "${{ matrix.os }} / Dependencies need to update",
"url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
"commit": "${{ github.sha }}",
- "branch": "${{ github.ref }}".split('/').reverse()[0]
+ "branch": "${{ github.ref_name }}"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
diff --git a/.github/workflows/check_misc.yml b/.github/workflows/check_misc.yml
deleted file mode 100644
index 27365d81a5..0000000000
--- a/.github/workflows/check_misc.yml
+++ /dev/null
@@ -1,92 +0,0 @@
-name: Miscellaneous checks
-on: [push, pull_request]
-
-concurrency:
- group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
- cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
-
-jobs:
- checks:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v2
- - name: Check if C-sources are US-ASCII
- run: |
- ! grep -r -n '[^ -~]' *.[chy] include internal win32/*.[ch]
- - name: Check for trailing spaces
- run: |
- ! git grep -n '[ ]$' '*.rb' '*.[chy]'
- - name: Check for header macros
- run: |
- ! for header in ruby/*.h; do \
- git grep -l -F -e $header -e HAVE_`echo $header | tr a-z./ A-Z__` -- . > /dev/null || echo $header
- done | grep -F .
- working-directory: include
-
- - uses: actions/cache@v2
- with:
- path: .downloaded-cache
- key: downloaded-cache
-
- - name: Download previous gems list
- run: |
- curl -o .downloaded-cache/default_gems.json https://stdgems.org/default_gems.json
- ln -s .downloaded-cache/default_gems.json .
-
- - name: Make default gems list
- run: |
- require 'rubygems'
- $:.unshift "lib"
- rgver = File.foreach("lib/rubygems.rb") do |line|
- break $1 if /^\s*VERSION\s*=\s*"([^"]+)"/ =~ line
- end
- gems = Dir.glob("{ext,lib}/**/*.gemspec").map do |f|
- spec = Gem::Specification.load(f)
- "#{spec.name} #{spec.version}"
- end.sort
- File.open("gems/default_gems", "w") do |f|
- f.puts "RubyGems #{rgver}"
- f.puts gems
- end
- shell: ruby --disable=gems {0}
-
- - name: Maintain updated gems list in NEWS
- run: |
- require 'json'
- news = File.read("NEWS.md")
- prev = news[/since the \*+(\d+\.\d+\.\d+)\*+/, 1]
- prevs = [prev, prev.sub(/\.\d+\z/, '')]
- %W[default].each do |type|
- last = JSON.parse(File.read("#{type}_gems.json"))['gems'].filter_map do |g|
- v = g['versions'].values_at(*prevs).compact.first
- g = g['gem']
- g = 'RubyGems' if g == 'rubygems'
- [g, v] if v
- end.to_h
- changed = File.foreach("gems/#{type}_gems").filter_map do |l|
- next if l.start_with?("#")
- g, v = l.split(" ", 3)
- [g, v] unless last[g] == v
- end
- news.sub!(/^\*\s+The following #{type} gems? are updated\.(\n\s+\*\s+)\K.*(?:\1.*)*/) do
- changed.map {|g, v|"#{g} #{v}"}.join($1)
- end or exit
- File.write("NEWS.md", news)
- end
- shell: ruby {0}
-
- - name: Check diffs
- id: diff
- run: |
- git diff --color --no-ext-diff --ignore-submodules --exit-code NEWS.md
- continue-on-error: true
- - name: Commit
- run: |
- git pull --ff-only origin ${GITHUB_REF#refs/heads/}
- git commit --message="Update default gems list at ${GITHUB_SHA:0:30} [ci skip]" NEWS.md
- git push origin ${GITHUB_REF#refs/heads/}
- env:
- EMAIL: svn-admin@ruby-lang.org
- GIT_AUTHOR_NAME: git
- GIT_COMMITTER_NAME: git
- if: ${{ steps.diff.outcome == 'failure' }}
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index f81c79902d..8dba76fbe2 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -1,29 +1,42 @@
name: "Code scanning - action"
on:
- push:
- paths-ignore:
- - 'doc/**'
- - '**.md'
- - '**.rdoc'
- pull_request:
- paths-ignore:
- - 'doc/**'
- - '**.md'
- - '**.rdoc'
+ # push:
+ # paths-ignore:
+ # - 'doc/**'
+ # - '**/man'
+ # - '**.md'
+ # - '**.rdoc'
+ # - '**/.document'
+ # pull_request:
+ # paths-ignore:
+ # - 'doc/**'
+ # - '**/man'
+ # - '**.md'
+ # - '**.rdoc'
+ # - '**/.document'
schedule:
- - cron: '0 12 * * 4'
+ - cron: '0 12 * * *'
+ workflow_dispatch:
concurrency:
group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+permissions: # added using https://github.com/step-security/secure-workflows
+ contents: read
+
jobs:
CodeQL-Build:
# CodeQL runs on ubuntu-latest and windows-latest
+ permissions:
+ actions: read # for github/codeql-action/init to get workflow details
+ contents: read # for actions/checkout to fetch code
+ security-events: write # for github/codeql-action/autobuild to send a status report
runs-on: ubuntu-latest
- if: ${{ !startsWith(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
+ # CodeQL fails to run pull requests from dependabot due to missing write access to upload results.
+ if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') && github.event.head_commit.pusher.name != 'dependabot[bot]' }}
env:
enable_install_doc: no
@@ -36,9 +49,9 @@ jobs:
sudo apt-get install --no-install-recommends -q -y build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev bison autoconf ruby
- name: Checkout repository
- uses: actions/checkout@v2
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- - uses: actions/cache@v2
+ - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: .downloaded-cache
key: downloaded-cache
@@ -47,15 +60,16 @@ jobs:
run: sudo rm /usr/lib/ruby/vendor_ruby/rubygems/defaults/operating_system.rb
- name: Initialize CodeQL
- uses: github/codeql-action/init@v1
+ uses: github/codeql-action/init@959cbb7472c4d4ad70cdfe6f4976053fe48ab394 # v2.1.37
with:
config-file: ./.github/codeql/codeql-config.yml
+ trap-caching: false
- name: Set ENV
run: echo "GNUMAKEFLAGS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV
- name: Autobuild
- uses: github/codeql-action/autobuild@v1
+ uses: github/codeql-action/autobuild@959cbb7472c4d4ad70cdfe6f4976053fe48ab394 # v2.1.37
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v1
+ uses: github/codeql-action/analyze@959cbb7472c4d4ad70cdfe6f4976053fe48ab394 # v2.1.37
diff --git a/.github/workflows/compilers.yml b/.github/workflows/compilers.yml
index 2af9fa55d8..caf12cc0f4 100644
--- a/.github/workflows/compilers.yml
+++ b/.github/workflows/compilers.yml
@@ -4,28 +4,36 @@ on:
push:
paths-ignore:
- 'doc/**'
+ - '**/man'
- '**.md'
- '**.rdoc'
+ - '**/.document'
pull_request:
paths-ignore:
- 'doc/**'
- - '**.md'
+ - '**/man'
+ - '**.rdoc'
+ - '**/.document'
+ merge_group:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
- '**.rdoc'
+ - '**/.document'
concurrency:
group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
-# Github actions does not support YAML anchors. This creative use of
+# GitHub actions does not support YAML anchors. This creative use of
# environment variables (plus the "echo $GITHUB_ENV" hack) is to reroute that
# restriction.
env:
- default_cc: clang-14
+ default_cc: clang-15
append_cc: ''
- crosshost: ''
# -O1 is faster than -O3 in our tests... Majority of time are consumed trying
- # to optimize binaries. Also Github Actions run on relatively modern CPUs
+ # to optimize binaries. Also GitHub Actions run on relatively modern CPUs
# compared to, say, GCC 4 or Clang 3. We don't specify `-march=native`
# because compilers tend not understand what the CPU is.
optflags: '-O1'
@@ -55,140 +63,160 @@ env:
--color=always
--tty=no
+permissions:
+ contents: read
+
jobs:
compile:
strategy:
fail-fast: false
matrix:
+ env:
+ - {}
entry:
- - { key: default_cc, name: gcc-11, value: gcc-11, container: gcc-11 }
- - { key: default_cc, name: gcc-10, value: gcc-10, container: gcc-10 }
- - { key: default_cc, name: gcc-9, value: gcc-9, container: gcc-9 }
- - { key: default_cc, name: gcc-8, value: gcc-8, container: gcc-8 }
- - { key: default_cc, name: gcc-7, value: gcc-7, container: gcc-7 }
- - { key: default_cc, name: gcc-6, value: gcc-6, container: gcc-6 }
- - { key: default_cc, name: gcc-5, value: gcc-5, container: gcc-5 }
- - { key: default_cc, name: gcc-4.8, value: gcc-4.8, container: gcc-4.8 }
- - key: default_cc
- name: 'gcc-11 LTO'
- value: 'gcc-11 -O2 -flto=auto -ffat-lto-objects'
- container: gcc-11
- shared: '--disable-shared'
+ - { name: gcc-12, env: { default_cc: gcc-12 } }
+ - { name: gcc-11, env: { default_cc: gcc-11 } }
+ - { name: gcc-10, env: { default_cc: gcc-10 } }
+ - { name: gcc-9, env: { default_cc: gcc-9 } }
+ - { name: gcc-8, env: { default_cc: gcc-8 } }
+ - { name: gcc-7, env: { default_cc: gcc-7 } }
+ - name: 'gcc-13 LTO'
+ container: gcc-13
+ env:
+ default_cc: 'gcc-13 -flto=auto -ffat-lto-objects -Werror=lto-type-mismatch'
+ optflags: '-O2'
+ shared: disable
# check: true
- - { key: default_cc, name: clang-14, value: clang-14, container: clang-14 }
- - { key: default_cc, name: clang-13, value: clang-13, container: clang-13 }
- - { key: default_cc, name: clang-12, value: clang-12, container: clang-12 }
- - { key: default_cc, name: clang-11, value: clang-11, container: clang-11 }
- - { key: default_cc, name: clang-10, value: clang-10, container: clang-10 }
- - { key: default_cc, name: clang-9, value: clang-9, container: clang-9 }
- - { key: default_cc, name: clang-8, value: clang-8, container: clang-8 }
- - { key: default_cc, name: clang-7, value: clang-7, container: clang-7 }
- - { key: default_cc, name: clang-6.0, value: clang-6.0, container: clang-6.0 }
- - { key: default_cc, name: clang-5.0, value: clang-5.0, container: clang-5.0 }
- - { key: default_cc, name: clang-4.0, value: clang-4.0, container: clang-4.0 }
- - { key: default_cc, name: clang-3.9, value: clang-3.9, container: clang-3.9 }
- - key: default_cc
- name: 'clang-14 LTO'
- value: 'clang-14 -O2 -flto=auto'
- container: clang-14
- shared: '--disable-shared'
+ - { name: clang-16, env: { default_cc: clang-16 } }
+ - { name: clang-15, env: { default_cc: clang-15 } }
+ - { name: clang-14, env: { default_cc: clang-14 } }
+ - { name: clang-13, env: { default_cc: clang-13 } }
+ - { name: clang-12, env: { default_cc: clang-12 } }
+ - { name: clang-11, env: { default_cc: clang-11 } }
+ - { name: clang-10, env: { default_cc: clang-10 } }
+ # llvm-objcopy<=9 doesn't have --wildcard. It compiles, but leaves Rust symbols in libyjit.o.
+ - { name: clang-9, env: { default_cc: clang-9, append_configure: '--disable-yjit' } }
+ - { name: clang-8, env: { default_cc: clang-8, append_configure: '--disable-yjit' } }
+ - { name: clang-7, env: { default_cc: clang-7, append_configure: '--disable-yjit' } }
+ - { name: clang-6.0, env: { default_cc: clang-6.0, append_configure: '--disable-yjit' } }
+ - name: 'clang-16 LTO'
+ container: clang-16
+ env:
+ default_cc: 'clang-16 -flto=auto'
+ optflags: '-O2'
+ shared: disable
# check: true
- - { key: crosshost, name: aarch64-linux-gnu, value: aarch64-linux-gnu, container: crossbuild-essential-arm64 }
-# - { key: crosshost, name: arm-linux-gnueabi, value: arm-linux-gnueabi }
-# - { key: crosshost, name: arm-linux-gnueabihf, value: arm-linux-gnueabihf }
-# - { key: crosshost, name: i686-w64-mingw32, value: i686-w64-mingw32 }
-# - { key: crosshost, name: powerpc-linux-gnu, value: powerpc-linux-gnu }
- - { key: crosshost, name: powerpc64le-linux-gnu, value: powerpc64le-linux-gnu, container: crossbuild-essential-ppc64el }
- - { key: crosshost, name: s390x-linux-gnu, value: s390x-linux-gnu, container: crossbuild-essential-s390x }
- - { key: crosshost, name: x86_64-w64-mingw32, value: x86_64-w64-mingw32, container: mingw-w64 }
-
- - { key: append_cc, name: c99, value: '-std=c99 -Werror=pedantic -pedantic-errors' }
-# - { key: append_cc, name: c11, value: '-std=c11 -Werror=pedantic -pedantic-errors' }
-# - { key: append_cc, name: c17, value: '-std=c17 -Werror=pedantic -pedantic-errors' }
- - { key: append_cc, name: c2x, value: '-std=c2x -Werror=pedantic -pedantic-errors' }
- - { key: CXXFLAGS, name: c++98, value: '-std=c++98 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' }
-# - { key: CXXFLAGS, name: c++11, value: '-std=c++11 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' }
-# - { key: CXXFLAGS, name: c++14, value: '-std=c++14 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' }
-# - { key: CXXFLAGS, name: c++17, value: '-std=c++17 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' }
- - { key: CXXFLAGS, name: c++2a, value: '-std=c++2a -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' }
-
- - { key: optflags, name: '-O0', value: '-O0 -march=x86-64 -mtune=generic' }
-# - { key: optflags, name: '-O3', value: '-O3 -march=x86-64 -mtune=generic', check: true }
-
- - { key: append_configure, name: gmp, value: '--with-gmp' }
- - { key: append_configure, name: jemalloc, value: '--with-jemalloc' }
- - { key: append_configure, name: valgrind, value: '--with-valgrind' }
- - { key: append_configure, name: 'coroutine=ucontext', value: '--with-coroutine=ucontext' }
- - { key: append_configure, name: 'coroutine=pthread', value: '--with-coroutine=pthread' }
- - { key: append_configure, name: disable-jit-support, value: '--disable-jit-support' }
- - { key: append_configure, name: disable-dln, value: '--disable-dln' }
- - { key: append_configure, name: disable-rubygems, value: '--disable-rubygems' }
-
- - { key: cppflags, name: OPT_THREADED_CODE=1, value: '-DOPT_THREADED_CODE=1' }
- - { key: cppflags, name: OPT_THREADED_CODE=2, value: '-DOPT_THREADED_CODE=2' }
- - { key: cppflags, name: OPT_THREADED_CODE=3, value: '-DOPT_THREADED_CODE=3' }
-
- - { key: cppflags, name: NDEBUG, value: '-DNDEBUG' }
- - { key: cppflags, name: RUBY_DEBUG, value: '-DRUBY_DEBUG' }
-# - { key: cppflags, name: ARRAY_DEBUG, value: '-DARRAY_DEBUG' }
-# - { key: cppflags, name: BIGNUM_DEBUG, value: '-DBIGNUM_DEBUG' }
-# - { key: cppflags, name: CCAN_LIST_DEBUG, value: '-DCCAN_LIST_DEBUG' }
-# - { key: cppflags, name: CPDEBUG=-1, value: '-DCPDEBUG=-1' }
-# - { key: cppflags, name: ENC_DEBUG, value: '-DENC_DEBUG' }
-# - { key: cppflags, name: GC_DEBUG, value: '-DGC_DEBUG' }
-# - { key: cppflags, name: HASH_DEBUG, value: '-DHASH_DEBUG' }
-# - { key: cppflags, name: ID_TABLE_DEBUG, value: '-DID_TABLE_DEBUG' }
-# - { key: cppflags, name: RGENGC_DEBUG=-1, value: '-DRGENGC_DEBUG=-1' }
-# - { key: cppflags, name: SYMBOL_DEBUG, value: '-DSYMBOL_DEBUG' }
-# - { key: cppflags, name: THREAD_DEBUG=-1, value: '-DTHREAD_DEBUG=-1' }
-
-# - { key: cppflags, name: RGENGC_CHECK_MODE, value: '-DRGENGC_CHECK_MODE' }
-# - { key: cppflags, name: TRANSIENT_HEAP_CHECK_MODE, value: '-DTRANSIENT_HEAP_CHECK_MODE' }
-# - { key: cppflags, name: VM_CHECK_MODE, value: '-DVM_CHECK_MODE' }
-
- - { key: cppflags, name: USE_EMBED_CI=0, value: '-DUSE_EMBED_CI=0' }
- - { key: cppflags, name: USE_FLONUM=0, value: '-DUSE_FLONUM=0' }
-# - { key: cppflags, name: USE_GC_MALLOC_OBJ_INFO_DETAILS, value: '-DUSE_GC_MALLOC_OBJ_INFO_DETAILS' }
- - { key: cppflags, name: USE_LAZY_LOAD, value: '-DUSE_LAZY_LOAD' }
-# - { key: cppflags, name: USE_RINCGC=0, value: '-DUSE_RINCGC=0' }
-# - { key: cppflags, name: USE_SYMBOL_GC=0, value: '-DUSE_SYMBOL_GC=0' }
-# - { key: cppflags, name: USE_THREAD_CACHE=0, value: '-DUSE_THREAD_CACHE=0' }
-# - { key: cppflags, name: USE_TRANSIENT_HEAP=0, value: '-DUSE_TRANSIENT_HEAP=0' }
-# - { key: cppflags, name: USE_RUBY_DEBUG_LOG=1, value: '-DUSE_RUBY_DEBUG_LOG=1' }
-
- - { key: cppflags, name: DEBUG_FIND_TIME_NUMGUESS, value: '-DDEBUG_FIND_TIME_NUMGUESS' }
- - { key: cppflags, name: DEBUG_INTEGER_PACK, value: '-DDEBUG_INTEGER_PACK' }
-# - { key: cppflags, name: ENABLE_PATH_CHECK, value: '-DENABLE_PATH_CHECK' }
-
- - { key: cppflags, name: GC_DEBUG_STRESS_TO_CLASS, value: '-DGC_DEBUG_STRESS_TO_CLASS' }
-# - { key: cppflags, name: GC_ENABLE_LAZY_SWEEP=0, value: '-DGC_ENABLE_LAZY_SWEEP=0' }
-# - { key: cppflags, name: GC_PROFILE_DETAIL_MEMOTY, value: '-DGC_PROFILE_DETAIL_MEMOTY' }
-# - { key: cppflags, name: GC_PROFILE_MORE_DETAIL, value: '-DGC_PROFILE_MORE_DETAIL' }
-
-# - { key: cppflags, name: CALC_EXACT_MALLOC_SIZE, value: '-DCALC_EXACT_MALLOC_SIZE' }
-# - { key: cppflags, name: MALLOC_ALLOCATED_SIZE_CHECK, value: '-DMALLOC_ALLOCATED_SIZE_CHECK' }
-
-# - { key: cppflags, name: IBF_ISEQ_ENABLE_LOCAL_BUFFER, value: '-DIBF_ISEQ_ENABLE_LOCAL_BUFFER' }
-
-# - { key: cppflags, name: RGENGC_ESTIMATE_OLDMALLOC, value: '-DRGENGC_ESTIMATE_OLDMALLOC' }
-# - { key: cppflags, name: RGENGC_FORCE_MAJOR_GC, value: '-DRGENGC_FORCE_MAJOR_GC' }
-# - { key: cppflags, name: RGENGC_OBJ_INFO, value: '-DRGENGC_OBJ_INFO' }
-# - { key: cppflags, name: RGENGC_OLD_NEWOBJ_CHECK, value: '-DRGENGC_OLD_NEWOBJ_CHECK' }
-# - { key: cppflags, name: RGENGC_PROFILE, value: '-DRGENGC_PROFILE' }
-
-# - { key: cppflags, name: VM_DEBUG_BP_CHECK, value: '-DVM_DEBUG_BP_CHECK' }
-# - { key: cppflags, name: VM_DEBUG_VERIFY_METHOD_CACHE, value: '-DVM_DEBUG_VERIFY_METHOD_CACHE' }
-
- - { key: cppflags, name: MJIT_FORCE_ENABLE, value: '-DMJIT_FORCE_ENABLE' }
- - { key: cppflags, name: YJIT_FORCE_ENABLE, value: '-DYJIT_FORCE_ENABLE' }
+# - { name: aarch64-linux-gnu, crosshost: aarch64-linux-gnu, container: crossbuild-essential-arm64 }
+# - { name: arm-linux-gnueabi, crosshost: arm-linux-gnueabi }
+# - { name: arm-linux-gnueabihf, crosshost: arm-linux-gnueabihf }
+# - { name: i686-w64-mingw32, crosshost: i686-w64-mingw32 }
+# - { name: powerpc-linux-gnu, crosshost: powerpc-linux-gnu }
+# - { name: powerpc64le-linux-gnu, crosshost: powerpc64le-linux-gnu, container: crossbuild-essential-ppc64el }
+# - { name: s390x-linux-gnu, crosshost: s390x-linux-gnu, container: crossbuild-essential-s390x }
+# - { name: x86_64-w64-mingw32, crosshost: x86_64-w64-mingw32, container: mingw-w64 }
+
+ # -Wno-strict-prototypes is necessary with current clang-15 since
+ # older autoconf generate functions without prototype and -pedantic
+ # now implies strict-prototypes. Disabling the error but leaving the
+ # warning generates a lot of noise from use of ANYARGS in
+ # rb_define_method() and friends.
+ # See: https://github.com/llvm/llvm-project/commit/11da1b53d8cd3507959022cd790d5a7ad4573d94
+ - { name: c99, env: { append_cc: '-std=c99 -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' } }
+# - { name: c11, env: { append_cc: '-std=c11 -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' } }
+# - { name: c17, env: { append_cc: '-std=c17 -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' } }
+ - { name: c2x, env: { append_cc: '-std=c2x -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' } }
+ - { name: c++98, env: { CXXFLAGS: '-std=c++98 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } }
+# - { name: c++11, env: { CXXFLAGS: '-std=c++11 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } }
+# - { name: c++14, env: { CXXFLAGS: '-std=c++14 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } }
+# - { name: c++17, env: { CXXFLAGS: '-std=c++17 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } }
+ - { name: c++2a, env: { CXXFLAGS: '-std=c++2a -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } }
+
+ - { name: '-O0', env: { optflags: '-O0 -march=x86-64 -mtune=generic' } }
+# - { name: '-O3', env: { optflags: '-O3 -march=x86-64 -mtune=generic' }, check: true }
+
+ - { name: gmp, env: { append_configure: '--with-gmp' } }
+ - { name: jemalloc, env: { append_configure: '--with-jemalloc' } }
+ - { name: valgrind, env: { append_configure: '--with-valgrind' } }
+ - { name: 'coroutine=ucontext', env: { append_configure: '--with-coroutine=ucontext' } }
+ - { name: 'coroutine=pthread', env: { append_configure: '--with-coroutine=pthread' } }
+ - { name: disable-jit-support, env: { append_configure: '--disable-jit-support' } }
+ - { name: disable-dln, env: { append_configure: '--disable-dln' } }
+ - { name: enable-mkmf-verbose, env: { append_configure: '--enable-mkmf-verbose' } }
+ - { name: disable-rubygems, env: { append_configure: '--disable-rubygems' } }
+ - { name: RUBY_DEVEL, env: { append_configure: '--enable-devel' } }
+
+ - { name: OPT_THREADED_CODE=1, env: { cppflags: '-DOPT_THREADED_CODE=1' } }
+ - { name: OPT_THREADED_CODE=2, env: { cppflags: '-DOPT_THREADED_CODE=2' } }
+ - { name: OPT_THREADED_CODE=3, env: { cppflags: '-DOPT_THREADED_CODE=3' } }
+
+ - { name: NDEBUG, env: { cppflags: '-DNDEBUG' } }
+ - { name: RUBY_DEBUG, env: { cppflags: '-DRUBY_DEBUG' } }
+# - { name: ARRAY_DEBUG, env: { cppflags: '-DARRAY_DEBUG' } }
+# - { name: BIGNUM_DEBUG, env: { cppflags: '-DBIGNUM_DEBUG' } }
+# - { name: CCAN_LIST_DEBUG, env: { cppflags: '-DCCAN_LIST_DEBUG' } }
+# - { name: CPDEBUG=-1, env: { cppflags: '-DCPDEBUG=-1' } }
+# - { name: ENC_DEBUG, env: { cppflags: '-DENC_DEBUG' } }
+# - { name: GC_DEBUG, env: { cppflags: '-DGC_DEBUG' } }
+# - { name: HASH_DEBUG, env: { cppflags: '-DHASH_DEBUG' } }
+# - { name: ID_TABLE_DEBUG, env: { cppflags: '-DID_TABLE_DEBUG' } }
+# - { name: RGENGC_DEBUG=-1, env: { cppflags: '-DRGENGC_DEBUG=-1' } }
+# - { name: SYMBOL_DEBUG, env: { cppflags: '-DSYMBOL_DEBUG' } }
+
+# - { name: RGENGC_CHECK_MODE, env: { cppflags: '-DRGENGC_CHECK_MODE' } }
+# - { name: TRANSIENT_HEAP_CHECK_MODE, env: { cppflags: '-DTRANSIENT_HEAP_CHECK_MODE' } }
+# - { name: VM_CHECK_MODE, env: { cppflags: '-DVM_CHECK_MODE' } }
+
+ - { name: USE_EMBED_CI=0, env: { cppflags: '-DUSE_EMBED_CI=0' } }
+ - name: USE_FLONUM=0,
+ env:
+ cppflags: '-DUSE_FLONUM=0'
+ # yjit requires FLONUM for the pointer tagging scheme
+ append_configure: '--disable-yjit'
+# - { name: USE_GC_MALLOC_OBJ_INFO_DETAILS, env: { cppflags: '-DUSE_GC_MALLOC_OBJ_INFO_DETAILS' } }
+ - { name: USE_LAZY_LOAD, env: { cppflags: '-DUSE_LAZY_LOAD' } }
+# - { name: USE_RINCGC=0, env: { cppflags: '-DUSE_RINCGC=0' } }
+# - { name: USE_SYMBOL_GC=0, env: { cppflags: '-DUSE_SYMBOL_GC=0' } }
+# - { name: USE_THREAD_CACHE=0, env: { cppflags: '-DUSE_THREAD_CACHE=0' } }
+# - { name: USE_TRANSIENT_HEAP=0, env: { cppflags: '-DUSE_TRANSIENT_HEAP=0' } }
+# - { name: USE_RUBY_DEBUG_LOG=1, env: { cppflags: '-DUSE_RUBY_DEBUG_LOG=1' } }
+ - { name: USE_RVARGC=0, env: { cppflags: '-DUSE_RVARGC=0' } }
+# - { name: USE_RVARGC=1, env: { cppflags: '-DUSE_RVARGC=1' } }
+# - { name: USE_DEBUG_COUNTER, env: { cppflags: '-DUSE_DEBUG_COUNTER=1', RUBY_DEBUG_COUNTER_DISABLE: '1' } }
+
+ - { name: DEBUG_FIND_TIME_NUMGUESS, env: { cppflags: '-DDEBUG_FIND_TIME_NUMGUESS' } }
+ - { name: DEBUG_INTEGER_PACK, env: { cppflags: '-DDEBUG_INTEGER_PACK' } }
+# - { name: ENABLE_PATH_CHECK, env: { cppflags: '-DENABLE_PATH_CHECK' } }
+
+ - { name: GC_DEBUG_STRESS_TO_CLASS, env: { cppflags: '-DGC_DEBUG_STRESS_TO_CLASS' } }
+# - { name: GC_ENABLE_LAZY_SWEEP=0, env: { cppflags: '-DGC_ENABLE_LAZY_SWEEP=0' } }
+# - { name: GC_PROFILE_DETAIL_MEMOTY, env: { cppflags: '-DGC_PROFILE_DETAIL_MEMOTY' } }
+# - { name: GC_PROFILE_MORE_DETAIL, env: { cppflags: '-DGC_PROFILE_MORE_DETAIL' } }
+
+# - { name: CALC_EXACT_MALLOC_SIZE, env: { cppflags: '-DCALC_EXACT_MALLOC_SIZE' } }
+# - { name: MALLOC_ALLOCATED_SIZE_CHECK, env: { cppflags: '-DMALLOC_ALLOCATED_SIZE_CHECK' } }
+
+# - { name: IBF_ISEQ_ENABLE_LOCAL_BUFFER, env: { cppflags: '-DIBF_ISEQ_ENABLE_LOCAL_BUFFER' } }
+
+# - { name: RGENGC_ESTIMATE_OLDMALLOC, env: { cppflags: '-DRGENGC_ESTIMATE_OLDMALLOC' } }
+# - { name: RGENGC_FORCE_MAJOR_GC, env: { cppflags: '-DRGENGC_FORCE_MAJOR_GC' } }
+# - { name: RGENGC_OBJ_INFO, env: { cppflags: '-DRGENGC_OBJ_INFO' } }
+# - { name: RGENGC_OLD_NEWOBJ_CHECK, env: { cppflags: '-DRGENGC_OLD_NEWOBJ_CHECK' } }
+# - { name: RGENGC_PROFILE, env: { cppflags: '-DRGENGC_PROFILE' } }
+
+# - { name: VM_DEBUG_BP_CHECK, env: { cppflags: '-DVM_DEBUG_BP_CHECK' } }
+# - { name: VM_DEBUG_VERIFY_METHOD_CACHE, env: { cppflags: '-DVM_DEBUG_VERIFY_METHOD_CACHE' } }
+
+ - { name: MJIT_FORCE_ENABLE, env: { cppflags: '-DMJIT_FORCE_ENABLE' } }
+ - { name: YJIT_FORCE_ENABLE, env: { cppflags: '-DYJIT_FORCE_ENABLE' } }
name: ${{ matrix.entry.name }}
runs-on: ubuntu-latest
container:
- image: ghcr.io/ruby/ruby-ci-image:${{ matrix.entry.container || 'clang-14' }}
+ image: ghcr.io/ruby/ruby-ci-image:${{ matrix.entry.container || matrix.entry.env.default_cc || 'clang-15' }}
options: --user root
- if: ${{ !startsWith(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
+ if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
+ env: ${{ matrix.entry.env || matrix.env }}
steps:
- run: id
working-directory:
@@ -196,12 +224,11 @@ jobs:
working-directory:
- name: setenv
run: |
- echo "${{ matrix.entry.key }}=${{ matrix.entry.value }}" >> $GITHUB_ENV
echo "GNUMAKEFLAGS=-sj$((1 + $(nproc --all)))" >> $GITHUB_ENV
- - uses: actions/checkout@v2
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
path: src
- - uses: actions/cache@v2
+ - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: src/.downloaded-cache
key: downloaded-cache
@@ -210,25 +237,32 @@ jobs:
- name: Run configure
run: >
../src/configure -C ${default_configure} ${append_configure}
- ${{ matrix.entry.key == 'crosshost' && '--host="${crosshost}"' || '--with-gcc="${default_cc} ${append_cc}"' }}
- ${{ matrix.entry.shared || '--enable-shared' }}
+ --${{
+ matrix.entry.crosshost && 'host' || 'with-gcc'
+ }}=${{
+ matrix.entry.crosshost || '"${default_cc}${append_cc:+ $append_cc}"'
+ }}
+ --${{ matrix.entry.shared || 'enable' }}-shared
- run: make extract-extlibs
- run: make incs
+ - run: make showflags
- run: make
- run: make leaked-globals
- run: make test
- run: make install
if: ${{ matrix.entry.check }}
- - run: make prepare-gems
- if: ${{ matrix.entry.check }}
- run: make test-tool
if: ${{ matrix.entry.check }}
- run: make test-all TESTS='-- ruby -ext-'
if: ${{ matrix.entry.check }}
- run: make test-spec
+ env:
+ CHECK_LEAKS: true
if: ${{ matrix.entry.check }}
+ - run: make test-annocheck
+ if: ${{ matrix.entry.check && endsWith(matrix.entry.name, 'annocheck') }}
- - uses: k0kubun/action-slack@v2.0.0
+ - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1
with:
payload: |
{
@@ -236,7 +270,7 @@ jobs:
"env": "${{ github.workflow }} / ${{ matrix.entry.name }}",
"url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
"commit": "${{ github.sha }}",
- "branch": "${{ github.ref }}".split('/').reverse()[0]
+ "branch": "${{ github.ref_name }}"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml
new file mode 100644
index 0000000000..d8dc58b119
--- /dev/null
+++ b/.github/workflows/macos.yml
@@ -0,0 +1,113 @@
+name: macOS
+on:
+ push:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ pull_request:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ merge_group:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
+
+jobs:
+ make:
+ strategy:
+ matrix:
+ test_task: ["check"] # "test-bundler-parallel", "test-bundled-gems"
+ os:
+ - macos-13
+ - macos-14
+ - macos-15
+ fail-fast: false
+ env:
+ GITPULLOPTIONS: --no-tags origin ${{github.ref}}
+ runs-on: ${{ matrix.os }}
+ if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
+ steps:
+ - run: mkdir build
+ working-directory:
+ - name: git config
+ run: |
+ git config --global advice.detachedHead 0
+ git config --global init.defaultBranch garbage
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ with:
+ path: src
+ - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
+ with:
+ path: src/.downloaded-cache
+ key: downloaded-cache
+ - name: Install libraries
+ run: |
+ brew install gmp libffi openssl@1.1 zlib autoconf automake libtool readline bison
+ working-directory: src
+ - name: Set ENV
+ run: |
+ echo "MAKEFLAGS=-j$((1 + $(sysctl -n hw.activecpu)))" >> $GITHUB_ENV
+ echo "PATH="/usr/local/opt/bison/bin:/opt/homebrew/opt/bison/bin:$PATH"" >> $GITHUB_ENV
+ - run: ./autogen.sh
+ working-directory: src
+ - name: Run configure
+ run: ../src/configure -C --disable-install-doc --with-openssl-dir=$(brew --prefix openssl@1.1) --with-readline-dir=$(brew --prefix readline)
+ - run: make incs
+ - run: make prepare-gems
+ if: ${{ matrix.test_task == 'test-bundled-gems' }}
+ - run: make
+ - run: make leaked-globals
+ if: ${{ matrix.test_task == 'check' }}
+ - name: make ${{ matrix.test_task }}
+ run: |
+ make -s ${{ matrix.test_task }} ${TESTS:+TESTS=`echo "$TESTS" | sed 's| |$$/ -n!/|g;s|^|-n!/|;s|$|$$/|'`}
+ timeout-minutes: 40
+ env:
+ RUBY_TESTOPTS: "-q --tty=no"
+ TESTS: ${{ matrix.test_task == 'check' && matrix.skipped_tests || '' }}
+ TEST_BUNDLED_GEMS_ALLOW_FAILURES: ""
+ PRECHECK_BUNDLED_GEMS: "no"
+ - name: make skipped tests
+ run: |
+ make -s test-all TESTS=`echo "$TESTS" | sed 's| |$$/ -n/|g;s|^|-n/|;s|$|$$/|'`
+ env:
+ GNUMAKEFLAGS: ""
+ RUBY_TESTOPTS: "-v --tty=no"
+ TESTS: ${{ matrix.skipped_tests }}
+ PRECHECK_BUNDLED_GEMS: "no"
+ if: ${{ matrix.test_task == 'check' && matrix.skipped_tests != '' }}
+ continue-on-error: ${{ matrix.continue-on-skipped_tests || false }}
+ - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1
+ with:
+ payload: |
+ {
+ "ci": "GitHub Actions",
+ "env": "${{ matrix.os }} / ${{ matrix.test_task }}${{ matrix.configure }}",
+ "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
+ "commit": "${{ github.sha }}",
+ "branch": "${{ github.ref_name }}"
+ }
+ env:
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() && github.event_name == 'push' }}
+
+defaults:
+ run:
+ working-directory: build
diff --git a/.github/workflows/mingw.yml b/.github/workflows/mingw.yml
index 0d7eef67c0..0df917d3d8 100644
--- a/.github/workflows/mingw.yml
+++ b/.github/workflows/mingw.yml
@@ -3,18 +3,32 @@ on:
push:
paths-ignore:
- 'doc/**'
+ - '**/man'
- '**.md'
- '**.rdoc'
+ - '**/.document'
pull_request:
paths-ignore:
- 'doc/**'
+ - '**/man'
- '**.md'
- '**.rdoc'
+ - '**/.document'
+ merge_group:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
concurrency:
group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+permissions:
+ contents: read
+
# Notes:
# Actions console encoding causes issues, see test-all & test-spec steps
#
@@ -26,23 +40,22 @@ jobs:
MSYSTEM: ${{ matrix.msystem }}
MSYS2_ARCH: x86_64
CHOST: "x86_64-w64-mingw32"
- CFLAGS: "-march=x86-64 -mtune=generic -O3 -pipe -fstack-protector-strong"
+ CFLAGS: "-march=x86-64 -mtune=generic -O3 -pipe"
CXXFLAGS: "-march=x86-64 -mtune=generic -O3 -pipe"
CPPFLAGS: "-D_FORTIFY_SOURCE=2 -D__USE_MINGW_ANSI_STDIO=1 -DFD_SETSIZE=2048"
- LDFLAGS: "-pipe -fstack-protector-strong"
+ LDFLAGS: "-pipe"
UPDATE_UNICODE: "UNICODE_FILES=. UNICODE_PROPERTY_FILES=. UNICODE_AUXILIARY_FILES=. UNICODE_EMOJI_FILES=."
GITPULLOPTIONS: --no-tags origin ${{github.ref}}
strategy:
matrix:
include:
- - msystem: "MINGW64"
- base_ruby: 2.6
- test_task: [ "check" ] # to make job names consistent
+ # To mitigate flakiness of MinGW CI, we test only one runtime that newer MSYS2 uses.
- msystem: "UCRT64"
base_ruby: head
- test_task: [ "check" ] # to make job names consistent
+ test_task: "check"
+ test-all-opts: "--name=!/TestObjSpace#test_reachable_objects_during_iteration/"
fail-fast: false
- if: ${{ !startsWith(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
+ if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
steps:
- run: mkdir build
working-directory:
@@ -52,25 +65,26 @@ jobs:
git config --global core.eol lf
git config --global advice.detachedHead 0
git config --global init.defaultBranch garbage
- - uses: actions/checkout@v2
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
path: src
- - uses: actions/cache@v2
+ - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: src/.downloaded-cache
key: downloaded-cache
- name: Set up Ruby & MSYS2
- uses: MSP-Greg/ruby-setup-ruby@win-ucrt-1
+ uses: ruby/setup-ruby@13e7a03dc3ac6c3798f4570bfead2aed4d96abfb # v1.244.0
with:
ruby-version: ${{ matrix.base_ruby }}
- name: set env
run: |
echo "GNUMAKEFLAGS=-j$((2 * NUMBER_OF_PROCESSORS))" >> $GITHUB_ENV
- echo "TEST_JOBS=$((15 * NUMBER_OF_PROCESSORS / 10))" >> $GITHUB_ENV
- name: where check
run: |
# show where
+ mv /c/Windows/System32/libcrypto-1_1-x64.dll /c/Windows/System32/libcrypto-1_1-x64.dll_
+ mv /c/Windows/System32/libssl-1_1-x64.dll /c/Windows/System32/libssl-1_1-x64.dll_
result=true
for e in gcc.exe ragel.exe make.exe bison.exe libcrypto-1_1-x64.dll libssl-1_1-x64.dll; do
echo '##['group']'$'\033[93m'$e$'\033[m'
@@ -79,6 +93,18 @@ jobs:
done
$result
+ - name: version check
+ run: |
+ # show version
+ result=true
+ for e in gcc ragel make bison "openssl version"; do
+ case "$e" in *" "*) ;; *) e="$e --version";; esac
+ echo '##['group']'$'\033[93m'$e$'\033[m'
+ $e || result=false
+ echo '##['endgroup']'
+ done
+ $result
+
- name: autogen
run: |
./autogen.sh
@@ -98,7 +124,7 @@ jobs:
make update-gems
- name: make all
- timeout-minutes: 20
+ timeout-minutes: 30
run: |
make
@@ -112,31 +138,36 @@ jobs:
timeout-minutes: 5
run: |
make test
+ if: ${{matrix.test_task == 'check' || matrix.test_task == 'test'}}
- name: test-all
timeout-minutes: 45
run: |
# Actions uses UTF8, causes test failures, similar to normal OS setup
chcp.com 437
- make test-all
+ make ${{ StartsWith(matrix.test_task, 'test/') && matrix.test_task || 'test-all' }}
env:
- RUBY_TESTOPTS: -j${{env.TEST_JOBS}} --retry --job-status=normal --show-skip --timeout-scale=1.5
+ RUBY_TESTOPTS: >-
+ --retry --job-status=normal --show-skip --timeout-scale=1.5
+ ${{ matrix.test-all-opts }}
BUNDLER_VERSION:
+ if: ${{matrix.test_task == 'check' || matrix.test_task == 'test-all' || StartsWith(matrix.test_task, 'test/')}}
- name: test-spec
timeout-minutes: 10
run: |
- make test-spec
+ make ${{ StartsWith(matrix.test_task, 'spec/') && matrix.test_task || 'test-spec' }}
+ if: ${{matrix.test_task == 'check' || matrix.test_task == 'test-spec' || StartsWith(matrix.test_task, 'spec/')}}
- - uses: k0kubun/action-slack@v2.0.0
+ - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1
with:
payload: |
{
"ci": "GitHub Actions",
- "env": "${{ github.workflow }} / ${{ matrix.test_task }}",
+ "env": "${{ github.workflow }} ${{ matrix.msystem }} / ${{ matrix.test_task }}",
"url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
"commit": "${{ github.sha }}",
- "branch": "${{ github.ref }}".split('/').reverse()[0]
+ "branch": "${{ github.ref_name }}"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
diff --git a/.github/workflows/mjit-bindgen.yml b/.github/workflows/mjit-bindgen.yml
new file mode 100644
index 0000000000..26f8a1b2aa
--- /dev/null
+++ b/.github/workflows/mjit-bindgen.yml
@@ -0,0 +1,104 @@
+name: MJIT bindgen
+on:
+ push:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ pull_request:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ merge_group:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
+
+jobs:
+ make:
+ strategy:
+ matrix:
+ include:
+ - task: mjit-bindgen
+ fail-fast: false
+ runs-on: ubuntu-22.04
+ if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
+ steps:
+ - run: mkdir build
+ working-directory:
+ - name: Set ENV
+ run: |
+ echo "GNUMAKEFLAGS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV
+ - name: Install libraries
+ run: |
+ set -x
+ sudo apt-get update -q || :
+ sudo apt-get install --no-install-recommends -q -y \
+ build-essential \
+ libssl-dev libyaml-dev libreadline6-dev \
+ zlib1g-dev libncurses5-dev libffi-dev \
+ libclang1-14 \
+ bison autoconf
+ sudo apt-get install -q -y pkg-config || :
+ - name: Set up Ruby
+ uses: ruby/setup-ruby@13e7a03dc3ac6c3798f4570bfead2aed4d96abfb # v1.244.0
+ with:
+ ruby-version: '3.1'
+ - name: git config
+ run: |
+ git config --global advice.detachedHead 0
+ git config --global init.defaultBranch garbage
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ with:
+ path: src
+ - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
+ with:
+ path: src/.downloaded-cache
+ key: downloaded-cache
+ - name: Fixed world writable dirs
+ run: |
+ chmod -v go-w $HOME $HOME/.config
+ sudo chmod -R go-w /usr/share
+ sudo bash -c 'IFS=:; for d in '"$PATH"'; do chmod -v go-w $d; done' || :
+ - run: ./autogen.sh
+ working-directory: src
+ - name: Run configure
+ run: ../src/configure -C --disable-install-doc --prefix=$(pwd)/install --enable-yjit=dev_nodebug
+ - run: make incs
+ - run: make
+ - run: make install
+ - run: make ${{ matrix.task }}
+ - run: git diff --exit-code
+ working-directory: src
+ - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1
+ with:
+ payload: |
+ {
+ "ci": "GitHub Actions",
+ "env": "${{ matrix.os }} / ${{ matrix.test_task }}${{ matrix.configure }}",
+ "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
+ "commit": "${{ github.sha }}",
+ "branch": "${{ github.ref_name }}"
+ }
+ env:
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() && github.event_name == 'push' }}
+
+defaults:
+ run:
+ working-directory: build
diff --git a/.github/workflows/mjit.yml b/.github/workflows/mjit.yml
index 75e5b1088c..6f7181489a 100644
--- a/.github/workflows/mjit.yml
+++ b/.github/workflows/mjit.yml
@@ -3,30 +3,47 @@ on:
push:
paths-ignore:
- 'doc/**'
+ - '**/man'
- '**.md'
- '**.rdoc'
+ - '**/.document'
pull_request:
paths-ignore:
- 'doc/**'
+ - '**/man'
- '**.md'
- '**.rdoc'
+ - '**/.document'
+ - '**.[1-8]'
+ - '**.ronn'
+ merge_group:
+ paths-ignore:
+ - 'doc/**'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '**.[1-8]'
+ - '**.ronn'
concurrency:
group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+permissions:
+ contents: read
+
jobs:
make:
strategy:
matrix:
- test_task: [ "check" ] # to make job names consistent
- jit_opts: [ "--mjit", "--mjit-wait" ]
+ test_task: [check] # to make job names consistent
+ mjit_opts: [--mjit-wait]
fail-fast: false
runs-on: ubuntu-latest
- if: ${{ !startsWith(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
+ if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
env:
TESTOPTS: '-q --tty=no'
- RUN_OPTS: '--disable-gems ${{ matrix.jit_opts }} --mjit-debug=-ggdb3'
+ RUN_OPTS: '--disable-gems ${{ matrix.mjit_opts }} --mjit-debug=-ggdb3'
GITPULLOPTIONS: --no-tags origin ${{github.ref}}
steps:
- run: mkdir build
@@ -40,10 +57,10 @@ jobs:
run: |
git config --global advice.detachedHead 0
git config --global init.defaultBranch garbage
- - uses: actions/checkout@v2
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
path: src
- - uses: actions/cache@v2
+ - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: src/.downloaded-cache
key: downloaded-cache
@@ -62,31 +79,30 @@ jobs:
- run: make incs
- run: make
- run: sudo make -s install
- - run: sudo apt-get install gdb # used by test / test-all failure
- name: Run test
run: |
- ulimit -c unlimited
+ unset GNUMAKEFLAGS
make -s test RUN_OPTS="$RUN_OPTS"
timeout-minutes: 60
- - name: Run test-all
- run: |
- ulimit -c unlimited
- make -s test-all RUN_OPTS="$RUN_OPTS"
- timeout-minutes: 60
+ # - name: Run test-all
+ # run: |
+ # ulimit -c unlimited
+ # make -s test-all RUN_OPTS="$RUN_OPTS"
+ # timeout-minutes: 60
- name: Run test-spec
run: |
- ulimit -c unlimited
+ unset GNUMAKEFLAGS
make -s test-spec RUN_OPTS="$RUN_OPTS"
timeout-minutes: 60
- - uses: k0kubun/action-slack@v2.0.0
+ - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1
with:
payload: |
{
"ci": "GitHub Actions",
- "env": "${{ github.workflow }} / ${{ matrix.test_task }} ${{ matrix.jit_opts }}",
+ "env": "${{ github.workflow }} / ${{ matrix.test_task }} ${{ matrix.mjit_opts }}",
"url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
"commit": "${{ github.sha }}",
- "branch": "${{ github.ref }}".split('/').reverse()[0]
+ "branch": "${{ github.ref_name }}"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
new file mode 100644
index 0000000000..5d4474d978
--- /dev/null
+++ b/.github/workflows/publish.yml
@@ -0,0 +1,18 @@
+name: Start release workflow
+on:
+ push:
+ tags:
+ - '*'
+
+jobs:
+ notify:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Build release package
+ run: |
+ curl -L -X POST \
+ -H "Authorization: Bearer ${{ secrets.MATZBOT_GITHUB_WORKFLOW_TOKEN }}" \
+ -H "Accept: application/vnd.github+json" \
+ -H "X-GitHub-Api-Version: 2022-11-28" \
+ https://api.github.com/repos/ruby/actions/dispatches \
+ -d '{"event_type": "${{ github.ref }}"}'
diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml
new file mode 100644
index 0000000000..c12a95362d
--- /dev/null
+++ b/.github/workflows/scorecards.yml
@@ -0,0 +1,72 @@
+# This workflow uses actions that are not certified by GitHub. They are provided
+# by a third-party and are governed by separate terms of service, privacy
+# policy, and support documentation.
+
+name: Scorecards supply-chain security
+on:
+ # For Branch-Protection check. Only the default branch is supported. See
+ # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection
+ branch_protection_rule:
+ # To guarantee Maintained check is occasionally updated. See
+ # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained
+ schedule:
+ - cron: '22 4 * * 2'
+ push:
+ branches: [ "master" ]
+
+# Declare default permissions as read only.
+permissions: read-all
+
+jobs:
+ analysis:
+ name: Scorecards analysis
+ runs-on: ubuntu-latest
+ permissions:
+ # Needed to upload the results to code-scanning dashboard.
+ security-events: write
+ # Needed to publish results and get a badge (see publish_results below).
+ id-token: write
+ # Uncomment the permissions below if installing in a private repository.
+ # contents: read
+ # actions: read
+
+ steps:
+ - name: "Checkout code"
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ with:
+ persist-credentials: false
+
+ - name: "Run analysis"
+ uses: ossf/scorecard-action@ea651e62978af7915d09fe2e282747c798bf2dab # v2.4.1
+ with:
+ results_file: results.sarif
+ results_format: sarif
+ # (Optional) Read-only PAT token. Uncomment the `repo_token` line below if:
+ # - you want to enable the Branch-Protection check on a *public* repository, or
+ # - you are installing Scorecards on a *private* repository
+ # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat.
+ repo_token: ${{ secrets.SCORECARD_READ_TOKEN }}
+
+ # Public repositories:
+ # - Publish results to OpenSSF REST API for easy access by consumers
+ # - Allows the repository to include the Scorecard badge.
+ # - See https://github.com/ossf/scorecard-action#publishing-results.
+ # For private repositories:
+ # - `publish_results` will always be set to `false`, regardless
+ # of the value entered here.
+ publish_results: true
+
+ # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
+ # format to the repository Actions tab.
+ - name: "Upload artifact"
+ uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ with:
+ name: SARIF file
+ path: results.sarif
+ retention-days: 5
+
+ # Upload the results to GitHub's code scanning dashboard.
+ - name: "Upload to code-scanning"
+ uses: github/codeql-action/upload-sarif@959cbb7472c4d4ad70cdfe6f4976053fe48ab394 # v2.1.27
+ with:
+ sarif_file: results.sarif
diff --git a/.github/workflows/spec_guards.yml b/.github/workflows/spec_guards.yml
index 3f829650d5..4521195a2b 100644
--- a/.github/workflows/spec_guards.yml
+++ b/.github/workflows/spec_guards.yml
@@ -2,43 +2,61 @@ name: Rubyspec Version Guards Check
on:
push:
- paths-ignore:
- - 'doc/**'
- - '**.md'
- - '**.rdoc'
+ paths:
+ - 'spec/**'
+ - '!spec/*.md'
pull_request:
- paths-ignore:
- - 'doc/**'
- - '**.md'
- - '**.rdoc'
+ paths:
+ - 'spec/**'
+ - '!spec/*.md'
+ merge_group:
concurrency:
group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+permissions:
+ contents: read
+
jobs:
rubyspec:
name: Rubyspec
- runs-on: ubuntu-20.04
- if: ${{ !startsWith(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
+
+ runs-on: ubuntu-22.04
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.head_commit.message, 'Document')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.title, 'Document')
+ || contains(github.event.pull_request.labels.*.name, 'Document')
+ || (github.event_name == 'push' && github.actor == 'dependabot[bot]')
+ )}}
+
strategy:
matrix:
# Specs from ruby/spec should still run on all supported Ruby versions.
# This also ensures the needed ruby_version_is guards are there, see spec/README.md.
ruby:
- - ruby-2.7
- - ruby-3.0
+ - ruby-3.1
+ - ruby-3.2
steps:
- - uses: actions/checkout@v2
- - uses: ruby/setup-ruby@v1
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+
+ - uses: ruby/setup-ruby@13e7a03dc3ac6c3798f4570bfead2aed4d96abfb # v1.244.0
with:
ruby-version: ${{ matrix.ruby }}
bundler: none
+
- run: gem install webrick
+
- run: ruby ../mspec/bin/mspec
working-directory: spec/ruby
- - uses: k0kubun/action-slack@v2.0.0
+ env:
+ CHECK_LEAKS: true
+ - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1
with:
payload: |
{
@@ -46,8 +64,8 @@ jobs:
"env": "${{ github.workflow }} / rubyspec @ ${{ matrix.ruby }}",
"url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
"commit": "${{ github.sha }}",
- "branch": "${{ github.ref }}".split('/').reverse()[0]
+ "branch": "${{ github.ref_name }}"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
- if: ${{ failure() && github.event_name == 'push' }}
+ if: ${{ failure() }}
diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml
index ff79dad880..4fbca1170e 100644
--- a/.github/workflows/ubuntu.yml
+++ b/.github/workflows/ubuntu.yml
@@ -3,54 +3,69 @@ on:
push:
paths-ignore:
- 'doc/**'
+ - '**/man'
- '**.md'
- '**.rdoc'
+ - '**/.document'
pull_request:
paths-ignore:
- 'doc/**'
+ - '**/man'
- '**.md'
- '**.rdoc'
+ - '**/.document'
+ merge_group:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
concurrency:
group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+permissions:
+ contents: read
+
jobs:
make:
strategy:
matrix:
- test_task: ["check", "test-bundler-parallel", "test-bundled-gems"]
- os:
- - ubuntu-20.04
-# - ubuntu-18.04
- configure: ["", "cppflags=-DRUBY_DEBUG"]
+ # main variables included in the job name
+ test_task: [check]
+ configure: [cppflags=-DRUBY_DEBUG] # default to use more assertions
+ arch: ['']
+ # specify all jobs with `include` to avoid testing duplicated things
include:
- - test_task: "check"
- os: ubuntu-20.04
- configure: "--host=i686-$OSTYPE"
- - test_task: "test-all TESTS=--repeat-count=2"
- os: ubuntu-20.04
- configure: ""
+ - test_task: check
+ - test_task: check
+ arch: i686
+ configure: '' # test without -DRUBY_DEBUG as well
+ - test_task: check
+ configure: "--enable-shared --enable-load-relative"
+ - test_task: test-all TESTS=--repeat-count=2
+ - test_task: test-bundler-parallel
+ - test_task: test-bundled-gems
fail-fast: false
env:
GITPULLOPTIONS: --no-tags origin ${{github.ref}}
RUBY_DEBUG: ci
- runs-on: ${{ matrix.os }}
- if: ${{ !startsWith(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
+ SETARCH: ${{ matrix.arch && format('setarch {0}', matrix.arch) }}
+ runs-on: ubuntu-22.04
+ if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
steps:
- run: mkdir build
working-directory:
- name: Set ENV
- env:
- configure: ${{matrix.configure}}
run: |
echo "GNUMAKEFLAGS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV
- arch=`echo " $configure" | sed '/.* --host=/!d;s///;s/[- ].*//'`
- echo "SETARCH=${arch:+setarch $arch}" >> $GITHUB_ENV
- name: Install libraries
+ env:
+ arch: ${{matrix.arch}}
run: |
set -x
- arch="${SETARCH##* }"
arch=${arch:+:${arch/i[3-6]86/i386}}
${arch:+sudo dpkg --add-architecture ${arch#:}}
sudo apt-get update -q || :
@@ -64,10 +79,10 @@ jobs:
run: |
git config --global advice.detachedHead 0
git config --global init.defaultBranch garbage
- - uses: actions/checkout@v2
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
path: src
- - uses: actions/cache@v2
+ - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: src/.downloaded-cache
key: downloaded-cache
@@ -83,42 +98,44 @@ jobs:
arch: ${{matrix.arch}}
run: >-
$SETARCH ../src/configure -C --disable-install-doc ${{ matrix.configure }}
- ${arch:+--target=$arch-$OSTYPE}
+ ${arch:+--target=$arch-$OSTYPE --host=$arch-$OSTYPE}
- run: $SETARCH make incs
+ - run: $SETARCH make prepare-gems
+ if: ${{ matrix.test_task == 'test-bundled-gems' }}
- run: $SETARCH make
- run: $SETARCH make leaked-globals
if: ${{ matrix.test_task == 'check' }}
- - run: $SETARCH make prepare-gems
- if: ${{ matrix.test_task == 'check' }}
- name: Create dummy files in build dir
run: |
$SETARCH ./miniruby -e '(("a".."z").to_a+("A".."Z").to_a+("0".."9").to_a+%w[foo bar test zzz]).each{|basename|File.write("#{basename}.rb", "raise %(do not load #{basename}.rb)")}'
if: ${{ matrix.test_task == 'check' }}
- name: make ${{ matrix.test_task }}
run: |
- $SETARCH make -s ${{ matrix.test_task }} ${TESTS:+TESTS=`echo "$TESTS" | sed 's| |$/ -n!/|g;s|^|-n!/|;s|$|$$/|'`}
+ $SETARCH make -s ${{ matrix.test_task }} ${TESTS:+TESTS=`echo "$TESTS" | sed 's| |$$/ -n!/|g;s|^|-n!/|;s|$|$$/|'`}
timeout-minutes: 40
env:
RUBY_TESTOPTS: "-q --tty=no"
TESTS: ${{ matrix.test_task == 'check' && matrix.skipped_tests || '' }}
TEST_BUNDLED_GEMS_ALLOW_FAILURES: ""
+ PRECHECK_BUNDLED_GEMS: "no"
- name: make skipped tests
run: |
- $SETARCH make -s test-all TESTS=`echo "$TESTS" | sed 's| |$/ -n/|g;s|^|-n/|;s|$|$$/|'`
+ $SETARCH make -s test-all TESTS=`echo "$TESTS" | sed 's| |$$/ -n/|g;s|^|-n/|;s|$|$$/|'`
env:
GNUMAKEFLAGS: ""
RUBY_TESTOPTS: "-v --tty=no"
TESTS: ${{ matrix.skipped_tests }}
if: ${{ matrix.test_task == 'check' && matrix.skipped_tests != '' }}
- - uses: k0kubun/action-slack@v2.0.0
+ continue-on-error: ${{ matrix.continue-on-skipped_tests || false }}
+ - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1
with:
payload: |
{
"ci": "GitHub Actions",
- "env": "${{ matrix.os }} / ${{ matrix.test_task }}${{ matrix.configure }}",
+ "env": "${{ github.workflow }} / ${{ matrix.test_task }} ${{ matrix.configure }}${{ matrix.arch }}",
"url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
"commit": "${{ github.sha }}",
- "branch": "${{ github.ref }}".split('/').reverse()[0]
+ "branch": "${{ github.ref_name }}"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
diff --git a/.github/workflows/wasm.yml b/.github/workflows/wasm.yml
new file mode 100644
index 0000000000..27920b5821
--- /dev/null
+++ b/.github/workflows/wasm.yml
@@ -0,0 +1,146 @@
+name: WebAssembly
+on:
+ push:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ pull_request:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ merge_group:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions: # added using https://github.com/step-security/secure-workflows
+ contents: read
+
+jobs:
+ make:
+ strategy:
+ matrix:
+ entry:
+# # wasmtime can't compile non-optimized Asyncified binary due to locals explosion
+# - { name: O0-debuginfo, optflags: "-O0", debugflags: "-g", wasmoptflags: "-O1" }
+# - { name: O1, optflags: "-O1", debugflags: "" , wasmoptflags: "-O1" }
+ - { name: O2, optflags: "-O2", debugflags: "" , wasmoptflags: "-O2" }
+# - { name: O3, optflags: "-O3", debugflags: "" , wasmoptflags: "-O3" }
+# # -O4 is equivalent to -O3 in clang, but it's different in wasm-opt
+# - { name: O4, optflags: "-O3", debugflags: "" , wasmoptflags: "-O4" }
+# - { name: Oz, optflags: "-Oz", debugflags: "" , wasmoptflags: "-Oz" }
+ fail-fast: false
+ env:
+ RUBY_TESTOPTS: '-q --tty=no'
+ GITPULLOPTIONS: --no-tags origin ${{github.ref}}
+ WASI_SDK_VERSION_MAJOR: 14
+ WASI_SDK_VERSION_MINOR: 0
+ BINARYEN_VERSION: 109
+ WASMTIME_VERSION: v0.33.0
+ runs-on: ubuntu-22.04
+ if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
+ steps:
+ - run: mkdir build
+ working-directory:
+ - name: git config
+ run: |
+ git config --global advice.detachedHead 0
+ git config --global init.defaultBranch garbage
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ with:
+ path: src
+ - name: Install libraries
+ run: |
+ set -ex
+ sudo apt-get update -q || :
+ sudo apt-get install --no-install-recommends -q -y ruby bison make autoconf git wget
+
+ wasi_sdk_deb="wasi-sdk_${WASI_SDK_VERSION_MAJOR}.${WASI_SDK_VERSION_MINOR}_amd64.deb"
+ wget "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_VERSION_MAJOR}/${wasi_sdk_deb}"
+ sudo dpkg -i "$wasi_sdk_deb"
+ rm -f "$wasi_sdk_deb"
+
+ mkdir build-sdk
+ pushd build-sdk
+
+ wasmtime_url="https://github.com/bytecodealliance/wasmtime/releases/download/${WASMTIME_VERSION}/wasmtime-${WASMTIME_VERSION}-x86_64-linux.tar.xz"
+ wget -O - "$wasmtime_url" | tar xJf -
+ sudo ln -fs "$PWD/wasmtime-${WASMTIME_VERSION}-x86_64-linux/wasmtime" /usr/local/bin/wasmtime
+
+ binaryen_tarball="binaryen-version_${BINARYEN_VERSION}-x86_64-linux.tar.gz"
+ binaryen_url="https://github.com/WebAssembly/binaryen/releases/download/version_${BINARYEN_VERSION}/${binaryen_tarball}"
+ wget -O - "$binaryen_url" | tar xfz -
+ sudo ln -fs "$PWD/binaryen-version_${BINARYEN_VERSION}/bin/wasm-opt" /usr/local/bin/wasm-opt
+ working-directory: src
+ - name: Set ENV
+ run: |
+ echo "MAKEFLAGS=-j$((1 + $(sysctl -n hw.activecpu)))" >> $GITHUB_ENV
+ echo "WASI_SDK_PATH=/opt/wasi-sdk" >> $GITHUB_ENV
+ - run: ./autogen.sh
+ working-directory: src
+
+ - uses: ruby/setup-ruby@13e7a03dc3ac6c3798f4570bfead2aed4d96abfb # v1.244.0
+ with:
+ ruby-version: '3.0'
+ bundler: none
+
+ - name: Download config.guess with wasi version
+ run: |
+ rm tool/config.guess tool/config.sub
+ ruby tool/downloader.rb -d tool -e gnu config.guess config.sub
+ working-directory: src
+
+ - name: Run configure
+ run: |
+ ../src/configure \
+ --host wasm32-unknown-wasi \
+ --with-static-linked-ext \
+ LDFLAGS=" \
+ -Xlinker --stack-first \
+ -Xlinker -z -Xlinker stack-size=16777216 \
+ " \
+ optflags="${{ matrix.entry.optflags }}" \
+ debugflags="${{ matrix.entry.debugflags }}" \
+ wasmoptflags="${{ matrix.entry.wasmoptflags }} ${{ matrix.entry.debugflags }}"
+
+ # miniruby may not be built when cross-compling
+ - run: make mini ruby
+ - name: Run basictest
+ run: wasmtime run ./../build/miniruby --mapdir /::./ -- basictest/test.rb
+ working-directory: src
+ - name: Run bootstraptest (no thread)
+ run: |
+ NO_THREAD_TESTS="$(grep -L Thread -R ./bootstraptest | awk -F/ '{ print $NF }' | uniq | sed -n 's/test_\(.*\).rb/\1/p' | paste -s -d, -)"
+ ruby ./bootstraptest/runner.rb --ruby="$(which wasmtime) run $PWD/../build/ruby --mapdir /::./ -- " --verbose "--sets=$NO_THREAD_TESTS"
+ working-directory: src
+
+ - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1
+ with:
+ payload: |
+ {
+ "ci": "GitHub Actions",
+ "env": "${{ github.workflow }} / ${{ matrix.name }}",
+ "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
+ "commit": "${{ github.sha }}",
+ "branch": "${{ github.ref_name }}"
+ }
+ env:
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() && github.event_name == 'push' }}
+
+defaults:
+ run:
+ working-directory: build
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index 574bfbf474..c2bd4881c2 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -3,119 +3,133 @@ on:
push:
paths-ignore:
- 'doc/**'
+ - '**/man'
- '**.md'
- '**.rdoc'
+ - '**/.document'
pull_request:
paths-ignore:
- 'doc/**'
+ - '**/man'
- '**.md'
- '**.rdoc'
+ - '**/.document'
+ merge_group:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
concurrency:
group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+permissions:
+ contents: read
+
jobs:
make:
strategy:
matrix:
include:
- - vs: 2019
- os: windows-2019
- vcvars: '"C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat"'
- # - vs: 2022
- # os: windows-2022
- # vcvars: '"C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"'
+ - vs: 2022
+ vcvers: -vcvars_ver=14.2
fail-fast: false
- runs-on: ${{ matrix.os }}
- if: ${{ !startsWith(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
+ runs-on: windows-${{ matrix.vs }}
+ if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
name: VisualStudio ${{ matrix.vs }}
env:
GITPULLOPTIONS: --no-tags origin ${{github.ref}}
- VCVARS: ${{ matrix.vcvars }}
PATCH: C:\msys64\usr\bin\patch.exe
+ OS_VER: windows-${{ matrix.vs }}
steps:
- run: md build
working-directory:
- - uses: msys2/setup-msys2@v2
+ - uses: msys2/setup-msys2@61f9e5e925871ba6c9e3e8da24ede83ea27fa91f # v2.27.0
id: setup-msys2
with:
update: true
- install: >-
- patch
- if: ${{ matrix.os != 'windows-2019' }}
+ install: bison patch
- name: patch path
shell: msys2 {0}
run: echo PATCH=$(cygpath -wa $(command -v patch)) >> $GITHUB_ENV
if: ${{ steps.setup-msys2.outcome == 'success' }}
- - uses: actions/cache@v2
+ - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
- path: C:\vcpkg\downloads
- key: ${{ runner.os }}-vcpkg-download-${{ matrix.os }}-${{ github.sha }}
+ path: C:\vcpkg\installed
+ key: ${{ runner.os }}-vcpkg-installed-windows-${{ matrix.vs }}-${{ github.sha }}
restore-keys: |
- ${{ runner.os }}-vcpkg-download-${{ matrix.os }}-
- ${{ runner.os }}-vcpkg-download-
+ ${{ runner.os }}-vcpkg-installed-windows-${{ matrix.vs }}-
+ ${{ runner.os }}-vcpkg-installed-windows-
- name: Install libraries with vcpkg
run: |
- vcpkg --triplet x64-windows install readline zlib
- - uses: actions/cache@v2
- with:
- path: C:\Users\runneradmin\AppData\Local\Temp\chocolatey
- key: ${{ runner.os }}-chocolatey-${{ matrix.os }}-${{ github.sha }}
- restore-keys: |
- ${{ runner.os }}-chocolatey-${{ matrix.os }}-
- ${{ runner.os }}-chocolatey-
- - name: Install libraries with chocolatey
- run: |
- # Using Choco-Install for retries, but it doesn't detect failures properly
- # if you pass multiple package names in a single command.
- Choco-Install -PackageName openssl
- Choco-Install -PackageName winflexbison3
- shell: pwsh
+ iex "& {$(irm get.scoop.sh)} -RunAsAdmin"
+ Join-Path (Resolve-Path ~).Path "scoop\shims" >> $Env:GITHUB_PATH
+ scoop install cmake@3.31.6
+ vcpkg --triplet x64-windows install libffi libyaml openssl readline zlib
+ shell:
+ pwsh
- name: git config
run: |
git config --global core.autocrlf false
git config --global core.eol lf
git config --global advice.detachedHead 0
git config --global init.defaultBranch garbage
- - uses: actions/checkout@v2
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
path: src
- - uses: actions/cache@v2
+ - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: src/.downloaded-cache
key: downloaded-cache
- name: setup env
# %TEMP% is inconsistent with %TMP% and test-all expects they are consistent.
# https://github.com/actions/virtual-environments/issues/712#issuecomment-613004302
+ # msys2/setup-msys2 installs MSYS2 to D:/a/_temp/msys64/usr/bin
run: |
+ set Path=D:/a/_temp/msys64/usr/bin;%Path%
+ if not "%VCVARS%" == "" goto :vcset
+ set VCVARS="C:\Program Files (x86)\Microsoft Visual Studio\${{ matrix.vs }}\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
+ if not exist %VCVARS% set VCVARS="C:\Program Files\Microsoft Visual Studio\${{ matrix.vs }}\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
+ :vcset
set | C:\msys64\usr\bin\sort > old.env
- call %VCVARS%
+ call %VCVARS% ${{ matrix.vcvers || ''}}
set TMP=%USERPROFILE%\AppData\Local\Temp
set TEMP=%USERPROFILE%\AppData\Local\Temp
set /a TEST_JOBS=(15 * %NUMBER_OF_PROCESSORS% / 10) > nul
set | C:\msys64\usr\bin\sort > new.env
C:\msys64\usr\bin\comm -13 old.env new.env >> %GITHUB_ENV%
del *.env
- - name: Configure
+ - name: compiler version
+ run: cl
+ - name: link libraries
run: |
- ../src/win32/configure.bat --disable-install-doc --enable-bundled-libffi --with-opt-dir=C:/vcpkg/installed/x64-windows --with-openssl-dir="C:/Program Files/OpenSSL-Win64"
+ for %%I in (C:\vcpkg\installed\x64-windows\bin\*.dll) do (
+ if not %%~nI == readline mklink %%~nxI %%I
+ )
+ for %%I in (libcrypto-1_1-x64 libssl-1_1-x64) do (
+ ren c:\Windows\System32\%%I.dll %%I.dll_
+ )
+ - name: Configure
+ run: >-
+ ../src/win32/configure.bat --disable-install-doc
+ --with-opt-dir=C:/vcpkg/installed/x64-windows
- run: nmake incs
- run: nmake extract-extlibs
- run: nmake
env:
- YACC: win_bison
+ YACC: bison.exe
- run: nmake test
timeout-minutes: 5
+ - run: nmake test-spec
+ timeout-minutes: 10
- run: nmake test-all
env:
RUBY_TESTOPTS: -j${{env.TEST_JOBS}} --job-status=normal
timeout-minutes: 60
- continue-on-error: ${{ matrix.continue-on-error || false }}
- - run: nmake test-spec
- timeout-minutes: 10
- continue-on-error: ${{ matrix.continue-on-error || false }}
- - uses: k0kubun/action-slack@v2.0.0
+ - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1
with:
payload: |
{
@@ -123,7 +137,7 @@ jobs:
"env": "VS${{ matrix.vs }} / ${{ matrix.test_task || 'check' }}",
"url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
"commit": "${{ github.sha }}",
- "branch": "${{ github.ref }}".split('/').reverse()[0]
+ "branch": "${{ github.ref_name }}"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
diff --git a/.github/workflows/yjit-ubuntu.yml b/.github/workflows/yjit-ubuntu.yml
index c479b8a624..0b7b9046e9 100644
--- a/.github/workflows/yjit-ubuntu.yml
+++ b/.github/workflows/yjit-ubuntu.yml
@@ -3,47 +3,90 @@ on:
push:
paths-ignore:
- 'doc/**'
+ - '**/man'
- '**.md'
- '**.rdoc'
+ - '**/.document'
pull_request:
paths-ignore:
- 'doc/**'
+ - '**/man'
- '**.md'
- '**.rdoc'
+ - '**/.document'
+ merge_group:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
concurrency:
group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+permissions:
+ contents: read
+
jobs:
+ cargo:
+ name: Rust cargo test
+ # GitHub Action's image seems to already contain a Rust 1.58.0.
+ runs-on: ubuntu-22.04
+ steps:
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ # For now we can't run cargo test --offline because it complains about the
+ # capstone dependency, even though the dependency is optional
+ #- run: cargo test --offline
+ - run: RUST_BACKTRACE=1 cargo test
+ working-directory: yjit
+ # Also compile and test with all features enabled
+ - run: RUST_BACKTRACE=1 cargo test --all-features
+ working-directory: yjit
+ # Check that we can build in release mode too
+ - run: cargo build --release
+ working-directory: yjit
make:
strategy:
+ fail-fast: false
matrix:
- test_task: ["check"] # "test-bundler-parallel",
- os:
- - ubuntu-20.04
-# - ubuntu-18.04
- yjit_opts: [
- "--yjit",
- "--yjit --yjit-call-threshold=1",
- ]
- configure: ["", "cppflags=-DRUBY_DEBUG"]
include:
+ - test_task: 'yjit-bindgen'
+ hint: 'To fix: use patch in logs'
+ configure: '--with-gcc=clang-14 --enable-yjit=dev'
+ libclang_path: '/usr/lib/llvm-14/lib/libclang.so.1'
+
+ - test_task: "check"
+ # YJIT should be automatically built in release mode on x86-64 Linux with rustc present
+ #configure: "--enable-yjit RUSTC='rustc +1.58.0'"
+ configure: "RUSTC='rustc +1.58.0'"
+ rust_version: "1.58.0"
+
+ - test_task: "check"
+ configure: "--enable-yjit=dev"
+
+ - test_task: "check"
+ configure: "--enable-yjit=dev"
+ yjit_opts: "--yjit-call-threshold=1 --yjit-verify-ctx"
+
- test_task: "test-all TESTS=--repeat-count=2"
- os: ubuntu-20.04
- configure: ""
- yjit_enable_env: RUBY_YJIT_ENABLE
+ configure: "--enable-yjit=dev"
+
- test_task: "test-bundled-gems"
- os: ubuntu-20.04
- configure: "cppflags=-DRUBY_DEBUG"
- yjit_enable_env: RUBY_YJIT_ENABLE
- fail-fast: false
+ configure: "--enable-yjit=dev"
+
+ - test_task: "yjit-bench"
+ configure: "--enable-yjit=dev"
+ yjit_bench_opts: "--yjit-stats"
env:
GITPULLOPTIONS: --no-tags origin ${{github.ref}}
RUN_OPTS: ${{ matrix.yjit_opts }}
+ YJIT_BENCH_OPTS: ${{ matrix.yjit_bench_opts }}
RUBY_DEBUG: ci
- runs-on: ${{ matrix.os }}
- if: ${{ !startsWith(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
+ BUNDLE_JOBS: 8 # for yjit-bench
+ runs-on: ubuntu-22.04
+ if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
steps:
- run: mkdir build
working-directory:
@@ -52,14 +95,17 @@ jobs:
set -x
sudo apt-get update -q || :
sudo apt-get install --no-install-recommends -q -y build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev bison autoconf ruby
+ - name: Install Rust
+ if: ${{ matrix.rust_version }}
+ run: rustup install ${{ matrix.rust_version }} --profile minimal
- name: git config
run: |
git config --global advice.detachedHead 0
git config --global init.defaultBranch garbage
- - uses: actions/checkout@v2
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
path: src
- - uses: actions/cache@v2
+ - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: src/.downloaded-cache
key: downloaded-cache
@@ -74,12 +120,12 @@ jobs:
- run: ./autogen.sh
working-directory: src
- name: Run configure
- run: ../src/configure -C --disable-install-doc ${{ matrix.configure }}
+ run: ../src/configure -C --disable-install-doc --prefix=$(pwd)/install ${{ matrix.configure }}
- run: make incs
- - run: make
- - run: make leaked-globals
- if: ${{ matrix.test_task == 'check' }}
- run: make prepare-gems
+ if: ${{ matrix.test_task == 'test-bundled-gems' }}
+ - run: make -j
+ - run: make leaked-globals
if: ${{ matrix.test_task == 'check' }}
- name: Create dummy files in build dir
run: |
@@ -87,21 +133,33 @@ jobs:
if: ${{ matrix.test_task == 'check' }}
- name: Enable YJIT through ENV
run: echo "RUBY_YJIT_ENABLE=1" >> $GITHUB_ENV
- if: ${{ matrix.yjit_enable_env }}
- - run: make -s ${{ matrix.test_task }} RUN_OPTS="$RUN_OPTS"
+ # Check that the binary was built with YJIT
+ - name: Check YJIT enabled
+ run: ./miniruby --yjit -v | grep "+YJIT"
+ - name: make ${{ matrix.test_task }}
+ run: make -s -j ${{ matrix.test_task }} RUN_OPTS="$RUN_OPTS" YJIT_BENCH_OPTS="$YJIT_BENCH_OPTS"
timeout-minutes: 60
env:
RUBY_TESTOPTS: "-q --tty=no"
TEST_BUNDLED_GEMS_ALLOW_FAILURES: ""
- - uses: k0kubun/action-slack@v2.0.0
+ PRECHECK_BUNDLED_GEMS: "no"
+ LIBCLANG_PATH: ${{ matrix.libclang_path }}
+ continue-on-error: ${{ matrix.test_task == 'yjit-bench' }}
+ - name: Show ${{ github.event.pull_request.base.ref }} GitHub URL for yjit-bench comparison
+ run: echo "https://github.com/${BASE_REPO}/commit/${BASE_SHA}"
+ env:
+ BASE_REPO: ${{ github.event.pull_request.base.repo.full_name }}
+ BASE_SHA: ${{ github.event.pull_request.base.sha }}
+ if: ${{ matrix.test_task == 'yjit-bench' && startsWith(github.event_name, 'pull') }}
+ - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1
with:
payload: |
{
"ci": "GitHub Actions",
- "env": "${{ matrix.os }} / ${{ matrix.test_task }}${{ matrix.configure }}",
+ "env": "${{ github.workflow }} / ${{ matrix.test_task }} ${{ matrix.configure }}",
"url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
"commit": "${{ github.sha }}",
- "branch": "${{ github.ref }}".split('/').reverse()[0]
+ "branch": "${{ github.ref_name }}"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
diff --git a/.github/workflows/yjit_asm_tests.yml b/.github/workflows/yjit_asm_tests.yml
deleted file mode 100644
index 8a9052dd41..0000000000
--- a/.github/workflows/yjit_asm_tests.yml
+++ /dev/null
@@ -1,38 +0,0 @@
-name: YJIT x86 assembler tests
-
-on:
- push:
- paths-ignore:
- - 'doc/**'
- - '**.md'
- - '**.rdoc'
- pull_request:
- paths-ignore:
- - 'doc/**'
- - '**.md'
- - '**.rdoc'
-
-concurrency:
- group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
- cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
-
-jobs:
- test:
- runs-on: ubuntu-latest
- if: ${{ !startsWith(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
- steps:
- - name: Install dependencies
- run: |
- set -x
- sudo apt-get update -q || :
- sudo apt-get install --no-install-recommends -q -y build-essential
- - name: git config
- run: |
- git config --global advice.detachedHead 0
- git config --global init.defaultBranch garbage
- - uses: actions/checkout@v2
- with:
- path: src
- - name: Run ASM tests
- run: ./misc/test_yjit_asm.sh
- working-directory: src
diff --git a/.gitignore b/.gitignore
index 31bfd787a7..99d32a1825 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,6 +14,7 @@
*.inc
*.log
*.o
+*.o.tmp
*.obj
*.old
*.orig
@@ -25,6 +26,7 @@
*.sav
*.sl
*.so
+*.so.*
*.swp
*.yarb
*~
@@ -127,6 +129,7 @@ lcov*.info
/ruby-runner
/ruby-runner.h
/ruby-man.rd.gz
+/rubyspec_temp
/run.gdb
/sizes.c
/static-ruby
@@ -144,6 +147,8 @@ lcov*.info
/bin/*.exe
/bin/*.dll
+/bin/goruby
+/bin/ruby
# /benchmark/
/benchmark/bm_require.data
@@ -218,6 +223,9 @@ lcov*.info
/lib/ruby/[1-9]*.*
/lib/ruby/vendor_ruby
+# /misc/
+/misc/**/__pycache__
+
# /spec/bundler
/.rspec_status
@@ -229,6 +237,14 @@ lcov*.info
/win32/*.ico
# MJIT
-/rb_mjit_header.h
-/mjit_config.h
/include/ruby-*/*/rb_mjit_min_header-*.h
+/lib/ruby_vm/mjit/instruction.rb
+/mjit_config.h
+/rb_mjit_header.h
+
+# YJIT
+/yjit-bench
+/yjit_exit_locations.dump
+
+# /wasm/
+/wasm/tests/*.wasm
diff --git a/.indent.pro b/.indent.pro
new file mode 100644
index 0000000000..1d61cbcad1
--- /dev/null
+++ b/.indent.pro
@@ -0,0 +1,32 @@
+-bap
+-nbbb
+-nbc
+-br
+-brs
+-nbs
+-ncdb
+-nce
+-cdw
+-cli2
+-cbi2
+-ndj
+-ncs
+-nfc1
+-i4
+-l120
+-lp
+-npcs
+-psl
+-sc
+-sob
+-sbi4
+-nut
+-par
+
+-TID
+-TVALUE
+-Tst_data_t
+-Tst_index_t
+-Tst_table
+-Trb_data_type_t
+-TFILE
diff --git a/.rdoc_options b/.rdoc_options
new file mode 100644
index 0000000000..760507c7a2
--- /dev/null
+++ b/.rdoc_options
@@ -0,0 +1,4 @@
+---
+page_dir: doc
+main_page: README.md
+title: Documentation for Ruby development version
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 0255e9611f..0000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,234 +0,0 @@
-# -*- YAML -*-
-# Copyright (C) 2011 Urabe, Shyouhei. All rights reserved.
-#
-# This file is a part of the programming language Ruby. Permission is hereby
-# granted, to either redistribute or modify this file, provided that the
-# conditions mentioned in the file COPYING are met. Consult the file for
-# details.
-
-# We only manage non-amd64 free pipelines.
-# https://docs.travis-ci.com/user/billing-overview/
-
-language: c
-
-os: linux
-
-if: commit_message !~ /^\[DOC\]/
-
-dist: focal
-
-git:
- quiet: true
-
-cache:
- ccache: true
- directories:
- - $HOME/config_2nd
- - $HOME/.downloaded-cache
-
-env:
- global:
- # The tests skipped in `make test-all`.
- - TEST_ALL_SKIPPED_TESTS=
- # The tests executed separately by `make test-all`.
- - TEST_ALL_SEPARATED_TESTS=
- # Reset timestamps early
- - _=$(touch NEWS && find . -type f -exec touch -r NEWS {} +)
- - CONFIGURE_TTY=no
- - CCACHE_COMPILERCHECK=none
- - CCACHE_NOCOMPRESS=1
- - CCACHE_MAXSIZE=512Mi
- - NPROC="`nproc`"
- # JOBS and SETARCH are overridden when necessary; see below.
- - JOBS=-j$((1+${NPROC}))
- - SETARCH=
- - RUBY_PREFIX=/tmp/ruby-prefix
- - GEMS_FOR_TEST='timezone tzinfo'
- # https://github.com/travis-ci/travis-build/blob/e411371dda21430a60f61b8f3f57943d2fe4d344/lib/travis/build/bash/travis_apt_get_options.bash#L7
- - travis_apt_get_options='--allow-downgrades --allow-remove-essential --allow-change-held-packages'
- - travis_apt_get_options="-yq --no-install-suggests --no-install-recommends $travis_apt_get_options"
- # -O1 is faster than -O3 in our tests.
- - optflags=-O1
- # -g0 disables backtraces when SEGV. Do not set that.
- - debugflags=-ggdb3
-
-.org.ruby-lang.ci.matrix-definitions:
-
- - &gcc-10
- compiler: gcc-10
- before_install:
- - tool/travis_retry.sh sudo bash -c "rm -rf '${TRAVIS_ROOT}/var/lib/apt/lists/'* && exec apt-get update -yq"
- - >-
- tool/travis_retry.sh sudo -E apt-get $travis_apt_get_options install
- ccache
- gcc-10
- g++-10
- libffi-dev
- libgdbm-dev
- libncurses-dev
- libncursesw5-dev
- libreadline-dev
- libssl-dev
- libyaml-dev
- openssl
- zlib1g-dev
-
- # --------
-
- - &arm64-linux
- name: arm64-linux
- arch: arm64
- <<: *gcc-10
-
- - &ppc64le-linux
- name: ppc64le-linux
- arch: ppc64le
- <<: *gcc-10
-
- - &s390x-linux
- name: s390x-linux
- arch: s390x
- <<: *gcc-10
-
- - &arm32-linux
- name: arm32-linux
- arch: arm64
- # https://packages.ubuntu.com/focal/crossbuild-essential-armhf
- compiler: arm-linux-gnueabihf-gcc
- env:
- - SETARCH='setarch linux32 --verbose --32bit'
- # The "TestReadline#test_interrupt_in_other_thread" started failing on arm32
- # from https://www.travis-ci.com/github/ruby/ruby/jobs/529005145
- - TEST_ALL_SKIPPED_TESTS=test_interrupt_in_other_thread
- before_install:
- - sudo dpkg --add-architecture armhf
- - tool/travis_retry.sh sudo bash -c "rm -rf '${TRAVIS_ROOT}/var/lib/apt/lists/'* && exec apt-get update -yq"
- - >-
- tool/travis_retry.sh sudo -E apt-get $travis_apt_get_options install
- ccache
- crossbuild-essential-armhf
- libc6:armhf
- libstdc++-10-dev:armhf
- libffi-dev:armhf
- libgdbm-dev:armhf
- libncurses-dev:armhf
- libncursesw5-dev:armhf
- libreadline-dev:armhf
- libssl-dev:armhf
- linux-libc-dev:armhf
- zlib1g-dev:armhf
-
-matrix:
- include:
- # Build every commit (Allowed Failures):
- - <<: *arm32-linux
- # Comment out as the 2nd arm64 pipeline is unstable.
- # - <<: *arm64-linux
- - <<: *ppc64le-linux
- - <<: *s390x-linux
- allow_failures:
- # We see multiple errors indicating errors on the Travis environment itself in a short while:
- # https://app.travis-ci.com/github/ruby/ruby/jobs/544382885
- # https://app.travis-ci.com/github/ruby/ruby/jobs/544361370
- # It's not a fault of Ruby's arm32 support but just Travis arm32 seems unsable.
- - name: arm32-linux
- # - name: arm64-linux
- # We see "Some worker was crashed." in about 40% of recent ppc64le-linux jobs
- # e.g. https://app.travis-ci.com/github/ruby/ruby/jobs/530959548
- - name: ppc64le-linux
- # - name: s390x-linux
- fast_finish: true
-
-before_script:
- - . tool/ci_functions.sh
- - |-
- if [ -n "${TEST_ALL_SKIPPED_TESTS}" ]; then
- TEST_ALL_OPTS="${TEST_ALL_OPTS} $(ci_to_excluded_test_opts "${TEST_ALL_SKIPPED_TESTS}")"
- if [ -z "${TEST_ALL_SEPARATED_TESTS}" ]; then
- TEST_ALL_SEPARATED_TESTS="${TEST_ALL_SKIPPED_TESTS}"
- fi
- fi
- - |-
- if [ -n "${TEST_ALL_SEPARATED_TESTS}" ]; then
- TEST_ALL_OPTS_SEPARATED="$(ci_to_included_test_opts "${TEST_ALL_SEPARATED_TESTS}")"
- fi
- - echo TEST_ALL_OPTS="${TEST_ALL_OPTS}" TEST_ALL_OPTS_SEPARATED="${TEST_ALL_OPTS_SEPARATED}"
- - rm -fr .ext autom4te.cache
- - |-
- [ -d ~/.downloaded-cache ] ||
- mkdir ~/.downloaded-cache
- - ln -s ~/.downloaded-cache
- - "> config.status"
- - "> .rbconfig.time"
- - sed -f tool/prereq.status template/Makefile.in common.mk > Makefile
- - make -s $JOBS up
- - make -s $JOBS srcs
- - rm -f config.status Makefile rbconfig.rb .rbconfig.time
- - |-
- if [ -d ~/config_2nd ]; then
- cp -pr ~/config_2nd build
- else
- mkdir build
- fi
- - mkdir config_1st config_2nd
- - chmod -R a-w .
- - chmod -R u+w build config_1st config_2nd
- - cd build
- - |-
- case "$CC" in
- gcc*) CC="ccache $CC${GCC_FLAGS:+ }$GCC_FLAGS -fno-diagnostics-color";;
- clang*) CC="ccache $CC${GCC_FLAGS:+ }$GCC_FLAGS -fno-color-diagnostics";;
- esac
- - |-
- [ ! -f config.cache ] ||
- [ "$CC" = "`sed -n s/^ac_cv_prog_CC=//p config.cache`" ] ||
- (set -x; exec rm config.cache)
- - $SETARCH ../configure -C --disable-install-doc --prefix=$RUBY_PREFIX $CONFIG_FLAG
- - cp -pr config.cache config.status .ext/include ../config_1st
- - $SETARCH make reconfig
- - cp -pr config.cache config.status .ext/include ../config_2nd
- - (cd .. && exec diff -ru config_1st config_2nd)
- - chmod u+w ..
- - rm -rf ~/config_2nd
- - mv ../config_2nd ~
- - chmod u-w ..
- - $SETARCH make -s $JOBS
- - make -s install
- - |-
- [ -z "${GEMS_FOR_TEST}" ] ||
- $RUBY_PREFIX/bin/gem install --no-document $GEMS_FOR_TEST
- - echo "raise 'do not load ~/.irbrc in test'" > ~/.irbrc
-
-script:
- - $SETARCH make -s test -o showflags TESTOPTS="${TESTOPTS=$JOBS -q --tty=no}"
- - ../tool/travis_wait.sh $SETARCH make -s test-all -o exts TESTOPTS="$JOBS -q --tty=no ${TEST_ALL_OPTS}" RUBYOPT="-w"
- # Run the failing tests separately returning ok status to check if it works,
- # visualize them.
- - |
- if [ -n "${TEST_ALL_OPTS_SEPARATED}" ]; then
- $SETARCH make -s test-all -o exts TESTOPTS="$JOBS -v --tty=no ${TEST_ALL_OPTS_SEPARATED}" RUBYOPT="-w" || :
- fi
- - $SETARCH make -s test-spec MSPECOPT=-ff # not using `-j` because sometimes `mspec -j` silently dies
- - $SETARCH make -s -o showflags leaked-globals
-
-# We enable Travis on the specific branches or forked repositories here.
-if: (repo = ruby/ruby AND (branch = master OR branch =~ /^ruby_\d_\d$/)) OR repo != ruby/ruby
-
-# We want to be notified when something happens.
-notifications:
- irc:
- channels:
- - "chat.freenode.net#ruby-core"
- on_success: change # [always|never|change] # default: always
- on_failure: always # [always|never|change] # default: always
- template:
- - "%{message} by @%{author}: See %{build_url}"
-
- webhooks:
- urls:
- - secure: mRsoS/UbqDkKkW5p3AEqM27d4SZnV6Gsylo3bm8T/deltQzTsGzZwrm7OIBXZv0UFZdE68XmPlyHfZFLSP2V9QZ7apXMf9/vw0GtcSe1gchtnjpAPF6lYBn7nMCbVPPx9cS0dwL927fjdRM1vj7IKZ2bk4F0lAJ25R25S6teqdk= # ruby-lang slack: ruby/simpler-alerts-bot (travis)
- on_success: never
- on_failure: always
-
- email:
- - jaruga@ruby-lang.org
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 7363c106a2..13df6087ca 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,5 +1 @@
-Please see the [official issue tracker], [doc/contributing.rdoc] and wiki [HowToContribute].
-
-[official issue tracker]: https://bugs.ruby-lang.org
-[doc/contributing.rdoc]: contributing.rdoc
-[HowToContribute]: https://bugs.ruby-lang.org/projects/ruby/wiki/HowToContribute
+See ["Contributing to Ruby"](https://docs.ruby-lang.org/en/master/contributing_md.html), which includes setup and build instructions.
diff --git a/LEGAL b/LEGAL
index 9645728efe..0423d57ac9 100644
--- a/LEGAL
+++ b/LEGAL
@@ -979,7 +979,6 @@ mentioned below.
{MIT License}[rdoc-label:label-MIT+License]
[lib/rubygems/resolver/molinillo]
-[lib/bundler/vendor/molinillo]
molinillo is under the following license.
@@ -988,6 +987,15 @@ mentioned below.
{MIT License}[rdoc-label:label-MIT+License]
+[lib/bundler/vendor/pub_grub]
+
+ pub_grub is under the following license.
+
+ >>>
+ Copyright (c) 2018 John Hawthorn
+
+ {MIT License}[rdoc-label:label-MIT+License]
+
[lib/bundler/vendor/connection_pool]
connection_pool is under the following license.
diff --git a/NEWS.md b/NEWS.md
index ce737b24fe..f6c3c6fc97 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,608 +1,820 @@
-# NEWS for Ruby 3.1.0
+# NEWS for Ruby 3.2.0
This document is a list of user-visible feature changes
-since the **3.0.0** release, except for bug fixes.
+since the **3.1.0** release, except for bug fixes.
Note that each entry is kept to a minimum, see links for details.
## Language changes
-* The block argument can now be anonymous if the block will
- only be passed to another method. [[Feature #11256]]
+* Anonymous rest and keyword rest arguments can now be passed as
+ arguments, instead of just used in method parameters.
+ [[Feature #18351]]
```ruby
- def foo(&)
- bar(&)
+ def foo(*)
+ bar(*)
+ end
+ def baz(**)
+ quux(**)
end
```
-* Pin operator now takes an expression. [[Feature #17411]]
+* A proc that accepts a single positional argument and keywords will
+ no longer autosplat. [[Bug #18633]]
```ruby
- Prime.each_cons(2).lazy.find_all{_1 in [n, ^(n + 2)]}.take(3).to_a
- #=> [[3, 5], [5, 7], [11, 13]]
+ proc{|a, **k| a}.call([1, 2])
+ # Ruby 3.1 and before
+ # => 1
+ # Ruby 3.2 and after
+ # => [1, 2]
```
-* Pin operator now supports instance, class, and global variables.
- [[Feature #17724]]
+* Constant assignment evaluation order for constants set on explicit
+ objects has been made consistent with single attribute assignment
+ evaluation order. With this code:
```ruby
- @n = 5
- Prime.each_cons(2).lazy.find{_1 in [n, ^@n]}
- #=> [3, 5]
+ foo::BAR = baz
```
-* One-line pattern matching is no longer experimental.
-
-* Parentheses can be omitted in one-line pattern matching.
- [[Feature #16182]]
+ `foo` is now called before `baz`. Similarly, for multiple assignments
+ to constants, left-to-right evaluation order is used. With this
+ code:
```ruby
- [0, 1] => _, x
- {y: 2} => y:
- x #=> 1
- y #=> 2
+ foo1::BAR1, foo2::BAR2 = baz1, baz2
```
-* Multiple assignment evaluation order has been made consistent with
- single assignment evaluation order. With single assignment, Ruby
- uses a left-to-right evaluation order. With this code:
+ The following evaluation order is now used:
- ```ruby
- foo[0] = bar
- ```
+ 1. `foo1`
+ 2. `foo2`
+ 3. `baz1`
+ 4. `baz2`
- The following evaluation order is used:
+ [[Bug #15928]]
- 1. `foo`
- 2. `bar`
- 3. `[]=` called on the result of `foo`
+* "Find pattern" is no longer experimental.
+ [[Feature #18585]]
- In Ruby before 3.1.0, multiple assignment did not follow this
- evaluation order. With this code:
+* Methods taking a rest parameter (like `*args`) and wishing to delegate keyword
+ arguments through `foo(*args)` must now be marked with `ruby2_keywords`
+ (if not already the case). In other words, all methods wishing to delegate
+ keyword arguments through `*args` must now be marked with `ruby2_keywords`,
+ with no exception. This will make it easier to transition to other ways of
+ delegation once a library can require Ruby 3+. Previously, the `ruby2_keywords`
+ flag was kept if the receiving method took `*args`, but this was a bug and an
+ inconsistency. A good technique to find the potentially-missing `ruby2_keywords`
+ is to run the test suite, for where it fails find the last method which must
+ receive keyword arguments, use `puts nil, caller, nil` there, and check each
+ method/block on the call chain which must delegate keywords is correctly marked
+ as `ruby2_keywords`. [[Bug #18625]] [[Bug #16466]]
```ruby
- foo[0], bar.baz = a, b
- ```
-
- Versions of Ruby before 3.1.0 would evaluate in the following
- order
+ def target(**kw)
+ end
- 1. `a`
- 2. `b`
- 3. `foo`
- 4. `[]=` called on the result of `foo`
- 5. `bar`
- 6. `baz=` called on the result of `bar`
+ # Accidentally worked without ruby2_keywords in Ruby 2.7-3.1, ruby2_keywords
+ # needed in 3.2+. Just like (*args, **kwargs) or (...) would be needed on
+ # both #foo and #bar when migrating away from ruby2_keywords.
+ ruby2_keywords def bar(*args)
+ target(*args)
+ end
- Starting in Ruby 3.1.0, the evaluation order is now consistent with
- single assignment, with the left-hand side being evaluated before
- the right-hand side:
+ ruby2_keywords def foo(*args)
+ bar(*args)
+ end
- 1. `foo`
- 2. `bar`
- 3. `a`
- 4. `b`
- 5. `[]=` called on the result of `foo`
- 6. `baz=` called on the result of `bar`
+ foo(k: 1)
+ ```
- [[Bug #4443]]
+## Core classes updates
-* Values in Hash literals and keyword arguments can be omitted.
- [[Feature #14579]]
+Note: We're only listing outstanding class updates.
- For example,
+* Fiber
- * `{x:, y:}` is a syntax sugar of `{x: x, y: y}`.
- * `foo(x:, y:)` is a syntax sugar of `foo(x: x, y: y)`.
+ * Introduce Fiber.[] and Fiber.[]= for inheritable fiber storage.
+ Introduce Fiber#storage and Fiber#storage= (experimental) for
+ getting and resetting the current storage. Introduce
+ `Fiber.new(storage:)` for setting the storage when creating a
+ fiber. [[Feature #19078]]
- Constant names, local variable names, and method names are allowed as
- key names. Note that a reserved word is considered as a local
- variable or method name even if it's a pseudo variable name such as
- `self`.
+ Existing Thread and Fiber local variables can be tricky to use.
+ Thread-local variables are shared between all fibers, making it
+ hard to isolate, while Fiber-local variables can be hard to
+ share. It is often desirable to define unit of execution
+ ("execution context") such that some state is shared between all
+ fibers and threads created in that context. This is what Fiber
+ storage provides.
-* Non main-Ractors can get instance variables (ivars) of classes/modules
- if ivars refer to shareable objects.
- [[Feature #17592]]
+ ```ruby
+ def log(message)
+ puts "#{Fiber[:request_id]}: #{message}"
+ end
+
+ def handle_requests
+ while request = read_request
+ Fiber.schedule do
+ Fiber[:request_id] = SecureRandom.uuid
+
+ request.messages.each do |message|
+ Fiber.schedule do
+ log("Handling #{message}") # Log includes inherited request_id.
+ end
+ end
+ end
+ end
+ end
+ ```
-* A command syntax is allowed in endless method definitions, i.e.,
- you can now write `def foo = puts "Hello"`.
- Note that `private def foo = puts "Hello"` does not parse.
- [[Feature #17398]]
+ You should generally consider Fiber storage for any state which
+ you want to be shared implicitly between all fibers and threads
+ created in a given context, e.g. a connection pool, a request
+ id, a logger level, environment variables, configuration, etc.
-## Command line options
+* Fiber::Scheduler
-* `--disable-gems` is now explicitly declared as "just for debugging".
- Never use it in any real-world codebase.
- [[Feature #17684]]
+ * Introduce `Fiber::Scheduler#io_select` for non-blocking IO.select.
+ [[Feature #19060]]
-## Core classes updates
+* IO
-Note: We're only listing outstanding class updates.
+ * Introduce IO#timeout= and IO#timeout which can cause
+ IO::TimeoutError to be raised if a blocking operation exceeds the
+ specified timeout. [[Feature #18630]]
-* Array
+ ```ruby
+ STDIN.timeout = 1
+ STDIN.read # => Blocking operation timed out! (IO::TimeoutError)
+ ```
- * Array#intersect? is added. [[Feature #15198]]
+ * Introduce `IO.new(..., path:)` and promote `File#path` to `IO#path`.
+ [[Feature #19036]]
* Class
- * Class#descendants, which returns an array of classes
- directly or indirectly inheriting from the receiver, not
- including the receiver or singleton classes.
- [[Feature #14394]]
+ * Class#attached_object, which returns the object for which
+ the receiver is the singleton class. Raises TypeError if the
+ receiver is not a singleton class.
+ [[Feature #12084]]
```ruby
- class A; end
- class B < A; end
- class C < B; end
- A.descendants #=> [B, C]
- B.descendants #=> [C]
- C.descendants #=> []
+ class Foo; end
+
+ Foo.singleton_class.attached_object #=> Foo
+ Foo.new.singleton_class.attached_object #=> #<Foo:0x000000010491a370>
+ Foo.attached_object #=> TypeError: `Foo' is not a singleton class
+ nil.singleton_class.attached_object #=> TypeError: `NilClass' is not a singleton class
```
- * Class#subclasses, which returns an array of classes
- directly inheriting from the receiver, not
- including singleton classes.
- [[Feature #18273]]
+* Data
+
+ * New core class to represent simple immutable value object. The class is
+ similar to Struct and partially shares an implementation, but has more
+ lean and strict API. [[Feature #16122]]
```ruby
- class A; end
- class B < A; end
- class C < B; end
- class D < A; end
- A.subclasses #=> [D, B]
- B.subclasses #=> [C]
- C.subclasses #=> []
+ Measure = Data.define(:amount, :unit)
+ distance = Measure.new(100, 'km') #=> #<data Measure amount=100, unit="km">
+ weight = Measure.new(amount: 50, unit: 'kg') #=> #<data Measure amount=50, unit="kg">
+ weight.with(amount: 40) #=> #<data Measure amount=40, unit="kg">
+ weight.amount #=> 50
+ weight.amount = 40 #=> NoMethodError: undefined method `amount='
```
-* Enumerable
+* Encoding
- * Enumerable#compact is added. [[Feature #17312]]
+ * Encoding#replicate has been deprecated and will be removed in 3.3. [[Feature #18949]]
+ * The dummy `Encoding::UTF_16` and `Encoding::UTF_32` encodings no longer
+ try to dynamically guess the endian based on a byte order mark.
+ Use `Encoding::UTF_16BE`/`UTF_16LE` and `Encoding::UTF_32BE`/`UTF_32LE` instead.
+ This change speeds up getting the encoding of a String. [[Feature #18949]]
+ * Limit maximum encoding set size by 256.
+ If exceeding maximum size, `EncodingError` will be raised. [[Feature #18949]]
- * Enumerable#tally now accepts an optional hash to count. [[Feature #17744]]
+* Enumerator
- * Enumerable#each_cons and each_slice to return a receiver. [[GH-1509]]
+ * Enumerator.product has been added. Enumerator::Product is the implementation. [[Feature #18685]]
- ```ruby
- [1, 2, 3].each_cons(2){}
- # 3.0 => nil
- # 3.1 => [1, 2, 3]
+* Exception
- [1, 2, 3].each_slice(2){}
- # 3.0 => nil
- # 3.1 => [1, 2, 3]
- ```
+ * Exception#detailed_message has been added.
+ The default error printer calls this method on the Exception object
+ instead of #message. [[Feature #18564]]
-* Enumerator::Lazy
+* Hash
- * Enumerator::Lazy#compact is added. [[Feature #17312]]
+ * Hash#shift now always returns nil if the hash is
+ empty, instead of returning the default value or
+ calling the default proc. [[Bug #16908]]
-* File
+* Integer
- * File.dirname now accepts an optional argument for the level to
- strip path components. [[Feature #12194]]
+ * Integer#ceildiv has been added. [[Feature #18809]]
-* GC
+* Kernel
- * "GC.measure_total_time = true" enables the measurement of GC.
- Measurement can introduce overhead. It is enabled by default.
- GC.measure_total_time returns the current setting.
- GC.stat[:time] or GC.stat(:time) returns measured time
- in milli-seconds.
+ * Kernel#binding raises RuntimeError if called from a non-Ruby frame
+ (such as a method defined in C). [[Bug #18487]]
- * GC.total_time returns measured time in nano-seconds.
+* MatchData
-* Integer
+ * MatchData#byteoffset has been added. [[Feature #13110]]
+ * MatchData#deconstruct has been added. [[Feature #18821]]
+ * MatchData#deconstruct_keys has been added. [[Feature #18821]]
- * Integer.try_convert is added. [[Feature #15211]]
+* Module
-* Kernel
+ * Module.used_refinements has been added. [[Feature #14332]]
+ * Module#refinements has been added. [[Feature #12737]]
+ * Module#const_added has been added. [[Feature #17881]]
+ * Module#undefined_instance_methods has been added. [[Feature #12655]]
+* Proc
- * Kernel#load now accepts a module as the second argument,
- and will load the file using the given module as the
- top-level module. [[Feature #6210]]
+ * Proc#dup returns an instance of subclass. [[Bug #17545]]
+ * Proc#parameters now accepts lambda keyword. [[Feature #15357]]
-* Marshal
+* Process
+ * Added `RLIMIT_NPTS` constant to FreeBSD platform
- * Marshal.load now accepts a `freeze: true` option.
- All returned objects are frozen except for `Class` and
- `Module` instances. Strings are deduplicated. [[Feature #18148]]
+* Regexp
-* MatchData
+ * The cache-based optimization is introduced.
+ Many (but not all) Regexp matching is now in linear time, which
+ will prevent regular expression denial of service (ReDoS)
+ vulnerability. [[Feature #19104]]
- * MatchData#match is added [[Feature #18172]]
+ * Regexp.linear_time? is introduced. [[Feature #19194]]
- * MatchData#match_length is added [[Feature #18172]]
+ * Regexp.new now supports passing the regexp flags not only as an Integer,
+ but also as a String. Unknown flags raise ArgumentError.
+ Otherwise, anything other than `true`, `false`, `nil` or Integer will be warned.
+ [[Feature #18788]]
-* Method/UnboundMethod
+ * Regexp.timeout= has been added. Also, Regexp.new new supports timeout keyword.
+ See [[Feature #17837]]
- * Method#public?, Method#private?, Method#protected?,
- UnboundMethod#public?, UnboundMethod#private?,
- UnboundMethod#protected? have been added. [[Feature #11689]]
+* Refinement
-* Module
+ * Refinement#refined_class has been added. [[Feature #12737]]
- * Module#prepend now modifies the ancestor chain if the receiver
- already includes the argument. Module#prepend still does not
- modify the ancestor chain if the receiver has already prepended
- the argument. [[Bug #17423]]
+* RubyVM::AbstractSyntaxTree
- * Module#private, #public, #protected, and #module_function will
- now return their arguments. If a single argument is given, it
- is returned. If no arguments are given, nil is returned. If
- multiple arguments are given, they are returned as an array.
- [[Feature #12495]]
+ * Add `error_tolerant` option for `parse`, `parse_file` and `of`. [[Feature #19013]]
+ With this option
-* Process
+ 1. SyntaxError is suppressed
+ 2. AST is returned for invalid input
+ 3. `end` is complemented when a parser reaches to the end of input but `end` is insufficient
+ 4. `end` is treated as keyword based on indent
- * Process.\_fork is added. This is a core method for fork(2).
- Do not call this method directly; it is called by existing
- fork methods: Kernel.#fork, Process.fork, and IO.popen("-").
- Application monitoring libraries can overwrite this method to
- hook fork events. [[Feature #17795]]
+ ```ruby
+ # Without error_tolerant option
+ root = RubyVM::AbstractSyntaxTree.parse(<<~RUBY)
+ def m
+ a = 10
+ if
+ end
+ RUBY
+ # => <internal:ast>:33:in `parse': syntax error, unexpected `end' (SyntaxError)
+
+ # With error_tolerant option
+ root = RubyVM::AbstractSyntaxTree.parse(<<~RUBY, error_tolerant: true)
+ def m
+ a = 10
+ if
+ end
+ RUBY
+ p root # => #<RubyVM::AbstractSyntaxTree::Node:SCOPE@1:0-4:3>
+
+ # `end` is treated as keyword based on indent
+ root = RubyVM::AbstractSyntaxTree.parse(<<~RUBY, error_tolerant: true)
+ module Z
+ class Foo
+ foo.
+ end
+
+ def bar
+ end
+ end
+ RUBY
+ p root.children[-1].children[-1].children[-1].children[-2..-1]
+ # => [#<RubyVM::AbstractSyntaxTree::Node:CLASS@2:2-4:5>, #<RubyVM::AbstractSyntaxTree::Node:DEFN@6:2-7:5>]
+ ```
-* Struct
+ * Add `keep_tokens` option for `parse`, `parse_file` and `of`. Add `#tokens` and `#all_tokens`
+ for RubyVM::AbstractSyntaxTree::Node [[Feature #19070]]
- * Passing only keyword arguments to Struct#initialize is warned.
- You need to use a Hash literal to set a Hash to a first member.
- [[Feature #16806]]
+ ```ruby
+ root = RubyVM::AbstractSyntaxTree.parse("x = 1 + 2", keep_tokens: true)
+ root.tokens # => [[0, :tIDENTIFIER, "x", [1, 0, 1, 1]], [1, :tSP, " ", [1, 1, 1, 2]], ...]
+ root.tokens.map{_1[2]}.join # => "x = 1 + 2"
+ ```
+
+* Set
- * StructClass#keyword_init? is added [[Feature #18008]]
+ * Set is now available as a built-in class without the need for `require "set"`. [[Feature #16989]]
+ It is currently autoloaded via the Set constant or a call to Enumerable#to_set.
* String
- * Update Unicode version to 13.0.0 [[Feature #17750]]
- and Emoji version to 13.0 [[Feature #18029]]
+ * String#byteindex and String#byterindex have been added. [[Feature #13110]]
+ * Update Unicode to Version 15.0.0 and Emoji Version 15.0. [[Feature #18639]]
+ (also applies to Regexp)
+ * String#bytesplice has been added. [[Feature #18598]]
+ * String#dedup has been added as an alias to String#-@. [[Feature #18595]]
- * String#unpack and String#unpack1 now accept an `offset:` keyword
- argument to start the unpacking after an arbitrary number of bytes
- have been skipped. If `offset` is outside of the string bounds
- `ArgumentError` is raised. [[Feature #18254]]
+* Struct
-* Queue
+ * A Struct class can also be initialized with keyword arguments
+ without `keyword_init: true` on Struct.new [[Feature #16806]]
- * Queue#initialize now accepts an Enumerable of initial values.
- [[Feature #17327]]
+ ```ruby
+ Post = Struct.new(:id, :name)
+ Post.new(1, "hello") #=> #<struct Post id=1, name="hello">
+ # From Ruby 3.2, the following code also works without keyword_init: true.
+ Post.new(id: 1, name: "hello") #=> #<struct Post id=1, name="hello">
+ ```
* Thread
- * Thread#native_thread_id is added. [[Feature #17853]]
+ * Thread.each_caller_location is added. [[Feature #16663]]
+
+* Thread::Queue
-* Thread::Backtrace
+ * Thread::Queue#pop(timeout: sec) is added. [[Feature #18774]]
- * Thread::Backtrace.limit, which returns the value to limit backtrace
- length set by `--backtrace-limit` command line option, is added.
- [[Feature #17479]]
+* Thread::SizedQueue
+
+ * Thread::SizedQueue#pop(timeout: sec) is added. [[Feature #18774]]
+ * Thread::SizedQueue#push(timeout: sec) is added. [[Feature #18944]]
* Time
- * Time.new now accepts optional `in:` keyword argument for the
- timezone, as well as `Time.at` and `Time.now`, so that is now
- you can omit minor arguments to `Time.new`. [[Feature #17485]]
+ * Time#deconstruct_keys is added, allowing to use Time instances
+ in pattern-matching expressions [[Feature #19071]]
+
+ * Time.new now can parse a string like generated by Time#inspect
+ and return a Time instance based on the given argument.
+ [[Feature #18033]]
- * Time#strftime supports RFC 3339 UTC for unknown offset local
- time, `-0000`, as `%-z`. [[Feature #17544]]
+* SyntaxError
+ * SyntaxError#path has been added. [[Feature #19138]]
* TracePoint
- * TracePoint.allow_reenter is added to allow reenter while TracePoint
- callback.
- [[Feature #15912]]
+ * TracePoint#binding now returns `nil` for `c_call`/`c_return` TracePoints.
+ [[Bug #18487]]
+ * TracePoint#enable `target_thread` keyword argument now defaults to the
+ current thread if a block is given and `target` and `target_line` keyword
+ arguments are not passed. [[Bug #16889]]
-* $LOAD_PATH
+* UnboundMethod
- * $LOAD_PATH.resolve_feature_path does not raise. [[Feature #16043]]
+ * `UnboundMethod#==` returns `true` if the actual method is same. For example,
+ `String.instance_method(:object_id) == Array.instance_method(:object_id)`
+ returns `true`. [[Feature #18798]]
-* Fiber Scheduler
+ * `UnboundMethod#inspect` does not show the receiver of `instance_method`.
+ For example `String.instance_method(:object_id).inspect` returns
+ `"#<UnboundMethod: Kernel#object_id()>"`
+ (was `"#<UnboundMethod: String(Kernel)#object_id()>"`).
- * Add support for `Addrinfo.getaddrinfo` using `address_resolve` hook.
- [[Feature #17370]]
+* GC
- * Introduce non-blocking `Timeout.timeout` using `timeout_after` hook.
- [[Feature #17470]]
+ * Expose `need_major_gc` via `GC.latest_gc_info`. [GH-6791]
- * Introduce new scheduler hooks `io_read` and `io_write` along with a
- low level `IO::Buffer` for zero-copy read/write. [[Feature #18020]]
+* ObjectSpace
- * IO hooks `io_wait`, `io_read`, `io_write`, receive the original IO object
- where possible. [[Bug #18003]]
+ * `ObjectSpace.dump_all` dump shapes as well. [GH-6868]
- * Make `Monitor` fiber-safe. [[Bug #17827]]
+## Stdlib updates
- * Replace copy coroutine with pthread implementation. [[Feature #18015]]
+* Bundler
-* Refinement
+ * Bundler now uses [PubGrub] resolver instead of [Molinillo] for performance improvement.
+ * Add --ext=rust support to bundle gem for creating simple gems with Rust extensions.
+ [[GH-rubygems-6149]]
+ * Make cloning git repos faster [[GH-rubygems-4475]]
- * New class which represents a module created by Module#refine.
- `include` and `prepend` are deprecated, and `import_methods` is added
- instead. [[Bug #17429]]
+* RubyGems
-## Stdlib updates
+ * Add mswin support for cargo builder. [[GH-rubygems-6167]]
+
+* CGI
+
+ * `CGI.escapeURIComponent` and `CGI.unescapeURIComponent` are added.
+ [[Feature #18822]]
+
+* Coverage
+
+ * `Coverage.setup` now accepts `eval: true`. By this, `eval` and related methods are
+ able to generate code coverage. [[Feature #19008]]
+
+ * `Coverage.supported?(mode)` enables detection of what coverage modes are
+ supported. [[Feature #19026]]
+
+* Date
+
+ * Added `Date#deconstruct_keys` and `DateTime#deconstruct_keys` same as [[Feature #19071]]
+
+* ERB
+
+ * `ERB::Util.html_escape` is made faster than `CGI.escapeHTML`.
+ * It no longer allocates a String object when no character needs to be escaped.
+ * It skips calling `#to_s` method when an argument is already a String.
+ * `ERB::Escape.html_escape` is added as an alias to `ERB::Util.html_escape`,
+ which has not been monkey-patched by Rails.
+ * `ERB::Util.url_encode` is made faster using `CGI.escapeURIComponent`.
+ * `-S` option is removed from `erb` command.
+
+* FileUtils
+
+ * Add FileUtils.ln_sr method and `relative:` option to FileUtils.ln_s.
+ [[Feature #18925]]
+
+* IRB
+
+ * debug.gem integration commands have been added: `debug`, `break`, `catch`,
+ `next`, `delete`, `step`, `continue`, `finish`, `backtrace`, `info`
+ * They work even if you don't have `gem "debug"` in your Gemfile.
+ * See also: [What's new in Ruby 3.2's IRB?](https://st0012.dev/whats-new-in-ruby-3-2-irb)
+ * More Pry-like commands and features have been added.
+ * `edit` and `show_cmds` (like Pry's `help`) are added.
+ * `ls` takes `-g` or `-G` option to filter out outputs.
+ * `show_source` is aliased from `$` and accepts unquoted inputs.
+ * `whereami` is aliased from `@`.
+
+* Net::Protocol
+
+ * Improve `Net::BufferedIO` performance. [[GH-net-protocol-14]]
+
+* Pathname
+
+ * Added `Pathname#lutime`. [[GH-pathname-20]]
+
+* Socket
+
+ * Added the following constants for supported platforms.
+ * `SO_INCOMING_CPU`
+ * `SO_INCOMING_NAPI_ID`
+ * `SO_RTABLE`
+ * `SO_SETFIB`
+ * `SO_USER_COOKIE`
+ * `TCP_KEEPALIVE`
+ * `TCP_CONNECTION_INFO`
+
+* SyntaxSuggest
+
+ * The feature of `syntax_suggest` formerly `dead_end` is integrated in Ruby.
+ [[Feature #18159]]
+
+* UNIXSocket
+
+ * Add support for UNIXSocket on Windows. Emulate anonymous sockets. Add
+ support for File.socket? and File::Stat#socket? where possible.
+ [[Feature #19135]]
+
+* The following default gems are updated.
+
+ * RubyGems 3.4.1
+ * abbrev 0.1.1
+ * benchmark 0.2.1
+ * bigdecimal 3.1.3
+ * bundler 2.4.1
+ * cgi 0.3.6
+ * csv 3.2.6
+ * date 3.3.3
+ * delegate 0.3.0
+ * did_you_mean 1.6.3
+ * digest 3.1.1
+ * drb 2.1.1
+ * english 0.7.2
+ * erb 4.0.2
+ * error_highlight 0.5.1
+ * etc 1.4.2
+ * fcntl 1.0.2
+ * fiddle 1.1.1
+ * fileutils 1.7.0
+ * forwardable 1.3.3
+ * getoptlong 0.2.0
+ * io-console 0.6.0
+ * io-nonblock 0.2.0
+ * io-wait 0.3.0
+ * ipaddr 1.2.5
+ * irb 1.6.2
+ * json 2.6.3
+ * logger 1.5.3
+ * mutex_m 0.1.2
+ * net-http 0.4.0
+ * net-protocol 0.2.1
+ * nkf 0.1.2
+ * open-uri 0.3.0
+ * open3 0.1.2
+ * openssl 3.1.0
+ * optparse 0.3.1
+ * ostruct 0.5.5
+ * pathname 0.2.1
+ * pp 0.4.0
+ * pstore 0.1.2
+ * psych 5.0.1
+ * racc 1.6.2
+ * rdoc 6.5.0
+ * readline-ext 0.1.5
+ * reline 0.3.2
+ * resolv 0.2.2
+ * resolv-replace 0.1.1
+ * securerandom 0.2.2
+ * set 1.0.3
+ * stringio 3.0.4
+ * strscan 3.0.5
+ * syntax_suggest 1.0.2
+ * syslog 0.1.1
+ * tempfile 0.1.3
+ * time 0.2.1
+ * timeout 0.3.1
+ * tmpdir 0.1.3
+ * tsort 0.1.1
+ * un 0.2.1
+ * uri 0.12.0
+ * weakref 0.1.2
+ * win32ole 1.8.9
+ * yaml 0.2.1
+ * zlib 3.0.0
-* The following default gem are updated.
- * RubyGems 3.3.0.dev
- * base64 0.1.1
- * benchmark 0.2.0
- * bigdecimal 3.1.0.dev
- * bundler 2.3.0.dev
- * cgi 0.3.1
- * csv 3.2.1
- * date 3.2.2
- * did_you_mean 1.6.0.pre.alpha
- * digest 3.1.0.pre3
- * drb 2.1.0
- * erb 2.2.3
- * error_highlight 0.2.0
- * etc 1.3.0
- * fcntl 1.0.1
- * fiddle 1.1.0
- * fileutils 1.6.0
- * find 0.1.1
- * io-console 0.5.9
- * io-wait 0.2.1
- * ipaddr 1.2.3
- * irb 1.3.8.pre.11
- * json 2.6.1
- * logger 1.5.0
- * net-http 0.2.0
- * net-protocol 0.1.2
- * nkf 0.1.1
- * open-uri 0.2.0
- * openssl 3.0.0.pre
- * optparse 0.2.0
- * ostruct 0.5.2
- * pathname 0.2.0
- * pp 0.3.0
- * prettyprint 0.1.1
- * psych 4.0.3
- * racc 1.6.0
- * rdoc 6.3.2
- * readline-ext 0.1.3
- * reline 0.2.8.pre.11
- * resolv 0.2.1
- * rinda 0.1.1
- * ruby2_keywords 0.0.5
- * securerandom 0.1.1
- * set 1.0.2
- * stringio 3.0.1
- * strscan 3.0.1
- * tempfile 0.1.2
- * time 0.2.0
- * timeout 0.2.0
- * tmpdir 0.1.2
- * un 0.2.0
- * uri 0.11.0
- * yaml 0.2.0
- * zlib 2.1.1
* The following bundled gems are updated.
- * minitest 5.15.0
- * power_assert 2.0.1
- * rake 13.0.6
- * test-unit 3.5.3
- * rexml 3.2.5
- * rbs 1.8.1
- * typeprof 0.21.0
-* The following default gems are now bundled gems.
- * net-ftp 0.1.3
- * net-imap 0.2.2
- * net-pop 0.1.1
- * net-smtp 0.3.1
- * matrix 0.4.2
- * prime 0.1.2
- * debug 1.4.0
-
-* Coverage measurement now supports suspension. You can use `Coverage.suspend`
- to stop the measurement temporarily, and `Coverage.resume` to restart it.
- See [[Feature #18176]] in detail.
-
-* Random::Formatter is moved to random/formatter.rb, so that you can
- use `Random#hex`, `Random#base64`, and so on without SecureRandom.
- [[Feature #18190]]
+
+ * minitest 5.16.3
+ * power_assert 2.0.3
+ * test-unit 3.5.7
+ * net-ftp 0.2.0
+ * net-imap 0.3.4
+ * net-pop 0.1.2
+ * net-smtp 0.3.3
+ * rbs 2.8.2
+ * typeprof 0.21.3
+ * debug 1.7.1
+
+See GitHub releases like [GitHub Releases of Logger](https://github.com/ruby/logger/releases) or changelog for details of the default gems or bundled gems.
+
+## Supported platforms
+
+* WebAssembly/WASI is added. See [wasm/README.md] and [ruby.wasm] for more details. [[Feature #18462]]
## Compatibility issues
-Note: Excluding feature bug fixes.
+* `String#to_c` currently treat a sequence of underscores as an end of Complex
+ string. [[Bug #19087]]
-* `rb_io_wait_readable`, `rb_io_wait_writable` and `rb_wait_for_single_fd` are
- deprecated in favour of `rb_io_maybe_wait_readable`,
- `rb_io_maybe_wait_writable` and `rb_io_maybe_wait` respectively.
- `rb_thread_wait_fd` and `rb_thread_fd_writable` are deprecated. [[Bug #18003]]
+* Now `ENV.clone` raises `TypeError` as well as `ENV.dup` [[Bug #17767]]
-## Stdlib compatibility issues
+### Removed constants
-* `ERB#initialize` warns `safe_level` and later arguments even without -w.
- [[Feature #14256]]
+The following deprecated constants are removed.
-* `lib/debug.rb` is replaced with `debug.gem`
+* `Fixnum` and `Bignum` [[Feature #12005]]
+* `Random::DEFAULT` [[Feature #17351]]
+* `Struct::Group`
+* `Struct::Passwd`
-* `Kernel#pp` in `lib/pp.rb` uses the width of `IO#winsize` by default.
- This means that the output width is automatically changed depending on
- your terminal size. [[Feature #12913]]
+### Removed methods
-## C API updates
+The following deprecated methods are removed.
-* Documented. [[GH-4815]]
+* `Dir.exists?` [[Feature #17391]]
+* `File.exists?` [[Feature #17391]]
+* `Kernel#=~` [[Feature #15231]]
+* `Kernel#taint`, `Kernel#untaint`, `Kernel#tainted?`
+ [[Feature #16131]]
+* `Kernel#trust`, `Kernel#untrust`, `Kernel#untrusted?`
+ [[Feature #16131]]
+* `Method#public?`, `Method#private?`, `Method#protected?`,
+ `UnboundMethod#public?`, `UnboundMethod#private?`, `UnboundMethod#protected?`
+ [[Bug #18729]] [[Bug #18751]] [[Bug #18435]]
-* `rb_gc_force_recycle` is deprecated and has been changed to a no-op.
- [[Feature #18290]]
+### Source code incompatibility of extension libraries
-## Implementation improvements
+* Extension libraries provide PRNG, subclasses of Random, need updates.
+ See [PRNG update] below for more information. [[Bug #19100]]
-* `instance_eval` and `instance_exec` now only allocate a singleton class when
- required, avoiding extra objects and improving performance. [[GH-5146]]
+### Error printer
-* The performance of `Struct` accessors is improved. [[GH-5131]]
+* Ruby no longer escapes control characters and backslashes in an
+ error message. [[Feature #18367]]
-* `mandatory_only?` builtin special form to improve performance on
- builtin methods. [[GH-5112]]
+### Constant lookup when defining a class/module
-* Experimental feature Variable Width Allocation in the garbage collector.
- This feature is turned off by default and can be enabled by compiling Ruby
- with flag `USE_RVARGC=1` set. [[Feature #18045]] [[Feature #18239]]
+* When defining a class/module directly under the Object class by class/module
+ statement, if there is already a class/module defined by `Module#include`
+ with the same name, the statement was handled as "open class" in Ruby 3.1 or before.
+ Since Ruby 3.2, a new class is defined instead. [[Feature #18832]]
-## JIT
+## Stdlib compatibility issues
-* Rename Ruby 3.0's `--jit` to `--mjit`, and alias `--jit` to `--yjit`
- on non-Windows x86-64 platforms and to `--mjit` on others.
+* Psych no longer bundles libyaml sources.
+ And also Fiddle no longer bundles libffi sources.
+ Users need to install the libyaml/libffi library themselves via the package
+ manager like apt, yum, brew, etc.
-### MJIT
+ Psych and fiddle supported the static build with specific version of libyaml
+ and libffi sources. You can build psych with libyaml-0.2.5 like this.
-* The default `--mjit-max-cache` is changed from 100 to 10000.
+ ```bash
+ $ ./configure --with-libyaml-source-dir=/path/to/libyaml-0.2.5
+ ```
-* JIT-ed code is no longer cancelled when a TracePoint for class events
- is enabled.
+ And you can build fiddle with libffi-3.4.4 like this.
-* The JIT compiler no longer skips compilation of methods longer than
- 1000 instructions.
+ ```bash
+ $ ./configure --with-libffi-source-dir=/path/to/libffi-3.4.4
+ ```
-* `--mjit-verbose` and `--mjit-warning` output "JIT cancel" when JIT-ed
- code is disabled because TracePoint or GC.compact is used.
+ [[Feature #18571]]
-### YJIT: New experimental in-process JIT compiler
+* Check cookie name/path/domain characters in `CGI::Cookie`. [[CVE-2021-33621]]
-New JIT compiler available as an experimental feature. [[Feature #18229]]
+* `URI.parse` return empty string in host instead of nil. [[sec-156615]]
-See [this blog post](https://shopify.engineering/yjit-just-in-time-compiler-cruby
-) introducing the project.
+## C API updates
-* Disabled by default, use `--yjit` command-line option to enable YJIT.
+### Updated C APIs
-* Performance improvements on most real-world software, up to 22% on railsbench, 39% on liquid-render.
+The following APIs are updated.
-* Fast warm-up times.
+* PRNG update
-* Limited to macOS & Linux on x86-64 platforms for now.
+ `rb_random_interface_t` in ruby/random.h updated and versioned.
+ Extension libraries which use this interface and built for older
+ versions need to rebuild with adding `init_int32` function.
-## Static analysis
+### Added C APIs
-### RBS
+* `VALUE rb_hash_new_capa(long capa)` was added to created hashes with the desired capacity.
+* `rb_internal_thread_add_event_hook` and `rb_internal_thread_add_event_hook` were added to instrument threads scheduling.
+ The following events are available:
+ * `RUBY_INTERNAL_THREAD_EVENT_STARTED`
+ * `RUBY_INTERNAL_THREAD_EVENT_READY`
+ * `RUBY_INTERNAL_THREAD_EVENT_RESUMED`
+ * `RUBY_INTERNAL_THREAD_EVENT_SUSPENDED`
+ * `RUBY_INTERNAL_THREAD_EVENT_EXITED`
+* `rb_debug_inspector_current_depth` and `rb_debug_inspector_frame_depth` are added for debuggers.
-* [rbs collection](https://github.com/ruby/rbs/blob/master/docs/collection.md) has been introduced to manage gems’ RBSs.
-* Many signatures for built-in and standard libraries have been added/updated.
-* It includes many bug fixes and performance improvements too.
+### Removed C APIs
-See the [CHANGELOG.md](https://github.com/ruby/rbs/blob/master/CHANGELOG.md) for more information.
+The following deprecated APIs are removed.
-### TypeProf
+* `rb_cData` variable.
+* "taintedness" and "trustedness" functions. [[Feature #16131]]
+
+## Implementation improvements
-* [Experimental IDE support](https://github.com/ruby/typeprof/blob/master/doc/ide.md) has been implemented.
-* Many bug fixes and performance improvements since Ruby 3.0.0.
+* Fixed several race conditions in Kernel#autoload. [[Bug #18782]]
+* Cache invalidation for expressions referencing constants is now
+ more fine-grained. `RubyVM.stat(:global_constant_state)` was
+ removed because it was closely tied to the previous caching scheme
+ where setting any constant invalidates all caches in the system.
+ New keys, `:constant_cache_invalidations` and `:constant_cache_misses`,
+ were introduced to help with use cases for `:global_constant_state`.
+ [[Feature #18589]]
+* The cache-based optimization for Regexp matching is introduced.
+ [[Feature #19104]]
+* [Variable Width Allocation](https://shopify.engineering/ruby-variable-width-allocation)
+ is now enabled by default. [[Feature #18239]]
+* Added a new instance variable caching mechanism, called object shapes, which
+ improves inline cache hits for most objects and allows us to generate very
+ efficient JIT code. Objects whose instance variables are defined in a
+ consistent order will see the most performance benefits.
+ [[Feature #18776]]
+* Speed up marking instruction sequences by using a bitmap to find "markable"
+ objects. This change results in faster major collections.
+ [[Feature #18875]]
-## Debugger
+## JIT
+
+### YJIT
+
+* YJIT is no longer experimental
+ * Has been tested on production workloads for over a year and proven to be quite stable.
+* YJIT now supports both x86-64 and arm64/aarch64 CPUs on Linux, MacOS, BSD and other UNIX platforms.
+ * This release brings support for Mac M1/M2, AWS Graviton and Raspberry Pi 4.
+* Building YJIT now requires Rust 1.58.0+. [[Feature #18481]]
+ * In order to ensure that CRuby is built with YJIT, please install `rustc` >= 1.58.0
+ before running `./configure`
+ * Please reach out to the YJIT team should you run into any issues.
+* Physical memory for JIT code is lazily allocated. Unlike Ruby 3.1,
+ the RSS of a Ruby process is minimized because virtual memory pages
+ allocated by `--yjit-exec-mem-size` will not be mapped to physical
+ memory pages until actually utilized by JIT code.
+* Introduce Code GC that frees all code pages when the memory consumption
+ by JIT code reaches `--yjit-exec-mem-size`.
+ * `RubyVM::YJIT.runtime_stats` returns Code GC metrics in addition to
+ existing `inline_code_size` and `outlined_code_size` keys:
+ `code_gc_count`, `live_page_count`, `freed_page_count`, and `freed_code_size`.
+* Most of the statistics produced by `RubyVM::YJIT.runtime_stats` are now available in release builds.
+ * Simply run ruby with `--yjit-stats` to compute and dump stats (incurs some run-time overhead).
+* YJIT is now optimized to take advantage of object shapes. [[Feature #18776]]
+* Take advantage of finer-grained constant invalidation to invalidate less code when defining new constants. [[Feature #18589]]
+* The default `--yjit-exec-mem-size` is changed to 64 (MiB).
+* The default `--yjit-call-threshold` is changed to 30.
+
+### MJIT
-* A new debugger [debug.gem](https://github.com/ruby/debug) is bundled.
- debug.gem is a fast debugger implementation, and it provides many features
- like remote debugging, colorful REPL, IDE (VSCode) integration, and more.
- It replaces `lib/debug.rb` standard library.
-
-* `rdbg` command is also installed into `bin/` directory to start and control
- debugging execution.
-
-## error_highlight
-
-A built-in gem called error_highlight has been introduced.
-It shows fine-grained error locations in the backtrace.
-
-Example: `title = json[:article][:title]`
-
-If `json` is nil, it shows:
-
-```
-$ ruby test.rb
-test.rb:2:in `<main>': undefined method `[]' for nil:NilClass (NoMethodError)
-
-title = json[:article][:title]
- ^^^^^^^^^^
-```
-
-If `json[:article]` returns nil, it shows:
-
-```
-$ ruby test.rb
-test.rb:2:in `<main>': undefined method `[]' for nil:NilClass (NoMethodError)
-
-title = json[:article][:title]
- ^^^^^^^^
-```
-
-This feature is enabled by default.
-You can disable it by using a command-line option `--disable-error_highlight`.
-See [the repository](https://github.com/ruby/error_highlight) in detail.
-
-## Miscellaneous changes
-
-* lib/objspace/trace.rb is added, which is a tool for tracing the object
- allocation. Just by requiring this file, tracing is started *immediately*.
- Just by `Kernel#p`, you can investigate where an object was created.
- Note that just requiring this file brings a large performance overhead.
- This is only for debugging purposes. Do not use this in production.
- [[Feature #17762]]
-
-* Now exceptions raised in finalizers will be printed to `STDERR`, unless
- `$VERBOSE` is `nil`. [[Feature #17798]]
-
-* `ruby -run -e httpd` displays URLs to access. [[Feature #17847]]
-
-* Add `ruby -run -e colorize` to colorize Ruby code using
- `IRB::Color.colorize_code`.
-
-[Bug #4443]: https://bugs.ruby-lang.org/issues/4443
-[Feature #6210]: https://bugs.ruby-lang.org/issues/6210
-[Feature #11256]: https://bugs.ruby-lang.org/issues/11256
-[Feature #11689]: https://bugs.ruby-lang.org/issues/11689
-[Feature #12194]: https://bugs.ruby-lang.org/issues/12194
-[Feature #12495]: https://bugs.ruby-lang.org/issues/12495
-[Feature #12913]: https://bugs.ruby-lang.org/issues/12913
-[Feature #14256]: https://bugs.ruby-lang.org/issues/14256
-[Feature #14394]: https://bugs.ruby-lang.org/issues/14394
-[Feature #14579]: https://bugs.ruby-lang.org/issues/14579
-[Feature #15198]: https://bugs.ruby-lang.org/issues/15198
-[Feature #15211]: https://bugs.ruby-lang.org/issues/15211
-[Feature #15912]: https://bugs.ruby-lang.org/issues/15912
-[Feature #16043]: https://bugs.ruby-lang.org/issues/16043
-[Feature #16182]: https://bugs.ruby-lang.org/issues/16182
-[Feature #16806]: https://bugs.ruby-lang.org/issues/16806
-[Feature #17312]: https://bugs.ruby-lang.org/issues/17312
-[Feature #17327]: https://bugs.ruby-lang.org/issues/17327
-[Feature #17370]: https://bugs.ruby-lang.org/issues/17370
-[Feature #17398]: https://bugs.ruby-lang.org/issues/17398
-[Feature #17411]: https://bugs.ruby-lang.org/issues/17411
-[Bug #17423]: https://bugs.ruby-lang.org/issues/17423
-[Bug #17429]: https://bugs.ruby-lang.org/issues/17429
-[Feature #17470]: https://bugs.ruby-lang.org/issues/17470
-[Feature #17479]: https://bugs.ruby-lang.org/issues/17479
-[Feature #17485]: https://bugs.ruby-lang.org/issues/17485
-[Feature #17544]: https://bugs.ruby-lang.org/issues/17544
-[Feature #17592]: https://bugs.ruby-lang.org/issues/17592
-[Feature #17684]: https://bugs.ruby-lang.org/issues/17684
-[Feature #17724]: https://bugs.ruby-lang.org/issues/17724
-[Feature #17744]: https://bugs.ruby-lang.org/issues/17744
-[Feature #17750]: https://bugs.ruby-lang.org/issues/17750
-[Feature #17762]: https://bugs.ruby-lang.org/issues/17762
-[Feature #17795]: https://bugs.ruby-lang.org/issues/17795
-[Feature #17798]: https://bugs.ruby-lang.org/issues/17798
-[Bug #17827]: https://bugs.ruby-lang.org/issues/17827
-[Feature #17847]: https://bugs.ruby-lang.org/issues/17847
-[Feature #17853]: https://bugs.ruby-lang.org/issues/17853
-[Bug #18003]: https://bugs.ruby-lang.org/issues/18003
-[Feature #18008]: https://bugs.ruby-lang.org/issues/18008
-[Feature #18015]: https://bugs.ruby-lang.org/issues/18015
-[Feature #18020]: https://bugs.ruby-lang.org/issues/18020
-[Feature #18029]: https://bugs.ruby-lang.org/issues/18029
-[Feature #18045]: https://bugs.ruby-lang.org/issues/18045
-[Feature #18148]: https://bugs.ruby-lang.org/issues/18148
-[Feature #18172]: https://bugs.ruby-lang.org/issues/18172
-[Feature #18176]: https://bugs.ruby-lang.org/issues/18176
-[Feature #18190]: https://bugs.ruby-lang.org/issues/18190
-[Feature #18229]: https://bugs.ruby-lang.org/issues/18229
-[Feature #18239]: https://bugs.ruby-lang.org/issues/18239
-[Feature #18254]: https://bugs.ruby-lang.org/issues/18254
-[Feature #18273]: https://bugs.ruby-lang.org/issues/18273
-[Feature #18290]: https://bugs.ruby-lang.org/issues/18290
-
-[GH-1509]: https://github.com/ruby/ruby/pull/1509
-[GH-4815]: https://github.com/ruby/ruby/pull/4815
-[GH-5112]: https://github.com/ruby/ruby/pull/5112
-[GH-5131]: https://github.com/ruby/ruby/pull/5131
-[GH-5146]: https://github.com/ruby/ruby/pull/5146
+* The MJIT compiler is re-implemented in Ruby as `ruby_vm/mjit/compiler`.
+* MJIT compiler is executed under a forked Ruby process instead of
+ doing it in a native thread called MJIT worker. [[Feature #18968]]
+ * As a result, Microsoft Visual Studio (MSWIN) is no longer supported.
+* MinGW is no longer supported. [[Feature #18824]]
+* Rename `--mjit-min-calls` to `--mjit-call-threshold`.
+* Change default `--mjit-max-cache` back from 10000 to 100.
+
+[Feature #12005]: https://bugs.ruby-lang.org/issues/12005
+[Feature #12084]: https://bugs.ruby-lang.org/issues/12084
+[Feature #12655]: https://bugs.ruby-lang.org/issues/12655
+[Feature #12737]: https://bugs.ruby-lang.org/issues/12737
+[Feature #13110]: https://bugs.ruby-lang.org/issues/13110
+[Feature #14332]: https://bugs.ruby-lang.org/issues/14332
+[Feature #15231]: https://bugs.ruby-lang.org/issues/15231
+[Feature #15357]: https://bugs.ruby-lang.org/issues/15357
+[Bug #15928]: https://bugs.ruby-lang.org/issues/15928
+[Feature #16122]: https://bugs.ruby-lang.org/issues/16122
+[Feature #16131]: https://bugs.ruby-lang.org/issues/16131
+[Bug #16466]: https://bugs.ruby-lang.org/issues/16466
+[Feature #16663]: https://bugs.ruby-lang.org/issues/16663
+[Feature #16806]: https://bugs.ruby-lang.org/issues/16806
+[Bug #16889]: https://bugs.ruby-lang.org/issues/16889
+[Bug #16908]: https://bugs.ruby-lang.org/issues/16908
+[Feature #16989]: https://bugs.ruby-lang.org/issues/16989
+[Feature #17351]: https://bugs.ruby-lang.org/issues/17351
+[Feature #17391]: https://bugs.ruby-lang.org/issues/17391
+[Bug #17545]: https://bugs.ruby-lang.org/issues/17545
+[Bug #17767]: https://bugs.ruby-lang.org/issues/17767
+[Feature #17837]: https://bugs.ruby-lang.org/issues/17837
+[Feature #17881]: https://bugs.ruby-lang.org/issues/17881
+[Feature #18033]: https://bugs.ruby-lang.org/issues/18033
+[Feature #18159]: https://bugs.ruby-lang.org/issues/18159
+[Feature #18239]: https://bugs.ruby-lang.org/issues/18239#note-17
+[Feature #18351]: https://bugs.ruby-lang.org/issues/18351
+[Feature #18367]: https://bugs.ruby-lang.org/issues/18367
+[Bug #18435]: https://bugs.ruby-lang.org/issues/18435
+[Feature #18462]: https://bugs.ruby-lang.org/issues/18462
+[Feature #18481]: https://bugs.ruby-lang.org/issues/18481
+[Bug #18487]: https://bugs.ruby-lang.org/issues/18487
+[Feature #18564]: https://bugs.ruby-lang.org/issues/18564
+[Feature #18571]: https://bugs.ruby-lang.org/issues/18571
+[Feature #18585]: https://bugs.ruby-lang.org/issues/18585
+[Feature #18589]: https://bugs.ruby-lang.org/issues/18589
+[Feature #18595]: https://bugs.ruby-lang.org/issues/18595
+[Feature #18598]: https://bugs.ruby-lang.org/issues/18598
+[Bug #18625]: https://bugs.ruby-lang.org/issues/18625
+[Feature #18630]: https://bugs.ruby-lang.org/issues/18630
+[Bug #18633]: https://bugs.ruby-lang.org/issues/18633
+[Feature #18639]: https://bugs.ruby-lang.org/issues/18639
+[Feature #18685]: https://bugs.ruby-lang.org/issues/18685
+[Bug #18729]: https://bugs.ruby-lang.org/issues/18729
+[Bug #18751]: https://bugs.ruby-lang.org/issues/18751
+[Feature #18774]: https://bugs.ruby-lang.org/issues/18774
+[Feature #18776]: https://bugs.ruby-lang.org/issues/18776
+[Bug #18782]: https://bugs.ruby-lang.org/issues/18782
+[Feature #18788]: https://bugs.ruby-lang.org/issues/18788
+[Feature #18798]: https://bugs.ruby-lang.org/issues/18798
+[Feature #18809]: https://bugs.ruby-lang.org/issues/18809
+[Feature #18821]: https://bugs.ruby-lang.org/issues/18821
+[Feature #18822]: https://bugs.ruby-lang.org/issues/18822
+[Feature #18824]: https://bugs.ruby-lang.org/issues/18824
+[Feature #18832]: https://bugs.ruby-lang.org/issues/18832
+[Feature #18875]: https://bugs.ruby-lang.org/issues/18875
+[Feature #18925]: https://bugs.ruby-lang.org/issues/18925
+[Feature #18944]: https://bugs.ruby-lang.org/issues/18944
+[Feature #18949]: https://bugs.ruby-lang.org/issues/18949
+[Feature #18968]: https://bugs.ruby-lang.org/issues/18968
+[Feature #19008]: https://bugs.ruby-lang.org/issues/19008
+[Feature #19013]: https://bugs.ruby-lang.org/issues/19013
+[Feature #19026]: https://bugs.ruby-lang.org/issues/19026
+[Feature #19036]: https://bugs.ruby-lang.org/issues/19036
+[Feature #19060]: https://bugs.ruby-lang.org/issues/19060
+[Feature #19070]: https://bugs.ruby-lang.org/issues/19070
+[Feature #19071]: https://bugs.ruby-lang.org/issues/19071
+[Feature #19078]: https://bugs.ruby-lang.org/issues/19078
+[Bug #19087]: https://bugs.ruby-lang.org/issues/19087
+[Bug #19100]: https://bugs.ruby-lang.org/issues/19100
+[Feature #19104]: https://bugs.ruby-lang.org/issues/19104
+[Feature #19135]: https://bugs.ruby-lang.org/issues/19135
+[Feature #19138]: https://bugs.ruby-lang.org/issues/19138
+[Feature #19194]: https://bugs.ruby-lang.org/issues/19194
+[Molinillo]: https://github.com/CocoaPods/Molinillo
+[PubGrub]: https://github.com/jhawthorn/pub_grub
+[GH-net-protocol-14]: https://github.com/ruby/net-protocol/pull/14
+[GH-pathname-20]: https://github.com/ruby/pathname/pull/20
+[GH-6791]: https://github.com/ruby/ruby/pull/6791
+[GH-6868]: https://github.com/ruby/ruby/pull/6868
+[GH-rubygems-4475]: https://github.com/rubygems/rubygems/pull/4475
+[GH-rubygems-6149]: https://github.com/rubygems/rubygems/pull/6149
+[GH-rubygems-6167]: https://github.com/rubygems/rubygems/pull/6167
+[sec-156615]: https://hackerone.com/reports/156615
+[CVE-2021-33621]: https://www.ruby-lang.org/en/news/2022/11/22/http-response-splitting-in-cgi-cve-2021-33621/
+[wasm/README.md]: https://github.com/ruby/ruby/blob/master/wasm/README.md
+[ruby.wasm]: https://github.com/ruby/ruby.wasm
diff --git a/README.ja.md b/README.ja.md
index 4516c71459..93c0131690 100644
--- a/README.ja.md
+++ b/README.ja.md
@@ -1,10 +1,9 @@
-[![Build Status](https://travis-ci.org/ruby/ruby.svg?branch=master)](https://travis-ci.org/ruby/ruby)
-[![Build status](https://ci.appveyor.com/api/projects/status/0sy8rrxut4o0k960/branch/master?svg=true)](https://ci.appveyor.com/project/ruby/ruby/branch/master)
-[![Actions Status: macOS](https://github.com/ruby/ruby/workflows/macOS/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"macOS")
[![Actions Status: MinGW](https://github.com/ruby/ruby/workflows/MinGW/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"MinGW")
[![Actions Status: MJIT](https://github.com/ruby/ruby/workflows/MJIT/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"MJIT")
[![Actions Status: Ubuntu](https://github.com/ruby/ruby/workflows/Ubuntu/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"Ubuntu")
[![Actions Status: Windows](https://github.com/ruby/ruby/workflows/Windows/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"Windows")
+[![AppVeyor status](https://ci.appveyor.com/api/projects/status/0sy8rrxut4o0k960/branch/master?svg=true)](https://ci.appveyor.com/project/ruby/ruby/branch/master)
+[![Travis Status](https://app.travis-ci.com/ruby/ruby.svg?branch=master)](https://app.travis-ci.com/ruby/ruby)
# Rubyとは
diff --git a/README.md b/README.md
index 9b5a553ffb..c445448c71 100644
--- a/README.md
+++ b/README.md
@@ -4,9 +4,8 @@
[![Actions Status: Windows](https://github.com/ruby/ruby/workflows/Windows/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"Windows")
[![AppVeyor status](https://ci.appveyor.com/api/projects/status/0sy8rrxut4o0k960/branch/master?svg=true)](https://ci.appveyor.com/project/ruby/ruby/branch/master)
[![Travis Status](https://app.travis-ci.com/ruby/ruby.svg?branch=master)](https://app.travis-ci.com/ruby/ruby)
-[![Cirrus Status](https://api.cirrus-ci.com/github/ruby/ruby.svg)](https://cirrus-ci.com/github/ruby/ruby/master)
-# What's Ruby
+# What is Ruby?
Ruby is an interpreted object-oriented programming language often
used for web development. It also offers many scripting features
@@ -15,28 +14,25 @@ It is simple, straightforward, and extensible.
## Features of Ruby
-* Simple Syntax
-* **Normal** Object-oriented Features (e.g. class, method calls)
-* **Advanced** Object-oriented Features (e.g. mix-in, singleton-method)
-* Operator Overloading
-* Exception Handling
-* Iterators and Closures
-* Garbage Collection
-* Dynamic Loading of Object Files (on some architectures)
-* Highly Portable (works on many Unix-like/POSIX compatible platforms as
- well as Windows, macOS, etc.) cf.
- https://github.com/ruby/ruby/blob/master/doc/maintainers.rdoc#label-Platform+Maintainers
+* Simple Syntax
+* **Normal** Object-oriented Features (e.g. class, method calls)
+* **Advanced** Object-oriented Features (e.g. mix-in, singleton-method)
+* Operator Overloading
+* Exception Handling
+* Iterators and Closures
+* Garbage Collection
+* Dynamic Loading of Object Files (on some architectures)
+* Highly Portable (works on many Unix-like/POSIX compatible platforms as
+ well as Windows, macOS, etc.) cf.
+ https://github.com/ruby/ruby/blob/master/doc/maintainers.rdoc#label-Platform+Maintainers
-
-## How to get Ruby
+## How to get Ruby with Git
For a complete list of ways to install Ruby, including using third-party tools
like rvm, see:
https://www.ruby-lang.org/en/downloads/
-### Git
-
The mirror of the Ruby source tree can be checked out with the following command:
$ git clone https://github.com/ruby/ruby.git
@@ -49,22 +45,19 @@ to see the list of branches:
You may also want to use https://git.ruby-lang.org/ruby.git (actual master of Ruby source)
if you are a committer.
-### Subversion
-
-Stable branches for older Ruby versions can be checked out with also the
-following command:
-
- $ svn co https://svn.ruby-lang.org/repos/ruby/branches/ruby_2_6/ ruby
-
-Try the following command to see the list of branches:
-
- $ svn ls https://svn.ruby-lang.org/repos/ruby/branches/
+## How to build
+see [Building Ruby](doc/contributing/building_ruby.md)
## Ruby home page
https://www.ruby-lang.org/
+## Documentation
+
+- [English](https://docs.ruby-lang.org/en/master/index.html)
+- [Japanese](https://docs.ruby-lang.org/ja/master/index.html)
+
## Mailing list
There is a mailing list to discuss Ruby. To subscribe to this list, please
@@ -76,108 +69,20 @@ in the mail body (not subject) to the address [ruby-talk-request@ruby-lang.org].
[ruby-talk-request@ruby-lang.org]: mailto:ruby-talk-request@ruby-lang.org?subject=Join%20Ruby%20Mailing%20List&body=subscribe
-## Requirements to build from repository
-
-1. GNU or BSD make
-2. C99 compiler
-3. autoconf 2.67 or higher
-4. automake 1.15 or higher
-5. bison 2.3 or higher
-6. Ruby 2.2 or higher
-
-When building from a released version, only a C99 compiler and GNU or BSD make
-is required.
-
-## How to compile and install
-
-1. If you want to use Microsoft Visual C++ to compile Ruby, read
- [win32/README.win32](rdoc-ref:win32/README.win32) instead of this document.
-
-2. Run `./autogen.sh` to generate configure, when you build the source checked
- out from the Git repository.
-
-3. Run `./configure`, which will generate `config.h` and `Makefile`.
-
- Some C compiler flags may be added by default depending on your
- environment. Specify `optflags=..` and `warnflags=..` as necessary to
- override them.
-
-4. Edit `include/ruby/defines.h` if you need. Usually this step will not be needed.
-
-5. Optional: Remove comment mark(`#`) before the module names from `ext/Setup`.
-
- This step is only necessary if you want to link modules statically.
-
- If you don't want to compile dynamic extensions (probably on architectures
- which do not allow dynamic loading), remove comment mark from the line
- "`#option nodynamic`" in `ext/Setup`.
-
- Usually this step will not be needed.
-
-6. Run `make`.
-
- * On Mac, set RUBY\_CODESIGN environment variable with a signing identity.
- It uses the identity to sign `ruby` binary. See also codesign(1).
-
-7. Optionally, run '`make check`' to check whether the compiled Ruby
- interpreter works well. If you see the message "`check succeeded`", your
- Ruby works as it should (hopefully).
-
-8. Run '`make install`'.
-
- This command will create the following directories and install files into
- them.
-
- * `${DESTDIR}${prefix}/bin`
- * `${DESTDIR}${prefix}/include/ruby-${MAJOR}.${MINOR}.${TEENY}`
- * `${DESTDIR}${prefix}/include/ruby-${MAJOR}.${MINOR}.${TEENY}/${PLATFORM}`
- * `${DESTDIR}${prefix}/lib`
- * `${DESTDIR}${prefix}/lib/ruby`
- * `${DESTDIR}${prefix}/lib/ruby/${MAJOR}.${MINOR}.${TEENY}`
- * `${DESTDIR}${prefix}/lib/ruby/${MAJOR}.${MINOR}.${TEENY}/${PLATFORM}`
- * `${DESTDIR}${prefix}/lib/ruby/site_ruby`
- * `${DESTDIR}${prefix}/lib/ruby/site_ruby/${MAJOR}.${MINOR}.${TEENY}`
- * `${DESTDIR}${prefix}/lib/ruby/site_ruby/${MAJOR}.${MINOR}.${TEENY}/${PLATFORM}`
- * `${DESTDIR}${prefix}/lib/ruby/vendor_ruby`
- * `${DESTDIR}${prefix}/lib/ruby/vendor_ruby/${MAJOR}.${MINOR}.${TEENY}`
- * `${DESTDIR}${prefix}/lib/ruby/vendor_ruby/${MAJOR}.${MINOR}.${TEENY}/${PLATFORM}`
- * `${DESTDIR}${prefix}/lib/ruby/gems/${MAJOR}.${MINOR}.${TEENY}`
- * `${DESTDIR}${prefix}/share/man/man1`
- * `${DESTDIR}${prefix}/share/ri/${MAJOR}.${MINOR}.${TEENY}/system`
-
-
- If Ruby's API version is '*x.y.z*', the `${MAJOR}` is '*x*', the
- `${MINOR}` is '*y*', and the `${TEENY}` is '*z*'.
-
- **NOTE**: teeny of the API version may be different from one of Ruby's
- program version
-
- You may have to be a super user to install Ruby.
-
-If you fail to compile Ruby, please send the detailed error report with the
-error log and machine/OS type, to help others.
-
-Some extension libraries may not get compiled because of lack of necessary
-external libraries and/or headers, then you will need to run '`make distclean-ext`'
-to remove old configuration after installing them in such case.
-
## Copying
See the file [COPYING](rdoc-ref:COPYING).
## Feedback
-Questions about the Ruby language can be asked on the [Ruby-Talk] mailing list
+Questions about the Ruby language can be asked on the [Ruby-Talk](https://www.ruby-lang.org/en/community/mailing-lists) mailing list
or on websites like https://stackoverflow.com.
-Bugs should be reported at https://bugs.ruby-lang.org. Read [HowToReport] for more information.
-
-[Ruby-Talk]: https://www.ruby-lang.org/en/community/mailing-lists
-[HowToReport]: https://bugs.ruby-lang.org/projects/ruby/wiki/HowToReport
+Bugs should be reported at https://bugs.ruby-lang.org. Read ["Reporting Issues"](https://docs.ruby-lang.org/en/master/contributing/reporting_issues_md.html) for more information.
## Contributing
-See the file [CONTRIBUTING.md](rdoc-ref:CONTRIBUTING)
+See ["Contributing to Ruby"](https://docs.ruby-lang.org/en/master/contributing_md.html), which includes setup and build instructions.
## The Author
diff --git a/addr2line.c b/addr2line.c
index f660be9129..e5f25293e2 100644
--- a/addr2line.c
+++ b/addr2line.c
@@ -159,12 +159,15 @@ typedef struct obj_info {
struct dwarf_section debug_info;
struct dwarf_section debug_line;
struct dwarf_section debug_ranges;
+ struct dwarf_section debug_str_offsets;
+ struct dwarf_section debug_addr;
struct dwarf_section debug_rnglists;
struct dwarf_section debug_str;
+ struct dwarf_section debug_line_str;
struct obj_info *next;
} obj_info_t;
-#define DWARF_SECTION_COUNT 6
+#define DWARF_SECTION_COUNT 9
static struct dwarf_section *
obj_dwarf_section_at(obj_info_t *obj, int n)
@@ -174,8 +177,11 @@ obj_dwarf_section_at(obj_info_t *obj, int n)
&obj->debug_info,
&obj->debug_line,
&obj->debug_ranges,
+ &obj->debug_str_offsets,
+ &obj->debug_addr,
&obj->debug_rnglists,
- &obj->debug_str
+ &obj->debug_str,
+ &obj->debug_line_str
};
if (n < 0 || DWARF_SECTION_COUNT <= n) {
abort();
@@ -248,39 +254,51 @@ get_nth_dirname(unsigned long dir, const char *p)
return p;
}
+static const char *parse_ver5_debug_line_header(const char *p, int idx, uint8_t format, obj_info_t *obj, const char **out_path, uint64_t *out_directory_index);
+
static void
-fill_filename(int file, const char *include_directories, const char *filenames, line_info_t *line, obj_info_t *obj)
+fill_filename(int file, uint8_t format, uint16_t version, const char *include_directories, const char *filenames, line_info_t *line, obj_info_t *obj)
{
int i;
const char *p = filenames;
const char *filename;
unsigned long dir;
- for (i = 1; i <= file; i++) {
- filename = p;
- if (!*p) {
- /* Need to output binary file name? */
- kprintf("Unexpected file number %d in %s at %tx\n",
- file, binary_filename, filenames - obj->mapped);
- return;
- }
- while (*p) p++;
- p++;
- dir = uleb128(&p);
- /* last modified. */
- uleb128(&p);
- /* size of the file. */
- uleb128(&p);
-
- if (i == file) {
- line->filename = filename;
- line->dirname = get_nth_dirname(dir, include_directories);
- }
+ if (version >= 5) {
+ const char *path;
+ uint64_t directory_index = -1;
+ parse_ver5_debug_line_header(filenames, file, format, obj, &path, &directory_index);
+ line->filename = path;
+ parse_ver5_debug_line_header(include_directories, (int)directory_index, format, obj, &path, NULL);
+ line->dirname = path;
+ }
+ else {
+ for (i = 1; i <= file; i++) {
+ filename = p;
+ if (!*p) {
+ /* Need to output binary file name? */
+ kprintf("Unexpected file number %d in %s at %tx\n",
+ file, binary_filename, filenames - obj->mapped);
+ return;
+ }
+ while (*p) p++;
+ p++;
+ dir = uleb128(&p);
+ /* last modified. */
+ uleb128(&p);
+ /* size of the file. */
+ uleb128(&p);
+
+ if (i == file) {
+ line->filename = filename;
+ line->dirname = get_nth_dirname(dir, include_directories);
+ }
+ }
}
}
static void
fill_line(int num_traces, void **traces, uintptr_t addr, int file, int line,
- const char *include_directories, const char *filenames,
+ uint8_t format, uint16_t version, const char *include_directories, const char *filenames,
obj_info_t *obj, line_info_t *lines, int offset)
{
int i;
@@ -290,7 +308,7 @@ fill_line(int num_traces, void **traces, uintptr_t addr, int file, int line,
/* We assume one line code doesn't result >100 bytes of native code.
We may want more reliable way eventually... */
if (addr < a && a < addr + 100) {
- fill_filename(file, include_directories, filenames, &lines[i], obj);
+ fill_filename(file, format, version, include_directories, filenames, &lines[i], obj);
lines[i].line = line;
}
}
@@ -315,7 +333,7 @@ struct LineNumberProgramHeader {
};
static int
-parse_debug_line_header(const char **pp, struct LineNumberProgramHeader *header)
+parse_debug_line_header(obj_info_t *obj, const char **pp, struct LineNumberProgramHeader *header)
{
const char *p = *pp;
header->unit_length = *(uint32_t *)p;
@@ -332,7 +350,13 @@ parse_debug_line_header(const char **pp, struct LineNumberProgramHeader *header)
header->version = *(uint16_t *)p;
p += sizeof(uint16_t);
- if (header->version > 4) return -1;
+ if (header->version > 5) return -1;
+
+ if (header->version >= 5) {
+ /* address_size = *(uint8_t *)p++; */
+ /* segment_selector_size = *(uint8_t *)p++; */
+ p += 2;
+ }
header->header_length = header->format == 4 ? *(uint32_t *)p : *(uint64_t *)p;
p += header->format;
@@ -353,20 +377,27 @@ parse_debug_line_header(const char **pp, struct LineNumberProgramHeader *header)
/* header->standard_opcode_lengths = (uint8_t *)p - 1; */
p += header->opcode_base - 1;
- header->include_directories = p;
+ if (header->version >= 5) {
+ header->include_directories = p;
+ p = parse_ver5_debug_line_header(p, -1, header->format, obj, NULL, NULL);
+ header->filenames = p;
+ }
+ else {
+ header->include_directories = p;
- /* temporary measure for compress-debug-sections */
- if (p >= header->cu_end) return -1;
+ /* temporary measure for compress-debug-sections */
+ if (p >= header->cu_end) return -1;
- /* skip include directories */
- while (*p) {
- p = memchr(p, '\0', header->cu_end - p);
- if (!p) return -1;
- p++;
- }
- p++;
+ /* skip include directories */
+ while (*p) {
+ p = memchr(p, '\0', header->cu_end - p);
+ if (!p) return -1;
+ p++;
+ }
+ p++;
- header->filenames = p;
+ header->filenames = p;
+ }
*pp = header->cu_start;
@@ -392,13 +423,15 @@ parse_debug_line_cu(int num_traces, void **traces, const char **debug_line,
/* int epilogue_begin = 0; */
/* unsigned int isa = 0; */
- if (parse_debug_line_header(&p, &header))
+ if (parse_debug_line_header(obj, &p, &header))
return -1;
is_stmt = header.default_is_stmt;
#define FILL_LINE() \
do { \
fill_line(num_traces, traces, addr, file, line, \
+ header.format, \
+ header.version, \
header.include_directories, \
header.filenames, \
obj, lines, offset); \
@@ -827,16 +860,23 @@ enum {
VAL_cstr = 1,
VAL_data = 2,
VAL_uint = 3,
- VAL_int = 4
+ VAL_int = 4,
+ VAL_addr = 5
};
# define ABBREV_TABLE_SIZE 256
typedef struct {
obj_info_t *obj;
const char *file;
+ uint8_t current_version;
const char *current_cu;
uint64_t current_low_pc;
+ uint64_t current_str_offsets_base;
+ uint64_t current_addr_base;
+ uint64_t current_rnglists_base;
const char *debug_line_cu_end;
+ uint8_t debug_line_format;
+ uint16_t debug_line_version;
const char *debug_line_files;
const char *debug_line_directories;
const char *p;
@@ -861,6 +901,7 @@ typedef struct {
const char *ptr;
uint64_t uint64;
int64_t int64;
+ uint64_t addr_idx;
} as;
uint64_t off;
uint64_t at;
@@ -869,8 +910,11 @@ typedef struct {
int type;
} DebugInfoValue;
-/* TODO: Big Endian */
+#if defined(WORDS_BIGENDIAN)
+#define MERGE_2INTS(a,b,sz) (((uint64_t)(a)<<sz)|(b))
+#else
#define MERGE_2INTS(a,b,sz) (((uint64_t)(b)<<sz)|(a))
+#endif
static uint16_t
get_uint16(const uint8_t *p)
@@ -973,6 +1017,9 @@ debug_info_reader_init(DebugInfoReader *reader, obj_info_t *obj)
reader->pend = obj->debug_info.ptr + obj->debug_info.size;
reader->debug_line_cu_end = obj->debug_line.ptr;
reader->current_low_pc = 0;
+ reader->current_str_offsets_base = 0;
+ reader->current_addr_base = 0;
+ reader->current_rnglists_base = 0;
}
static void
@@ -1017,10 +1064,12 @@ di_read_debug_line_cu(DebugInfoReader *reader)
struct LineNumberProgramHeader header;
p = (const char *)reader->debug_line_cu_end;
- if (parse_debug_line_header(&p, &header))
+ if (parse_debug_line_header(reader->obj, &p, &header))
return -1;
reader->debug_line_cu_end = (char *)header.cu_end;
+ reader->debug_line_format = header.format;
+ reader->debug_line_version = header.version;
reader->debug_line_directories = (char *)header.include_directories;
reader->debug_line_files = (char *)header.filenames;
@@ -1028,6 +1077,13 @@ di_read_debug_line_cu(DebugInfoReader *reader)
}
static void
+set_addr_idx_value(DebugInfoValue *v, uint64_t n)
+{
+ v->as.addr_idx = n;
+ v->type = VAL_addr;
+}
+
+static void
set_uint_value(DebugInfoValue *v, uint64_t n)
{
v->as.uint64 = n;
@@ -1074,19 +1130,39 @@ get_cstr_value(DebugInfoValue *v)
}
}
+static const char *
+resolve_strx(DebugInfoReader *reader, uint64_t idx)
+{
+ const char *p = reader->obj->debug_str_offsets.ptr + reader->current_str_offsets_base;
+ uint64_t off;
+ if (reader->format == 4) {
+ off = ((uint32_t *)p)[idx];
+ }
+ else {
+ off = ((uint64_t *)p)[idx];
+ }
+ return reader->obj->debug_str.ptr + off;
+}
+
+static void
+debug_info_reader_read_addr_value(DebugInfoReader *reader, DebugInfoValue *v)
+{
+ if (reader->address_size == 4) {
+ set_uint_value(v, read_uint32(&reader->p));
+ } else if (reader->address_size == 8) {
+ set_uint_value(v, read_uint64(&reader->p));
+ } else {
+ fprintf(stderr,"unknown address_size:%d", reader->address_size);
+ abort();
+ }
+}
+
static void
debug_info_reader_read_value(DebugInfoReader *reader, uint64_t form, DebugInfoValue *v)
{
switch (form) {
case DW_FORM_addr:
- if (reader->address_size == 4) {
- set_uint_value(v, read_uint32(&reader->p));
- } else if (reader->address_size == 8) {
- set_uint_value(v, read_uint64(&reader->p));
- } else {
- fprintf(stderr,"unknown address_size:%d", reader->address_size);
- abort();
- }
+ debug_info_reader_read_addr_value(reader, v);
break;
case DW_FORM_block2:
v->size = read_uint16(&reader->p);
@@ -1138,13 +1214,19 @@ debug_info_reader_read_value(DebugInfoReader *reader, uint64_t form, DebugInfoVa
set_uint_value(v, read_uleb128(reader));
break;
case DW_FORM_ref_addr:
- if (reader->format == 4) {
- set_uint_value(v, read_uint32(&reader->p));
- } else if (reader->format == 8) {
- set_uint_value(v, read_uint64(&reader->p));
+ if (reader->current_version <= 2) {
+ // DWARF Version 2 specifies that references have
+ // the same size as an address on the target system
+ debug_info_reader_read_addr_value(reader, v);
} else {
- fprintf(stderr,"unknown format:%d", reader->format);
- abort();
+ if (reader->format == 4) {
+ set_uint_value(v, read_uint32(&reader->p));
+ } else if (reader->format == 8) {
+ set_uint_value(v, read_uint64(&reader->p));
+ } else {
+ fprintf(stderr,"unknown format:%d", reader->format);
+ abort();
+ }
}
break;
case DW_FORM_ref1:
@@ -1186,11 +1268,10 @@ debug_info_reader_read_value(DebugInfoReader *reader, uint64_t form, DebugInfoVa
set_uint_value(v, 1);
break;
case DW_FORM_strx:
- set_uint_value(v, uleb128(&reader->p));
+ set_cstr_value(v, resolve_strx(reader, uleb128(&reader->p)));
break;
case DW_FORM_addrx:
- /* TODO: read .debug_addr */
- set_uint_value(v, uleb128(&reader->p));
+ set_addr_idx_value(v, uleb128(&reader->p));
break;
case DW_FORM_ref_sup4:
set_uint_value(v, read_uint32(&reader->p));
@@ -1205,8 +1286,7 @@ debug_info_reader_read_value(DebugInfoReader *reader, uint64_t form, DebugInfoVa
reader->p += v->size;
break;
case DW_FORM_line_strp:
- set_uint_value(v, read_uint(reader));
- /* *p = reader->file + reader->line->sh_offset + ret; */
+ set_cstrp_value(v, reader->obj->debug_line_str.ptr, read_uint(reader));
break;
case DW_FORM_ref_sig8:
set_uint_value(v, read_uint64(&reader->p));
@@ -1224,28 +1304,28 @@ debug_info_reader_read_value(DebugInfoReader *reader, uint64_t form, DebugInfoVa
set_uint_value(v, read_uint64(&reader->p));
break;
case DW_FORM_strx1:
- set_uint_value(v, read_uint8(&reader->p));
+ set_cstr_value(v, resolve_strx(reader, read_uint8(&reader->p)));
break;
case DW_FORM_strx2:
- set_uint_value(v, read_uint16(&reader->p));
+ set_cstr_value(v, resolve_strx(reader, read_uint16(&reader->p)));
break;
case DW_FORM_strx3:
- set_uint_value(v, read_uint24(&reader->p));
+ set_cstr_value(v, resolve_strx(reader, read_uint24(&reader->p)));
break;
case DW_FORM_strx4:
- set_uint_value(v, read_uint32(&reader->p));
+ set_cstr_value(v, resolve_strx(reader, read_uint32(&reader->p)));
break;
case DW_FORM_addrx1:
- set_uint_value(v, read_uint8(&reader->p));
+ set_addr_idx_value(v, read_uint8(&reader->p));
break;
case DW_FORM_addrx2:
- set_uint_value(v, read_uint16(&reader->p));
+ set_addr_idx_value(v, read_uint16(&reader->p));
break;
case DW_FORM_addrx3:
- set_uint_value(v, read_uint24(&reader->p));
+ set_addr_idx_value(v, read_uint24(&reader->p));
break;
case DW_FORM_addrx4:
- set_uint_value(v, read_uint32(&reader->p));
+ set_addr_idx_value(v, read_uint32(&reader->p));
break;
case 0:
goto fail;
@@ -1292,7 +1372,7 @@ hexdump0(const unsigned char *p, size_t n)
for (i=0; i < n; i++){
switch (i & 15) {
case 0:
- fprintf(stderr, "%02zd: %02X ", i/16, p[i]);
+ fprintf(stderr, "%02" PRIdSIZE ": %02X ", i/16, p[i]);
break;
case 15:
fprintf(stderr, "%02X\n", p[i]);
@@ -1313,16 +1393,16 @@ div_inspect(DebugInfoValue *v)
{
switch (v->type) {
case VAL_uint:
- fprintf(stderr,"%d: type:%d size:%zx v:%"PRIx64"\n",__LINE__,v->type,v->size,v->as.uint64);
+ fprintf(stderr,"%d: type:%d size:%" PRIxSIZE " v:%"PRIx64"\n",__LINE__,v->type,v->size,v->as.uint64);
break;
case VAL_int:
- fprintf(stderr,"%d: type:%d size:%zx v:%"PRId64"\n",__LINE__,v->type,v->size,(int64_t)v->as.uint64);
+ fprintf(stderr,"%d: type:%d size:%" PRIxSIZE " v:%"PRId64"\n",__LINE__,v->type,v->size,(int64_t)v->as.uint64);
break;
case VAL_cstr:
- fprintf(stderr,"%d: type:%d size:%zx v:'%s'\n",__LINE__,v->type,v->size,v->as.ptr);
+ fprintf(stderr,"%d: type:%d size:%" PRIxSIZE " v:'%s'\n",__LINE__,v->type,v->size,v->as.ptr);
break;
case VAL_data:
- fprintf(stderr,"%d: type:%d size:%zx v:\n",__LINE__,v->type,v->size);
+ fprintf(stderr,"%d: type:%d size:%" PRIxSIZE " v:\n",__LINE__,v->type,v->size);
hexdump(v->as.ptr, 16);
break;
}
@@ -1373,6 +1453,76 @@ di_skip_records(DebugInfoReader *reader)
}
}
+typedef struct addr_header {
+ const char *ptr;
+ uint64_t unit_length;
+ uint8_t format;
+ uint8_t address_size;
+ /* uint8_t segment_selector_size; */
+} addr_header_t;
+
+static void
+addr_header_init(obj_info_t *obj, addr_header_t *header) {
+ const char *p = obj->debug_addr.ptr;
+
+ header->ptr = p;
+
+ if (!p) return;
+
+ header->unit_length = *(uint32_t *)p;
+ p += sizeof(uint32_t);
+
+ header->format = 4;
+ if (header->unit_length == 0xffffffff) {
+ header->unit_length = *(uint64_t *)p;
+ p += sizeof(uint64_t);
+ header->format = 8;
+ }
+
+ p += 2; /* version */
+ header->address_size = *p++;
+ p++; /* segment_selector_size */
+}
+
+static uint64_t
+read_addr(addr_header_t *header, uint64_t addr_base, uint64_t idx) {
+ if (header->address_size == 4) {
+ return ((uint32_t*)(header->ptr + addr_base))[idx];
+ }
+ else {
+ return ((uint64_t*)(header->ptr + addr_base))[idx];
+ }
+}
+
+typedef struct rnglists_header {
+ uint64_t unit_length;
+ uint8_t format;
+ uint8_t address_size;
+ uint32_t offset_entry_count;
+} rnglists_header_t;
+
+static void
+rnglists_header_init(obj_info_t *obj, rnglists_header_t *header) {
+ const char *p = obj->debug_rnglists.ptr;
+
+ if (!p) return;
+
+ header->unit_length = *(uint32_t *)p;
+ p += sizeof(uint32_t);
+
+ header->format = 4;
+ if (header->unit_length == 0xffffffff) {
+ header->unit_length = *(uint64_t *)p;
+ p += sizeof(uint64_t);
+ header->format = 8;
+ }
+
+ p += 2; /* version */
+ header->address_size = *p++;
+ p++; /* segment_selector_size */
+ header->offset_entry_count = *(uint32_t *)p;
+}
+
typedef struct {
uint64_t low_pc;
uint64_t high_pc;
@@ -1383,24 +1533,31 @@ typedef struct {
} ranges_t;
static void
-ranges_set(ranges_t *ptr, DebugInfoValue *v)
+ranges_set(ranges_t *ptr, DebugInfoValue *v, addr_header_t *addr_header, uint64_t addr_base)
{
+ uint64_t n = 0;
+ if (v->type == VAL_uint) {
+ n = v->as.uint64;
+ }
+ else if (v->type == VAL_addr) {
+ n = read_addr(addr_header, addr_base, v->as.addr_idx);
+ }
switch (v->at) {
case DW_AT_low_pc:
- ptr->low_pc = v->as.uint64;
+ ptr->low_pc = n;
ptr->low_pc_set = true;
break;
case DW_AT_high_pc:
if (v->form == DW_FORM_addr) {
- ptr->high_pc = v->as.uint64;
+ ptr->high_pc = n;
}
else {
- ptr->high_pc = ptr->low_pc + v->as.uint64;
+ ptr->high_pc = ptr->low_pc + n;
}
ptr->high_pc_set = true;
break;
case DW_AT_ranges:
- ptr->ranges = v->as.uint64;
+ ptr->ranges = n;
ptr->ranges_set = true;
break;
}
@@ -1422,7 +1579,7 @@ read_dw_form_addr(DebugInfoReader *reader, const char **ptr)
}
static uintptr_t
-ranges_include(DebugInfoReader *reader, ranges_t *ptr, uint64_t addr)
+ranges_include(DebugInfoReader *reader, ranges_t *ptr, uint64_t addr, rnglists_header_t *rnglists_header)
{
if (ptr->high_pc_set) {
if (ptr->ranges_set || !ptr->low_pc_set) {
@@ -1437,8 +1594,21 @@ ranges_include(DebugInfoReader *reader, ranges_t *ptr, uint64_t addr)
const char *p;
uint64_t base = ptr->low_pc_set ? ptr->low_pc : reader->current_low_pc;
bool base_valid = true;
- if (reader->obj->debug_rnglists.ptr) {
- p = reader->obj->debug_rnglists.ptr + ptr->ranges;
+ if (reader->current_version >= 5) {
+ if (rnglists_header->offset_entry_count == 0) {
+ // DW_FORM_sec_offset
+ p = reader->obj->debug_rnglists.ptr + ptr->ranges + reader->current_rnglists_base;
+ }
+ else {
+ // DW_FORM_rnglistx
+ const char *offset_array = reader->obj->debug_rnglists.ptr + reader->current_rnglists_base;
+ if (rnglists_header->format == 4) {
+ p = offset_array + ((uint32_t *)offset_array)[ptr->ranges];
+ }
+ else {
+ p = offset_array + ((uint64_t *)offset_array)[ptr->ranges];
+ }
+ }
for (;;) {
uint8_t rle = read_uint8(&p);
uintptr_t from = 0, to = 0;
@@ -1548,6 +1718,7 @@ di_read_cu(DebugInfoReader *reader)
}
reader->cu_end = reader->p + unit_length;
version = read_uint16(&reader->p);
+ reader->current_version = version;
if (version > 5) {
return -1;
}
@@ -1580,16 +1751,45 @@ di_read_cu(DebugInfoReader *reader)
break;
}
+ reader->current_str_offsets_base = 0;
+ reader->current_addr_base = 0;
+ reader->current_rnglists_base = 0;
+
+ DebugInfoValue low_pc = {{}};
/* enumerate abbrev */
for (;;) {
DebugInfoValue v = {{}};
if (!di_read_record(reader, &v)) break;
switch (v.at) {
case DW_AT_low_pc:
- reader->current_low_pc = v.as.uint64;
+ // clang may output DW_AT_addr_base after DW_AT_low_pc.
+ // We need to resolve the DW_FORM_addr* after DW_AT_addr_base is parsed.
+ low_pc = v;
+ break;
+ case DW_AT_str_offsets_base:
+ reader->current_str_offsets_base = v.as.uint64;
+ break;
+ case DW_AT_addr_base:
+ reader->current_addr_base = v.as.uint64;
+ break;
+ case DW_AT_rnglists_base:
+ reader->current_rnglists_base = v.as.uint64;
break;
}
}
+ // Resolve the DW_FORM_addr of DW_AT_low_pc
+ switch (low_pc.type) {
+ case VAL_uint:
+ reader->current_low_pc = low_pc.as.uint64;
+ break;
+ case VAL_addr:
+ {
+ addr_header_t header;
+ addr_header_init(reader->obj, &header);
+ reader->current_low_pc = read_addr(&header, reader->current_addr_base, low_pc.as.addr_idx);
+ }
+ break;
+ }
} while (0);
#endif
return 0;
@@ -1643,6 +1843,13 @@ read_abstract_origin(DebugInfoReader *reader, uint64_t form, uint64_t abstract_o
static void
debug_info_read(DebugInfoReader *reader, int num_traces, void **traces,
line_info_t *lines, int offset) {
+
+ addr_header_t addr_header = {};
+ addr_header_init(reader->obj, &addr_header);
+
+ rnglists_header_t rnglists_header = {};
+ rnglists_header_init(reader->obj, &rnglists_header);
+
while (reader->p < reader->cu_end) {
DIE die;
ranges_t ranges = {};
@@ -1669,7 +1876,7 @@ debug_info_read(DebugInfoReader *reader, int num_traces, void **traces,
line.sname = get_cstr_value(&v);
break;
case DW_AT_call_file:
- fill_filename((int)v.as.uint64, reader->debug_line_directories, reader->debug_line_files, &line, reader->obj);
+ fill_filename((int)v.as.uint64, reader->debug_line_format, reader->debug_line_version, reader->debug_line_directories, reader->debug_line_files, &line, reader->obj);
break;
case DW_AT_call_line:
line.line = (int)v.as.uint64;
@@ -1677,7 +1884,7 @@ debug_info_read(DebugInfoReader *reader, int num_traces, void **traces,
case DW_AT_low_pc:
case DW_AT_high_pc:
case DW_AT_ranges:
- ranges_set(&ranges, &v);
+ ranges_set(&ranges, &v, &addr_header, reader->current_addr_base);
break;
case DW_AT_declaration:
goto skip_die;
@@ -1694,9 +1901,9 @@ debug_info_read(DebugInfoReader *reader, int num_traces, void **traces,
for (int i=offset; i < num_traces; i++) {
uintptr_t addr = (uintptr_t)traces[i];
uintptr_t offset = addr - reader->obj->base_addr + reader->obj->vmaddr;
- uintptr_t saddr = ranges_include(reader, &ranges, offset);
+ uintptr_t saddr = ranges_include(reader, &ranges, offset, &rnglists_header);
if (saddr) {
- /* fprintf(stderr, "%d:%tx: %d %lx->%lx %x %s: %s/%s %d %s %s %s\n",__LINE__,die.pos, i,addr,offset, die.tag,line.sname,line.dirname,line.filename,line.line,reader->obj->path,line.sname,lines[i].sname); */
+ /* fprintf(stdout, "%d:%tx: %d %lx->%lx %x %s: %s/%s %d %s %s %s\n",__LINE__,die.pos, i,addr,offset, die.tag,line.sname,line.dirname,line.filename,line.line,reader->obj->path,line.sname,lines[i].sname); */
if (lines[i].sname) {
line_info_t *lp = malloc(sizeof(line_info_t));
memcpy(lp, &lines[i], sizeof(line_info_t));
@@ -1715,6 +1922,54 @@ debug_info_read(DebugInfoReader *reader, int num_traces, void **traces,
}
}
+// This function parses the following attributes of Line Number Program Header in DWARF 5:
+//
+// * directory_entry_format_count
+// * directory_entry_format
+// * directories_count
+// * directories
+//
+// or
+//
+// * file_name_entry_format_count
+// * file_name_entry_format
+// * file_names_count
+// * file_names
+//
+// It records DW_LNCT_path and DW_LNCT_directory_index at the index "idx".
+static const char *
+parse_ver5_debug_line_header(const char *p, int idx, uint8_t format, obj_info_t *obj, const char **out_path, uint64_t *out_directory_index) {
+ int i, j;
+ int entry_format_count = *(uint8_t *)p++;
+ const char *entry_format = p;
+
+ /* skip the part of entry_format */
+ for (i = 0; i < entry_format_count * 2; i++) uleb128(&p);
+
+ int entry_count = (int)uleb128(&p);
+
+ DebugInfoReader reader;
+ debug_info_reader_init(&reader, obj);
+ reader.format = format;
+ reader.p = p;
+ for (j = 0; j < entry_count; j++) {
+ const char *format = entry_format;
+ for (i = 0; i < entry_format_count; i++) {
+ DebugInfoValue v = {{}};
+ unsigned long dw_lnct = uleb128(&format);
+ unsigned long dw_form = uleb128(&format);
+ debug_info_reader_read_value(&reader, dw_form, &v);
+ if (dw_lnct == 1 /* DW_LNCT_path */ && v.type == VAL_cstr && out_path)
+ *out_path = v.as.ptr + v.off;
+ if (dw_lnct == 2 /* DW_LNCT_directory_index */ && v.type == VAL_uint && out_directory_index)
+ *out_directory_index = v.as.uint64;
+ }
+ if (j == idx) return 0;
+ }
+
+ return reader.p;
+}
+
#ifdef USE_ELF
static unsigned long
uncompress_debug_section(ElfW(Shdr) *shdr, char *file, char **ptr)
@@ -1843,8 +2098,11 @@ fill_lines(int num_traces, void **traces, int check_debuglink,
".debug_info",
".debug_line",
".debug_ranges",
+ ".debug_str_offsets",
+ ".debug_addr",
".debug_rnglists",
- ".debug_str"
+ ".debug_str",
+ ".debug_line_str"
};
for (j=0; j < DWARF_SECTION_COUNT; j++) {
@@ -2100,8 +2358,11 @@ found_mach_header:
"__debug_info",
"__debug_line",
"__debug_ranges",
+ "__debug_str_offsets",
+ "__debug_addr",
"__debug_rnglists",
- "__debug_str"
+ "__debug_str",
+ "__debug_line_str",
};
struct LP(segment_command) *scmd = (struct LP(segment_command) *)lcmd;
if (strcmp(scmd->segname, "__TEXT") == 0) {
@@ -2257,9 +2518,12 @@ print_line0(line_info_t *line, void *address)
else if (!line->path) {
kprintf("[0x%"PRIxPTR"]\n", addr);
}
- else if (!line->saddr || !line->sname) {
+ else if (!line->sname) {
kprintf("%s(0x%"PRIxPTR") [0x%"PRIxPTR"]\n", line->path, addr-line->base_addr, addr);
}
+ else if (!line->saddr) {
+ kprintf("%s(%s) [0x%"PRIxPTR"]\n", line->path, line->sname, addr);
+ }
else if (line->line <= 0) {
kprintf("%s(%s+0x%"PRIxPTR") [0x%"PRIxPTR"]\n", line->path, line->sname,
d, addr);
@@ -2296,6 +2560,7 @@ rb_dump_backtrace_with_lines(int num_traces, void **traces)
obj_info_t *obj = NULL;
/* 2 is NULL + main executable */
void **dladdr_fbases = (void **)calloc(num_traces+2, sizeof(void *));
+
#ifdef HAVE_MAIN_EXE_PATH
char *main_path = NULL; /* used on printing backtrace */
ssize_t len;
@@ -2326,8 +2591,8 @@ rb_dump_backtrace_with_lines(int num_traces, void **traces)
/* if the binary is strip-ed, this may effect */
for (p=dladdr_fbases; *p; p++) {
if (*p == info.dli_fbase) {
- lines[i].path = info.dli_fname;
- lines[i].sname = info.dli_sname;
+ if (info.dli_fname) lines[i].path = info.dli_fname;
+ if (info.dli_sname) lines[i].sname = info.dli_sname;
goto next_line;
}
}
@@ -2337,9 +2602,11 @@ rb_dump_backtrace_with_lines(int num_traces, void **traces)
obj->base_addr = (uintptr_t)info.dli_fbase;
path = info.dli_fname;
obj->path = path;
- lines[i].path = path;
- lines[i].sname = info.dli_sname;
- lines[i].saddr = (uintptr_t)info.dli_saddr;
+ if (path) lines[i].path = path;
+ if (info.dli_sname) {
+ lines[i].sname = info.dli_sname;
+ lines[i].saddr = (uintptr_t)info.dli_saddr;
+ }
strlcpy(binary_filename, path, PATH_MAX);
if (fill_lines(num_traces, traces, 1, &obj, lines, i) == (uintptr_t)-1)
break;
diff --git a/array.c b/array.c
index 8becdbbc91..b76e9a64a3 100644
--- a/array.c
+++ b/array.c
@@ -39,6 +39,37 @@
VALUE rb_cArray;
+/* Flags of RArray
+ *
+ * 1: RARRAY_EMBED_FLAG
+ * The array is embedded (its contents follow the header, rather than
+ * being on a separately allocated buffer).
+ * 2: RARRAY_SHARED_FLAG (equal to ELTS_SHARED)
+ * The array is shared. The buffer this array points to is owned by
+ * another array (the shared root).
+ * if USE_RVARGC
+ * 3-9: RARRAY_EMBED_LEN
+ * The length of the array when RARRAY_EMBED_FLAG is set.
+ * else
+ * 3-4: RARRAY_EMBED_LEN
+ * The length of the array when RARRAY_EMBED_FLAG is set.
+ * endif
+ * 12: RARRAY_SHARED_ROOT_FLAG
+ * The array is a shared root that does reference counting. The buffer
+ * this array points to is owned by this array but may be pointed to
+ * by other arrays.
+ * Note: Frozen arrays may be a shared root without this flag being
+ * set. Frozen arrays do not have reference counting because
+ * they cannot be modified. Not updating the reference count
+ * improves copy-on-write performance. Their reference count is
+ * assumed to be infinity.
+ * 13: RARRAY_TRANSIENT_FLAG
+ * The buffer of the array is allocated on the transient heap.
+ * 14: RARRAY_PTR_IN_USE_FLAG
+ * The buffer of the array is in use. This is only used during
+ * debugging.
+ */
+
/* for OPTIMIZED_CMP: */
#define id_cmp idCmp
@@ -53,23 +84,6 @@ should_be_T_ARRAY(VALUE ary)
return RB_TYPE_P(ary, T_ARRAY);
}
-RBIMPL_ATTR_MAYBE_UNUSED()
-static int
-should_not_be_shared_and_embedded(VALUE ary)
-{
- return !FL_TEST((ary), ELTS_SHARED) || !FL_TEST((ary), RARRAY_EMBED_FLAG);
-}
-
-#define ARY_SHARED_P(ary) \
- (assert(should_be_T_ARRAY((VALUE)(ary))), \
- assert(should_not_be_shared_and_embedded((VALUE)ary)), \
- FL_TEST_RAW((ary),ELTS_SHARED)!=0)
-
-#define ARY_EMBED_P(ary) \
- (assert(should_be_T_ARRAY((VALUE)(ary))), \
- assert(should_not_be_shared_and_embedded((VALUE)ary)), \
- FL_TEST_RAW((ary), RARRAY_EMBED_FLAG) != 0)
-
#define ARY_HEAP_PTR(a) (assert(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.ptr)
#define ARY_HEAP_LEN(a) (assert(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.len)
#define ARY_HEAP_CAPA(a) (assert(!ARY_EMBED_P(a)), assert(!ARY_SHARED_ROOT_P(a)), \
@@ -79,11 +93,11 @@ should_not_be_shared_and_embedded(VALUE ary)
#define ARY_EMBED_LEN(a) \
(assert(ARY_EMBED_P(a)), \
(long)((RBASIC(a)->flags >> RARRAY_EMBED_LEN_SHIFT) & \
- (RARRAY_EMBED_LEN_MASK >> RARRAY_EMBED_LEN_SHIFT)))
+ (RARRAY_EMBED_LEN_MASK >> RARRAY_EMBED_LEN_SHIFT)))
#define ARY_HEAP_SIZE(a) (assert(!ARY_EMBED_P(a)), assert(ARY_OWNS_HEAP_P(a)), ARY_CAPA(a) * sizeof(VALUE))
#define ARY_OWNS_HEAP_P(a) (assert(should_be_T_ARRAY((VALUE)(a))), \
- !FL_TEST_RAW((a), ELTS_SHARED|RARRAY_EMBED_FLAG))
+ !FL_TEST_RAW((a), RARRAY_SHARED_FLAG|RARRAY_EMBED_FLAG))
#define FL_SET_EMBED(a) do { \
assert(!ARY_SHARED_P(a)); \
@@ -95,9 +109,9 @@ should_not_be_shared_and_embedded(VALUE ary)
#define FL_UNSET_EMBED(ary) FL_UNSET((ary), RARRAY_EMBED_FLAG|RARRAY_EMBED_LEN_MASK)
#define FL_SET_SHARED(ary) do { \
assert(!ARY_EMBED_P(ary)); \
- FL_SET((ary), ELTS_SHARED); \
+ FL_SET((ary), RARRAY_SHARED_FLAG); \
} while (0)
-#define FL_UNSET_SHARED(ary) FL_UNSET((ary), ELTS_SHARED)
+#define FL_UNSET_SHARED(ary) FL_UNSET((ary), RARRAY_SHARED_FLAG)
#define ARY_SET_PTR(ary, p) do { \
assert(!ARY_EMBED_P(ary)); \
@@ -107,7 +121,6 @@ should_not_be_shared_and_embedded(VALUE ary)
#define ARY_SET_EMBED_LEN(ary, n) do { \
long tmp_n = (n); \
assert(ARY_EMBED_P(ary)); \
- assert(!OBJ_FROZEN(ary)); \
RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK; \
RBASIC(ary)->flags |= (tmp_n) << RARRAY_EMBED_LEN_SHIFT; \
} while (0)
@@ -139,7 +152,7 @@ should_not_be_shared_and_embedded(VALUE ary)
} \
} while (0)
-#define ARY_CAPA(ary) (ARY_EMBED_P(ary) ? RARRAY_EMBED_LEN_MAX : \
+#define ARY_CAPA(ary) (ARY_EMBED_P(ary) ? ary_embed_capa(ary) : \
ARY_SHARED_ROOT_P(ary) ? RARRAY_LEN(ary) : ARY_HEAP_CAPA(ary))
#define ARY_SET_CAPA(ary, n) do { \
assert(!ARY_EMBED_P(ary)); \
@@ -148,26 +161,25 @@ should_not_be_shared_and_embedded(VALUE ary)
RARRAY(ary)->as.heap.aux.capa = (n); \
} while (0)
-#define ARY_SHARED_ROOT(ary) (assert(ARY_SHARED_P(ary)), RARRAY(ary)->as.heap.aux.shared_root)
#define ARY_SET_SHARED(ary, value) do { \
const VALUE _ary_ = (ary); \
const VALUE _value_ = (value); \
assert(!ARY_EMBED_P(_ary_)); \
assert(ARY_SHARED_P(_ary_)); \
- assert(ARY_SHARED_ROOT_P(_value_)); \
+ assert(!OBJ_FROZEN(_ary_)); \
+ assert(ARY_SHARED_ROOT_P(_value_) || OBJ_FROZEN(_value_)); \
RB_OBJ_WRITE(_ary_, &RARRAY(_ary_)->as.heap.aux.shared_root, _value_); \
} while (0)
-#define RARRAY_SHARED_ROOT_FLAG FL_USER5
-#define ARY_SHARED_ROOT_P(ary) (assert(should_be_T_ARRAY((VALUE)(ary))), \
- FL_TEST_RAW((ary), RARRAY_SHARED_ROOT_FLAG))
-#define ARY_SHARED_ROOT_REFCNT(ary) \
- (assert(ARY_SHARED_ROOT_P(ary)), RARRAY(ary)->as.heap.aux.capa)
-#define ARY_SHARED_ROOT_OCCUPIED(ary) (ARY_SHARED_ROOT_REFCNT(ary) == 1)
+
+#define ARY_SHARED_ROOT_OCCUPIED(ary) (!OBJ_FROZEN(ary) && ARY_SHARED_ROOT_REFCNT(ary) == 1)
#define ARY_SET_SHARED_ROOT_REFCNT(ary, value) do { \
assert(ARY_SHARED_ROOT_P(ary)); \
+ assert(!OBJ_FROZEN(ary)); \
+ assert((value) >= 0); \
RARRAY(ary)->as.heap.aux.capa = (value); \
} while (0)
#define FL_SET_SHARED_ROOT(ary) do { \
+ assert(!OBJ_FROZEN(ary)); \
assert(!ARY_EMBED_P(ary)); \
assert(!RARRAY_TRANSIENT_P(ary)); \
FL_SET((ary), RARRAY_SHARED_ROOT_FLAG); \
@@ -183,6 +195,65 @@ ARY_SET(VALUE a, long i, VALUE v)
}
#undef RARRAY_ASET
+static long
+ary_embed_capa(VALUE ary)
+{
+#if USE_RVARGC
+ size_t size = rb_gc_obj_slot_size(ary) - offsetof(struct RArray, as.ary);
+ assert(size % sizeof(VALUE) == 0);
+ return size / sizeof(VALUE);
+#else
+ return RARRAY_EMBED_LEN_MAX;
+#endif
+}
+
+static size_t
+ary_embed_size(long capa)
+{
+ return offsetof(struct RArray, as.ary) + (sizeof(VALUE) * capa);
+}
+
+static bool
+ary_embeddable_p(long capa)
+{
+#if USE_RVARGC
+ return rb_gc_size_allocatable_p(ary_embed_size(capa));
+#else
+ return capa <= RARRAY_EMBED_LEN_MAX;
+#endif
+}
+
+bool
+rb_ary_embeddable_p(VALUE ary)
+{
+ /* An array cannot be turned embeddable when the array is:
+ * - Shared root: other objects may point to the buffer of this array
+ * so we cannot make it embedded.
+ * - Frozen: this array may also be a shared root without the shared root
+ * flag.
+ * - Shared: we don't want to re-embed an array that points to a shared
+ * root (to save memory).
+ */
+ return !(ARY_SHARED_ROOT_P(ary) || OBJ_FROZEN(ary) || ARY_SHARED_P(ary));
+}
+
+size_t
+rb_ary_size_as_embedded(VALUE ary)
+{
+ size_t real_size;
+
+ if (ARY_EMBED_P(ary)) {
+ real_size = ary_embed_size(ARY_EMBED_LEN(ary));
+ }
+ else if (rb_ary_embeddable_p(ary)) {
+ real_size = ary_embed_size(ARY_HEAP_CAPA(ary));
+ }
+ else {
+ real_size = sizeof(struct RArray);
+ }
+ return real_size;
+}
+
#if ARRAY_DEBUG
#define ary_verify(ary) ary_verify_(ary, __FILE__, __LINE__)
@@ -192,19 +263,19 @@ ary_verify_(VALUE ary, const char *file, int line)
{
assert(RB_TYPE_P(ary, T_ARRAY));
- if (FL_TEST(ary, ELTS_SHARED)) {
- VALUE root = RARRAY(ary)->as.heap.aux.shared_root;
+ if (ARY_SHARED_P(ary)) {
+ VALUE root = ARY_SHARED_ROOT(ary);
const VALUE *ptr = ARY_HEAP_PTR(ary);
const VALUE *root_ptr = RARRAY_CONST_PTR_TRANSIENT(root);
long len = ARY_HEAP_LEN(ary), root_len = RARRAY_LEN(root);
- assert(FL_TEST(root, RARRAY_SHARED_ROOT_FLAG));
+ assert(ARY_SHARED_ROOT_P(root) || OBJ_FROZEN(root));
assert(root_ptr <= ptr && ptr + len <= root_ptr + root_len);
ary_verify(root);
}
else if (ARY_EMBED_P(ary)) {
assert(!RARRAY_TRANSIENT_P(ary));
assert(!ARY_SHARED_P(ary));
- assert(RARRAY_LEN(ary) <= RARRAY_EMBED_LEN_MAX);
+ assert(RARRAY_LEN(ary) <= ary_embed_capa(ary));
}
else {
#if 1
@@ -260,7 +331,7 @@ void
rb_mem_clear(VALUE *mem, long size)
{
while (size--) {
- *mem++ = Qnil;
+ *mem++ = Qnil;
}
}
@@ -268,7 +339,7 @@ static void
ary_mem_clear(VALUE ary, long beg, long size)
{
RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
- rb_mem_clear(ptr + beg, size);
+ rb_mem_clear(ptr + beg, size);
});
}
@@ -276,7 +347,7 @@ static inline void
memfill(register VALUE *mem, register long size, register VALUE val)
{
while (size--) {
- *mem++ = val;
+ *mem++ = val;
}
}
@@ -284,8 +355,8 @@ static void
ary_memfill(VALUE ary, long beg, long size, VALUE val)
{
RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
- memfill(ptr + beg, size, val);
- RB_OBJ_WRITTEN(ary, Qundef, val);
+ memfill(ptr + beg, size, val);
+ RB_OBJ_WRITTEN(ary, Qundef, val);
});
}
@@ -390,14 +461,11 @@ static inline void
rb_ary_transient_heap_evacuate_(VALUE ary, int transient, int promote)
{
if (transient) {
+ assert(!ARY_SHARED_ROOT_P(ary));
+
VALUE *new_ptr;
const VALUE *old_ptr = ARY_HEAP_PTR(ary);
long capa = ARY_HEAP_CAPA(ary);
- long len = ARY_HEAP_LEN(ary);
-
- if (ARY_SHARED_ROOT_P(ary)) {
- capa = len;
- }
assert(ARY_OWNS_HEAP_P(ary));
assert(RARRAY_TRANSIENT_P(ary));
@@ -439,6 +507,27 @@ rb_ary_detransient(VALUE ary)
}
#endif
+void
+rb_ary_make_embedded(VALUE ary)
+{
+ assert(rb_ary_embeddable_p(ary));
+ if (!ARY_EMBED_P(ary)) {
+ const VALUE *buf = ARY_HEAP_PTR(ary);
+ long len = ARY_HEAP_LEN(ary);
+ bool was_transient = RARRAY_TRANSIENT_P(ary);
+
+ // FL_SET_EMBED also unsets the transient flag
+ FL_SET_EMBED(ary);
+ ARY_SET_EMBED_LEN(ary, len);
+
+ MEMCPY((void *)ARY_EMBED_PTR(ary), (void *)buf, VALUE, len);
+
+ if (!was_transient) {
+ ary_heap_free_ptr(ary, buf, len * sizeof(VALUE));
+ }
+ }
+}
+
static void
ary_resize_capa(VALUE ary, long capacity)
{
@@ -446,7 +535,7 @@ ary_resize_capa(VALUE ary, long capacity)
assert(!OBJ_FROZEN(ary));
assert(!ARY_SHARED_P(ary));
- if (capacity > RARRAY_EMBED_LEN_MAX) {
+ if (capacity > ary_embed_capa(ary)) {
size_t new_capa = capacity;
if (ARY_EMBED_P(ary)) {
long len = ARY_EMBED_LEN(ary);
@@ -498,10 +587,10 @@ ary_double_capa(VALUE ary, long min)
long new_capa = ARY_CAPA(ary) / 2;
if (new_capa < ARY_DEFAULT_SIZE) {
- new_capa = ARY_DEFAULT_SIZE;
+ new_capa = ARY_DEFAULT_SIZE;
}
if (new_capa >= ARY_MAX_SIZE - min) {
- new_capa = (ARY_MAX_SIZE - min) / 2;
+ new_capa = (ARY_MAX_SIZE - min) / 2;
}
new_capa += min;
ary_resize_capa(ary, new_capa);
@@ -512,35 +601,40 @@ ary_double_capa(VALUE ary, long min)
static void
rb_ary_decrement_share(VALUE shared_root)
{
- if (shared_root) {
- long num = ARY_SHARED_ROOT_REFCNT(shared_root) - 1;
- if (num > 0) {
- ARY_SET_SHARED_ROOT_REFCNT(shared_root, num);
- }
+ if (!OBJ_FROZEN(shared_root)) {
+ long num = ARY_SHARED_ROOT_REFCNT(shared_root);
+ ARY_SET_SHARED_ROOT_REFCNT(shared_root, num - 1);
}
}
static void
rb_ary_unshare(VALUE ary)
{
- VALUE shared_root = RARRAY(ary)->as.heap.aux.shared_root;
+ VALUE shared_root = ARY_SHARED_ROOT(ary);
rb_ary_decrement_share(shared_root);
FL_UNSET_SHARED(ary);
}
-static inline void
-rb_ary_unshare_safe(VALUE ary)
+static void
+rb_ary_reset(VALUE ary)
{
- if (ARY_SHARED_P(ary) && !ARY_EMBED_P(ary)) {
- rb_ary_unshare(ary);
+ if (ARY_OWNS_HEAP_P(ary)) {
+ ary_heap_free(ary);
+ }
+ else if (ARY_SHARED_P(ary)) {
+ rb_ary_unshare(ary);
}
+
+ FL_SET_EMBED(ary);
+ ARY_SET_EMBED_LEN(ary, 0);
}
static VALUE
rb_ary_increment_share(VALUE shared_root)
{
- long num = ARY_SHARED_ROOT_REFCNT(shared_root);
- if (num >= 0) {
+ if (!OBJ_FROZEN(shared_root)) {
+ long num = ARY_SHARED_ROOT_REFCNT(shared_root);
+ assert(num >= 0);
ARY_SET_SHARED_ROOT_REFCNT(shared_root, num + 1);
}
return shared_root;
@@ -571,7 +665,7 @@ rb_ary_cancel_sharing(VALUE ary)
ary_verify(shared_root);
- if (len <= RARRAY_EMBED_LEN_MAX) {
+ if (len <= ary_embed_capa(ary)) {
const VALUE *ptr = ARY_HEAP_PTR(ary);
FL_UNSET_SHARED(ary);
FL_SET_EMBED(ary);
@@ -618,40 +712,40 @@ ary_ensure_room_for_push(VALUE ary, long add_len)
long capa;
if (old_len > ARY_MAX_SIZE - add_len) {
- rb_raise(rb_eIndexError, "index %ld too big", new_len);
+ rb_raise(rb_eIndexError, "index %ld too big", new_len);
}
if (ARY_SHARED_P(ary)) {
- if (new_len > RARRAY_EMBED_LEN_MAX) {
+ if (new_len > ary_embed_capa(ary)) {
VALUE shared_root = ARY_SHARED_ROOT(ary);
if (ARY_SHARED_ROOT_OCCUPIED(shared_root)) {
if (ARY_HEAP_PTR(ary) - RARRAY_CONST_PTR_TRANSIENT(shared_root) + new_len <= RARRAY_LEN(shared_root)) {
- rb_ary_modify_check(ary);
+ rb_ary_modify_check(ary);
ary_verify(ary);
ary_verify(shared_root);
return shared_root;
- }
- else {
- /* if array is shared, then 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);
- }
+ }
+ else {
+ /* if array is shared, then 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);
+ }
ary_verify(ary);
- return ary;
- }
- }
- }
+ return ary;
+ }
+ }
+ }
ary_verify(ary);
rb_ary_modify(ary);
}
else {
- rb_ary_modify_check(ary);
+ rb_ary_modify_check(ary);
}
capa = ARY_CAPA(ary);
if (new_len > capa) {
- ary_double_capa(ary, new_len);
+ ary_double_capa(ary, new_len);
}
ary_verify(ary);
@@ -663,6 +757,7 @@ ary_ensure_room_for_push(VALUE ary, long add_len)
* array.freeze -> self
*
* Freezes +self+; returns +self+:
+ *
* a = []
* a.frozen? # => false
* a.freeze
@@ -688,18 +783,25 @@ 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_root == RARRAY(ary2)->as.heap.aux.shared_root &&
- RARRAY(ary1)->as.heap.len == RARRAY(ary2)->as.heap.len) {
- return Qtrue;
+ !ARY_EMBED_P(ary2) && ARY_SHARED_P(ary2) &&
+ ARY_SHARED_ROOT(ary1) == ARY_SHARED_ROOT(ary2) &&
+ ARY_HEAP_LEN(ary1) == ARY_HEAP_LEN(ary2)) {
+ return Qtrue;
}
return Qfalse;
}
static VALUE
-ary_alloc(VALUE klass)
+ary_alloc_embed(VALUE klass, long capa)
{
- NEWOBJ_OF(ary, struct RArray, klass, T_ARRAY | RARRAY_EMBED_FLAG | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0));
+ size_t size = ary_embed_size(capa);
+ assert(rb_gc_size_allocatable_p(size));
+#if !USE_RVARGC
+ assert(size <= sizeof(struct RArray));
+#endif
+ RVARGC_NEWOBJ_OF(ary, struct RArray, klass,
+ T_ARRAY | RARRAY_EMBED_FLAG | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
+ size);
/* Created array is:
* FL_SET_EMBED((VALUE)ary);
* ARY_SET_EMBED_LEN((VALUE)ary, 0);
@@ -708,10 +810,19 @@ ary_alloc(VALUE klass)
}
static VALUE
+ary_alloc_heap(VALUE klass)
+{
+ RVARGC_NEWOBJ_OF(ary, struct RArray, klass,
+ T_ARRAY | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
+ sizeof(struct RArray));
+ return (VALUE)ary;
+}
+
+static VALUE
empty_ary_alloc(VALUE klass)
{
RUBY_DTRACE_CREATE_HOOK(ARRAY, 0);
- return ary_alloc(klass);
+ return ary_alloc_embed(klass, 0);
}
static VALUE
@@ -720,20 +831,24 @@ ary_new(VALUE klass, long capa)
VALUE ary,*ptr;
if (capa < 0) {
- rb_raise(rb_eArgError, "negative array size (or size too big)");
+ rb_raise(rb_eArgError, "negative array size (or size too big)");
}
if (capa > ARY_MAX_SIZE) {
- rb_raise(rb_eArgError, "array size too big");
+ rb_raise(rb_eArgError, "array size too big");
}
RUBY_DTRACE_CREATE_HOOK(ARRAY, capa);
- ary = ary_alloc(klass);
- if (capa > RARRAY_EMBED_LEN_MAX) {
+ if (ary_embeddable_p(capa)) {
+ ary = ary_alloc_embed(klass, capa);
+ }
+ else {
+ ary = ary_alloc_heap(klass);
+ ARY_SET_CAPA(ary, capa);
+ assert(!ARY_EMBED_P(ary));
+
ptr = ary_heap_alloc(ary, capa);
- FL_UNSET_EMBED(ary);
ARY_SET_PTR(ary, ptr);
- ARY_SET_CAPA(ary, capa);
ARY_SET_HEAP_LEN(ary, 0);
}
@@ -749,7 +864,7 @@ rb_ary_new_capa(long capa)
VALUE
rb_ary_new(void)
{
- return rb_ary_new2(RARRAY_EMBED_LEN_MAX);
+ return rb_ary_new_capa(0);
}
VALUE
@@ -763,7 +878,7 @@ VALUE
va_start(ar, n);
for (i=0; i<n; i++) {
- ARY_SET(ary, i, va_arg(ar, VALUE));
+ ARY_SET(ary, i, va_arg(ar, VALUE));
}
va_end(ar);
@@ -778,8 +893,8 @@ rb_ary_tmp_new_from_values(VALUE klass, long n, const VALUE *elts)
ary = ary_new(klass, n);
if (n > 0 && elts) {
- ary_memcpy(ary, 0, n, elts);
- ARY_SET_LEN(ary, n);
+ ary_memcpy(ary, 0, n, elts);
+ ARY_SET_LEN(ary, n);
}
return ary;
@@ -792,9 +907,16 @@ rb_ary_new_from_values(long n, const VALUE *elts)
}
static VALUE
-ec_ary_alloc(rb_execution_context_t *ec, VALUE klass)
+ec_ary_alloc_embed(rb_execution_context_t *ec, VALUE klass, long capa)
{
- RB_EC_NEWOBJ_OF(ec, ary, struct RArray, klass, T_ARRAY | RARRAY_EMBED_FLAG | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0));
+ size_t size = ary_embed_size(capa);
+ assert(rb_gc_size_allocatable_p(size));
+#if !USE_RVARGC
+ assert(size <= sizeof(struct RArray));
+#endif
+ RB_RVARGC_EC_NEWOBJ_OF(ec, ary, struct RArray, klass,
+ T_ARRAY | RARRAY_EMBED_FLAG | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
+ size);
/* Created array is:
* FL_SET_EMBED((VALUE)ary);
* ARY_SET_EMBED_LEN((VALUE)ary, 0);
@@ -803,26 +925,38 @@ ec_ary_alloc(rb_execution_context_t *ec, VALUE klass)
}
static VALUE
+ec_ary_alloc_heap(rb_execution_context_t *ec, VALUE klass)
+{
+ RB_RVARGC_EC_NEWOBJ_OF(ec, ary, struct RArray, klass,
+ T_ARRAY | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
+ sizeof(struct RArray));
+ return (VALUE)ary;
+}
+
+static VALUE
ec_ary_new(rb_execution_context_t *ec, VALUE klass, long capa)
{
VALUE ary,*ptr;
if (capa < 0) {
- rb_raise(rb_eArgError, "negative array size (or size too big)");
+ rb_raise(rb_eArgError, "negative array size (or size too big)");
}
if (capa > ARY_MAX_SIZE) {
- rb_raise(rb_eArgError, "array size too big");
+ rb_raise(rb_eArgError, "array size too big");
}
RUBY_DTRACE_CREATE_HOOK(ARRAY, capa);
- ary = ec_ary_alloc(ec, klass);
+ if (ary_embeddable_p(capa)) {
+ ary = ec_ary_alloc_embed(ec, klass, capa);
+ }
+ else {
+ ary = ec_ary_alloc_heap(ec, klass);
+ ARY_SET_CAPA(ary, capa);
+ assert(!ARY_EMBED_P(ary));
- if (capa > RARRAY_EMBED_LEN_MAX) {
ptr = ary_heap_alloc(ary, capa);
- FL_UNSET_EMBED(ary);
ARY_SET_PTR(ary, ptr);
- ARY_SET_CAPA(ary, capa);
ARY_SET_HEAP_LEN(ary, 0);
}
@@ -836,15 +970,15 @@ rb_ec_ary_new_from_values(rb_execution_context_t *ec, long n, const VALUE *elts)
ary = ec_ary_new(ec, rb_cArray, n);
if (n > 0 && elts) {
- ary_memcpy(ary, 0, n, elts);
- ARY_SET_LEN(ary, n);
+ ary_memcpy(ary, 0, n, elts);
+ ARY_SET_LEN(ary, n);
}
return ary;
}
VALUE
-rb_ary_tmp_new(long capa)
+rb_ary_hidden_new(long capa)
{
VALUE ary = ary_new(0, capa);
rb_ary_transient_heap_evacuate(ary, TRUE);
@@ -852,12 +986,11 @@ rb_ary_tmp_new(long capa)
}
VALUE
-rb_ary_tmp_new_fill(long capa)
+rb_ary_hidden_new_fill(long capa)
{
- VALUE ary = ary_new(0, capa);
+ VALUE ary = rb_ary_hidden_new(capa);
ary_memfill(ary, 0, capa, Qnil);
ARY_SET_LEN(ary, capa);
- rb_ary_transient_heap_evacuate(ary, TRUE);
return ary;
}
@@ -895,64 +1028,69 @@ RUBY_FUNC_EXPORTED size_t
rb_ary_memsize(VALUE ary)
{
if (ARY_OWNS_HEAP_P(ary)) {
- return ARY_CAPA(ary) * sizeof(VALUE);
+ return ARY_CAPA(ary) * sizeof(VALUE);
}
else {
- return 0;
+ return 0;
}
}
-static inline void
-ary_discard(VALUE ary)
-{
- rb_ary_free(ary);
- RBASIC(ary)->flags |= RARRAY_EMBED_FLAG;
- RBASIC(ary)->flags &= ~(RARRAY_EMBED_LEN_MASK | RARRAY_TRANSIENT_FLAG);
-}
-
static VALUE
ary_make_shared(VALUE ary)
{
- assert(!ARY_EMBED_P(ary));
+ assert(USE_RVARGC || !ARY_EMBED_P(ary));
ary_verify(ary);
if (ARY_SHARED_P(ary)) {
return ARY_SHARED_ROOT(ary);
}
else if (ARY_SHARED_ROOT_P(ary)) {
- return ary;
+ return ary;
}
else if (OBJ_FROZEN(ary)) {
- rb_ary_transient_heap_evacuate(ary, TRUE);
- ary_shrink_capa(ary);
- FL_SET_SHARED_ROOT(ary);
- ARY_SET_SHARED_ROOT_REFCNT(ary, 1);
- return ary;
+ if (!ARY_EMBED_P(ary)) {
+ rb_ary_transient_heap_evacuate(ary, TRUE);
+ ary_shrink_capa(ary);
+ }
+ return ary;
}
else {
- long capa = ARY_CAPA(ary), len = RARRAY_LEN(ary);
- const VALUE *ptr;
- NEWOBJ_OF(shared, struct RArray, 0, T_ARRAY | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0));
- VALUE vshared = (VALUE)shared;
-
rb_ary_transient_heap_evacuate(ary, TRUE);
- ptr = ARY_HEAP_PTR(ary);
-
- FL_UNSET_EMBED(vshared);
- ARY_SET_LEN(vshared, capa);
- ARY_SET_PTR(vshared, ptr);
- ary_mem_clear(vshared, len, capa - len);
- FL_SET_SHARED_ROOT(vshared);
- ARY_SET_SHARED_ROOT_REFCNT(vshared, 1);
- FL_SET_SHARED(ary);
+
+ long capa = ARY_CAPA(ary);
+ long len = RARRAY_LEN(ary);
+
+ /* Shared roots cannot be embedded because the reference count
+ * (refcnt) is stored in as.heap.aux.capa. */
+ VALUE shared = ary_alloc_heap(0);
+ FL_SET_SHARED_ROOT(shared);
+
+ if (ARY_EMBED_P(ary)) {
+ /* Cannot use ary_heap_alloc because we don't want to allocate
+ * on the transient heap. */
+ VALUE *ptr = ALLOC_N(VALUE, capa);
+ ARY_SET_PTR(shared, ptr);
+ ary_memcpy(shared, 0, len, RARRAY_PTR(ary));
+
+ FL_UNSET_EMBED(ary);
+ ARY_SET_HEAP_LEN(ary, len);
+ ARY_SET_PTR(ary, ptr);
+ }
+ else {
+ ARY_SET_PTR(shared, RARRAY_PTR(ary));
+ }
+
+ ARY_SET_LEN(shared, capa);
+ ary_mem_clear(shared, len, capa - len);
+ ARY_SET_SHARED_ROOT_REFCNT(shared, 1);
+ FL_SET_SHARED(ary);
RB_DEBUG_COUNTER_INC(obj_ary_shared_create);
- ARY_SET_SHARED(ary, vshared);
- OBJ_FREEZE(vshared);
+ ARY_SET_SHARED(ary, shared);
- ary_verify(vshared);
+ ary_verify(shared);
ary_verify(ary);
- return vshared;
+ return shared;
}
}
@@ -961,8 +1099,10 @@ ary_make_substitution(VALUE ary)
{
long len = RARRAY_LEN(ary);
- if (len <= RARRAY_EMBED_LEN_MAX) {
- VALUE subst = rb_ary_new2(len);
+ if (ary_embeddable_p(len)) {
+ VALUE subst = rb_ary_new_capa(len);
+ assert(ARY_EMBED_P(subst));
+
ary_memcpy(subst, 0, len, RARRAY_CONST_PTR_TRANSIENT(ary));
ARY_SET_EMBED_LEN(subst, len);
return subst;
@@ -1023,6 +1163,30 @@ rb_ary_s_try_convert(VALUE dummy, VALUE ary)
return rb_check_array_type(ary);
}
+/* :nodoc: */
+static VALUE
+rb_ary_s_new(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE ary;
+
+ if (klass == rb_cArray) {
+ long size = 0;
+ if (argc > 0 && FIXNUM_P(argv[0])) {
+ size = FIX2LONG(argv[0]);
+ if (size < 0) size = 0;
+ }
+
+ ary = ary_new(klass, size);
+
+ rb_obj_call_init_kw(ary, argc, argv, RB_PASS_CALLED_KEYWORDS);
+ }
+ else {
+ ary = rb_class_new_instance_pass_kw(argc, argv, klass);
+ }
+
+ return ary;
+}
+
/*
* call-seq:
* Array.new -> new_empty_array
@@ -1037,6 +1201,7 @@ rb_ary_s_try_convert(VALUE dummy, VALUE ary)
*
* With no block and a single \Array argument +array+,
* returns a new \Array formed from +array+:
+ *
* a = Array.new([:foo, 'bar', 2])
* a.class # => Array
* a # => [:foo, "bar", 2]
@@ -1044,12 +1209,14 @@ rb_ary_s_try_convert(VALUE dummy, VALUE ary)
* With no block and a single \Integer argument +size+,
* returns a new \Array of the given size
* whose elements are all +nil+:
+ *
* a = Array.new(3)
* a # => [nil, nil, nil]
*
* With no block and arguments +size+ and +default_value+,
* returns an \Array of the given size;
* each element is that same +default_value+:
+ *
* a = Array.new(3, 'x')
* a # => ['x', 'x', 'x']
*
@@ -1057,6 +1224,7 @@ rb_ary_s_try_convert(VALUE dummy, VALUE ary)
* returns an \Array of the given size;
* the block is called with each successive integer +index+;
* the element for that +index+ is the return value from the block:
+ *
* a = Array.new(3) {|index| "Element #{index}" }
* a # => ["Element 0", "Element 1", "Element 2"]
*
@@ -1075,51 +1243,48 @@ rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
rb_ary_modify(ary);
if (argc == 0) {
- if (ARY_OWNS_HEAP_P(ary) && ARY_HEAP_PTR(ary) != NULL) {
- ary_heap_free(ary);
- }
- rb_ary_unshare_safe(ary);
- FL_SET_EMBED(ary);
- ARY_SET_EMBED_LEN(ary, 0);
- if (rb_block_given_p()) {
- rb_warning("given block not used");
- }
- return ary;
+ rb_ary_reset(ary);
+ assert(ARY_EMBED_P(ary));
+ assert(ARY_EMBED_LEN(ary) == 0);
+ if (rb_block_given_p()) {
+ rb_warning("given block not used");
+ }
+ return ary;
}
rb_scan_args(argc, argv, "02", &size, &val);
if (argc == 1 && !FIXNUM_P(size)) {
- val = rb_check_array_type(size);
- if (!NIL_P(val)) {
- rb_ary_replace(ary, val);
- return ary;
- }
+ val = rb_check_array_type(size);
+ if (!NIL_P(val)) {
+ rb_ary_replace(ary, val);
+ return ary;
+ }
}
len = NUM2LONG(size);
/* NUM2LONG() may call size.to_int, ary can be frozen, modified, etc */
if (len < 0) {
- rb_raise(rb_eArgError, "negative array size");
+ rb_raise(rb_eArgError, "negative array size");
}
if (len > ARY_MAX_SIZE) {
- rb_raise(rb_eArgError, "array size too big");
+ rb_raise(rb_eArgError, "array size too big");
}
/* recheck after argument conversion */
rb_ary_modify(ary);
ary_resize_capa(ary, len);
if (rb_block_given_p()) {
- long i;
+ long i;
- if (argc == 2) {
- rb_warn("block supersedes default value argument");
- }
- for (i=0; i<len; i++) {
- rb_ary_store(ary, i, rb_yield(LONG2NUM(i)));
- ARY_SET_LEN(ary, i + 1);
- }
+ if (argc == 2) {
+ rb_warn("block supersedes default value argument");
+ }
+ for (i=0; i<len; i++) {
+ rb_ary_store(ary, i, rb_yield(LONG2NUM(i)));
+ ARY_SET_LEN(ary, i + 1);
+ }
}
else {
- ary_memfill(ary, 0, len, val);
- ARY_SET_LEN(ary, len);
+ ary_memfill(ary, 0, len, val);
+ ARY_SET_LEN(ary, len);
}
return ary;
}
@@ -1150,26 +1315,26 @@ rb_ary_store(VALUE ary, long idx, VALUE val)
long len = RARRAY_LEN(ary);
if (idx < 0) {
- idx += len;
- if (idx < 0) {
- rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
- idx - len, -len);
- }
+ idx += len;
+ if (idx < 0) {
+ rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
+ idx - len, -len);
+ }
}
else if (idx >= ARY_MAX_SIZE) {
- rb_raise(rb_eIndexError, "index %ld too big", idx);
+ rb_raise(rb_eIndexError, "index %ld too big", idx);
}
rb_ary_modify(ary);
if (idx >= ARY_CAPA(ary)) {
- ary_double_capa(ary, idx);
+ ary_double_capa(ary, idx);
}
if (idx > len) {
- ary_mem_clear(ary, len, idx - len + 1);
+ ary_mem_clear(ary, len, idx - len + 1);
}
if (idx >= len) {
- ARY_SET_LEN(ary, idx + 1);
+ ARY_SET_LEN(ary, idx + 1);
}
ARY_SET(ary, idx, val);
}
@@ -1181,17 +1346,20 @@ ary_make_partial(VALUE ary, VALUE klass, long offset, long len)
assert(len >= 0);
assert(offset+len <= RARRAY_LEN(ary));
- if (len <= RARRAY_EMBED_LEN_MAX) {
- VALUE result = ary_alloc(klass);
+ const size_t rarray_embed_capa_max = (sizeof(struct RArray) - offsetof(struct RArray, as.ary)) / sizeof(VALUE);
+
+ if ((size_t)len <= rarray_embed_capa_max && ary_embeddable_p(len)) {
+ VALUE result = ary_alloc_embed(klass, len);
ary_memcpy(result, 0, len, RARRAY_CONST_PTR_TRANSIENT(ary) + offset);
ARY_SET_EMBED_LEN(result, len);
return result;
}
else {
- VALUE shared, result = ary_alloc(klass);
- FL_UNSET_EMBED(result);
+ VALUE shared = ary_make_shared(ary);
+
+ VALUE result = ary_alloc_heap(klass);
+ assert(!ARY_EMBED_P(result));
- shared = ary_make_shared(ary);
ARY_SET_PTR(result, RARRAY_CONST_PTR_TRANSIENT(ary));
ARY_SET_LEN(result, RARRAY_LEN(ary));
rb_ary_set_shared(result, shared);
@@ -1216,21 +1384,25 @@ ary_make_partial_step(VALUE ary, VALUE klass, long offset, long len, long step)
const VALUE *values = RARRAY_CONST_PTR_TRANSIENT(ary);
const long orig_len = len;
- if ((step > 0 && step >= len) || (step < 0 && (step < -len))) {
+ if (step > 0 && step >= len) {
VALUE result = ary_new(klass, 1);
VALUE *ptr = (VALUE *)ARY_EMBED_PTR(result);
RB_OBJ_WRITE(result, ptr, values[offset]);
ARY_SET_EMBED_LEN(result, 1);
return result;
}
+ else if (step < 0 && step < -len) {
+ step = -len;
+ }
long ustep = (step < 0) ? -step : step;
- len = (len + ustep - 1) / ustep;
+ len = roomof(len, ustep);
long i;
long j = offset + ((step > 0) ? 0 : (orig_len - 1));
+
VALUE result = ary_new(klass, len);
- if (len <= RARRAY_EMBED_LEN_MAX) {
+ if (ARY_EMBED_P(result)) {
VALUE *ptr = (VALUE *)ARY_EMBED_PTR(result);
for (i = 0; i < len; ++i) {
RB_OBJ_WRITE(result, ptr+i, values[j]);
@@ -1279,13 +1451,13 @@ ary_take_first_or_last(int argc, const VALUE *argv, VALUE ary, enum ary_take_pos
n = NUM2LONG(argv[0]);
len = RARRAY_LEN(ary);
if (n > len) {
- n = len;
+ n = len;
}
else if (n < 0) {
- rb_raise(rb_eArgError, "negative array size");
+ rb_raise(rb_eArgError, "negative array size");
}
if (last) {
- offset = len - n;
+ offset = len - n;
}
return ary_make_partial(ary, rb_cArray, offset, n);
}
@@ -1295,13 +1467,16 @@ ary_take_first_or_last(int argc, const VALUE *argv, VALUE ary, enum ary_take_pos
* array << object -> self
*
* Appends +object+ to +self+; returns +self+:
+ *
* a = [:foo, 'bar', 2]
* a << :baz # => [:foo, "bar", 2, :baz]
*
* Appends +object+ as one element, even if it is another \Array:
+ *
* a = [:foo, 'bar', 2]
* a1 = a << [3, 4]
* a1 # => [:foo, "bar", 2, [3, 4]]
+ *
*/
VALUE
@@ -1310,7 +1485,7 @@ rb_ary_push(VALUE ary, VALUE item)
long idx = RARRAY_LEN((ary_verify(ary), ary));
VALUE target_ary = ary_ensure_room_for_push(ary, 1);
RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
- RB_OBJ_WRITE(target_ary, &ptr[idx], item);
+ RB_OBJ_WRITE(target_ary, &ptr[idx], item);
});
ARY_SET_LEN(ary, idx + 1);
ary_verify(ary);
@@ -1334,15 +1509,17 @@ rb_ary_cat(VALUE ary, const VALUE *argv, long len)
* Appends trailing elements.
*
* Appends each argument in +objects+ to +self+; returns +self+:
+ *
* a = [:foo, 'bar', 2]
* a.push(:baz, :bat) # => [:foo, "bar", 2, :baz, :bat]
*
* Appends each argument as one element, even if it is another \Array:
+ *
* a = [:foo, 'bar', 2]
* a1 = a.push([:baz, :bat], [:bam, :bad])
* a1 # => [:foo, "bar", 2, [:baz, :bat], [:bam, :bad]]
*
- * Array#append is an alias for \Array#push.
+ * Array#append is an alias for Array#push.
*
* Related: #pop, #shift, #unshift.
*/
@@ -1361,10 +1538,10 @@ rb_ary_pop(VALUE ary)
n = RARRAY_LEN(ary);
if (n == 0) return Qnil;
if (ARY_OWNS_HEAP_P(ary) &&
- n * 3 < ARY_CAPA(ary) &&
- ARY_CAPA(ary) > ARY_DEFAULT_SIZE)
+ n * 3 < ARY_CAPA(ary) &&
+ ARY_CAPA(ary) > ARY_DEFAULT_SIZE)
{
- ary_resize_capa(ary, n * 2);
+ ary_resize_capa(ary, n * 2);
}
--n;
ARY_SET_LEN(ary, n);
@@ -1381,6 +1558,7 @@ rb_ary_pop(VALUE ary)
*
* When no argument is given and +self+ is not empty,
* removes and returns the last element:
+ *
* a = [:foo, 'bar', 2]
* a.pop # => 2
* a # => [:foo, "bar"]
@@ -1388,12 +1566,14 @@ rb_ary_pop(VALUE ary)
* Returns +nil+ if the array is empty.
*
* When a non-negative \Integer argument +n+ is given and is in range,
+ *
* removes and returns the last +n+ elements in a new \Array:
* a = [:foo, 'bar', 2]
* a.pop(2) # => ["bar", 2]
*
* If +n+ is positive and out of range,
* removes and returns all elements:
+ *
* a = [:foo, 'bar', 2]
* a.pop(50) # => [:foo, "bar", 2]
*
@@ -1406,7 +1586,7 @@ rb_ary_pop_m(int argc, VALUE *argv, VALUE ary)
VALUE result;
if (argc == 0) {
- return rb_ary_pop(ary);
+ return rb_ary_pop(ary);
}
rb_ary_modify_check(ary);
@@ -1422,30 +1602,14 @@ rb_ary_shift(VALUE ary)
VALUE top;
long len = RARRAY_LEN(ary);
- rb_ary_modify_check(ary);
- if (len == 0) return Qnil;
- top = RARRAY_AREF(ary, 0);
- if (!ARY_SHARED_P(ary)) {
- if (len < ARY_DEFAULT_SIZE) {
- RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
- MEMMOVE(ptr, ptr+1, VALUE, len-1);
- }); /* WB: no new reference */
- ARY_INCREASE_LEN(ary, -1);
- ary_verify(ary);
- return top;
- }
- assert(!ARY_EMBED_P(ary)); /* ARY_EMBED_LEN_MAX < ARY_DEFAULT_SIZE */
-
- ARY_SET(ary, 0, Qnil);
- ary_make_shared(ary);
- }
- else if (ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary))) {
- RARRAY_PTR_USE_TRANSIENT(ary, ptr, ptr[0] = Qnil);
+ if (len == 0) {
+ rb_ary_modify_check(ary);
+ return Qnil;
}
- ARY_INCREASE_PTR(ary, 1); /* shift ptr */
- ARY_INCREASE_LEN(ary, -1);
- ary_verify(ary);
+ top = RARRAY_AREF(ary, 0);
+
+ rb_ary_behead(ary, 1);
return top;
}
@@ -1458,6 +1622,7 @@ rb_ary_shift(VALUE ary)
* Removes and returns leading elements.
*
* When no argument is given, removes and returns the first element:
+ *
* a = [:foo, 'bar', 2]
* a.shift # => :foo
* a # => ['bar', 2]
@@ -1466,12 +1631,14 @@ rb_ary_shift(VALUE ary)
*
* When positive \Integer argument +n+ is given, removes the first +n+ elements;
* returns those elements in a new \Array:
+ *
* a = [:foo, 'bar', 2]
* a.shift(2) # => [:foo, 'bar']
* a # => [2]
*
* If +n+ is as large as or larger than <tt>self.length</tt>,
* removes all elements; returns those elements in a new \Array:
+ *
* a = [:foo, 'bar', 2]
* a.shift(3) # => [:foo, 'bar', 2]
*
@@ -1487,7 +1654,7 @@ rb_ary_shift_m(int argc, VALUE *argv, VALUE ary)
long n;
if (argc == 0) {
- return rb_ary_shift(ary);
+ return rb_ary_shift(ary);
}
rb_ary_modify_check(ary);
@@ -1498,48 +1665,37 @@ rb_ary_shift_m(int argc, VALUE *argv, VALUE ary)
return result;
}
-static VALUE
-behead_shared(VALUE ary, long n)
-{
- assert(ARY_SHARED_P(ary));
- rb_ary_modify_check(ary);
- if (ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary))) {
- ary_mem_clear(ary, 0, n);
- }
- ARY_INCREASE_PTR(ary, n);
- ARY_INCREASE_LEN(ary, -n);
- ary_verify(ary);
- return ary;
-}
-
-static VALUE
-behead_transient(VALUE ary, long n)
-{
- rb_ary_modify_check(ary);
- RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
- MEMMOVE(ptr, ptr+n, VALUE, RARRAY_LEN(ary)-n);
- }); /* WB: no new reference */
- ARY_INCREASE_LEN(ary, -n);
- ary_verify(ary);
- return ary;
-}
-
MJIT_FUNC_EXPORTED VALUE
rb_ary_behead(VALUE ary, long n)
{
if (n <= 0) {
return ary;
}
- else if (ARY_SHARED_P(ary)) {
- return behead_shared(ary, n);
- }
- else if (RARRAY_LEN(ary) >= ARY_DEFAULT_SIZE) {
+
+ rb_ary_modify_check(ary);
+
+ if (!ARY_SHARED_P(ary)) {
+ if (ARY_EMBED_P(ary) || RARRAY_LEN(ary) < ARY_DEFAULT_SIZE) {
+ RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
+ MEMMOVE(ptr, ptr + n, VALUE, RARRAY_LEN(ary) - n);
+ }); /* WB: no new reference */
+ ARY_INCREASE_LEN(ary, -n);
+ ary_verify(ary);
+ return ary;
+ }
+
+ ary_mem_clear(ary, 0, n);
ary_make_shared(ary);
- return behead_shared(ary, n);
}
- else {
- return behead_transient(ary, n);
+ else if (ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary))) {
+ ary_mem_clear(ary, 0, n);
}
+
+ ARY_INCREASE_PTR(ary, n);
+ ARY_INCREASE_LEN(ary, -n);
+ ary_verify(ary);
+
+ return ary;
}
static VALUE
@@ -1570,28 +1726,28 @@ ary_modify_for_unshift(VALUE ary, int argc)
rb_ary_modify(ary);
capa = ARY_CAPA(ary);
if (capa - (capa >> 6) <= new_len) {
- ary_double_capa(ary, new_len);
+ ary_double_capa(ary, new_len);
}
/* use shared array for big "queues" */
- if (new_len > ARY_DEFAULT_SIZE * 4) {
+ if (new_len > ARY_DEFAULT_SIZE * 4 && !ARY_EMBED_P(ary)) {
ary_verify(ary);
/* make a room for unshifted items */
- capa = ARY_CAPA(ary);
- ary_make_shared(ary);
+ capa = ARY_CAPA(ary);
+ ary_make_shared(ary);
head = sharedp = RARRAY_CONST_PTR_TRANSIENT(ary);
return make_room_for_unshift(ary, head, (void *)sharedp, argc, capa, len);
}
else {
- /* sliding items */
+ /* sliding items */
RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
- MEMMOVE(ptr + argc, ptr, VALUE, len);
- });
+ MEMMOVE(ptr + argc, ptr, VALUE, len);
+ });
ary_verify(ary);
- return ary;
+ return ary;
}
}
@@ -1632,6 +1788,7 @@ ary_ensure_room_for_unshift(VALUE ary, int argc)
* array.unshift(*objects) -> self
*
* Prepends the given +objects+ to +self+:
+ *
* a = [:foo, 'bar', 2]
* a.unshift(:bam, :bat) # => [:bam, :bat, :foo, "bar", 2]
*
@@ -1647,8 +1804,8 @@ rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary)
VALUE target_ary;
if (argc == 0) {
- rb_ary_modify_check(ary);
- return ary;
+ rb_ary_modify_check(ary);
+ return ary;
}
target_ary = ary_ensure_room_for_unshift(ary, argc);
@@ -1670,7 +1827,7 @@ rb_ary_elt(VALUE ary, long offset)
long len = RARRAY_LEN(ary);
if (len == 0) return Qnil;
if (offset < 0 || len <= offset) {
- return Qnil;
+ return Qnil;
}
return RARRAY_AREF(ary, offset);
}
@@ -1691,7 +1848,7 @@ rb_ary_subseq_step(VALUE ary, long beg, long len, long step)
if (beg < 0 || len < 0) return Qnil;
if (alen < len || alen < beg + len) {
- len = alen - beg;
+ len = alen - beg;
}
klass = rb_cArray;
if (len == 0) return ary_new(klass, 0);
@@ -1725,12 +1882,14 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
* Returns elements from +self+; does not modify +self+.
*
* When a single \Integer argument +index+ is given, returns the element at offset +index+:
+ *
* a = [:foo, 'bar', 2]
* a[0] # => :foo
* a[2] # => 2
* a # => [:foo, "bar", 2]
*
* If +index+ is negative, counts relative to the end of +self+:
+ *
* a = [:foo, 'bar', 2]
* a[-1] # => 2
* a[-2] # => "bar"
@@ -1739,12 +1898,14 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
*
* When two \Integer arguments +start+ and +length+ are given,
* returns a new \Array of size +length+ containing successive elements beginning at offset +start+:
+ *
* a = [:foo, 'bar', 2]
* a[0, 2] # => [:foo, "bar"]
* a[1, 2] # => ["bar", 2]
*
* If <tt>start + length</tt> is greater than <tt>self.length</tt>,
* returns all elements from offset +start+ to the end:
+ *
* a = [:foo, 'bar', 2]
* a[0, 4] # => [:foo, "bar", 2]
* a[1, 3] # => ["bar", 2]
@@ -1758,6 +1919,7 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
* When a single \Range argument +range+ is given,
* treats <tt>range.min</tt> as +start+ above
* and <tt>range.size</tt> as +length+ above:
+ *
* a = [:foo, 'bar', 2]
* a[0..1] # => [:foo, "bar"]
* a[1..2] # => ["bar", 2]
@@ -1765,31 +1927,36 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
* Special case: If <tt>range.start == a.size</tt>, returns a new empty \Array.
*
* If <tt>range.end</tt> is negative, calculates the end index from the end:
+ *
* a = [:foo, 'bar', 2]
* a[0..-1] # => [:foo, "bar", 2]
* a[0..-2] # => [:foo, "bar"]
* a[0..-3] # => [:foo]
*
* If <tt>range.start</tt> is negative, calculates the start index from the end:
+ *
* a = [:foo, 'bar', 2]
* a[-1..2] # => [2]
* a[-2..2] # => ["bar", 2]
* a[-3..2] # => [:foo, "bar", 2]
*
* If <tt>range.start</tt> is larger than the array size, returns +nil+.
+ *
* a = [:foo, 'bar', 2]
* a[4..1] # => nil
* a[4..0] # => nil
* a[4..-1] # => nil
*
* When a single Enumerator::ArithmeticSequence argument +aseq+ is given,
- * returns an Array of elements corresponding to the indexes produced by
+ * returns an \Array of elements corresponding to the indexes produced by
* the sequence.
+ *
* a = ['--', 'data1', '--', 'data2', '--', 'data3']
* a[(1..).step(2)] # => ["data1", "data2", "data3"]
*
* Unlike slicing with range, if the start or the end of the arithmetic sequence
* is larger than array size, throws RangeError.
+ *
* a = ['--', 'data1', '--', 'data2', '--', 'data3']
* a[(1..11).step(2)]
* # RangeError (((1..11).step(2)) out of range)
@@ -1798,6 +1965,7 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
*
* If given a single argument, and its type is not one of the listed, tries to
* convert it to Integer, and raises if it is impossible:
+ *
* a = [:foo, 'bar', 2]
* # Raises TypeError (no implicit conversion of Symbol into Integer):
* a[:foo]
@@ -1810,7 +1978,7 @@ rb_ary_aref(int argc, const VALUE *argv, VALUE ary)
{
rb_check_arity(argc, 1, 2);
if (argc == 2) {
- return rb_ary_aref2(ary, argv[0], argv[1]);
+ return rb_ary_aref2(ary, argv[0], argv[1]);
}
return rb_ary_aref1(ary, argv[0]);
}
@@ -1821,7 +1989,7 @@ rb_ary_aref2(VALUE ary, VALUE b, VALUE e)
long beg = NUM2LONG(b);
long len = NUM2LONG(e);
if (beg < 0) {
- beg += RARRAY_LEN(ary);
+ beg += RARRAY_LEN(ary);
}
return rb_ary_subseq(ary, beg, len);
}
@@ -1833,7 +2001,7 @@ rb_ary_aref1(VALUE ary, VALUE arg)
/* special case - speeding up */
if (FIXNUM_P(arg)) {
- return rb_ary_entry(ary, FIX2LONG(arg));
+ return rb_ary_entry(ary, FIX2LONG(arg));
}
/* check if idx is Range or ArithmeticSequence */
switch (rb_arithmetic_sequence_beg_len_step(arg, &beg, &len, &step, RARRAY_LEN(ary), 0)) {
@@ -1856,6 +2024,7 @@ rb_ary_aref1(VALUE ary, VALUE arg)
* a = [:foo, 'bar', 2]
* a.at(0) # => :foo
* a.at(2) # => 2
+ *
*/
VALUE
@@ -1872,6 +2041,7 @@ rb_ary_at(VALUE ary, VALUE pos)
* Returns elements from +self+; does not modify +self+.
*
* When no argument is given, returns the first element:
+ *
* a = [:foo, 'bar', 2]
* a.first # => :foo
* a # => [:foo, "bar", 2]
@@ -1880,14 +2050,17 @@ rb_ary_at(VALUE ary, VALUE pos)
*
* When non-negative \Integer argument +n+ is given,
* returns the first +n+ elements in a new \Array:
+ *
* a = [:foo, 'bar', 2]
* a.first(2) # => [:foo, "bar"]
*
* If <tt>n >= array.size</tt>, returns all elements:
+ *
* a = [:foo, 'bar', 2]
* a.first(50) # => [:foo, "bar", 2]
*
* If <tt>n == 0</tt> returns an new empty \Array:
+ *
* a = [:foo, 'bar', 2]
* a.first(0) # []
*
@@ -1897,11 +2070,11 @@ static VALUE
rb_ary_first(int argc, VALUE *argv, VALUE ary)
{
if (argc == 0) {
- if (RARRAY_LEN(ary) == 0) return Qnil;
- return RARRAY_AREF(ary, 0);
+ if (RARRAY_LEN(ary) == 0) return Qnil;
+ return RARRAY_AREF(ary, 0);
}
else {
- return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
+ return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
}
}
@@ -1913,22 +2086,26 @@ rb_ary_first(int argc, VALUE *argv, VALUE ary)
* Returns elements from +self+; +self+ is not modified.
*
* When no argument is given, returns the last element:
+ *
* a = [:foo, 'bar', 2]
* a.last # => 2
* a # => [:foo, "bar", 2]
*
* If +self+ is empty, returns +nil+.
*
- * When non-negative \Innteger argument +n+ is given,
+ * When non-negative \Integer argument +n+ is given,
* returns the last +n+ elements in a new \Array:
+ *
* a = [:foo, 'bar', 2]
* a.last(2) # => ["bar", 2]
*
* If <tt>n >= array.size</tt>, returns all elements:
+ *
* a = [:foo, 'bar', 2]
* a.last(50) # => [:foo, "bar", 2]
*
* If <tt>n == 0</tt>, returns an new empty \Array:
+ *
* a = [:foo, 'bar', 2]
* a.last(0) # []
*
@@ -1939,12 +2116,12 @@ VALUE
rb_ary_last(int argc, const VALUE *argv, VALUE ary)
{
if (argc == 0) {
- long len = RARRAY_LEN(ary);
- if (len == 0) return Qnil;
- return RARRAY_AREF(ary, len-1);
+ long len = RARRAY_LEN(ary);
+ if (len == 0) return Qnil;
+ return RARRAY_AREF(ary, len-1);
}
else {
- return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
+ return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
}
}
@@ -1958,10 +2135,12 @@ rb_ary_last(int argc, const VALUE *argv, VALUE ary)
*
* With the single \Integer argument +index+,
* returns the element at offset +index+:
+ *
* a = [:foo, 'bar', 2]
* a.fetch(1) # => "bar"
*
* If +index+ is negative, counts from the end of the array:
+ *
* a = [:foo, 'bar', 2]
* a.fetch(-1) # => 2
* a.fetch(-2) # => "bar"
@@ -1969,6 +2148,7 @@ rb_ary_last(int argc, const VALUE *argv, VALUE ary)
* With arguments +index+ and +default_value+,
* returns the element at offset +index+ if index is in range,
* otherwise returns +default_value+:
+ *
* a = [:foo, 'bar', 2]
* a.fetch(1, nil) # => "bar"
*
@@ -1979,6 +2159,7 @@ rb_ary_last(int argc, const VALUE *argv, VALUE ary)
* a = [:foo, 'bar', 2]
* a.fetch(1) {|index| raise 'Cannot happen' } # => "bar"
* a.fetch(50) {|index| "Value for #{index}" } # => "Value for 50"
+ *
*/
static VALUE
@@ -1991,20 +2172,20 @@ rb_ary_fetch(int argc, VALUE *argv, VALUE ary)
rb_scan_args(argc, argv, "11", &pos, &ifnone);
block_given = rb_block_given_p();
if (block_given && argc == 2) {
- rb_warn("block supersedes default value argument");
+ rb_warn("block supersedes default value argument");
}
idx = NUM2LONG(pos);
if (idx < 0) {
- idx += RARRAY_LEN(ary);
+ idx += RARRAY_LEN(ary);
}
if (idx < 0 || RARRAY_LEN(ary) <= idx) {
- if (block_given) return rb_yield(pos);
- if (argc == 1) {
- rb_raise(rb_eIndexError, "index %ld outside of array bounds: %ld...%ld",
- idx - (idx < 0 ? RARRAY_LEN(ary) : 0), -RARRAY_LEN(ary), RARRAY_LEN(ary));
- }
- return ifnone;
+ if (block_given) return rb_yield(pos);
+ if (argc == 1) {
+ rb_raise(rb_eIndexError, "index %ld outside of array bounds: %ld...%ld",
+ idx - (idx < 0 ? RARRAY_LEN(ary) : 0), -RARRAY_LEN(ary), RARRAY_LEN(ary));
+ }
+ return ifnone;
}
return RARRAY_AREF(ary, idx);
}
@@ -2020,6 +2201,7 @@ rb_ary_fetch(int argc, VALUE *argv, VALUE ary)
* When argument +object+ is given but no block,
* returns the index of the first element +element+
* for which <tt>object == element</tt>:
+ *
* a = [:foo, 'bar', 2, 'bar']
* a.index('bar') # => 1
*
@@ -2028,12 +2210,14 @@ rb_ary_fetch(int argc, VALUE *argv, VALUE ary)
* When both argument +object+ and a block are given,
* calls the block with each successive element;
* returns the index of the first element for which the block returns a truthy value:
+ *
* a = [:foo, 'bar', 2, 'bar']
* a.index {|element| element == 'bar' } # => 1
*
* Returns +nil+ if the block never returns a truthy value.
*
* When neither an argument nor a block is given, returns a new Enumerator:
+ *
* a = [:foo, 'bar', 2]
* e = a.index
* e # => #<Enumerator: [:foo, "bar", 2]:index>
@@ -2051,23 +2235,23 @@ rb_ary_index(int argc, VALUE *argv, VALUE ary)
long i;
if (argc == 0) {
- RETURN_ENUMERATOR(ary, 0, 0);
- for (i=0; i<RARRAY_LEN(ary); i++) {
- if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
- return LONG2NUM(i);
- }
- }
- return Qnil;
+ RETURN_ENUMERATOR(ary, 0, 0);
+ for (i=0; i<RARRAY_LEN(ary); i++) {
+ if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
+ return LONG2NUM(i);
+ }
+ }
+ return Qnil;
}
rb_check_arity(argc, 0, 1);
val = argv[0];
if (rb_block_given_p())
- rb_warn("given block not used");
+ rb_warn("given block not used");
for (i=0; i<RARRAY_LEN(ary); i++) {
- VALUE e = RARRAY_AREF(ary, i);
- if (rb_equal(e, val)) {
- return LONG2NUM(i);
- }
+ VALUE e = RARRAY_AREF(ary, i);
+ if (rb_equal(e, val)) {
+ return LONG2NUM(i);
+ }
}
return Qnil;
}
@@ -2081,6 +2265,7 @@ rb_ary_index(int argc, VALUE *argv, VALUE ary)
* Returns the index of the last element for which <tt>object == element</tt>.
*
* When argument +object+ is given but no block, returns the index of the last such element found:
+ *
* a = [:foo, 'bar', 2, 'bar']
* a.rindex('bar') # => 3
*
@@ -2088,6 +2273,7 @@ rb_ary_index(int argc, VALUE *argv, VALUE ary)
*
* When a block is given but no argument, calls the block with each successive element;
* returns the index of the last element for which the block returns a truthy value:
+ *
* a = [:foo, 'bar', 2, 'bar']
* a.rindex {|element| element == 'bar' } # => 3
*
@@ -2110,25 +2296,25 @@ rb_ary_rindex(int argc, VALUE *argv, VALUE ary)
long i = RARRAY_LEN(ary), len;
if (argc == 0) {
- RETURN_ENUMERATOR(ary, 0, 0);
- while (i--) {
- if (RTEST(rb_yield(RARRAY_AREF(ary, i))))
- return LONG2NUM(i);
- if (i > (len = RARRAY_LEN(ary))) {
- i = len;
- }
- }
- return Qnil;
+ RETURN_ENUMERATOR(ary, 0, 0);
+ while (i--) {
+ if (RTEST(rb_yield(RARRAY_AREF(ary, i))))
+ return LONG2NUM(i);
+ if (i > (len = RARRAY_LEN(ary))) {
+ i = len;
+ }
+ }
+ return Qnil;
}
rb_check_arity(argc, 0, 1);
val = argv[0];
if (rb_block_given_p())
- rb_warn("given block not used");
+ rb_warn("given block not used");
while (i--) {
- VALUE e = RARRAY_AREF(ary, i);
- if (rb_equal(e, val)) {
- return LONG2NUM(i);
- }
+ VALUE e = RARRAY_AREF(ary, i);
+ if (rb_equal(e, val)) {
+ return LONG2NUM(i);
+ }
if (i > RARRAY_LEN(ary)) {
break;
}
@@ -2154,54 +2340,54 @@ rb_ary_splice(VALUE ary, long beg, long len, const VALUE *rptr, long rlen)
if (len < 0) rb_raise(rb_eIndexError, "negative length (%ld)", len);
olen = RARRAY_LEN(ary);
if (beg < 0) {
- beg += olen;
- if (beg < 0) {
- rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
- beg - olen, -olen);
- }
+ beg += olen;
+ if (beg < 0) {
+ rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
+ beg - olen, -olen);
+ }
}
if (olen < len || olen < beg + len) {
- len = olen - beg;
+ len = olen - beg;
}
{
const VALUE *optr = RARRAY_CONST_PTR_TRANSIENT(ary);
- rofs = (rptr >= optr && rptr < optr + olen) ? rptr - optr : -1;
+ rofs = (rptr >= optr && rptr < optr + olen) ? rptr - optr : -1;
}
if (beg >= olen) {
- VALUE target_ary;
- if (beg > ARY_MAX_SIZE - rlen) {
- rb_raise(rb_eIndexError, "index %ld too big", beg);
- }
- target_ary = ary_ensure_room_for_push(ary, rlen-len); /* len is 0 or negative */
- len = beg + rlen;
- ary_mem_clear(ary, olen, beg - olen);
- if (rlen > 0) {
+ VALUE target_ary;
+ if (beg > ARY_MAX_SIZE - rlen) {
+ rb_raise(rb_eIndexError, "index %ld too big", beg);
+ }
+ target_ary = ary_ensure_room_for_push(ary, rlen-len); /* len is 0 or negative */
+ len = beg + rlen;
+ ary_mem_clear(ary, olen, beg - olen);
+ if (rlen > 0) {
if (rofs != -1) rptr = RARRAY_CONST_PTR_TRANSIENT(ary) + rofs;
- ary_memcpy0(ary, beg, rlen, rptr, target_ary);
- }
- ARY_SET_LEN(ary, len);
+ ary_memcpy0(ary, beg, rlen, rptr, target_ary);
+ }
+ ARY_SET_LEN(ary, len);
}
else {
- long alen;
-
- if (olen - len > ARY_MAX_SIZE - rlen) {
- rb_raise(rb_eIndexError, "index %ld too big", olen + rlen - len);
- }
- rb_ary_modify(ary);
- alen = olen + rlen - len;
- if (alen >= ARY_CAPA(ary)) {
- ary_double_capa(ary, alen);
- }
-
- if (len != rlen) {
+ long alen;
+
+ if (olen - len > ARY_MAX_SIZE - rlen) {
+ rb_raise(rb_eIndexError, "index %ld too big", olen + rlen - len);
+ }
+ rb_ary_modify(ary);
+ alen = olen + rlen - len;
+ if (alen >= ARY_CAPA(ary)) {
+ ary_double_capa(ary, alen);
+ }
+
+ if (len != rlen) {
RARRAY_PTR_USE_TRANSIENT(ary, ptr,
MEMMOVE(ptr + beg + rlen, ptr + beg + len,
VALUE, olen - (beg + len)));
- ARY_SET_LEN(ary, alen);
- }
- if (rlen > 0) {
+ ARY_SET_LEN(ary, alen);
+ }
+ if (rlen > 0) {
if (rofs != -1) rptr = RARRAY_CONST_PTR_TRANSIENT(ary) + rofs;
/* give up wb-protected ary */
RB_OBJ_WB_UNPROTECT_FOR(ARRAY, ary);
@@ -2211,7 +2397,7 @@ rb_ary_splice(VALUE ary, long beg, long len, const VALUE *rptr, long rlen)
*/
RARRAY_PTR_USE_TRANSIENT(ary, ptr,
MEMMOVE(ptr + beg, rptr, VALUE, rlen));
- }
+ }
}
}
@@ -2222,10 +2408,10 @@ rb_ary_set_len(VALUE ary, long len)
rb_ary_modify_check(ary);
if (ARY_SHARED_P(ary)) {
- rb_raise(rb_eRuntimeError, "can't set length of shared ");
+ rb_raise(rb_eRuntimeError, "can't set length of shared ");
}
if (len > (capa = (long)ARY_CAPA(ary))) {
- rb_bug("probable buffer overflow: %ld for %ld", len, capa);
+ rb_bug("probable buffer overflow: %ld for %ld", len, capa);
}
ARY_SET_LEN(ary, len);
}
@@ -2239,31 +2425,37 @@ rb_ary_resize(VALUE ary, long len)
olen = RARRAY_LEN(ary);
if (len == olen) return ary;
if (len > ARY_MAX_SIZE) {
- rb_raise(rb_eIndexError, "index %ld too big", len);
+ rb_raise(rb_eIndexError, "index %ld too big", len);
}
if (len > olen) {
- if (len >= ARY_CAPA(ary)) {
- ary_double_capa(ary, len);
- }
- ary_mem_clear(ary, olen, len - olen);
- ARY_SET_LEN(ary, len);
+ if (len >= ARY_CAPA(ary)) {
+ ary_double_capa(ary, len);
+ }
+ ary_mem_clear(ary, olen, len - olen);
+ ARY_SET_LEN(ary, len);
}
else if (ARY_EMBED_P(ary)) {
ARY_SET_EMBED_LEN(ary, len);
}
- else if (len <= RARRAY_EMBED_LEN_MAX) {
- VALUE tmp[RARRAY_EMBED_LEN_MAX];
- MEMCPY(tmp, ARY_HEAP_PTR(ary), VALUE, len);
- ary_discard(ary);
- MEMCPY((VALUE *)ARY_EMBED_PTR(ary), tmp, VALUE, len); /* WB: no new reference */
+ else if (len <= ary_embed_capa(ary)) {
+ const VALUE *ptr = ARY_HEAP_PTR(ary);
+ long ptr_capa = ARY_HEAP_SIZE(ary);
+ bool is_malloc_ptr = !ARY_SHARED_P(ary) && !RARRAY_TRANSIENT_P(ary);
+
+ FL_UNSET(ary, RARRAY_TRANSIENT_FLAG);
+ FL_SET_EMBED(ary);
+
+ MEMCPY((VALUE *)ARY_EMBED_PTR(ary), ptr, VALUE, len); /* WB: no new reference */
ARY_SET_EMBED_LEN(ary, len);
+
+ if (is_malloc_ptr) ruby_sized_xfree((void *)ptr, ptr_capa);
}
else {
- if (olen > len + ARY_DEFAULT_SIZE) {
+ if (olen > len + ARY_DEFAULT_SIZE) {
size_t new_capa = ary_heap_realloc(ary, len);
ARY_SET_CAPA(ary, new_capa);
- }
- ARY_SET_HEAP_LEN(ary, len);
+ }
+ ARY_SET_HEAP_LEN(ary, len);
}
ary_verify(ary);
return ary;
@@ -2296,16 +2488,19 @@ ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val)
* When \Integer argument +index+ is given, assigns +object+ to an element in +self+.
*
* If +index+ is non-negative, assigns +object+ the element at offset +index+:
+ *
* a = [:foo, 'bar', 2]
* a[0] = 'foo' # => "foo"
* a # => ["foo", "bar", 2]
*
* If +index+ is greater than <tt>self.length</tt>, extends the array:
+ *
* a = [:foo, 'bar', 2]
* a[7] = 'foo' # => "foo"
* a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"]
*
* If +index+ is negative, counts backwards from the end of the array:
+ *
* a = [:foo, 'bar', 2]
* a[-1] = 'two' # => "two"
* a # => [:foo, "bar", "two"]
@@ -2313,11 +2508,13 @@ ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val)
* When \Integer arguments +start+ and +length+ are given and +object+ is not an \Array,
* removes <tt>length - 1</tt> elements beginning at offset +start+,
* and assigns +object+ at offset +start+:
+ *
* a = [:foo, 'bar', 2]
* a[0, 2] = 'foo' # => "foo"
* a # => ["foo", 2]
*
* If +start+ is negative, counts backwards from the end of the array:
+ *
* a = [:foo, 'bar', 2]
* a[-2, 2] = 'foo' # => "foo"
* a # => [:foo, "foo"]
@@ -2325,17 +2522,20 @@ ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val)
* If +start+ is non-negative and outside the array (<tt> >= self.size</tt>),
* extends the array with +nil+, assigns +object+ at offset +start+,
* and ignores +length+:
+ *
* a = [:foo, 'bar', 2]
* a[6, 50] = 'foo' # => "foo"
* a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
*
* If +length+ is zero, shifts elements at and following offset +start+
* and assigns +object+ at offset +start+:
+ *
* a = [:foo, 'bar', 2]
* a[1, 0] = 'foo' # => "foo"
* a # => [:foo, "foo", "bar", 2]
*
* If +length+ is too large for the existing array, does not extend the array:
+ *
* a = [:foo, 'bar', 2]
* a[1, 5] = 'foo' # => "foo"
* a # => [:foo, "foo"]
@@ -2343,29 +2543,34 @@ ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val)
* When \Range argument +range+ is given and +object+ is an \Array,
* removes <tt>length - 1</tt> elements beginning at offset +start+,
* and assigns +object+ at offset +start+:
+ *
* a = [:foo, 'bar', 2]
* a[0..1] = 'foo' # => "foo"
* a # => ["foo", 2]
*
* if <tt>range.begin</tt> is negative, counts backwards from the end of the array:
+ *
* a = [:foo, 'bar', 2]
* a[-2..2] = 'foo' # => "foo"
* a # => [:foo, "foo"]
*
* If the array length is less than <tt>range.begin</tt>,
* assigns +object+ at offset <tt>range.begin</tt>, and ignores +length+:
+ *
* a = [:foo, 'bar', 2]
* a[6..50] = 'foo' # => "foo"
* a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
*
* If <tt>range.end</tt> is zero, shifts elements at and following offset +start+
* and assigns +object+ at offset +start+:
+ *
* a = [:foo, 'bar', 2]
* a[1..0] = 'foo' # => "foo"
* a # => [:foo, "foo", "bar", 2]
*
* If <tt>range.end</tt> is negative, assigns +object+ at offset +start+,
* retains <tt>range.end.abs -1</tt> elements past that, and removes those beyond:
+ *
* a = [:foo, 'bar', 2]
* a[1..-1] = 'foo' # => "foo"
* a # => [:foo, "foo"]
@@ -2379,9 +2584,11 @@ ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val)
*
* If <tt>range.end</tt> is too large for the existing array,
* replaces array elements, but does not extend the array with +nil+ values:
+ *
* a = [:foo, 'bar', 2]
* a[1..5] = 'foo' # => "foo"
* a # => [:foo, "foo"]
+ *
*/
static VALUE
@@ -2392,16 +2599,16 @@ rb_ary_aset(int argc, VALUE *argv, VALUE ary)
rb_check_arity(argc, 2, 3);
rb_ary_modify_check(ary);
if (argc == 3) {
- beg = NUM2LONG(argv[0]);
- len = NUM2LONG(argv[1]);
+ beg = NUM2LONG(argv[0]);
+ len = NUM2LONG(argv[1]);
return ary_aset_by_rb_ary_splice(ary, beg, len, argv[2]);
}
if (FIXNUM_P(argv[0])) {
- offset = FIX2LONG(argv[0]);
+ offset = FIX2LONG(argv[0]);
return ary_aset_by_rb_ary_store(ary, offset, argv[1]);
}
if (rb_range_beg_len(argv[0], &beg, &len, RARRAY_LEN(ary), 1)) {
- /* check if idx is Range */
+ /* check if idx is Range */
return ary_aset_by_rb_ary_splice(ary, beg, len, argv[1]);
}
@@ -2418,15 +2625,18 @@ rb_ary_aset(int argc, VALUE *argv, VALUE ary)
*
* When +index+ is non-negative, inserts all given +objects+
* before the element at offset +index+:
+ *
* a = [:foo, 'bar', 2]
* a.insert(1, :bat, :bam) # => [:foo, :bat, :bam, "bar", 2]
*
* Extends the array if +index+ is beyond the array (<tt>index >= self.size</tt>):
+ *
* a = [:foo, 'bar', 2]
* a.insert(5, :bat, :bam)
* a # => [:foo, "bar", 2, nil, nil, :bat, :bam]
*
* Does nothing if no objects given:
+ *
* a = [:foo, 'bar', 2]
* a.insert(1)
* a.insert(50)
@@ -2435,9 +2645,11 @@ rb_ary_aset(int argc, VALUE *argv, VALUE ary)
*
* When +index+ is negative, inserts all given +objects+
* _after_ the element at offset <tt>index+self.size</tt>:
+ *
* a = [:foo, 'bar', 2]
* a.insert(-2, :bat, :bam)
* a # => [:foo, "bar", :bat, :bam, 2]
+ *
*/
static VALUE
@@ -2450,15 +2662,15 @@ rb_ary_insert(int argc, VALUE *argv, VALUE ary)
pos = NUM2LONG(argv[0]);
if (argc == 1) return ary;
if (pos == -1) {
- pos = RARRAY_LEN(ary);
+ pos = RARRAY_LEN(ary);
}
else if (pos < 0) {
- long minpos = -RARRAY_LEN(ary) - 1;
- if (pos < minpos) {
- rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
- pos, minpos);
- }
- pos++;
+ long minpos = -RARRAY_LEN(ary) - 1;
+ if (pos < minpos) {
+ rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
+ pos, minpos);
+ }
+ pos++;
}
rb_ary_splice(ary, pos, 0, argv + 1, argc - 1);
return ary;
@@ -2482,29 +2694,35 @@ ary_enum_length(VALUE ary, VALUE args, VALUE eobj)
*
* When a block given, passes each successive array element to the block;
* returns +self+:
+ *
* a = [:foo, 'bar', 2]
* a.each {|element| puts "#{element.class} #{element}" }
*
* Output:
+ *
* Symbol foo
* String bar
* Integer 2
*
* Allows the array to be modified during iteration:
+ *
* a = [:foo, 'bar', 2]
* a.each {|element| puts element; a.clear if element.to_s.start_with?('b') }
*
* Output:
+ *
* foo
* bar
*
* When no block given, returns a new \Enumerator:
* a = [:foo, 'bar', 2]
+ *
* e = a.each
* e # => #<Enumerator: [:foo, "bar", 2]:each>
* a1 = e.each {|element| puts "#{element.class} #{element}" }
*
* Output:
+ *
* Symbol foo
* String bar
* Integer 2
@@ -2519,7 +2737,7 @@ rb_ary_each(VALUE ary)
ary_verify(ary);
RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
for (i=0; i<RARRAY_LEN(ary); i++) {
- rb_yield(RARRAY_AREF(ary, i));
+ rb_yield(RARRAY_AREF(ary, i));
}
return ary;
}
@@ -2533,29 +2751,35 @@ rb_ary_each(VALUE ary)
*
* When a block given, passes each successive array index to the block;
* returns +self+:
+ *
* a = [:foo, 'bar', 2]
* a.each_index {|index| puts "#{index} #{a[index]}" }
*
* Output:
+ *
* 0 foo
* 1 bar
* 2 2
*
* Allows the array to be modified during iteration:
+ *
* a = [:foo, 'bar', 2]
* a.each_index {|index| puts index; a.clear if index > 0 }
*
* Output:
+ *
* 0
* 1
*
* When no block given, returns a new \Enumerator:
+ *
* a = [:foo, 'bar', 2]
* e = a.each_index
* e # => #<Enumerator: [:foo, "bar", 2]:each_index>
* a1 = e.each {|index| puts "#{index} #{a[index]}"}
*
* Output:
+ *
* 0 foo
* 1 bar
* 2 2
@@ -2570,7 +2794,7 @@ rb_ary_each_index(VALUE ary)
RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
for (i=0; i<RARRAY_LEN(ary); i++) {
- rb_yield(LONG2NUM(i));
+ rb_yield(LONG2NUM(i));
}
return ary;
}
@@ -2584,28 +2808,35 @@ rb_ary_each_index(VALUE ary)
*
* When a block given, passes, in reverse order, each element to the block;
* returns +self+:
+ *
* a = [:foo, 'bar', 2]
* a.reverse_each {|element| puts "#{element.class} #{element}" }
*
* Output:
+ *
* Integer 2
* String bar
* Symbol foo
*
* Allows the array to be modified during iteration:
+ *
* a = [:foo, 'bar', 2]
* a.reverse_each {|element| puts element; a.clear if element.to_s.start_with?('b') }
*
* Output:
+ *
* 2
* bar
*
* When no block given, returns a new \Enumerator:
+ *
* a = [:foo, 'bar', 2]
* e = a.reverse_each
* e # => #<Enumerator: [:foo, "bar", 2]:reverse_each>
* a1 = e.each {|element| puts "#{element.class} #{element}" }
+ *
* Output:
+ *
* Integer 2
* String bar
* Symbol foo
@@ -2621,12 +2852,12 @@ rb_ary_reverse_each(VALUE ary)
RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
len = RARRAY_LEN(ary);
while (len--) {
- long nlen;
- rb_yield(RARRAY_AREF(ary, len));
- nlen = RARRAY_LEN(ary);
- if (nlen < len) {
- len = nlen;
- }
+ long nlen;
+ rb_yield(RARRAY_AREF(ary, len));
+ nlen = RARRAY_LEN(ary);
+ if (nlen < len) {
+ len = nlen;
+ }
}
return ary;
}
@@ -2692,10 +2923,10 @@ recursive_join(VALUE obj, VALUE argp, int recur)
int *first = (int *)arg[3];
if (recur) {
- rb_raise(rb_eArgError, "recursive array join");
+ rb_raise(rb_eArgError, "recursive array join");
}
else {
- ary_join_1(obj, ary, sep, 0, result, first);
+ ary_join_1(obj, ary, sep, 0, result, first);
}
return Qnil;
}
@@ -2708,11 +2939,11 @@ ary_join_0(VALUE ary, VALUE sep, long max, VALUE result)
if (max > 0) rb_enc_copy(result, RARRAY_AREF(ary, 0));
for (i=0; i<max; i++) {
- val = RARRAY_AREF(ary, i);
+ val = RARRAY_AREF(ary, i);
if (!RB_TYPE_P(val, T_STRING)) break;
- if (i > 0 && !NIL_P(sep))
- rb_str_buf_append(result, sep);
- rb_str_buf_append(result, val);
+ if (i > 0 && !NIL_P(sep))
+ rb_str_buf_append(result, sep);
+ rb_str_buf_append(result, val);
}
return i;
}
@@ -2751,16 +2982,16 @@ ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first)
VALUE val, tmp;
for (; i<RARRAY_LEN(ary); i++) {
- if (i > 0 && !NIL_P(sep))
- rb_str_buf_append(result, sep);
+ if (i > 0 && !NIL_P(sep))
+ rb_str_buf_append(result, sep);
- val = RARRAY_AREF(ary, i);
- if (RB_TYPE_P(val, T_STRING)) {
+ val = RARRAY_AREF(ary, i);
+ if (RB_TYPE_P(val, T_STRING)) {
ary_join_1_str(result, val, first);
- }
- else if (RB_TYPE_P(val, T_ARRAY)) {
+ }
+ else if (RB_TYPE_P(val, T_ARRAY)) {
ary_join_1_ary(val, ary, sep, result, val, first);
- }
+ }
else if (!NIL_P(tmp = rb_check_string_type(val))) {
ary_join_1_str(result, tmp, first);
}
@@ -2769,7 +3000,7 @@ ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first)
}
else {
ary_join_1_str(result, rb_obj_as_string(val), first);
- }
+ }
}
}
@@ -2782,26 +3013,26 @@ rb_ary_join(VALUE ary, VALUE sep)
if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new(0, 0);
if (!NIL_P(sep)) {
- StringValue(sep);
- len += RSTRING_LEN(sep) * (RARRAY_LEN(ary) - 1);
+ StringValue(sep);
+ len += RSTRING_LEN(sep) * (RARRAY_LEN(ary) - 1);
}
for (i=0; i<RARRAY_LEN(ary); i++) {
- val = RARRAY_AREF(ary, i);
- tmp = rb_check_string_type(val);
+ val = RARRAY_AREF(ary, i);
+ tmp = rb_check_string_type(val);
- if (NIL_P(tmp) || tmp != val) {
- int first;
+ if (NIL_P(tmp) || tmp != val) {
+ int first;
long n = RARRAY_LEN(ary);
if (i > n) i = n;
result = rb_str_buf_new(len + (n-i)*10);
- rb_enc_associate(result, rb_usascii_encoding());
+ rb_enc_associate(result, rb_usascii_encoding());
i = ary_join_0(ary, sep, i, result);
- first = i == 0;
- ary_join_1(ary, ary, sep, i, result, &first);
- return result;
- }
+ first = i == 0;
+ ary_join_1(ary, ary, sep, i, result, &first);
+ return result;
+ }
- len += RSTRING_LEN(tmp);
+ len += RSTRING_LEN(tmp);
}
result = rb_str_new(0, len);
@@ -2818,22 +3049,27 @@ rb_ary_join(VALUE ary, VALUE sep)
* array.join(separator = $,) -> new_string
*
* Returns the new \String formed by joining the array elements after conversion.
- * For each element +element+
+ * For each element +element+:
+ *
* - Uses <tt>element.to_s</tt> if +element+ is not a <tt>kind_of?(Array)</tt>.
* - Uses recursive <tt>element.join(separator)</tt> if +element+ is a <tt>kind_of?(Array)</tt>.
*
* With no argument, joins using the output field separator, <tt>$,</tt>:
+ *
* a = [:foo, 'bar', 2]
* $, # => nil
* a.join # => "foobar2"
*
* With \string argument +separator+, joins using that separator:
+ *
* a = [:foo, 'bar', 2]
* a.join("\n") # => "foo\nbar\n2"
*
* Joins recursively for nested Arrays:
+ *
* a = [:foo, [:bar, [:baz, :bat]]]
* a.join # => "foobarbazbat"
+ *
*/
static VALUE
rb_ary_join_m(int argc, VALUE *argv, VALUE ary)
@@ -2859,10 +3095,10 @@ inspect_ary(VALUE ary, VALUE dummy, int recur)
if (recur) return rb_usascii_str_new_cstr("[...]");
str = rb_str_buf_new2("[");
for (i=0; i<RARRAY_LEN(ary); i++) {
- s = rb_inspect(RARRAY_AREF(ary, i));
- if (i > 0) rb_str_buf_cat2(str, ", ");
- else rb_enc_copy(str, s);
- rb_str_buf_append(str, s);
+ s = rb_inspect(RARRAY_AREF(ary, i));
+ if (i > 0) rb_str_buf_cat2(str, ", ");
+ else rb_enc_copy(str, s);
+ rb_str_buf_append(str, s);
}
rb_str_buf_cat2(str, "]");
return str;
@@ -2874,6 +3110,7 @@ inspect_ary(VALUE ary, VALUE dummy, int recur)
*
* Returns the new \String formed by calling method <tt>#inspect</tt>
* on each array element:
+ *
* a = [:foo, 'bar', 2]
* a.inspect # => "[:foo, \"bar\", 2]"
*
@@ -2898,10 +3135,12 @@ rb_ary_to_s(VALUE ary)
* to_a -> self or new_array
*
* When +self+ is an instance of \Array, returns +self+:
+ *
* a = [:foo, 'bar', 2]
* a.to_a # => [:foo, "bar", 2]
*
* Otherwise, returns a new \Array containing the elements of +self+:
+ *
* class MyArray < Array; end
* a = MyArray.new(['foo', 'bar', 'two'])
* a.instance_of?(Array) # => false
@@ -2909,15 +3148,16 @@ rb_ary_to_s(VALUE ary)
* a1 = a.to_a
* a1 # => ["foo", "bar", "two"]
* a1.class # => Array # Not MyArray
+ *
*/
static VALUE
rb_ary_to_a(VALUE ary)
{
if (rb_obj_class(ary) != rb_cArray) {
- VALUE dup = rb_ary_new2(RARRAY_LEN(ary));
- rb_ary_replace(dup, ary);
- return dup;
+ VALUE dup = rb_ary_new2(RARRAY_LEN(ary));
+ rb_ary_replace(dup, ary);
+ return dup;
}
return ary;
}
@@ -2932,16 +3172,19 @@ rb_ary_to_a(VALUE ary)
* When a block is given, calls the block with each array element;
* the block must return a 2-element \Array whose two elements
* form a key-value pair in the returned \Hash:
+ *
* a = ['foo', :bar, 1, [2, 3], {baz: 4}]
* h = a.to_h {|item| [item, item] }
* h # => {"foo"=>"foo", :bar=>:bar, 1=>1, [2, 3]=>[2, 3], {:baz=>4}=>{:baz=>4}}
*
* When no block is given, +self+ must be an \Array of 2-element sub-arrays,
* each sub-array is formed into a key-value pair in the new \Hash:
+ *
* [].to_h # => {}
* a = [['foo', 'zero'], ['bar', 'one'], ['baz', 'two']]
* h = a.to_h
* h # => {"foo"=>"zero", "bar"=>"one", "baz"=>"two"}
+ *
*/
static VALUE
@@ -2952,18 +3195,18 @@ rb_ary_to_h(VALUE ary)
int block_given = rb_block_given_p();
for (i=0; i<RARRAY_LEN(ary); i++) {
- const VALUE e = rb_ary_elt(ary, i);
- const VALUE elt = block_given ? rb_yield_force_blockarg(e) : e;
- const VALUE key_value_pair = rb_check_array_type(elt);
- if (NIL_P(key_value_pair)) {
- rb_raise(rb_eTypeError, "wrong element type %"PRIsVALUE" at %ld (expected array)",
- rb_obj_class(elt), i);
- }
- if (RARRAY_LEN(key_value_pair) != 2) {
- rb_raise(rb_eArgError, "wrong array length at %ld (expected 2, was %ld)",
- i, RARRAY_LEN(key_value_pair));
- }
- rb_hash_aset(hash, RARRAY_AREF(key_value_pair, 0), RARRAY_AREF(key_value_pair, 1));
+ const VALUE e = rb_ary_elt(ary, i);
+ const VALUE elt = block_given ? rb_yield_force_blockarg(e) : e;
+ const VALUE key_value_pair = rb_check_array_type(elt);
+ if (NIL_P(key_value_pair)) {
+ rb_raise(rb_eTypeError, "wrong element type %"PRIsVALUE" at %ld (expected array)",
+ rb_obj_class(elt), i);
+ }
+ if (RARRAY_LEN(key_value_pair) != 2) {
+ rb_raise(rb_eArgError, "wrong array length at %ld (expected 2, was %ld)",
+ i, RARRAY_LEN(key_value_pair));
+ }
+ rb_hash_aset(hash, RARRAY_AREF(key_value_pair, 0), RARRAY_AREF(key_value_pair, 1));
}
return hash;
}
@@ -2985,9 +3228,9 @@ static void
ary_reverse(VALUE *p1, VALUE *p2)
{
while (p1 < p2) {
- VALUE tmp = *p1;
- *p1++ = *p2;
- *p2-- = tmp;
+ VALUE tmp = *p1;
+ *p1++ = *p2;
+ *p2-- = tmp;
}
}
@@ -3002,7 +3245,7 @@ rb_ary_reverse(VALUE ary)
RARRAY_PTR_USE_TRANSIENT(ary, p1, {
p2 = p1 + len - 1; /* points last item */
ary_reverse(p1, p2);
- }); /* WB: no new reference */
+ }); /* WB: no new reference */
}
return ary;
}
@@ -3012,8 +3255,10 @@ rb_ary_reverse(VALUE ary)
* array.reverse! -> self
*
* Reverses +self+ in place:
+ *
* a = ['foo', 'bar', 'two']
* a.reverse! # => ["two", "bar", "foo"]
+ *
*/
static VALUE
@@ -3026,10 +3271,12 @@ rb_ary_reverse_bang(VALUE ary)
* call-seq:
* array.reverse -> new_array
*
- * Returns a new \Array with the elements of +self+ in reverse order.
+ * Returns a new \Array with the elements of +self+ in reverse order:
+ *
* a = ['foo', 'bar', 'two']
* a1 = a.reverse
* a1 # => ["two", "bar", "foo"]
+ *
*/
static VALUE
@@ -3041,7 +3288,7 @@ rb_ary_reverse_m(VALUE ary)
if (len > 0) {
const VALUE *p1 = RARRAY_CONST_PTR_TRANSIENT(ary);
VALUE *p2 = (VALUE *)RARRAY_CONST_PTR_TRANSIENT(dup) + len - 1;
- do *p2-- = *p1++; while (--len > 0);
+ do *p2-- = *p1++; while (--len > 0);
}
ARY_SET_LEN(dup, RARRAY_LEN(ary));
return dup;
@@ -3097,35 +3344,42 @@ rb_ary_rotate(VALUE ary, long cnt)
* Rotates +self+ in place by moving elements from one end to the other; returns +self+.
*
* When no argument given, rotates the first element to the last position:
+ *
* a = [:foo, 'bar', 2, 'bar']
* a.rotate! # => ["bar", 2, "bar", :foo]
*
* When given a non-negative \Integer +count+,
* rotates +count+ elements from the beginning to the end:
+ *
* a = [:foo, 'bar', 2]
* a.rotate!(2)
* a # => [2, :foo, "bar"]
*
* If +count+ is large, uses <tt>count % array.size</tt> as the count:
+ *
* a = [:foo, 'bar', 2]
* a.rotate!(20)
* a # => [2, :foo, "bar"]
*
* If +count+ is zero, returns +self+ unmodified:
+ *
* a = [:foo, 'bar', 2]
* a.rotate!(0)
* a # => [:foo, "bar", 2]
*
* When given a negative Integer +count+, rotates in the opposite direction,
* from end to beginning:
+ *
* a = [:foo, 'bar', 2]
* a.rotate!(-2)
* a # => ["bar", 2, :foo]
*
* If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
+ *
* a = [:foo, 'bar', 2]
* a.rotate!(-5)
* a # => ["bar", 2, :foo]
+ *
*/
static VALUE
@@ -3146,36 +3400,43 @@ rb_ary_rotate_bang(int argc, VALUE *argv, VALUE ary)
*
* When no argument given, returns a new \Array that is like +self+,
* except that the first element has been rotated to the last position:
+ *
* a = [:foo, 'bar', 2, 'bar']
* a1 = a.rotate
* a1 # => ["bar", 2, "bar", :foo]
*
* When given a non-negative \Integer +count+,
* returns a new \Array with +count+ elements rotated from the beginning to the end:
+ *
* a = [:foo, 'bar', 2]
* a1 = a.rotate(2)
* a1 # => [2, :foo, "bar"]
*
* If +count+ is large, uses <tt>count % array.size</tt> as the count:
+ *
* a = [:foo, 'bar', 2]
* a1 = a.rotate(20)
* a1 # => [2, :foo, "bar"]
*
* If +count+ is zero, returns a copy of +self+, unmodified:
+ *
* a = [:foo, 'bar', 2]
* a1 = a.rotate(0)
* a1 # => [:foo, "bar", 2]
*
* When given a negative \Integer +count+, rotates in the opposite direction,
* from end to beginning:
+ *
* a = [:foo, 'bar', 2]
* a1 = a.rotate(-2)
* a1 # => ["bar", 2, :foo]
*
* If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
+ *
* a = [:foo, 'bar', 2]
* a1 = a.rotate(-5)
* a1 # => ["bar", 2, :foo]
+ *
*/
static VALUE
@@ -3189,11 +3450,11 @@ rb_ary_rotate_m(int argc, VALUE *argv, VALUE ary)
len = RARRAY_LEN(ary);
rotated = rb_ary_new2(len);
if (len > 0) {
- cnt = rotate_count(cnt, len);
+ cnt = rotate_count(cnt, len);
ptr = RARRAY_CONST_PTR_TRANSIENT(ary);
- len -= cnt;
- ary_memcpy(rotated, 0, len, ptr + cnt);
- ary_memcpy(rotated, len, cnt, ptr);
+ len -= cnt;
+ ary_memcpy(rotated, 0, len, ptr + cnt);
+ ary_memcpy(rotated, len, cnt, ptr);
}
ARY_SET_LEN(rotated, RARRAY_LEN(ary));
return rotated;
@@ -3202,14 +3463,13 @@ rb_ary_rotate_m(int argc, VALUE *argv, VALUE ary)
struct ary_sort_data {
VALUE ary;
VALUE receiver;
- struct cmp_opt_data cmp_opt;
};
static VALUE
sort_reentered(VALUE ary)
{
if (RBASIC(ary)->klass) {
- rb_raise(rb_eRuntimeError, "sort reentered");
+ rb_raise(rb_eRuntimeError, "sort reentered");
}
return Qnil;
}
@@ -3248,16 +3508,16 @@ sort_2(const void *ap, const void *bp, void *dummy)
VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
int n;
- if (FIXNUM_P(a) && FIXNUM_P(b) && CMP_OPTIMIZABLE(data->cmp_opt, Integer)) {
- if ((long)a > (long)b) return 1;
- if ((long)a < (long)b) return -1;
- return 0;
+ if (FIXNUM_P(a) && FIXNUM_P(b) && CMP_OPTIMIZABLE(INTEGER)) {
+ if ((long)a > (long)b) return 1;
+ if ((long)a < (long)b) return -1;
+ return 0;
}
- if (STRING_P(a) && STRING_P(b) && CMP_OPTIMIZABLE(data->cmp_opt, String)) {
- return rb_str_cmp(a, b);
+ if (STRING_P(a) && STRING_P(b) && CMP_OPTIMIZABLE(STRING)) {
+ return rb_str_cmp(a, b);
}
- if (RB_FLOAT_TYPE_P(a) && CMP_OPTIMIZABLE(data->cmp_opt, Float)) {
- return rb_float_cmp(a, b);
+ if (RB_FLOAT_TYPE_P(a) && CMP_OPTIMIZABLE(FLOAT)) {
+ return rb_float_cmp(a, b);
}
retval = rb_funcallv(a, id_cmp, 1, &b);
@@ -3276,6 +3536,7 @@ sort_2(const void *ap, const void *bp, void *dummy)
*
* With no block, compares elements using operator <tt><=></tt>
* (see Comparable):
+ *
* a = 'abcde'.split('').shuffle
* a # => ["e", "b", "d", "a", "c"]
* a.sort!
@@ -3283,11 +3544,13 @@ sort_2(const void *ap, const void *bp, void *dummy)
*
* With a block, calls the block with each element pair;
* for each element pair +a+ and +b+, the block should return an integer:
+ *
* - Negative when +b+ is to follow +a+.
* - Zero when +a+ and +b+ are equivalent.
* - Positive when +a+ is to follow +b+.
*
* Example:
+ *
* a = 'abcde'.split('').shuffle
* a # => ["e", "b", "d", "a", "c"]
* a.sort! {|a, b| a <=> b }
@@ -3297,10 +3560,12 @@ sort_2(const void *ap, const void *bp, void *dummy)
*
* When the block returns zero, the order for +a+ and +b+ is indeterminate,
* and may be unstable:
+ *
* a = 'abcde'.split('').shuffle
* a # => ["e", "b", "d", "a", "c"]
* a.sort! {|a, b| 0 }
* a # => ["d", "e", "c", "a", "b"]
+ *
*/
VALUE
@@ -3309,25 +3574,23 @@ rb_ary_sort_bang(VALUE ary)
rb_ary_modify(ary);
assert(!ARY_SHARED_P(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_CLEAR_CLASS(tmp);
- data.ary = tmp;
+ VALUE tmp = ary_make_substitution(ary); /* only ary refers tmp */
+ struct ary_sort_data data;
+ long len = RARRAY_LEN(ary);
+ RBASIC_CLEAR_CLASS(tmp);
+ data.ary = tmp;
data.receiver = ary;
- data.cmp_opt.opt_methods = 0;
- data.cmp_opt.opt_inited = 0;
- RARRAY_PTR_USE(tmp, ptr, {
+ RARRAY_PTR_USE(tmp, ptr, {
ruby_qsort(ptr, len, sizeof(VALUE),
rb_block_given_p()?sort_1:sort_2, &data);
- }); /* WB: no new reference */
- rb_ary_modify(ary);
+ }); /* WB: no new reference */
+ rb_ary_modify(ary);
if (ARY_EMBED_P(tmp)) {
if (ARY_SHARED_P(ary)) { /* ary might be destructively operated in the given block */
rb_ary_unshare(ary);
- FL_SET_EMBED(ary);
+ FL_SET_EMBED(ary);
}
- ary_memcpy(ary, 0, ARY_EMBED_LEN(tmp), ARY_EMBED_PTR(tmp));
+ ary_memcpy(ary, 0, ARY_EMBED_LEN(tmp), ARY_EMBED_PTR(tmp));
ARY_SET_LEN(ary, ARY_EMBED_LEN(tmp));
}
else {
@@ -3373,6 +3636,7 @@ rb_ary_sort_bang(VALUE ary)
*
* With no block, compares elements using operator <tt><=></tt>
* (see Comparable):
+ *
* a = 'abcde'.split('').shuffle
* a # => ["e", "b", "d", "a", "c"]
* a1 = a.sort
@@ -3380,11 +3644,13 @@ rb_ary_sort_bang(VALUE ary)
*
* With a block, calls the block with each element pair;
* for each element pair +a+ and +b+, the block should return an integer:
+ *
* - Negative when +b+ is to follow +a+.
* - Zero when +a+ and +b+ are equivalent.
* - Positive when +a+ is to follow +b+.
*
* Example:
+ *
* a = 'abcde'.split('').shuffle
* a # => ["e", "b", "d", "a", "c"]
* a1 = a.sort {|a, b| a <=> b }
@@ -3394,6 +3660,7 @@ rb_ary_sort_bang(VALUE ary)
*
* When the block returns zero, the order for +a+ and +b+ is indeterminate,
* and may be unstable:
+ *
* a = 'abcde'.split('').shuffle
* a # => ["e", "b", "d", "a", "c"]
* a1 = a.sort {|a, b| 0 }
@@ -3428,7 +3695,7 @@ rb_ary_bsearch(VALUE ary)
VALUE index_result = rb_ary_bsearch_index(ary);
if (FIXNUM_P(index_result)) {
- return rb_ary_entry(ary, FIX2LONG(index_result));
+ return rb_ary_entry(ary, FIX2LONG(index_result));
}
return index_result;
}
@@ -3451,39 +3718,39 @@ rb_ary_bsearch_index(VALUE ary)
RETURN_ENUMERATOR(ary, 0, 0);
while (low < high) {
- mid = low + ((high - low) / 2);
- val = rb_ary_entry(ary, mid);
- v = rb_yield(val);
- if (FIXNUM_P(v)) {
- if (v == INT2FIX(0)) return INT2FIX(mid);
- smaller = (SIGNED_VALUE)v < 0; /* Fixnum preserves its sign-bit */
- }
- else if (v == Qtrue) {
- satisfied = 1;
- smaller = 1;
- }
- else if (!RTEST(v)) {
- smaller = 0;
- }
- else if (rb_obj_is_kind_of(v, rb_cNumeric)) {
- const VALUE zero = INT2FIX(0);
- switch (rb_cmpint(rb_funcallv(v, id_cmp, 1, &zero), v, zero)) {
- case 0: return INT2FIX(mid);
- case 1: smaller = 1; break;
- case -1: smaller = 0;
- }
- }
- else {
- rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE
- " (must be numeric, true, false or nil)",
- rb_obj_class(v));
- }
- if (smaller) {
- high = mid;
- }
- else {
- low = mid + 1;
- }
+ mid = low + ((high - low) / 2);
+ val = rb_ary_entry(ary, mid);
+ v = rb_yield(val);
+ if (FIXNUM_P(v)) {
+ if (v == INT2FIX(0)) return INT2FIX(mid);
+ smaller = (SIGNED_VALUE)v < 0; /* Fixnum preserves its sign-bit */
+ }
+ else if (v == Qtrue) {
+ satisfied = 1;
+ smaller = 1;
+ }
+ else if (!RTEST(v)) {
+ smaller = 0;
+ }
+ else if (rb_obj_is_kind_of(v, rb_cNumeric)) {
+ const VALUE zero = INT2FIX(0);
+ switch (rb_cmpint(rb_funcallv(v, id_cmp, 1, &zero), v, zero)) {
+ case 0: return INT2FIX(mid);
+ case 1: smaller = 0; break;
+ case -1: smaller = 1;
+ }
+ }
+ else {
+ rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE
+ " (must be numeric, true, false or nil)",
+ rb_obj_class(v));
+ }
+ if (smaller) {
+ high = mid;
+ }
+ else {
+ low = mid + 1;
+ }
}
if (!satisfied) return Qnil;
return INT2FIX(low);
@@ -3510,6 +3777,7 @@ sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, dummy))
* For duplicates returned by the block, the ordering is indeterminate, and may be unstable.
*
* This example sorts strings based on their sizes:
+ *
* a = ['aaaa', 'bbb', 'cc', 'd']
* a.sort_by! {|element| element.size }
* a # => ["d", "cc", "bbb", "aaaa"]
@@ -3518,6 +3786,7 @@ sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, dummy))
*
* a = ['aaaa', 'bbb', 'cc', 'd']
* a.sort_by! # => #<Enumerator: ["aaaa", "bbb", "cc", "d"]:sort_by!>
+ *
*/
static VALUE
@@ -3540,6 +3809,7 @@ rb_ary_sort_by_bang(VALUE ary)
*
* Calls the block, if given, with each element of +self+;
* returns a new \Array whose elements are the return values from the block:
+ *
* a = [:foo, 'bar', 2]
* a1 = a.map {|element| element.class }
* a1 # => [Symbol, String, Integer]
@@ -3574,10 +3844,12 @@ rb_ary_collect(VALUE ary)
*
* Calls the block, if given, with each element;
* replaces the element with the block's return value:
+ *
* a = [:foo, 'bar', 2]
* a.map! { |element| element.class } # => [Symbol, String, Integer]
*
* Returns a new \Enumerator if no block given:
+ *
* a = [:foo, 'bar', 2]
* a1 = a.map!
* a1 # => #<Enumerator: [:foo, "bar", 2]:map!>
@@ -3593,7 +3865,7 @@ rb_ary_collect_bang(VALUE ary)
RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
rb_ary_modify(ary);
for (i = 0; i < RARRAY_LEN(ary); i++) {
- rb_ary_store(ary, i, rb_yield(RARRAY_AREF(ary, i)));
+ rb_ary_store(ary, i, rb_yield(RARRAY_AREF(ary, i)));
}
return ary;
}
@@ -3605,21 +3877,21 @@ rb_get_values_at(VALUE obj, long olen, int argc, const VALUE *argv, VALUE (*func
long beg, len, i, j;
for (i=0; i<argc; i++) {
- if (FIXNUM_P(argv[i])) {
- rb_ary_push(result, (*func)(obj, FIX2LONG(argv[i])));
- continue;
- }
- /* check if idx is Range */
- if (rb_range_beg_len(argv[i], &beg, &len, olen, 1)) {
- long end = olen < beg+len ? olen : beg+len;
- for (j = beg; j < end; j++) {
- rb_ary_push(result, (*func)(obj, j));
- }
- if (beg + len > j)
- rb_ary_resize(result, RARRAY_LEN(result) + (beg + len) - j);
- continue;
- }
- rb_ary_push(result, (*func)(obj, NUM2LONG(argv[i])));
+ if (FIXNUM_P(argv[i])) {
+ rb_ary_push(result, (*func)(obj, FIX2LONG(argv[i])));
+ continue;
+ }
+ /* check if idx is Range */
+ if (rb_range_beg_len(argv[i], &beg, &len, olen, 1)) {
+ long end = olen < beg+len ? olen : beg+len;
+ for (j = beg; j < end; j++) {
+ rb_ary_push(result, (*func)(obj, j));
+ }
+ if (beg + len > j)
+ rb_ary_resize(result, RARRAY_LEN(result) + (beg + len) - j);
+ continue;
+ }
+ rb_ary_push(result, (*func)(obj, NUM2LONG(argv[i])));
}
return result;
}
@@ -3629,25 +3901,25 @@ append_values_at_single(VALUE result, VALUE ary, long olen, VALUE idx)
{
long beg, len;
if (FIXNUM_P(idx)) {
- beg = FIX2LONG(idx);
+ beg = FIX2LONG(idx);
}
/* check if idx is Range */
else if (rb_range_beg_len(idx, &beg, &len, olen, 1)) {
- if (len > 0) {
+ if (len > 0) {
const VALUE *const src = RARRAY_CONST_PTR_TRANSIENT(ary);
- const long end = beg + len;
- const long prevlen = RARRAY_LEN(result);
- if (beg < olen) {
- rb_ary_cat(result, src + beg, end > olen ? olen-beg : len);
- }
- if (end > olen) {
- rb_ary_store(result, prevlen + len - 1, Qnil);
- }
- }
- return result;
+ const long end = beg + len;
+ const long prevlen = RARRAY_LEN(result);
+ if (beg < olen) {
+ rb_ary_cat(result, src + beg, end > olen ? olen-beg : len);
+ }
+ if (end > olen) {
+ rb_ary_store(result, prevlen + len - 1, Qnil);
+ }
+ }
+ return result;
}
else {
- beg = NUM2LONG(idx);
+ beg = NUM2LONG(idx);
}
return rb_ary_push(result, rb_ary_entry(ary, beg));
}
@@ -3660,32 +3932,39 @@ append_values_at_single(VALUE result, VALUE ary, long olen, VALUE idx)
* of +self+ at the given \Integer or \Range +indexes+.
*
* For each positive +index+, returns the element at offset +index+:
+ *
* a = [:foo, 'bar', 2]
* a.values_at(0, 2) # => [:foo, 2]
* a.values_at(0..1) # => [:foo, "bar"]
*
* The given +indexes+ may be in any order, and may repeat:
+ *
* a = [:foo, 'bar', 2]
* a.values_at(2, 0, 1, 0, 2) # => [2, :foo, "bar", :foo, 2]
* a.values_at(1, 0..2) # => ["bar", :foo, "bar", 2]
*
* Assigns +nil+ for an +index+ that is too large:
+ *
* a = [:foo, 'bar', 2]
* a.values_at(0, 3, 1, 3) # => [:foo, nil, "bar", nil]
*
* Returns a new empty \Array if no arguments given.
*
* For each negative +index+, counts backward from the end of the array:
+ *
* a = [:foo, 'bar', 2]
* a.values_at(-1, -3) # => [2, :foo]
*
* Assigns +nil+ for an +index+ that is too small:
+ *
* a = [:foo, 'bar', 2]
* a.values_at(0, -5, 1, -6, 2) # => [:foo, nil, "bar", nil, 2]
*
* The given +indexes+ may have a mixture of signs:
+ *
* a = [:foo, 'bar', 2]
* a.values_at(0, -2, 1, -1) # => [:foo, "bar", "bar", 2]
+ *
*/
static VALUE
@@ -3694,7 +3973,7 @@ rb_ary_values_at(int argc, VALUE *argv, VALUE ary)
long i, olen = RARRAY_LEN(ary);
VALUE result = rb_ary_new_capa(argc);
for (i = 0; i < argc; ++i) {
- append_values_at_single(result, ary, olen, argv[i]);
+ append_values_at_single(result, ary, olen, argv[i]);
}
RB_GC_GUARD(ary);
return result;
@@ -3709,11 +3988,13 @@ rb_ary_values_at(int argc, VALUE *argv, VALUE ary)
* Calls the block, if given, with each element of +self+;
* returns a new \Array containing those elements of +self+
* for which the block returns a truthy value:
+ *
* a = [:foo, 'bar', 2, :bam]
* a1 = a.select {|element| element.to_s.start_with?('b') }
* a1 # => ["bar", :bam]
*
* Returns a new \Enumerator if no block given:
+ *
* a = [:foo, 'bar', 2, :bam]
* a.select # => #<Enumerator: [:foo, "bar", 2, :bam]:select>
*
@@ -3729,9 +4010,9 @@ rb_ary_select(VALUE ary)
RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
result = rb_ary_new2(RARRAY_LEN(ary));
for (i = 0; i < RARRAY_LEN(ary); i++) {
- if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
- rb_ary_push(result, rb_ary_elt(ary, i));
- }
+ if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
+ rb_ary_push(result, rb_ary_elt(ary, i));
+ }
}
return result;
}
@@ -3749,12 +4030,12 @@ select_bang_i(VALUE a)
long i1, i2;
for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); arg->len[0] = ++i1) {
- VALUE v = RARRAY_AREF(ary, i1);
- if (!RTEST(rb_yield(v))) continue;
- if (i1 != i2) {
- rb_ary_store(ary, i2, v);
- }
- arg->len[1] = ++i2;
+ VALUE v = RARRAY_AREF(ary, i1);
+ if (!RTEST(rb_yield(v))) continue;
+ if (i1 != i2) {
+ rb_ary_store(ary, i2, v);
+ }
+ arg->len[1] = ++i2;
}
return (i1 == i2) ? Qnil : ary;
}
@@ -3768,15 +4049,15 @@ select_bang_ensure(VALUE a)
long i1 = arg->len[0], i2 = arg->len[1];
if (i2 < len && i2 < i1) {
- long tail = 0;
+ long tail = 0;
rb_ary_modify(ary);
- if (i1 < len) {
- tail = len - i1;
+ if (i1 < len) {
+ tail = len - i1;
RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
- MEMMOVE(ptr + i2, ptr + i1, VALUE, tail);
- });
- }
- ARY_SET_LEN(ary, i2 + tail);
+ MEMMOVE(ptr + i2, ptr + i1, VALUE, tail);
+ });
+ }
+ ARY_SET_LEN(ary, i2 + tail);
}
return ary;
}
@@ -3790,12 +4071,14 @@ select_bang_ensure(VALUE a)
* removes from +self+ those elements for which the block returns +false+ or +nil+.
*
* Returns +self+ if any elements were removed:
+ *
* a = [:foo, 'bar', 2, :bam]
* a.select! {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
*
* Returns +nil+ if no elements were removed.
*
* Returns a new \Enumerator if no block given:
+ *
* a = [:foo, 'bar', 2, :bam]
* a.select! # => #<Enumerator: [:foo, "bar", 2, :bam]:select!>
*
@@ -3822,12 +4105,15 @@ rb_ary_select_bang(VALUE ary)
*
* Retains those elements for which the block returns a truthy value;
* deletes all other elements; returns +self+:
+ *
* a = [:foo, 'bar', 2, :bam]
* a.keep_if {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
*
* Returns a new \Enumerator if no block given:
+ *
* a = [:foo, 'bar', 2, :bam]
* a.keep_if # => #<Enumerator: [:foo, "bar", 2, :bam]:keep_if>
+ *
*/
static VALUE
@@ -3843,11 +4129,11 @@ ary_resize_smaller(VALUE ary, long len)
{
rb_ary_modify(ary);
if (RARRAY_LEN(ary) > len) {
- ARY_SET_LEN(ary, len);
- if (len * 2 < ARY_CAPA(ary) &&
- ARY_CAPA(ary) > ARY_DEFAULT_SIZE) {
- ary_resize_capa(ary, len * 2);
- }
+ ARY_SET_LEN(ary, len);
+ if (len * 2 < ARY_CAPA(ary) &&
+ ARY_CAPA(ary) > ARY_DEFAULT_SIZE) {
+ ary_resize_capa(ary, len * 2);
+ }
}
}
@@ -3856,11 +4142,12 @@ ary_resize_smaller(VALUE ary, long len)
* array.delete(obj) -> deleted_object
* array.delete(obj) {|nosuch| ... } -> deleted_object or block_return
*
- * Removes zero or more elements from +self+; returns +self+.
+ * Removes zero or more elements from +self+.
*
* When no block is given,
* removes from +self+ each element +ele+ such that <tt>ele == obj</tt>;
* returns the last deleted element:
+ *
* s1 = 'bar'; s2 = 'bar'
* a = [:foo, s1, 2, s2]
* a.delete('bar') # => "bar"
@@ -3873,14 +4160,17 @@ ary_resize_smaller(VALUE ary, long len)
*
* If any such elements are found, ignores the block
* and returns the last deleted element:
+ *
* s1 = 'bar'; s2 = 'bar'
* a = [:foo, s1, 2, s2]
* deleted_obj = a.delete('bar') {|obj| fail 'Cannot happen' }
* a # => [:foo, 2]
*
* If no such elements are found, returns the block's return value:
+ *
* a = [:foo, 'bar', 2]
* a.delete(:nosuch) {|obj| "#{obj} not found" } # => "nosuch not found"
+ *
*/
VALUE
@@ -3890,22 +4180,22 @@ rb_ary_delete(VALUE ary, VALUE item)
long i1, i2;
for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
- VALUE e = RARRAY_AREF(ary, i1);
+ VALUE e = RARRAY_AREF(ary, i1);
- if (rb_equal(e, item)) {
- v = e;
- continue;
- }
- if (i1 != i2) {
- rb_ary_store(ary, i2, e);
- }
- i2++;
+ if (rb_equal(e, item)) {
+ v = e;
+ continue;
+ }
+ if (i1 != i2) {
+ rb_ary_store(ary, i2, e);
+ }
+ i2++;
}
if (RARRAY_LEN(ary) == i2) {
- if (rb_block_given_p()) {
- return rb_yield(item);
- }
- return Qnil;
+ if (rb_block_given_p()) {
+ return rb_yield(item);
+ }
+ return Qnil;
}
ary_resize_smaller(ary, i2);
@@ -3920,18 +4210,18 @@ rb_ary_delete_same(VALUE ary, VALUE item)
long i1, i2;
for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
- VALUE e = RARRAY_AREF(ary, i1);
+ VALUE e = RARRAY_AREF(ary, i1);
- if (e == item) {
- continue;
- }
- if (i1 != i2) {
- rb_ary_store(ary, i2, e);
- }
- i2++;
+ if (e == item) {
+ continue;
+ }
+ if (i1 != i2) {
+ rb_ary_store(ary, i2, e);
+ }
+ i2++;
}
if (RARRAY_LEN(ary) == i2) {
- return;
+ return;
}
ary_resize_smaller(ary, i2);
@@ -3945,8 +4235,8 @@ rb_ary_delete_at(VALUE ary, long pos)
if (pos >= len) return Qnil;
if (pos < 0) {
- pos += len;
- if (pos < 0) return Qnil;
+ pos += len;
+ if (pos < 0) return Qnil;
}
rb_ary_modify(ary);
@@ -3966,6 +4256,7 @@ rb_ary_delete_at(VALUE ary, long pos)
* Deletes an element from +self+, per the given \Integer +index+.
*
* When +index+ is non-negative, deletes the element at offset +index+:
+ *
* a = [:foo, 'bar', 2]
* a.delete_at(1) # => "bar"
* a # => [:foo, 2]
@@ -3973,6 +4264,7 @@ rb_ary_delete_at(VALUE ary, long pos)
* If index is too large, returns +nil+.
*
* When +index+ is negative, counts backward from the end of the array:
+ *
* a = [:foo, 'bar', 2]
* a.delete_at(-2) # => "bar"
* a # => [:foo, 2]
@@ -4026,11 +4318,13 @@ ary_slice_bang_by_rb_ary_splice(VALUE ary, long pos, long len)
*
* When the only argument is an \Integer +n+,
* removes and returns the _nth_ element in +self+:
+ *
* a = [:foo, 'bar', 2]
* a.slice!(1) # => "bar"
* a # => [:foo, 2]
*
* If +n+ is negative, counts backwards from the end of +self+:
+ *
* a = [:foo, 'bar', 2]
* a.slice!(-1) # => 2
* a # => [:foo, "bar"]
@@ -4039,13 +4333,15 @@ ary_slice_bang_by_rb_ary_splice(VALUE ary, long pos, long len)
*
* When the only arguments are Integers +start+ and +length+,
* removes +length+ elements from +self+ beginning at offset +start+;
- * returns the deleted objects in a new Array:
+ * returns the deleted objects in a new \Array:
+ *
* a = [:foo, 'bar', 2]
* a.slice!(0, 2) # => [:foo, "bar"]
* a # => [2]
*
* If <tt>start + length</tt> exceeds the array size,
* removes and returns all elements from offset +start+ to the end:
+ *
* a = [:foo, 'bar', 2]
* a.slice!(1, 50) # => ["bar", 2]
* a # => [:foo]
@@ -4057,8 +4353,9 @@ ary_slice_bang_by_rb_ary_splice(VALUE ary, long pos, long len)
*
* When the only argument is a \Range object +range+,
* treats <tt>range.min</tt> as +start+ above and <tt>range.size</tt> as +length+ above:
+ *
* a = [:foo, 'bar', 2]
- * a.slice!(1..2) # => ["bar", 2]
+ * a.slice!(1..2) # => ["bar", 2]
* a # => [:foo]
*
* If <tt>range.start == a.size</tt>, returns a new empty \Array.
@@ -4066,15 +4363,18 @@ ary_slice_bang_by_rb_ary_splice(VALUE ary, long pos, long len)
* If <tt>range.start</tt> is larger than the array size, returns +nil+.
*
* If <tt>range.end</tt> is negative, counts backwards from the end of the array:
+ *
* a = [:foo, 'bar', 2]
* a.slice!(0..-2) # => [:foo, "bar"]
* a # => [2]
*
* If <tt>range.start</tt> is negative,
* calculates the start index backwards from the end of the array:
+ *
* a = [:foo, 'bar', 2]
* a.slice!(-2..2) # => ["bar", 2]
* a # => [:foo]
+ *
*/
static VALUE
@@ -4088,23 +4388,23 @@ rb_ary_slice_bang(int argc, VALUE *argv, VALUE ary)
arg1 = argv[0];
if (argc == 2) {
- pos = NUM2LONG(argv[0]);
- len = NUM2LONG(argv[1]);
+ pos = NUM2LONG(argv[0]);
+ len = NUM2LONG(argv[1]);
return ary_slice_bang_by_rb_ary_splice(ary, pos, len);
}
if (!FIXNUM_P(arg1)) {
- switch (rb_range_beg_len(arg1, &pos, &len, RARRAY_LEN(ary), 0)) {
- case Qtrue:
- /* valid range */
+ switch (rb_range_beg_len(arg1, &pos, &len, RARRAY_LEN(ary), 0)) {
+ case Qtrue:
+ /* valid range */
return ary_slice_bang_by_rb_ary_splice(ary, pos, len);
- case Qnil:
- /* invalid range */
- return Qnil;
- default:
- /* not a range */
- break;
- }
+ case Qnil:
+ /* invalid range */
+ return Qnil;
+ default:
+ /* not a range */
+ break;
+ }
}
return rb_ary_delete_at(ary, NUM2LONG(arg1));
@@ -4116,11 +4416,11 @@ ary_reject(VALUE orig, VALUE result)
long i;
for (i = 0; i < RARRAY_LEN(orig); i++) {
- VALUE v = RARRAY_AREF(orig, i);
+ VALUE v = RARRAY_AREF(orig, i);
if (!RTEST(rb_yield(v))) {
- rb_ary_push(result, v);
- }
+ rb_ary_push(result, v);
+ }
}
return result;
}
@@ -4133,12 +4433,12 @@ reject_bang_i(VALUE a)
long i1, i2;
for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); arg->len[0] = ++i1) {
- VALUE v = RARRAY_AREF(ary, i1);
- if (RTEST(rb_yield(v))) continue;
- if (i1 != i2) {
- rb_ary_store(ary, i2, v);
- }
- arg->len[1] = ++i2;
+ VALUE v = RARRAY_AREF(ary, i1);
+ if (RTEST(rb_yield(v))) continue;
+ if (i1 != i2) {
+ rb_ary_store(ary, i2, v);
+ }
+ arg->len[1] = ++i2;
}
return (i1 == i2) ? Qnil : ary;
}
@@ -4161,14 +4461,17 @@ ary_reject_bang(VALUE ary)
* Removes each element for which the block returns a truthy value.
*
* Returns +self+ if any elements removed:
+ *
* a = [:foo, 'bar', 2, 'bat']
* a.reject! {|element| element.to_s.start_with?('b') } # => [:foo, 2]
*
* Returns +nil+ if no elements removed.
*
* Returns a new \Enumerator if no block given:
+ *
* a = [:foo, 'bar', 2]
* a.reject! # => #<Enumerator: [:foo, "bar", 2]:reject!>
+ *
*/
static VALUE
@@ -4186,13 +4489,16 @@ rb_ary_reject_bang(VALUE ary)
*
* Returns a new \Array whose elements are all those from +self+
* for which the block returns +false+ or +nil+:
+ *
* a = [:foo, 'bar', 2, 'bat']
* a1 = a.reject {|element| element.to_s.start_with?('b') }
* a1 # => [:foo, 2]
*
* Returns a new \Enumerator if no block given:
+ *
* a = [:foo, 'bar', 2]
* a.reject # => #<Enumerator: [:foo, "bar", 2]:reject>
+ *
*/
static VALUE
@@ -4213,13 +4519,16 @@ rb_ary_reject(VALUE ary)
*
* Removes each element in +self+ for which the block returns a truthy value;
* returns +self+:
+ *
* a = [:foo, 'bar', 2, 'bat']
* a.delete_if {|element| element.to_s.start_with?('b') } # => [:foo, 2]
*
* Returns a new \Enumerator if no block given:
+ *
* a = [:foo, 'bar', 2]
* a.delete_if # => #<Enumerator: [:foo, "bar", 2]:delete_if>
- */
+ *
+3 */
static VALUE
rb_ary_delete_if(VALUE ary)
@@ -4250,9 +4559,9 @@ take_items(VALUE obj, long n)
if (!NIL_P(result)) return rb_ary_subseq(result, 0, n);
result = rb_ary_new2(n);
args[0] = result; args[1] = (VALUE)n;
- if (rb_check_block_call(obj, idEach, 0, 0, take_i, (VALUE)args) == Qundef)
- rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (must respond to :each)",
- rb_obj_class(obj));
+ if (UNDEF_P(rb_check_block_call(obj, idEach, 0, 0, take_i, (VALUE)args)))
+ rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (must respond to :each)",
+ rb_obj_class(obj));
return result;
}
@@ -4267,10 +4576,12 @@ take_items(VALUE obj, long n)
*
* Each nested array <tt>new_array[n]</tt> is of size <tt>other_arrays.size+1</tt>,
* and contains:
+ *
* - The _nth_ element of +self+.
* - The _nth_ element of each of the +other_arrays+.
*
* If all +other_arrays+ and +self+ are the same size:
+ *
* a = [:a0, :a1, :a2, :a3]
* b = [:b0, :b1, :b2, :b3]
* c = [:c0, :c1, :c2, :c3]
@@ -4279,6 +4590,7 @@ take_items(VALUE obj, long n)
*
* If any array in +other_arrays+ is smaller than +self+,
* fills to <tt>self.size</tt> with +nil+:
+ *
* a = [:a0, :a1, :a2, :a3]
* b = [:b0, :b1, :b2]
* c = [:c0, :c1]
@@ -4287,23 +4599,27 @@ take_items(VALUE obj, long n)
*
* If any array in +other_arrays+ is larger than +self+,
* its trailing elements are ignored:
+ *
* a = [:a0, :a1, :a2, :a3]
* b = [:b0, :b1, :b2, :b3, :b4]
* c = [:c0, :c1, :c2, :c3, :c4, :c5]
* d = a.zip(b, c)
* d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]]
*
- * When a block is given, calls the block with each of the sub-arrays (formed as above); returns nil
+ * When a block is given, calls the block with each of the sub-arrays (formed as above); returns +nil+:
+ *
* a = [:a0, :a1, :a2, :a3]
* b = [:b0, :b1, :b2, :b3]
* c = [:c0, :c1, :c2, :c3]
* a.zip(b, c) {|sub_array| p sub_array} # => nil
*
* Output:
+ *
* [:a0, :b0, :c0]
* [:a1, :b1, :c1]
* [:a2, :b2, :c2]
* [:a3, :b3, :c3]
+ *
*/
static VALUE
@@ -4314,51 +4630,51 @@ rb_ary_zip(int argc, VALUE *argv, VALUE ary)
VALUE result = Qnil;
for (i=0; i<argc; i++) {
- argv[i] = take_items(argv[i], len);
+ argv[i] = take_items(argv[i], len);
}
if (rb_block_given_p()) {
- int arity = rb_block_arity();
-
- if (arity > 1) {
- VALUE work, *tmp;
-
- tmp = ALLOCV_N(VALUE, work, argc+1);
-
- for (i=0; i<RARRAY_LEN(ary); i++) {
- tmp[0] = RARRAY_AREF(ary, i);
- for (j=0; j<argc; j++) {
- tmp[j+1] = rb_ary_elt(argv[j], i);
- }
- rb_yield_values2(argc+1, tmp);
- }
-
- if (work) ALLOCV_END(work);
- }
- else {
- for (i=0; i<RARRAY_LEN(ary); i++) {
- VALUE tmp = rb_ary_new2(argc+1);
-
- rb_ary_push(tmp, RARRAY_AREF(ary, i));
- for (j=0; j<argc; j++) {
- rb_ary_push(tmp, rb_ary_elt(argv[j], i));
- }
- rb_yield(tmp);
- }
- }
+ int arity = rb_block_arity();
+
+ if (arity > 1) {
+ VALUE work, *tmp;
+
+ tmp = ALLOCV_N(VALUE, work, argc+1);
+
+ for (i=0; i<RARRAY_LEN(ary); i++) {
+ tmp[0] = RARRAY_AREF(ary, i);
+ for (j=0; j<argc; j++) {
+ tmp[j+1] = rb_ary_elt(argv[j], i);
+ }
+ rb_yield_values2(argc+1, tmp);
+ }
+
+ if (work) ALLOCV_END(work);
+ }
+ else {
+ for (i=0; i<RARRAY_LEN(ary); i++) {
+ VALUE tmp = rb_ary_new2(argc+1);
+
+ rb_ary_push(tmp, RARRAY_AREF(ary, i));
+ for (j=0; j<argc; j++) {
+ rb_ary_push(tmp, rb_ary_elt(argv[j], i));
+ }
+ rb_yield(tmp);
+ }
+ }
}
else {
- result = rb_ary_new_capa(len);
+ result = rb_ary_new_capa(len);
- for (i=0; i<len; i++) {
- VALUE tmp = rb_ary_new_capa(argc+1);
+ for (i=0; i<len; i++) {
+ VALUE tmp = rb_ary_new_capa(argc+1);
- rb_ary_push(tmp, RARRAY_AREF(ary, i));
- for (j=0; j<argc; j++) {
- rb_ary_push(tmp, rb_ary_elt(argv[j], i));
- }
- rb_ary_push(result, tmp);
- }
+ rb_ary_push(tmp, RARRAY_AREF(ary, i));
+ for (j=0; j<argc; j++) {
+ rb_ary_push(tmp, rb_ary_elt(argv[j], i));
+ }
+ rb_ary_push(result, tmp);
+ }
}
return result;
@@ -4370,8 +4686,10 @@ rb_ary_zip(int argc, VALUE *argv, VALUE ary)
*
* Transposes the rows and columns in an \Array of Arrays;
* the nested Arrays must all be the same size:
+ *
* a = [[:a0, :a1], [:b0, :b1], [:c0, :c1]]
* a.transpose # => [[:a0, :b0, :c0], [:a1, :b1, :c1]]
+ *
*/
static VALUE
@@ -4383,21 +4701,21 @@ rb_ary_transpose(VALUE ary)
alen = RARRAY_LEN(ary);
if (alen == 0) return rb_ary_dup(ary);
for (i=0; i<alen; i++) {
- tmp = to_ary(rb_ary_elt(ary, i));
- if (elen < 0) { /* first element */
- elen = RARRAY_LEN(tmp);
- result = rb_ary_new2(elen);
- for (j=0; j<elen; j++) {
- rb_ary_store(result, j, rb_ary_new2(alen));
- }
- }
- else if (elen != RARRAY_LEN(tmp)) {
- rb_raise(rb_eIndexError, "element size differs (%ld should be %ld)",
- RARRAY_LEN(tmp), elen);
- }
- for (j=0; j<elen; j++) {
- rb_ary_store(rb_ary_elt(result, j), i, rb_ary_elt(tmp, j));
- }
+ tmp = to_ary(rb_ary_elt(ary, i));
+ if (elen < 0) { /* first element */
+ elen = RARRAY_LEN(tmp);
+ result = rb_ary_new2(elen);
+ for (j=0; j<elen; j++) {
+ rb_ary_store(result, j, rb_ary_new2(alen));
+ }
+ }
+ else if (elen != RARRAY_LEN(tmp)) {
+ rb_raise(rb_eIndexError, "element size differs (%ld should be %ld)",
+ RARRAY_LEN(tmp), elen);
+ }
+ for (j=0; j<elen; j++) {
+ rb_ary_store(rb_ary_elt(result, j), i, rb_ary_elt(tmp, j));
+ }
}
return result;
}
@@ -4407,8 +4725,10 @@ rb_ary_transpose(VALUE ary)
* array.replace(other_array) -> self
*
* Replaces the content of +self+ with the content of +other_array+; returns +self+:
+ *
* a = [:foo, 'bar', 2]
* a.replace(['foo', :bar, 3]) # => ["foo", :bar, 3]
+ *
*/
VALUE
@@ -4418,31 +4738,35 @@ rb_ary_replace(VALUE copy, VALUE orig)
orig = to_ary(orig);
if (copy == orig) return copy;
- if (RARRAY_LEN(orig) <= RARRAY_EMBED_LEN_MAX) {
- VALUE shared_root = 0;
+ rb_ary_reset(copy);
- if (ARY_OWNS_HEAP_P(copy)) {
- ary_heap_free(copy);
- }
- else if (ARY_SHARED_P(copy)) {
- shared_root = ARY_SHARED_ROOT(copy);
- FL_UNSET_SHARED(copy);
- }
- FL_SET_EMBED(copy);
+ /* orig has enough space to embed the contents of orig. */
+ if (RARRAY_LEN(orig) <= ary_embed_capa(copy)) {
+ assert(ARY_EMBED_P(copy));
ary_memcpy(copy, 0, RARRAY_LEN(orig), RARRAY_CONST_PTR_TRANSIENT(orig));
- if (shared_root) {
- rb_ary_decrement_share(shared_root);
- }
- ARY_SET_LEN(copy, RARRAY_LEN(orig));
+ ARY_SET_EMBED_LEN(copy, RARRAY_LEN(orig));
}
+#if USE_RVARGC
+ /* orig is embedded but copy does not have enough space to embed the
+ * contents of orig. */
+ else if (ARY_EMBED_P(orig)) {
+ long len = ARY_EMBED_LEN(orig);
+ VALUE *ptr = ary_heap_alloc(copy, len);
+
+ FL_UNSET_EMBED(copy);
+ ARY_SET_PTR(copy, ptr);
+ ARY_SET_LEN(copy, len);
+ ARY_SET_CAPA(copy, len);
+
+ // No allocation and exception expected that could leave `copy` in a
+ // bad state from the edits above.
+ ary_memcpy(copy, 0, len, RARRAY_CONST_PTR_TRANSIENT(orig));
+ }
+#endif
+ /* Otherwise, orig is on heap and copy does not have enough space to embed
+ * the contents of orig. */
else {
VALUE shared_root = ary_make_shared(orig);
- if (ARY_OWNS_HEAP_P(copy)) {
- ary_heap_free(copy);
- }
- else {
- rb_ary_unshare_safe(copy);
- }
FL_UNSET_EMBED(copy);
ARY_SET_PTR(copy, ARY_HEAP_PTR(orig));
ARY_SET_LEN(copy, ARY_HEAP_LEN(orig));
@@ -4457,8 +4781,10 @@ rb_ary_replace(VALUE copy, VALUE orig)
* array.clear -> self
*
* Removes all elements from +self+:
+ *
* a = [:foo, 'bar', 2]
* a.clear # => []
+ *
*/
VALUE
@@ -4466,11 +4792,11 @@ rb_ary_clear(VALUE ary)
{
rb_ary_modify_check(ary);
if (ARY_SHARED_P(ary)) {
- if (!ARY_EMBED_P(ary)) {
- rb_ary_unshare(ary);
- FL_SET_EMBED(ary);
+ if (!ARY_EMBED_P(ary)) {
+ rb_ary_unshare(ary);
+ FL_SET_EMBED(ary);
ARY_SET_EMBED_LEN(ary, 0);
- }
+ }
}
else {
ARY_SET_LEN(ary, 0);
@@ -4496,6 +4822,7 @@ rb_ary_clear(VALUE ary)
* Replaces specified elements in +self+ with specified objects; returns +self+.
*
* With argument +obj+ and no block given, replaces all elements with that one object:
+ *
* a = ['a', 'b', 'c', 'd']
* a # => ["a", "b", "c", "d"]
* a.fill(:X) # => [:X, :X, :X, :X]
@@ -4505,20 +4832,24 @@ rb_ary_clear(VALUE ary)
*
* If +start+ is in range (<tt>0 <= start < array.size</tt>),
* replaces all elements from offset +start+ through the end:
+ *
* a = ['a', 'b', 'c', 'd']
* a.fill(:X, 2) # => ["a", "b", :X, :X]
*
* If +start+ is too large (<tt>start >= array.size</tt>), does nothing:
+ *
* a = ['a', 'b', 'c', 'd']
* a.fill(:X, 4) # => ["a", "b", "c", "d"]
* a = ['a', 'b', 'c', 'd']
* a.fill(:X, 5) # => ["a", "b", "c", "d"]
*
* If +start+ is negative, counts from the end (starting index is <tt>start + array.size</tt>):
+ *
* a = ['a', 'b', 'c', 'd']
* a.fill(:X, -2) # => ["a", "b", :X, :X]
*
* If +start+ is too small (less than and far from zero), replaces all elements:
+ *
* a = ['a', 'b', 'c', 'd']
* a.fill(:X, -6) # => [:X, :X, :X, :X]
* a = ['a', 'b', 'c', 'd']
@@ -4528,20 +4859,24 @@ rb_ary_clear(VALUE ary)
* replaces elements based on the given +start+ and +length+.
*
* If +start+ is in range, replaces +length+ elements beginning at offset +start+:
+ *
* a = ['a', 'b', 'c', 'd']
* a.fill(:X, 1, 1) # => ["a", :X, "c", "d"]
*
* If +start+ is negative, counts from the end:
+ *
* a = ['a', 'b', 'c', 'd']
* a.fill(:X, -2, 1) # => ["a", "b", :X, "d"]
*
* If +start+ is large (<tt>start >= array.size</tt>), extends +self+ with +nil+:
+ *
* a = ['a', 'b', 'c', 'd']
* a.fill(:X, 5, 0) # => ["a", "b", "c", "d", nil]
* a = ['a', 'b', 'c', 'd']
* a.fill(:X, 5, 2) # => ["a", "b", "c", "d", nil, :X, :X]
*
* If +length+ is zero or negative, replaces no elements:
+ *
* a = ['a', 'b', 'c', 'd']
* a.fill(:X, 1, 0) # => ["a", "b", "c", "d"]
* a.fill(:X, 1, -1) # => ["a", "b", "c", "d"]
@@ -4551,14 +4886,17 @@ rb_ary_clear(VALUE ary)
*
* If the range is positive and ascending (<tt>0 < range.begin <= range.end</tt>),
* replaces elements from <tt>range.begin</tt> to <tt>range.end</tt>:
+ *
* a = ['a', 'b', 'c', 'd']
* a.fill(:X, (1..1)) # => ["a", :X, "c", "d"]
*
* If <tt>range.first</tt> is negative, replaces no elements:
+ *
* a = ['a', 'b', 'c', 'd']
* a.fill(:X, (-1..1)) # => ["a", "b", "c", "d"]
*
* If <tt>range.last</tt> is negative, counts from the end:
+ *
* a = ['a', 'b', 'c', 'd']
* a.fill(:X, (0..-2)) # => [:X, :X, :X, "d"]
* a = ['a', 'b', 'c', 'd']
@@ -4566,6 +4904,7 @@ rb_ary_clear(VALUE ary)
*
* If <tt>range.last</tt> and <tt>range.last</tt> are both negative,
* both count from the end of the array:
+ *
* a = ['a', 'b', 'c', 'd']
* a.fill(:X, (-1..-1)) # => ["a", "b", "c", :X]
* a = ['a', 'b', 'c', 'd']
@@ -4573,29 +4912,34 @@ rb_ary_clear(VALUE ary)
*
* With no arguments and a block given, calls the block with each index;
* replaces the corresponding element with the block's return value:
+ *
* a = ['a', 'b', 'c', 'd']
* a.fill { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "new_3"]
*
* With argument +start+ and a block given, calls the block with each index
* from offset +start+ to the end; replaces the corresponding element
- * with the block's return value:
+ * with the block's return value.
*
* If start is in range (<tt>0 <= start < array.size</tt>),
* replaces from offset +start+ to the end:
+ *
* a = ['a', 'b', 'c', 'd']
* a.fill(1) { |index| "new_#{index}" } # => ["a", "new_1", "new_2", "new_3"]
*
* If +start+ is too large(<tt>start >= array.size</tt>), does nothing:
+ *
* a = ['a', 'b', 'c', 'd']
* a.fill(4) { |index| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
* a = ['a', 'b', 'c', 'd']
* a.fill(4) { |index| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
*
* If +start+ is negative, counts from the end:
+ *
* a = ['a', 'b', 'c', 'd']
* a.fill(-2) { |index| "new_#{index}" } # => ["a", "b", "new_2", "new_3"]
*
* If start is too small (<tt>start <= -array.size</tt>, replaces all elements:
+ *
* a = ['a', 'b', 'c', 'd']
* a.fill(-6) { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "new_3"]
* a = ['a', 'b', 'c', 'd']
@@ -4606,20 +4950,24 @@ rb_ary_clear(VALUE ary)
* replaces the corresponding element with the block's return value.
*
* If +start+ is in range, replaces +length+ elements beginning at offset +start+:
+ *
* a = ['a', 'b', 'c', 'd']
* a.fill(1, 1) { |index| "new_#{index}" } # => ["a", "new_1", "c", "d"]
*
* If start is negative, counts from the end:
+ *
* a = ['a', 'b', 'c', 'd']
* a.fill(-2, 1) { |index| "new_#{index}" } # => ["a", "b", "new_2", "d"]
*
* If +start+ is large (<tt>start >= array.size</tt>), extends +self+ with +nil+:
+ *
* a = ['a', 'b', 'c', 'd']
* a.fill(5, 0) { |index| "new_#{index}" } # => ["a", "b", "c", "d", nil]
* a = ['a', 'b', 'c', 'd']
* a.fill(5, 2) { |index| "new_#{index}" } # => ["a", "b", "c", "d", nil, "new_5", "new_6"]
*
* If +length+ is zero or less, replaces no elements:
+ *
* a = ['a', 'b', 'c', 'd']
* a.fill(1, 0) { |index| "new_#{index}" } # => ["a", "b", "c", "d"]
* a.fill(1, -1) { |index| "new_#{index}" } # => ["a", "b", "c", "d"]
@@ -4630,14 +4978,17 @@ rb_ary_clear(VALUE ary)
*
* If the range is positive and ascending (<tt>range 0 < range.begin <= range.end</tt>,
* replaces elements from <tt>range.begin</tt> to <tt>range.end</tt>:
+ *
* a = ['a', 'b', 'c', 'd']
* a.fill(1..1) { |index| "new_#{index}" } # => ["a", "new_1", "c", "d"]
*
* If +range.first+ is negative, does nothing:
+ *
* a = ['a', 'b', 'c', 'd']
* a.fill(-1..1) { |index| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
*
* If <tt>range.last</tt> is negative, counts from the end:
+ *
* a = ['a', 'b', 'c', 'd']
* a.fill(0..-2) { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "d"]
* a = ['a', 'b', 'c', 'd']
@@ -4645,10 +4996,12 @@ rb_ary_clear(VALUE ary)
*
* If <tt>range.first</tt> and <tt>range.last</tt> are both negative,
* both count from the end:
+ *
* a = ['a', 'b', 'c', 'd']
* a.fill(-1..-1) { |index| "new_#{index}" } # => ["a", "b", "c", "new_3"]
* a = ['a', 'b', 'c', 'd']
* a.fill(-2..-2) { |index| "new_#{index}" } # => ["a", "b", "new_2", "d"]
+ *
*/
static VALUE
@@ -4658,59 +5011,59 @@ rb_ary_fill(int argc, VALUE *argv, VALUE ary)
long beg = 0, end = 0, len = 0;
if (rb_block_given_p()) {
- rb_scan_args(argc, argv, "02", &arg1, &arg2);
- argc += 1; /* hackish */
+ rb_scan_args(argc, argv, "02", &arg1, &arg2);
+ argc += 1; /* hackish */
}
else {
- rb_scan_args(argc, argv, "12", &item, &arg1, &arg2);
+ rb_scan_args(argc, argv, "12", &item, &arg1, &arg2);
}
switch (argc) {
case 1:
- beg = 0;
- len = RARRAY_LEN(ary);
- break;
+ beg = 0;
+ len = RARRAY_LEN(ary);
+ break;
case 2:
- if (rb_range_beg_len(arg1, &beg, &len, RARRAY_LEN(ary), 1)) {
- break;
- }
- /* fall through */
+ if (rb_range_beg_len(arg1, &beg, &len, RARRAY_LEN(ary), 1)) {
+ break;
+ }
+ /* fall through */
case 3:
- beg = NIL_P(arg1) ? 0 : NUM2LONG(arg1);
- if (beg < 0) {
- beg = RARRAY_LEN(ary) + beg;
- if (beg < 0) beg = 0;
- }
- len = NIL_P(arg2) ? RARRAY_LEN(ary) - beg : NUM2LONG(arg2);
- break;
+ beg = NIL_P(arg1) ? 0 : NUM2LONG(arg1);
+ if (beg < 0) {
+ beg = RARRAY_LEN(ary) + beg;
+ if (beg < 0) beg = 0;
+ }
+ len = NIL_P(arg2) ? RARRAY_LEN(ary) - beg : NUM2LONG(arg2);
+ break;
}
rb_ary_modify(ary);
if (len < 0) {
return ary;
}
if (beg >= ARY_MAX_SIZE || len > ARY_MAX_SIZE - beg) {
- rb_raise(rb_eArgError, "argument too big");
+ rb_raise(rb_eArgError, "argument too big");
}
end = beg + len;
if (RARRAY_LEN(ary) < end) {
- if (end >= ARY_CAPA(ary)) {
- ary_resize_capa(ary, end);
- }
- ary_mem_clear(ary, RARRAY_LEN(ary), end - RARRAY_LEN(ary));
- ARY_SET_LEN(ary, end);
+ if (end >= ARY_CAPA(ary)) {
+ ary_resize_capa(ary, end);
+ }
+ ary_mem_clear(ary, RARRAY_LEN(ary), end - RARRAY_LEN(ary));
+ ARY_SET_LEN(ary, end);
}
- if (item == Qundef) {
- VALUE v;
- long i;
+ if (UNDEF_P(item)) {
+ VALUE v;
+ long i;
- for (i=beg; i<end; i++) {
- v = rb_yield(LONG2NUM(i));
- if (i>=RARRAY_LEN(ary)) break;
- ARY_SET(ary, i, v);
- }
+ for (i=beg; i<end; i++) {
+ v = rb_yield(LONG2NUM(i));
+ if (i>=RARRAY_LEN(ary)) break;
+ ARY_SET(ary, i, v);
+ }
}
else {
- ary_memfill(ary, beg, len, item);
+ ary_memfill(ary, beg, len, item);
}
return ary;
}
@@ -4721,6 +5074,7 @@ rb_ary_fill(int argc, VALUE *argv, VALUE ary)
*
* Returns a new \Array containing all elements of +array+
* followed by all elements of +other_array+:
+ *
* a = [0, 1] + [2, 3]
* a # => [0, 1, 2, 3]
*
@@ -4761,6 +5115,7 @@ ary_append(VALUE x, VALUE y)
* array.concat(*other_arrays) -> self
*
* Adds to +array+ all elements from each \Array in +other_arrays+; returns +self+:
+ *
* a = [0, 1]
* a.concat([2, 3], [4, 5]) # => [0, 1, 2, 3, 4, 5]
*/
@@ -4771,15 +5126,15 @@ rb_ary_concat_multi(int argc, VALUE *argv, VALUE ary)
rb_ary_modify_check(ary);
if (argc == 1) {
- rb_ary_concat(ary, argv[0]);
+ rb_ary_concat(ary, argv[0]);
}
else if (argc > 1) {
- int i;
- VALUE args = rb_ary_tmp_new(argc);
- for (i = 0; i < argc; i++) {
- rb_ary_concat(args, argv[i]);
- }
- ary_append(ary, args);
+ int i;
+ VALUE args = rb_ary_hidden_new(argc);
+ for (i = 0; i < argc; i++) {
+ rb_ary_concat(args, argv[i]);
+ }
+ ary_append(ary, args);
}
ary_verify(ary);
@@ -4799,12 +5154,15 @@ rb_ary_concat(VALUE x, VALUE y)
*
* When non-negative argument \Integer +n+ is given,
* returns a new \Array built by concatenating the +n+ copies of +self+:
+ *
* a = ['x', 'y']
* a * 3 # => ["x", "y", "x", "y", "x", "y"]
*
* When \String argument +string_separator+ is given,
* equivalent to <tt>array.join(string_separator)</tt>:
+ *
* [0, [0, 1], {foo: 0}] * ', ' # => "0, 0, 1, {:foo=>0}"
+ *
*/
static VALUE
@@ -4816,19 +5174,19 @@ rb_ary_times(VALUE ary, VALUE times)
tmp = rb_check_string_type(times);
if (!NIL_P(tmp)) {
- return rb_ary_join(ary, tmp);
+ return rb_ary_join(ary, tmp);
}
len = NUM2LONG(times);
if (len == 0) {
ary2 = ary_new(rb_cArray, 0);
- goto out;
+ goto out;
}
if (len < 0) {
- rb_raise(rb_eArgError, "negative argument");
+ rb_raise(rb_eArgError, "negative argument");
}
if (ARY_MAX_SIZE/len < RARRAY_LEN(ary)) {
- rb_raise(rb_eArgError, "argument too big");
+ rb_raise(rb_eArgError, "argument too big");
}
len *= RARRAY_LEN(ary);
@@ -4838,8 +5196,8 @@ rb_ary_times(VALUE ary, VALUE times)
ptr = RARRAY_CONST_PTR_TRANSIENT(ary);
t = RARRAY_LEN(ary);
if (0 < t) {
- ary_memcpy(ary2, 0, t, ptr);
- while (t <= len/2) {
+ ary_memcpy(ary2, 0, t, ptr);
+ while (t <= len/2) {
ary_memcpy(ary2, t, t, RARRAY_CONST_PTR_TRANSIENT(ary2));
t *= 2;
}
@@ -4857,6 +5215,7 @@ rb_ary_times(VALUE ary, VALUE times)
*
* Returns the first element in +self+ that is an \Array
* whose first element <tt>==</tt> +obj+:
+ *
* a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
* a.assoc(4) # => [4, 5, 6]
*
@@ -4872,10 +5231,10 @@ rb_ary_assoc(VALUE ary, VALUE key)
VALUE v;
for (i = 0; i < RARRAY_LEN(ary); ++i) {
- v = rb_check_array_type(RARRAY_AREF(ary, i));
- if (!NIL_P(v) && RARRAY_LEN(v) > 0 &&
- rb_equal(RARRAY_AREF(v, 0), key))
- return v;
+ v = rb_check_array_type(RARRAY_AREF(ary, i));
+ if (!NIL_P(v) && RARRAY_LEN(v) > 0 &&
+ rb_equal(RARRAY_AREF(v, 0), key))
+ return v;
}
return Qnil;
}
@@ -4886,6 +5245,7 @@ rb_ary_assoc(VALUE ary, VALUE key)
*
* Returns the first element in +self+ that is an \Array
* whose second element <tt>==</tt> +obj+:
+ *
* a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
* a.rassoc(4) # => [2, 4]
*
@@ -4901,11 +5261,11 @@ rb_ary_rassoc(VALUE ary, VALUE value)
VALUE v;
for (i = 0; i < RARRAY_LEN(ary); ++i) {
- v = RARRAY_AREF(ary, i);
- if (RB_TYPE_P(v, T_ARRAY) &&
- RARRAY_LEN(v) > 1 &&
- rb_equal(RARRAY_AREF(v, 1), value))
- return v;
+ v = RARRAY_AREF(ary, i);
+ if (RB_TYPE_P(v, T_ARRAY) &&
+ RARRAY_LEN(v) > 1 &&
+ rb_equal(RARRAY_AREF(v, 1), value))
+ return v;
}
return Qnil;
}
@@ -4924,22 +5284,22 @@ recursive_equal(VALUE ary1, VALUE ary2, int recur)
len1 = RARRAY_LEN(ary1);
for (i = 0; i < len1; i++) {
- if (*p1 != *p2) {
- if (rb_equal(*p1, *p2)) {
- len1 = RARRAY_LEN(ary1);
- if (len1 != RARRAY_LEN(ary2))
- return Qfalse;
- if (len1 < i)
- return Qtrue;
+ if (*p1 != *p2) {
+ if (rb_equal(*p1, *p2)) {
+ len1 = RARRAY_LEN(ary1);
+ if (len1 != RARRAY_LEN(ary2))
+ return Qfalse;
+ if (len1 < i)
+ return Qtrue;
p1 = RARRAY_CONST_PTR(ary1) + i;
p2 = RARRAY_CONST_PTR(ary2) + i;
- }
- else {
- return Qfalse;
- }
- }
- p1++;
- p2++;
+ }
+ else {
+ return Qfalse;
+ }
+ }
+ p1++;
+ p2++;
}
return Qtrue;
}
@@ -4950,6 +5310,7 @@ recursive_equal(VALUE ary1, VALUE ary2, int recur)
*
* Returns +true+ if both <tt>array.size == other_array.size</tt>
* and for each index +i+ in +array+, <tt>array[i] == other_array[i]</tt>:
+ *
* a0 = [:foo, 'bar', 2]
* a1 = [:foo, 'bar', 2.0]
* a1 == a0 # => true
@@ -4966,10 +5327,10 @@ rb_ary_equal(VALUE ary1, VALUE ary2)
{
if (ary1 == ary2) return Qtrue;
if (!RB_TYPE_P(ary2, T_ARRAY)) {
- if (!rb_respond_to(ary2, idTo_ary)) {
- return Qfalse;
- }
- return rb_equal(ary2, ary1);
+ if (!rb_respond_to(ary2, idTo_ary)) {
+ return Qfalse;
+ }
+ return rb_equal(ary2, ary1);
}
if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
if (RARRAY_CONST_PTR_TRANSIENT(ary1) == RARRAY_CONST_PTR_TRANSIENT(ary2)) return Qtrue;
@@ -4983,8 +5344,8 @@ recursive_eql(VALUE ary1, VALUE ary2, int recur)
if (recur) return Qtrue; /* Subtle! */
for (i=0; i<RARRAY_LEN(ary1); i++) {
- if (!rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
- return Qfalse;
+ if (!rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
+ return Qfalse;
}
return Qtrue;
}
@@ -4995,13 +5356,14 @@ recursive_eql(VALUE ary1, VALUE ary2, int recur)
*
* Returns +true+ if +self+ and +other_array+ are the same size,
* and if, for each index +i+ in +self+, <tt>self[i].eql? other_array[i]</tt>:
+ *
* a0 = [:foo, 'bar', 2]
* a1 = [:foo, 'bar', 2]
* a1.eql?(a0) # => true
*
* Otherwise, returns +false+.
*
- * This method is different from method {Array#==}[#method-i-3D-3D],
+ * This method is different from method Array#==,
* which compares using method <tt>Object#==</tt>.
*/
@@ -5022,8 +5384,10 @@ rb_ary_eql(VALUE ary1, VALUE ary2)
* Returns the integer hash value for +self+.
*
* Two arrays with the same content will have the same hash code (and will compare using eql?):
+ *
* [0, 1, 2].hash == [0, 1, 2].hash # => true
* [0, 1, 2].hash == [0, 1, 3].hash # => false
+ *
*/
static VALUE
@@ -5036,8 +5400,8 @@ rb_ary_hash(VALUE ary)
h = rb_hash_start(RARRAY_LEN(ary));
h = rb_hash_uint(h, (st_index_t)rb_ary_hash);
for (i=0; i<RARRAY_LEN(ary); i++) {
- n = rb_hash(RARRAY_AREF(ary, i));
- h = rb_hash_uint(h, NUM2LONG(n));
+ n = rb_hash(RARRAY_AREF(ary, i));
+ h = rb_hash_uint(h, NUM2LONG(n));
}
h = rb_hash_end(h);
return ST2FIX(h);
@@ -5049,6 +5413,7 @@ rb_ary_hash(VALUE ary)
*
* Returns +true+ if for some index +i+ in +self+, <tt>obj == self[i]</tt>;
* otherwise +false+:
+ *
* [0, 1, 2].include?(2) # => true
* [0, 1, 2].include?(3) # => false
*/
@@ -5060,10 +5425,10 @@ rb_ary_includes(VALUE ary, VALUE item)
VALUE e;
for (i=0; i<RARRAY_LEN(ary); i++) {
- e = RARRAY_AREF(ary, i);
- if (rb_equal(e, item)) {
- return Qtrue;
- }
+ e = RARRAY_AREF(ary, i);
+ if (rb_equal(e, item)) {
+ return Qtrue;
+ }
}
return Qfalse;
}
@@ -5075,10 +5440,10 @@ rb_ary_includes_by_eql(VALUE ary, VALUE item)
VALUE e;
for (i=0; i<RARRAY_LEN(ary); i++) {
- e = RARRAY_AREF(ary, i);
- if (rb_eql(item, e)) {
- return Qtrue;
- }
+ e = RARRAY_AREF(ary, i);
+ if (rb_eql(item, e)) {
+ return Qtrue;
+ }
}
return Qfalse;
}
@@ -5091,14 +5456,14 @@ recursive_cmp(VALUE ary1, VALUE ary2, int recur)
if (recur) return Qundef; /* Subtle! */
len = RARRAY_LEN(ary1);
if (len > RARRAY_LEN(ary2)) {
- len = RARRAY_LEN(ary2);
+ len = RARRAY_LEN(ary2);
}
for (i=0; i<len; i++) {
- VALUE e1 = rb_ary_elt(ary1, i), e2 = rb_ary_elt(ary2, i);
- VALUE v = rb_funcallv(e1, id_cmp, 1, &e2);
- if (v != INT2FIX(0)) {
- return v;
- }
+ VALUE e1 = rb_ary_elt(ary1, i), e2 = rb_ary_elt(ary2, i);
+ VALUE v = rb_funcallv(e1, id_cmp, 1, &e2);
+ if (v != INT2FIX(0)) {
+ return v;
+ }
}
return Qundef;
}
@@ -5111,18 +5476,27 @@ recursive_cmp(VALUE ary1, VALUE ary2, int recur)
* For each index +i+ in +self+, evaluates <tt>result = self[i] <=> other_array[i]</tt>.
*
* Returns -1 if any result is -1:
+ *
* [0, 1, 2] <=> [0, 1, 3] # => -1
*
* Returns 1 if any result is 1:
+ *
* [0, 1, 2] <=> [0, 1, 1] # => 1
*
* When all results are zero:
+ *
* - Returns -1 if +array+ is smaller than +other_array+:
+ *
* [0, 1, 2] <=> [0, 1, 2, 3] # => -1
+ *
* - Returns 1 if +array+ is larger than +other_array+:
+ *
* [0, 1, 2] <=> [0, 1] # => 1
+ *
* - Returns 0 if +array+ and +other_array+ are the same size:
+ *
* [0, 1, 2] <=> [0, 1, 2] # => 0
+ *
*/
VALUE
@@ -5135,7 +5509,7 @@ rb_ary_cmp(VALUE ary1, VALUE ary2)
if (NIL_P(ary2)) return Qnil;
if (ary1 == ary2) return INT2FIX(0);
v = rb_exec_recursive_paired(recursive_cmp, ary1, ary2, ary2);
- if (v != Qundef) return v;
+ if (!UNDEF_P(v)) return v;
len = RARRAY_LEN(ary1) - RARRAY_LEN(ary2);
if (len == 0) return INT2FIX(0);
if (len > 0) return INT2FIX(1);
@@ -5148,8 +5522,8 @@ ary_add_hash(VALUE hash, VALUE ary)
long i;
for (i=0; i<RARRAY_LEN(ary); i++) {
- VALUE elt = RARRAY_AREF(ary, i);
- rb_hash_add_new_element(hash, elt, elt);
+ VALUE elt = RARRAY_AREF(ary, i);
+ rb_hash_add_new_element(hash, elt, elt);
}
return hash;
}
@@ -5177,8 +5551,8 @@ ary_add_hash_by(VALUE hash, VALUE ary)
long i;
for (i = 0; i < RARRAY_LEN(ary); ++i) {
- VALUE v = rb_ary_elt(ary, i), k = rb_yield(v);
- rb_hash_add_new_element(hash, k, v);
+ VALUE v = rb_ary_elt(ary, i), k = rb_yield(v);
+ rb_hash_add_new_element(hash, k, v);
}
return hash;
}
@@ -5196,7 +5570,7 @@ ary_recycle_hash(VALUE hash)
assert(RBASIC_CLASS(hash) == 0);
if (RHASH_ST_TABLE_P(hash)) {
st_table *tbl = RHASH_ST_TABLE(hash);
- st_free_table(tbl);
+ st_free_table(tbl);
RHASH_ST_CLEAR(hash);
}
}
@@ -5209,6 +5583,7 @@ ary_recycle_hash(VALUE hash)
* that are not found in \Array +other_array+;
* items are compared using <tt>eql?</tt>;
* the order from +array+ is preserved:
+ *
* [0, 1, 1, 2, 1, 1, 3, 1, 1] - [1] # => [0, 2, 3]
* [0, 1, 2, 3] - [3, 0] # => [1, 2]
* [0, 1, 2] - [4] # => [0, 1, 2]
@@ -5216,7 +5591,7 @@ ary_recycle_hash(VALUE hash)
* Related: Array#difference.
*/
-static VALUE
+VALUE
rb_ary_diff(VALUE ary1, VALUE ary2)
{
VALUE ary3;
@@ -5228,18 +5603,18 @@ rb_ary_diff(VALUE ary1, VALUE ary2)
ary3 = rb_ary_new();
if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN || RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
- for (i=0; i<RARRAY_LEN(ary1); i++) {
- VALUE elt = rb_ary_elt(ary1, i);
- if (rb_ary_includes_by_eql(ary2, elt)) continue;
- rb_ary_push(ary3, elt);
- }
- return ary3;
+ for (i=0; i<RARRAY_LEN(ary1); i++) {
+ VALUE elt = rb_ary_elt(ary1, i);
+ if (rb_ary_includes_by_eql(ary2, elt)) continue;
+ rb_ary_push(ary3, elt);
+ }
+ return ary3;
}
hash = ary_make_hash(ary2);
for (i=0; i<RARRAY_LEN(ary1); i++) {
if (rb_hash_stlike_lookup(hash, RARRAY_AREF(ary1, i), NULL)) continue;
- rb_ary_push(ary3, rb_ary_elt(ary1, i));
+ rb_ary_push(ary3, rb_ary_elt(ary1, i));
}
ary_recycle_hash(hash);
return ary3;
@@ -5252,6 +5627,7 @@ rb_ary_diff(VALUE ary1, VALUE ary2)
* Returns a new \Array containing only those elements from +self+
* that are not found in any of the Arrays +other_arrays+;
* items are compared using <tt>eql?</tt>; order from +self+ is preserved:
+ *
* [0, 1, 1, 2, 1, 1, 3, 1, 1].difference([1]) # => [0, 2, 3]
* [0, 1, 2, 3].difference([3, 0], [1, 3]) # => [2]
* [0, 1, 2].difference([4]) # => [0, 1, 2]
@@ -5304,10 +5680,12 @@ rb_ary_difference_multi(int argc, VALUE *argv, VALUE ary)
*
* Returns a new \Array containing each element found in both +array+ and \Array +other_array+;
* duplicates are omitted; items are compared using <tt>eql?</tt>:
+ *
* [0, 1, 2, 3] & [1, 2] # => [1, 2]
* [0, 1, 0, 1] & [0, 1] # => [0, 1]
*
* Preserves order from +array+:
+ *
* [0, 1, 2] & [3, 2, 1, 0] # => [0, 1, 2]
*
* Related: Array#intersection.
@@ -5326,23 +5704,23 @@ rb_ary_and(VALUE ary1, VALUE ary2)
if (RARRAY_LEN(ary1) == 0 || RARRAY_LEN(ary2) == 0) return ary3;
if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN && RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
- for (i=0; i<RARRAY_LEN(ary1); i++) {
- v = RARRAY_AREF(ary1, i);
- if (!rb_ary_includes_by_eql(ary2, v)) continue;
- if (rb_ary_includes_by_eql(ary3, v)) continue;
- rb_ary_push(ary3, v);
- }
- return ary3;
+ for (i=0; i<RARRAY_LEN(ary1); i++) {
+ v = RARRAY_AREF(ary1, i);
+ if (!rb_ary_includes_by_eql(ary2, v)) continue;
+ if (rb_ary_includes_by_eql(ary3, v)) continue;
+ rb_ary_push(ary3, v);
+ }
+ return ary3;
}
hash = ary_make_hash(ary2);
for (i=0; i<RARRAY_LEN(ary1); i++) {
- v = RARRAY_AREF(ary1, i);
- vv = (st_data_t)v;
+ v = RARRAY_AREF(ary1, i);
+ vv = (st_data_t)v;
if (rb_hash_stlike_delete(hash, &vv, 0)) {
- rb_ary_push(ary3, v);
- }
+ rb_ary_push(ary3, v);
+ }
}
ary_recycle_hash(hash);
@@ -5356,10 +5734,12 @@ rb_ary_and(VALUE ary1, VALUE ary2)
* Returns a new \Array containing each element found both in +self+
* and in all of the given Arrays +other_arrays+;
* duplicates are omitted; items are compared using <tt>eql?</tt>:
+ *
* [0, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3]) # => [0, 1]
* [0, 0, 1, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3]) # => [0, 1]
*
* Preserves order from +self+:
+ *
* [0, 1, 2].intersection([2, 1, 0]) # => [0, 1, 2]
*
* Returns a copy of +self+ if no arguments given.
@@ -5418,6 +5798,7 @@ rb_ary_union_hash(VALUE hash, VALUE ary2)
* Returns the union of +array+ and \Array +other_array+;
* duplicates are removed; order is preserved;
* items are compared using <tt>eql?</tt>:
+ *
* [0, 1] | [2, 3] # => [0, 1, 2, 3]
* [0, 1, 1] | [2, 2, 3] # => [0, 1, 2, 3]
* [0, 1, 2] | [3, 2, 1, 0] # => [0, 1, 2, 3]
@@ -5432,10 +5813,10 @@ rb_ary_or(VALUE ary1, VALUE ary2)
ary2 = to_ary(ary2);
if (RARRAY_LEN(ary1) + RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
- ary3 = rb_ary_new();
+ ary3 = rb_ary_new();
rb_ary_union(ary3, ary1);
rb_ary_union(ary3, ary2);
- return ary3;
+ return ary3;
}
hash = ary_make_hash(ary1);
@@ -5452,6 +5833,7 @@ rb_ary_or(VALUE ary1, VALUE ary2)
*
* Returns a new \Array that is the union of +self+ and all given Arrays +other_arrays+;
* duplicates are removed; order is preserved; items are compared using <tt>eql?</tt>:
+ *
* [0, 1, 2, 3].union([4, 5], [6, 7]) # => [0, 1, 2, 3, 4, 5, 6, 7]
* [0, 1, 1].union([2, 1], [3, 1]) # => [0, 1, 2, 3]
* [0, 1, 2, 3].union([3, 2], [1, 0]) # => [0, 1, 2, 3]
@@ -5496,13 +5878,14 @@ rb_ary_union_multi(int argc, VALUE *argv, VALUE ary)
* ary.intersect?(other_ary) -> true or false
*
* Returns +true+ if the array and +other_ary+ have at least one element in
- * common, otherwise returns +false+.
+ * common, otherwise returns +false+:
*
* a = [ 1, 2, 3 ]
* b = [ 3, 4, 5 ]
* c = [ 5, 6, 7 ]
* a.intersect?(b) #=> true
* a.intersect?(c) #=> false
+ *
*/
static VALUE
@@ -5643,6 +6026,7 @@ ary_max_opt_string(VALUE ary, long i, VALUE vmax)
* array.max(n) {|a, b| ... } -> new_array
*
* Returns one of the following:
+ *
* - The maximum-valued element from +self+.
* - A new \Array of maximum-valued elements selected from +self+.
*
@@ -5651,10 +6035,12 @@ ary_max_opt_string(VALUE ary, long i, VALUE vmax)
*
* With no argument and no block, returns the element in +self+
* having the maximum value per method <tt><=></tt>:
+ *
* [0, 1, 2].max # => 2
*
* With an argument \Integer +n+ and no block, returns a new \Array with at most +n+ elements,
* in descending order per method <tt><=></tt>:
+ *
* [0, 1, 2, 3].max(3) # => [3, 2, 1]
* [0, 1, 2, 3].max(6) # => [3, 2, 1, 0]
*
@@ -5662,16 +6048,18 @@ ary_max_opt_string(VALUE ary, long i, VALUE vmax)
*
* With a block and no argument, calls the block <tt>self.size-1</tt> times to compare elements;
* returns the element having the maximum value per the block:
+ *
* ['0', '00', '000'].max {|a, b| a.size <=> b.size } # => "000"
*
* With an argument +n+ and a block, returns a new \Array with at most +n+ elements,
* in descending order per the block:
+ *
* ['0', '00', '000'].max(2) {|a, b| a.size <=> b.size } # => ["000", "00"]
+ *
*/
static VALUE
rb_ary_max(int argc, VALUE *argv, VALUE ary)
{
- struct cmp_opt_data cmp_opt = { 0, 0 };
VALUE result = Qundef, v;
VALUE num;
long i;
@@ -5681,23 +6069,23 @@ rb_ary_max(int argc, VALUE *argv, VALUE ary)
const long n = RARRAY_LEN(ary);
if (rb_block_given_p()) {
- for (i = 0; i < RARRAY_LEN(ary); i++) {
- v = RARRAY_AREF(ary, i);
- if (result == Qundef || rb_cmpint(rb_yield_values(2, v, result), v, result) > 0) {
- result = v;
- }
- }
+ for (i = 0; i < RARRAY_LEN(ary); i++) {
+ v = RARRAY_AREF(ary, i);
+ if (UNDEF_P(result) || rb_cmpint(rb_yield_values(2, v, result), v, result) > 0) {
+ result = v;
+ }
+ }
}
else if (n > 0) {
result = RARRAY_AREF(ary, 0);
if (n > 1) {
- if (FIXNUM_P(result) && CMP_OPTIMIZABLE(cmp_opt, Integer)) {
+ if (FIXNUM_P(result) && CMP_OPTIMIZABLE(INTEGER)) {
return ary_max_opt_fixnum(ary, 1, result);
}
- else if (STRING_P(result) && CMP_OPTIMIZABLE(cmp_opt, String)) {
+ else if (STRING_P(result) && CMP_OPTIMIZABLE(STRING)) {
return ary_max_opt_string(ary, 1, result);
}
- else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(cmp_opt, Float)) {
+ else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(FLOAT)) {
return ary_max_opt_float(ary, 1, result);
}
else {
@@ -5705,7 +6093,7 @@ rb_ary_max(int argc, VALUE *argv, VALUE ary)
}
}
}
- if (result == Qundef) return Qnil;
+ if (UNDEF_P(result)) return Qnil;
return result;
}
@@ -5806,6 +6194,7 @@ ary_min_opt_string(VALUE ary, long i, VALUE vmin)
* array.min(n) { |a, b| ... } -> new_array
*
* Returns one of the following:
+ *
* - The minimum-valued element from +self+.
* - A new \Array of minimum-valued elements selected from +self+.
*
@@ -5814,10 +6203,12 @@ ary_min_opt_string(VALUE ary, long i, VALUE vmin)
*
* With no argument and no block, returns the element in +self+
* having the minimum value per method <tt><=></tt>:
+ *
* [0, 1, 2].min # => 0
*
* With \Integer argument +n+ and no block, returns a new \Array with at most +n+ elements,
* in ascending order per method <tt><=></tt>:
+ *
* [0, 1, 2, 3].min(3) # => [0, 1, 2]
* [0, 1, 2, 3].min(6) # => [0, 1, 2, 3]
*
@@ -5825,16 +6216,18 @@ ary_min_opt_string(VALUE ary, long i, VALUE vmin)
*
* With a block and no argument, calls the block <tt>self.size-1</tt> times to compare elements;
* returns the element having the minimum value per the block:
+ *
* ['0', '00', '000'].min { |a, b| a.size <=> b.size } # => "0"
*
* With an argument +n+ and a block, returns a new \Array with at most +n+ elements,
* in ascending order per the block:
+ *
* ['0', '00', '000'].min(2) {|a, b| a.size <=> b.size } # => ["0", "00"]
+ *
*/
static VALUE
rb_ary_min(int argc, VALUE *argv, VALUE ary)
{
- struct cmp_opt_data cmp_opt = { 0, 0 };
VALUE result = Qundef, v;
VALUE num;
long i;
@@ -5844,23 +6237,23 @@ rb_ary_min(int argc, VALUE *argv, VALUE ary)
const long n = RARRAY_LEN(ary);
if (rb_block_given_p()) {
- for (i = 0; i < RARRAY_LEN(ary); i++) {
- v = RARRAY_AREF(ary, i);
- if (result == Qundef || rb_cmpint(rb_yield_values(2, v, result), v, result) < 0) {
- result = v;
- }
- }
+ for (i = 0; i < RARRAY_LEN(ary); i++) {
+ v = RARRAY_AREF(ary, i);
+ if (UNDEF_P(result) || rb_cmpint(rb_yield_values(2, v, result), v, result) < 0) {
+ result = v;
+ }
+ }
}
else if (n > 0) {
result = RARRAY_AREF(ary, 0);
if (n > 1) {
- if (FIXNUM_P(result) && CMP_OPTIMIZABLE(cmp_opt, Integer)) {
+ if (FIXNUM_P(result) && CMP_OPTIMIZABLE(INTEGER)) {
return ary_min_opt_fixnum(ary, 1, result);
}
- else if (STRING_P(result) && CMP_OPTIMIZABLE(cmp_opt, String)) {
+ else if (STRING_P(result) && CMP_OPTIMIZABLE(STRING)) {
return ary_min_opt_string(ary, 1, result);
}
- else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(cmp_opt, Float)) {
+ else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(FLOAT)) {
return ary_min_opt_float(ary, 1, result);
}
else {
@@ -5868,7 +6261,7 @@ rb_ary_min(int argc, VALUE *argv, VALUE ary)
}
}
}
- if (result == Qundef) return Qnil;
+ if (UNDEF_P(result)) return Qnil;
return result;
}
@@ -5884,13 +6277,16 @@ rb_ary_min(int argc, VALUE *argv, VALUE ary)
* with an \Integer;
* returns a new 2-element \Array containing the minimum and maximum values
* from +self+, per method <tt><=></tt>:
+ *
* [0, 1, 2].minmax # => [0, 2]
*
* When a block is given, the block must return an \Integer;
* the block is called <tt>self.size-1</tt> times to compare elements;
* returns a new 2-element \Array containing the minimum and maximum values
* from +self+, per the block:
+ *
* ['0', '00', '000'].minmax {|a, b| a.size <=> b.size } # => ["0", "000"]
+ *
*/
static VALUE
rb_ary_minmax(VALUE ary)
@@ -5920,6 +6316,7 @@ push_value(st_data_t key, st_data_t val, st_data_t ary)
* to compare.
*
* Returns +self+ if any elements removed:
+ *
* a = [0, 0, 1, 1, 2, 2]
* a.uniq! # => [0, 1, 2]
*
@@ -5930,6 +6327,7 @@ push_value(st_data_t key, st_data_t val, st_data_t ary)
* elements for which the block returns duplicate values.
*
* Returns +self+ if any elements removed:
+ *
* a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
* a.uniq! {|element| element.size } # => ['a', 'aa', 'aaa']
*
@@ -5945,19 +6343,19 @@ rb_ary_uniq_bang(VALUE ary)
if (RARRAY_LEN(ary) <= 1)
return Qnil;
if (rb_block_given_p())
- hash = ary_make_hash_by(ary);
+ hash = ary_make_hash_by(ary);
else
- hash = ary_make_hash(ary);
+ hash = ary_make_hash(ary);
hash_size = RHASH_SIZE(hash);
if (RARRAY_LEN(ary) == hash_size) {
- return Qnil;
+ return Qnil;
}
rb_ary_modify_check(ary);
ARY_SET_LEN(ary, 0);
if (ARY_SHARED_P(ary) && !ARY_EMBED_P(ary)) {
- rb_ary_unshare(ary);
- FL_SET_EMBED(ary);
+ rb_ary_unshare(ary);
+ FL_SET_EMBED(ary);
}
ary_resize_capa(ary, hash_size);
rb_hash_foreach(hash, push_value, ary);
@@ -5975,15 +6373,18 @@ rb_ary_uniq_bang(VALUE ary)
* the first occurrence always being retained.
*
* With no block given, identifies and omits duplicates using method <tt>eql?</tt>
- * to compare.
+ * to compare:
+ *
* a = [0, 0, 1, 1, 2, 2]
* a.uniq # => [0, 1, 2]
*
* With a block given, calls the block for each element;
* identifies (using method <tt>eql?</tt>) and omits duplicate values,
* that is, those elements for which the block returns the same value:
+ *
* a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
* a.uniq {|element| element.size } # => ["a", "aa", "aaa"]
+ *
*/
static VALUE
@@ -5996,12 +6397,12 @@ rb_ary_uniq(VALUE ary)
uniq = rb_ary_dup(ary);
}
else if (rb_block_given_p()) {
- hash = ary_make_hash_by(ary);
- uniq = rb_hash_values(hash);
+ hash = ary_make_hash_by(ary);
+ uniq = rb_hash_values(hash);
}
else {
- hash = ary_make_hash(ary);
- uniq = rb_hash_values(hash);
+ hash = ary_make_hash(ary);
+ uniq = rb_hash_values(hash);
}
if (hash) {
ary_recycle_hash(hash);
@@ -6030,12 +6431,12 @@ rb_ary_compact_bang(VALUE ary)
end = p + RARRAY_LEN(ary);
while (t < end) {
- if (NIL_P(*t)) t++;
- else *p++ = *t++;
+ if (NIL_P(*t)) t++;
+ else *p++ = *t++;
}
n = p - RARRAY_CONST_PTR_TRANSIENT(ary);
if (RARRAY_LEN(ary) == n) {
- return Qnil;
+ return Qnil;
}
ary_resize_smaller(ary, n);
@@ -6047,6 +6448,7 @@ rb_ary_compact_bang(VALUE ary)
* array.compact -> new_array
*
* Returns a new \Array containing all non-+nil+ elements from +self+:
+ *
* a = [nil, 0, nil, 1, nil, 2, nil]
* a.compact # => [0, 1, 2]
*/
@@ -6068,19 +6470,22 @@ rb_ary_compact(VALUE ary)
* Returns a count of specified elements.
*
* With no argument and no block, returns the count of all elements:
+ *
* [0, 1, 2].count # => 3
* [].count # => 0
*
* With argument +obj+, returns the count of elements <tt>==</tt> to +obj+:
+ *
* [0, 1, 2, 0.0].count(0) # => 2
* [0, 1, 2].count(3) # => 0
*
* With no argument and a block given, calls the block with each element;
* returns the count of elements for which the block returns a truthy value:
+ *
* [0, 1, 2, 3].count {|element| element > 1} # => 2
*
* With argument +obj+ and a block given, issues a warning, ignores the block,
- * and returns the count of elements <tt>==</tt> to +obj+:
+ * and returns the count of elements <tt>==</tt> to +obj+.
*/
static VALUE
@@ -6089,25 +6494,25 @@ rb_ary_count(int argc, VALUE *argv, VALUE ary)
long i, n = 0;
if (rb_check_arity(argc, 0, 1) == 0) {
- VALUE v;
+ VALUE v;
- if (!rb_block_given_p())
- return LONG2NUM(RARRAY_LEN(ary));
+ if (!rb_block_given_p())
+ return LONG2NUM(RARRAY_LEN(ary));
- for (i = 0; i < RARRAY_LEN(ary); i++) {
- v = RARRAY_AREF(ary, i);
- if (RTEST(rb_yield(v))) n++;
- }
+ for (i = 0; i < RARRAY_LEN(ary); i++) {
+ v = RARRAY_AREF(ary, i);
+ if (RTEST(rb_yield(v))) n++;
+ }
}
else {
VALUE obj = argv[0];
- if (rb_block_given_p()) {
- rb_warn("given block not used");
- }
- for (i = 0; i < RARRAY_LEN(ary); i++) {
- if (rb_equal(RARRAY_AREF(ary, i), obj)) n++;
- }
+ if (rb_block_given_p()) {
+ rb_warn("given block not used");
+ }
+ for (i = 0; i < RARRAY_LEN(ary); i++) {
+ if (rb_equal(RARRAY_AREF(ary, i), obj)) n++;
+ }
}
return LONG2NUM(n);
@@ -6141,64 +6546,64 @@ flatten(VALUE ary, int level)
rb_ary_push(stack, LONG2NUM(i + 1));
if (level < 0) {
- vmemo = rb_hash_new();
- RBASIC_CLEAR_CLASS(vmemo);
- memo = st_init_numtable();
- rb_hash_st_table_set(vmemo, memo);
- st_insert(memo, (st_data_t)ary, (st_data_t)Qtrue);
- st_insert(memo, (st_data_t)tmp, (st_data_t)Qtrue);
+ vmemo = rb_hash_new();
+ RBASIC_CLEAR_CLASS(vmemo);
+ memo = st_init_numtable();
+ rb_hash_st_table_set(vmemo, memo);
+ st_insert(memo, (st_data_t)ary, (st_data_t)Qtrue);
+ st_insert(memo, (st_data_t)tmp, (st_data_t)Qtrue);
}
ary = tmp;
i = 0;
while (1) {
- while (i < RARRAY_LEN(ary)) {
- elt = RARRAY_AREF(ary, i++);
- if (level >= 0 && RARRAY_LEN(stack) / 2 >= level) {
- rb_ary_push(result, elt);
- continue;
- }
- tmp = rb_check_array_type(elt);
- if (RBASIC(result)->klass) {
- if (memo) {
- RB_GC_GUARD(vmemo);
- st_clear(memo);
- }
- rb_raise(rb_eRuntimeError, "flatten reentered");
- }
- if (NIL_P(tmp)) {
- rb_ary_push(result, elt);
- }
- else {
- if (memo) {
- id = (st_data_t)tmp;
- if (st_is_member(memo, id)) {
- st_clear(memo);
- rb_raise(rb_eArgError, "tried to flatten recursive array");
- }
- st_insert(memo, id, (st_data_t)Qtrue);
- }
- rb_ary_push(stack, ary);
- rb_ary_push(stack, LONG2NUM(i));
- ary = tmp;
- i = 0;
- }
- }
- if (RARRAY_LEN(stack) == 0) {
- break;
- }
- if (memo) {
- id = (st_data_t)ary;
- st_delete(memo, &id, 0);
- }
- tmp = rb_ary_pop(stack);
- i = NUM2LONG(tmp);
- ary = rb_ary_pop(stack);
+ while (i < RARRAY_LEN(ary)) {
+ elt = RARRAY_AREF(ary, i++);
+ if (level >= 0 && RARRAY_LEN(stack) / 2 >= level) {
+ rb_ary_push(result, elt);
+ continue;
+ }
+ tmp = rb_check_array_type(elt);
+ if (RBASIC(result)->klass) {
+ if (memo) {
+ RB_GC_GUARD(vmemo);
+ st_clear(memo);
+ }
+ rb_raise(rb_eRuntimeError, "flatten reentered");
+ }
+ if (NIL_P(tmp)) {
+ rb_ary_push(result, elt);
+ }
+ else {
+ if (memo) {
+ id = (st_data_t)tmp;
+ if (st_is_member(memo, id)) {
+ st_clear(memo);
+ rb_raise(rb_eArgError, "tried to flatten recursive array");
+ }
+ st_insert(memo, id, (st_data_t)Qtrue);
+ }
+ rb_ary_push(stack, ary);
+ rb_ary_push(stack, LONG2NUM(i));
+ ary = tmp;
+ i = 0;
+ }
+ }
+ if (RARRAY_LEN(stack) == 0) {
+ break;
+ }
+ if (memo) {
+ id = (st_data_t)ary;
+ st_delete(memo, &id, 0);
+ }
+ tmp = rb_ary_pop(stack);
+ i = NUM2LONG(tmp);
+ ary = rb_ary_pop(stack);
}
if (memo) {
- st_clear(memo);
+ st_clear(memo);
}
RBASIC_SET_CLASS(result, rb_cArray);
@@ -6214,6 +6619,7 @@ flatten(VALUE ary, int level)
* returns +self+ if any changes, +nil+ otherwise.
*
* With non-negative \Integer argument +level+, flattens recursively through +level+ levels:
+ *
* a = [ 0, [ 1, [2, 3], 4 ], 5 ]
* a.flatten!(1) # => [0, 1, [2, 3], 4, 5]
* a = [ 0, [ 1, [2, 3], 4 ], 5 ]
@@ -6223,6 +6629,7 @@ flatten(VALUE ary, int level)
* [0, 1, 2].flatten!(1) # => nil
*
* With no argument, a +nil+ argument, or with negative argument +level+, flattens all levels:
+ *
* a = [ 0, [ 1, [2, 3], 4 ], 5 ]
* a.flatten! # => [0, 1, 2, 3, 4, 5]
* [0, 1, 2].flatten! # => nil
@@ -6231,6 +6638,7 @@ flatten(VALUE ary, int level)
* a = [ 0, [ 1, [2, 3], 4 ], 5 ]
* a.flatten!(-2) # => [0, 1, 2, 3, 4, 5]
* [0, 1, 2].flatten!(-1) # => nil
+ *
*/
static VALUE
@@ -6246,7 +6654,7 @@ rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary)
result = flatten(ary, level);
if (result == ary) {
- return Qnil;
+ return Qnil;
}
if (!(mod = ARY_EMBED_P(result))) rb_obj_freeze(result);
rb_ary_replace(ary, result);
@@ -6265,6 +6673,7 @@ rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary)
* - Each \Array is replaced by its individual elements.
*
* With non-negative \Integer argument +level+, flattens recursively through +level+ levels:
+ *
* a = [ 0, [ 1, [2, 3], 4 ], 5 ]
* a.flatten(0) # => [0, [1, [2, 3], 4], 5]
* a = [ 0, [ 1, [2, 3], 4 ], 5 ]
@@ -6275,6 +6684,7 @@ rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary)
* a.flatten(3) # => [0, 1, 2, 3, 4, 5]
*
* With no argument, a +nil+ argument, or with negative argument +level+, flattens all levels:
+ *
* a = [ 0, [ 1, [2, 3], 4 ], 5 ]
* a.flatten # => [0, 1, 2, 3, 4, 5]
* [0, 1, 2].flatten # => [0, 1, 2]
@@ -6283,6 +6693,7 @@ rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary)
* a = [ 0, [ 1, [2, 3], 4 ], 5 ]
* a.flatten(-2) # => [0, 1, 2, 3, 4, 5]
* [0, 1, 2].flatten(-1) # => [0, 1, 2]
+ *
*/
static VALUE
@@ -6314,16 +6725,16 @@ rb_ary_shuffle_bang(rb_execution_context_t *ec, VALUE ary, VALUE randgen)
rb_ary_modify(ary);
i = len = RARRAY_LEN(ary);
RARRAY_PTR_USE(ary, ptr, {
- while (i) {
- long j = RAND_UPTO(i);
- VALUE tmp;
+ while (i) {
+ long j = RAND_UPTO(i);
+ VALUE tmp;
if (len != RARRAY_LEN(ary) || ptr != RARRAY_CONST_PTR_TRANSIENT(ary)) {
rb_raise(rb_eRuntimeError, "modified during shuffle");
- }
- tmp = ptr[--i];
- ptr[i] = ptr[j];
- ptr[j] = tmp;
- }
+ }
+ tmp = ptr[--i];
+ ptr[i] = ptr[j];
+ ptr[j] = tmp;
+ }
}); /* WB: no new reference */
return ary;
}
@@ -6346,120 +6757,120 @@ ary_sample(rb_execution_context_t *ec, VALUE ary, VALUE randgen, VALUE nv, VALUE
len = RARRAY_LEN(ary);
if (!to_array) {
- if (len < 2)
- i = 0;
- else
- i = RAND_UPTO(len);
+ if (len < 2)
+ i = 0;
+ else
+ i = RAND_UPTO(len);
- return rb_ary_elt(ary, i);
+ return rb_ary_elt(ary, i);
}
n = NUM2LONG(nv);
if (n < 0) rb_raise(rb_eArgError, "negative sample number");
if (n > len) n = len;
if (n <= numberof(idx)) {
- for (i = 0; i < n; ++i) {
- rnds[i] = RAND_UPTO(len - i);
- }
+ for (i = 0; i < n; ++i) {
+ rnds[i] = RAND_UPTO(len - i);
+ }
}
k = len;
len = RARRAY_LEN(ary);
if (len < k && n <= numberof(idx)) {
- for (i = 0; i < n; ++i) {
- if (rnds[i] >= len) return rb_ary_new_capa(0);
- }
+ for (i = 0; i < n; ++i) {
+ if (rnds[i] >= len) return rb_ary_new_capa(0);
+ }
}
if (n > len) n = len;
switch (n) {
case 0:
- return rb_ary_new_capa(0);
+ return rb_ary_new_capa(0);
case 1:
- i = rnds[0];
- return rb_ary_new_from_args(1, RARRAY_AREF(ary, i));
+ i = rnds[0];
+ return rb_ary_new_from_args(1, RARRAY_AREF(ary, i));
case 2:
- i = rnds[0];
- j = rnds[1];
- if (j >= i) j++;
- return rb_ary_new_from_args(2, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j));
+ i = rnds[0];
+ j = rnds[1];
+ if (j >= i) j++;
+ return rb_ary_new_from_args(2, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j));
case 3:
- i = rnds[0];
- j = rnds[1];
- k = rnds[2];
- {
- long l = j, g = i;
- if (j >= i) l = i, g = ++j;
- if (k >= l && (++k >= g)) ++k;
- }
- return rb_ary_new_from_args(3, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j), RARRAY_AREF(ary, k));
+ i = rnds[0];
+ j = rnds[1];
+ k = rnds[2];
+ {
+ long l = j, g = i;
+ if (j >= i) l = i, g = ++j;
+ if (k >= l && (++k >= g)) ++k;
+ }
+ return rb_ary_new_from_args(3, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j), RARRAY_AREF(ary, k));
}
memo_threshold =
- len < 2560 ? len / 128 :
- len < 5120 ? len / 64 :
- len < 10240 ? len / 32 :
- len / 16;
+ len < 2560 ? len / 128 :
+ len < 5120 ? len / 64 :
+ len < 10240 ? len / 32 :
+ len / 16;
if (n <= numberof(idx)) {
- long sorted[numberof(idx)];
- sorted[0] = idx[0] = rnds[0];
- for (i=1; i<n; i++) {
- k = rnds[i];
- for (j = 0; j < i; ++j) {
- if (k < sorted[j]) break;
- ++k;
- }
- memmove(&sorted[j+1], &sorted[j], sizeof(sorted[0])*(i-j));
- sorted[j] = idx[i] = k;
- }
- result = rb_ary_new_capa(n);
+ long sorted[numberof(idx)];
+ sorted[0] = idx[0] = rnds[0];
+ for (i=1; i<n; i++) {
+ k = rnds[i];
+ for (j = 0; j < i; ++j) {
+ if (k < sorted[j]) break;
+ ++k;
+ }
+ memmove(&sorted[j+1], &sorted[j], sizeof(sorted[0])*(i-j));
+ sorted[j] = idx[i] = k;
+ }
+ result = rb_ary_new_capa(n);
RARRAY_PTR_USE_TRANSIENT(result, ptr_result, {
- for (i=0; i<n; i++) {
- ptr_result[i] = RARRAY_AREF(ary, idx[i]);
- }
- });
+ for (i=0; i<n; i++) {
+ ptr_result[i] = RARRAY_AREF(ary, idx[i]);
+ }
+ });
}
else if (n <= memo_threshold / 2) {
- long max_idx = 0;
+ long max_idx = 0;
#undef RUBY_UNTYPED_DATA_WARNING
#define RUBY_UNTYPED_DATA_WARNING 0
- VALUE vmemo = Data_Wrap_Struct(0, 0, st_free_table, 0);
- st_table *memo = st_init_numtable_with_size(n);
- DATA_PTR(vmemo) = memo;
- result = rb_ary_new_capa(n);
- RARRAY_PTR_USE(result, ptr_result, {
- for (i=0; i<n; i++) {
- long r = RAND_UPTO(len-i) + i;
- ptr_result[i] = r;
- if (r > max_idx) max_idx = r;
- }
- len = RARRAY_LEN(ary);
- if (len <= max_idx) n = 0;
- else if (n > len) n = len;
+ VALUE vmemo = Data_Wrap_Struct(0, 0, st_free_table, 0);
+ st_table *memo = st_init_numtable_with_size(n);
+ DATA_PTR(vmemo) = memo;
+ result = rb_ary_new_capa(n);
+ RARRAY_PTR_USE(result, ptr_result, {
+ for (i=0; i<n; i++) {
+ long r = RAND_UPTO(len-i) + i;
+ ptr_result[i] = r;
+ if (r > max_idx) max_idx = r;
+ }
+ len = RARRAY_LEN(ary);
+ if (len <= max_idx) n = 0;
+ else if (n > len) n = len;
RARRAY_PTR_USE_TRANSIENT(ary, ptr_ary, {
- for (i=0; i<n; i++) {
- long j2 = j = ptr_result[i];
- long i2 = i;
- st_data_t value;
- if (st_lookup(memo, (st_data_t)i, &value)) i2 = (long)value;
- if (st_lookup(memo, (st_data_t)j, &value)) j2 = (long)value;
- st_insert(memo, (st_data_t)j, (st_data_t)i2);
- ptr_result[i] = ptr_ary[j2];
- }
- });
- });
- DATA_PTR(vmemo) = 0;
- st_free_table(memo);
+ for (i=0; i<n; i++) {
+ long j2 = j = ptr_result[i];
+ long i2 = i;
+ st_data_t value;
+ if (st_lookup(memo, (st_data_t)i, &value)) i2 = (long)value;
+ if (st_lookup(memo, (st_data_t)j, &value)) j2 = (long)value;
+ st_insert(memo, (st_data_t)j, (st_data_t)i2);
+ ptr_result[i] = ptr_ary[j2];
+ }
+ });
+ });
+ DATA_PTR(vmemo) = 0;
+ st_free_table(memo);
}
else {
- result = rb_ary_dup(ary);
- RBASIC_CLEAR_CLASS(result);
- RB_GC_GUARD(ary);
- RARRAY_PTR_USE(result, ptr_result, {
- for (i=0; i<n; i++) {
- j = RAND_UPTO(len-i) + i;
- nv = ptr_result[j];
- ptr_result[j] = ptr_result[i];
- ptr_result[i] = nv;
- }
- });
- RBASIC_SET_CLASS_RAW(result, rb_cArray);
+ result = rb_ary_dup(ary);
+ RBASIC_CLEAR_CLASS(result);
+ RB_GC_GUARD(ary);
+ RARRAY_PTR_USE(result, ptr_result, {
+ for (i=0; i<n; i++) {
+ j = RAND_UPTO(len-i) + i;
+ nv = ptr_result[j];
+ ptr_result[j] = ptr_result[i];
+ ptr_result[i] = nv;
+ }
+ });
+ RBASIC_SET_CLASS_RAW(result, rb_cArray);
}
ARY_SET_LEN(result, n);
@@ -6478,7 +6889,7 @@ rb_ary_cycle_size(VALUE self, VALUE args, VALUE eobj)
long mul;
VALUE n = Qnil;
if (args && (RARRAY_LEN(args) > 0)) {
- n = RARRAY_AREF(args, 0);
+ n = RARRAY_AREF(args, 0);
}
if (RARRAY_LEN(self) == 0) return INT2FIX(0);
if (NIL_P(n)) return DBL2NUM(HUGE_VAL);
@@ -6498,15 +6909,18 @@ rb_ary_cycle_size(VALUE self, VALUE args, VALUE eobj)
* When called with positive \Integer argument +count+ and a block,
* calls the block with each element, then does so again,
* until it has done so +count+ times; returns +nil+:
+ *
* output = []
* [0, 1].cycle(2) {|element| output.push(element) } # => nil
* output # => [0, 1, 0, 1]
*
* If +count+ is zero or negative, does not call the block:
+ *
* [0, 1].cycle(0) {|element| fail 'Cannot happen' } # => nil
* [0, 1].cycle(-1) {|element| fail 'Cannot happen' } # => nil
*
* When a block is given, and argument is omitted or +nil+, cycles forever:
+ *
* # Prints 0 and 1 forever.
* [0, 1].cycle {|element| puts element }
* [0, 1].cycle(nil) {|element| puts element }
@@ -6516,6 +6930,7 @@ rb_ary_cycle_size(VALUE self, VALUE args, VALUE eobj)
* [0, 1].cycle(2) # => #<Enumerator: [0, 1]:cycle(2)>
* [0, 1].cycle # => # => #<Enumerator: [0, 1]:cycle>
* [0, 1].cycle.first(5) # => [0, 1, 0, 1, 0]
+ *
*/
static VALUE
rb_ary_cycle(int argc, VALUE *argv, VALUE ary)
@@ -6541,9 +6956,6 @@ rb_ary_cycle(int argc, VALUE *argv, VALUE ary)
return Qnil;
}
-#define tmpary(n) rb_ary_tmp_new(n)
-#define tmpary_discard(a) (ary_discard(a), RBASIC_SET_CLASS_RAW(a, rb_cArray))
-
/*
* Build a ruby array of the corresponding values and yield it to the
* associated block.
@@ -6579,32 +6991,32 @@ permute0(const long n, const long r, long *const p, char *const used, const VALU
long i = 0, index = 0;
for (;;) {
- const char *const unused = memchr(&used[i], 0, n-i);
- if (!unused) {
- if (!index) break;
- i = p[--index]; /* pop index */
- used[i++] = 0; /* index unused */
- }
- else {
- i = unused - used;
- p[index] = i;
- used[i] = 1; /* mark index used */
- ++index;
- if (index < r-1) { /* if not done yet */
- p[index] = i = 0;
- continue;
- }
- for (i = 0; i < n; ++i) {
- if (used[i]) continue;
- p[index] = i;
- if (!yield_indexed_values(values, r, p)) {
- rb_raise(rb_eRuntimeError, "permute reentered");
- }
- }
- i = p[--index]; /* pop index */
- used[i] = 0; /* index unused */
- p[index] = ++i;
- }
+ const char *const unused = memchr(&used[i], 0, n-i);
+ if (!unused) {
+ if (!index) break;
+ i = p[--index]; /* pop index */
+ used[i++] = 0; /* index unused */
+ }
+ else {
+ i = unused - used;
+ p[index] = i;
+ used[i] = 1; /* mark index used */
+ ++index;
+ if (index < r-1) { /* if not done yet */
+ p[index] = i = 0;
+ continue;
+ }
+ for (i = 0; i < n; ++i) {
+ if (used[i]) continue;
+ p[index] = i;
+ if (!yield_indexed_values(values, r, p)) {
+ rb_raise(rb_eRuntimeError, "permute reentered");
+ }
+ }
+ i = p[--index]; /* pop index */
+ used[i] = 0; /* index unused */
+ p[index] = ++i;
+ }
}
}
@@ -6617,14 +7029,14 @@ descending_factorial(long from, long how_many)
{
VALUE cnt;
if (how_many > 0) {
- cnt = LONG2FIX(from);
- while (--how_many > 0) {
- long v = --from;
- cnt = rb_int_mul(cnt, LONG2FIX(v));
- }
+ cnt = LONG2FIX(from);
+ while (--how_many > 0) {
+ long v = --from;
+ cnt = rb_int_mul(cnt, LONG2FIX(v));
+ }
}
else {
- cnt = LONG2FIX(how_many == 0);
+ cnt = LONG2FIX(how_many == 0);
}
return cnt;
}
@@ -6635,18 +7047,18 @@ binomial_coefficient(long comb, long size)
VALUE r;
long i;
if (comb > size-comb) {
- comb = size-comb;
+ comb = size-comb;
}
if (comb < 0) {
- return LONG2FIX(0);
+ return LONG2FIX(0);
}
else if (comb == 0) {
- return LONG2FIX(1);
+ return LONG2FIX(1);
}
r = LONG2FIX(size);
for (i = 1; i < comb; ++i) {
- r = rb_int_mul(r, LONG2FIX(size - i));
- r = rb_int_idiv(r, LONG2FIX(i + 1));
+ r = rb_int_mul(r, LONG2FIX(size - i));
+ r = rb_int_idiv(r, LONG2FIX(i + 1));
}
return r;
}
@@ -6674,19 +7086,26 @@ rb_ary_permutation_size(VALUE ary, VALUE args, VALUE eobj)
* are given, calls the block with all +n+-tuple permutations of +self+.
*
* Example:
+ *
* a = [0, 1, 2]
* a.permutation(2) {|permutation| p permutation }
+ *
* Output:
+ *
* [0, 1]
* [0, 2]
* [1, 0]
* [1, 2]
* [2, 0]
* [2, 1]
+ *
* Another example:
+ *
* a = [0, 1, 2]
* a.permutation(3) {|permutation| p permutation }
+ *
* Output:
+ *
* [0, 1, 2]
* [0, 2, 1]
* [1, 0, 2]
@@ -6695,22 +7114,29 @@ rb_ary_permutation_size(VALUE ary, VALUE args, VALUE eobj)
* [2, 1, 0]
*
* When +n+ is zero, calls the block once with a new empty \Array:
+ *
* a = [0, 1, 2]
* a.permutation(0) {|permutation| p permutation }
+ *
* Output:
+ *
* []
*
* When +n+ is out of range (negative or larger than <tt>self.size</tt>),
* does not call the block:
+ *
* a = [0, 1, 2]
* a.permutation(-1) {|permutation| fail 'Cannot happen' }
* a.permutation(4) {|permutation| fail 'Cannot happen' }
*
* When a block given but no argument,
* behaves the same as <tt>a.permutation(a.size)</tt>:
+ *
* a = [0, 1, 2]
* a.permutation {|permutation| p permutation }
+ *
* Output:
+ *
* [0, 1, 2]
* [0, 2, 1]
* [1, 0, 2]
@@ -6719,9 +7145,11 @@ rb_ary_permutation_size(VALUE ary, VALUE args, VALUE eobj)
* [2, 1, 0]
*
* Returns a new \Enumerator if no block given:
+ *
* a = [0, 1, 2]
* a.permutation # => #<Enumerator: [0, 1, 2]:permutation>
* a.permutation(2) # => #<Enumerator: [0, 1, 2]:permutation(2)>
+ *
*/
static VALUE
@@ -6736,28 +7164,28 @@ rb_ary_permutation(int argc, VALUE *argv, VALUE ary)
r = NUM2LONG(argv[0]); /* Permutation size from argument */
if (r < 0 || n < r) {
- /* no permutations: yield nothing */
+ /* no permutations: yield nothing */
}
else if (r == 0) { /* exactly one permutation: the zero-length array */
- rb_yield(rb_ary_new2(0));
+ rb_yield(rb_ary_new2(0));
}
else if (r == 1) { /* this is a special, easy case */
- for (i = 0; i < RARRAY_LEN(ary); i++) {
- rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
- }
+ for (i = 0; i < RARRAY_LEN(ary); i++) {
+ rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
+ }
}
else { /* this is the general case */
- volatile VALUE t0;
- long *p = ALLOCV_N(long, t0, r+roomof(n, sizeof(long)));
- char *used = (char*)(p + r);
- VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
- RBASIC_CLEAR_CLASS(ary0);
+ volatile VALUE t0;
+ long *p = ALLOCV_N(long, t0, r+roomof(n, sizeof(long)));
+ char *used = (char*)(p + r);
+ VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
+ RBASIC_CLEAR_CLASS(ary0);
- MEMZERO(used, char, n); /* initialize array */
+ MEMZERO(used, char, n); /* initialize array */
- permute0(n, r, p, used, ary0); /* compute and yield permutations */
- ALLOCV_END(t0);
- RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
+ permute0(n, r, p, used, ary0); /* compute and yield permutations */
+ ALLOCV_END(t0);
+ RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
}
return ary;
}
@@ -6770,16 +7198,16 @@ combinate0(const long len, const long n, long *const stack, const VALUE values)
MEMZERO(stack+1, long, n);
stack[0] = -1;
for (;;) {
- for (lev++; lev < n; lev++) {
- stack[lev+1] = stack[lev]+1;
- }
- if (!yield_indexed_values(values, n, stack+1)) {
- rb_raise(rb_eRuntimeError, "combination reentered");
- }
- do {
- if (lev == 0) return;
- stack[lev--]++;
- } while (stack[lev+1]+n == len+lev+1);
+ for (lev++; lev < n; lev++) {
+ stack[lev+1] = stack[lev]+1;
+ }
+ if (!yield_indexed_values(values, n, stack+1)) {
+ rb_raise(rb_eRuntimeError, "combination reentered");
+ }
+ do {
+ if (lev == 0) return;
+ stack[lev--]++;
+ } while (stack[lev+1]+n == len+lev+1);
}
}
@@ -6804,34 +7232,46 @@ rb_ary_combination_size(VALUE ary, VALUE args, VALUE eobj)
* are given, calls the block with all +n+-tuple combinations of +self+.
*
* Example:
+ *
* a = [0, 1, 2]
* a.combination(2) {|combination| p combination }
+ *
* Output:
+ *
* [0, 1]
* [0, 2]
* [1, 2]
*
* Another example:
+ *
* a = [0, 1, 2]
* a.combination(3) {|combination| p combination }
+ *
* Output:
+ *
* [0, 1, 2]
*
* When +n+ is zero, calls the block once with a new empty \Array:
+ *
* a = [0, 1, 2]
* a1 = a.combination(0) {|combination| p combination }
+ *
* Output:
+ *
* []
*
* When +n+ is out of range (negative or larger than <tt>self.size</tt>),
* does not call the block:
+ *
* a = [0, 1, 2]
* a.combination(-1) {|combination| fail 'Cannot happen' }
* a.combination(4) {|combination| fail 'Cannot happen' }
*
* Returns a new \Enumerator if no block given:
+ *
* a = [0, 1, 2]
* a.combination(2) # => #<Enumerator: [0, 1, 2]:combination(2)>
+ *
*/
static VALUE
@@ -6843,25 +7283,25 @@ rb_ary_combination(VALUE ary, VALUE num)
RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_combination_size);
len = RARRAY_LEN(ary);
if (n < 0 || len < n) {
- /* yield nothing */
+ /* yield nothing */
}
else if (n == 0) {
- rb_yield(rb_ary_new2(0));
+ rb_yield(rb_ary_new2(0));
}
else if (n == 1) {
- for (i = 0; i < RARRAY_LEN(ary); i++) {
- rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
- }
+ for (i = 0; i < RARRAY_LEN(ary); i++) {
+ rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
+ }
}
else {
- VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
- volatile VALUE t0;
- long *stack = ALLOCV_N(long, t0, n+1);
+ VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
+ volatile VALUE t0;
+ long *stack = ALLOCV_N(long, t0, n+1);
- RBASIC_CLEAR_CLASS(ary0);
- combinate0(len, n, stack, ary0);
- ALLOCV_END(t0);
- RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
+ RBASIC_CLEAR_CLASS(ary0);
+ combinate0(len, n, stack, ary0);
+ ALLOCV_END(t0);
+ RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
}
return ary;
}
@@ -6885,19 +7325,19 @@ rpermute0(const long n, const long r, long *const p, const VALUE values)
p[index] = i;
for (;;) {
- if (++index < r-1) {
- p[index] = i = 0;
- continue;
- }
- for (i = 0; i < n; ++i) {
- p[index] = i;
- if (!yield_indexed_values(values, r, p)) {
- rb_raise(rb_eRuntimeError, "repeated permute reentered");
- }
- }
- do {
- if (index <= 0) return;
- } while ((i = ++p[--index]) >= n);
+ if (++index < r-1) {
+ p[index] = i = 0;
+ continue;
+ }
+ for (i = 0; i < n; ++i) {
+ p[index] = i;
+ if (!yield_indexed_values(values, r, p)) {
+ rb_raise(rb_eRuntimeError, "repeated permute reentered");
+ }
+ }
+ do {
+ if (index <= 0) return;
+ } while ((i = ++p[--index]) >= n);
}
}
@@ -6908,10 +7348,10 @@ rb_ary_repeated_permutation_size(VALUE ary, VALUE args, VALUE eobj)
long k = NUM2LONG(RARRAY_AREF(args, 0));
if (k < 0) {
- return LONG2FIX(0);
+ return LONG2FIX(0);
}
if (n <= 0) {
- return LONG2FIX(!k);
+ return LONG2FIX(!k);
}
return rb_int_positive_pow(n, (unsigned long)k);
}
@@ -6930,16 +7370,22 @@ rb_ary_repeated_permutation_size(VALUE ary, VALUE args, VALUE eobj)
* The number of permutations is <tt>self.size**n</tt>.
*
* +n+ = 1:
+ *
* a = [0, 1, 2]
* a.repeated_permutation(1) {|permutation| p permutation }
+ *
* Output:
+ *
* [0]
* [1]
* [2]
*
* +n+ = 2:
+ *
* a.repeated_permutation(2) {|permutation| p permutation }
+ *
* Output:
+ *
* [0, 0]
* [0, 1]
* [0, 2]
@@ -6953,14 +7399,17 @@ rb_ary_repeated_permutation_size(VALUE ary, VALUE args, VALUE eobj)
* If +n+ is zero, calls the block once with an empty \Array.
*
* If +n+ is negative, does not call the block:
+ *
* a.repeated_permutation(-1) {|permutation| fail 'Cannot happen' }
*
* Returns a new \Enumerator if no block given:
+ *
* a = [0, 1, 2]
* a.repeated_permutation(2) # => #<Enumerator: [0, 1, 2]:permutation(2)>
*
* Using Enumerators, it's convenient to show the permutations and counts
* for some values of +n+:
+ *
* e = a.repeated_permutation(0)
* e.size # => 1
* e.to_a # => [[]]
@@ -6970,6 +7419,7 @@ rb_ary_repeated_permutation_size(VALUE ary, VALUE args, VALUE eobj)
* e = a.repeated_permutation(2)
* e.size # => 9
* e.to_a # => [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
+ *
*/
static VALUE
rb_ary_repeated_permutation(VALUE ary, VALUE num)
@@ -6981,25 +7431,25 @@ rb_ary_repeated_permutation(VALUE ary, VALUE num)
r = NUM2LONG(num); /* Permutation size from argument */
if (r < 0) {
- /* no permutations: yield nothing */
+ /* no permutations: yield nothing */
}
else if (r == 0) { /* exactly one permutation: the zero-length array */
- rb_yield(rb_ary_new2(0));
+ rb_yield(rb_ary_new2(0));
}
else if (r == 1) { /* this is a special, easy case */
- for (i = 0; i < RARRAY_LEN(ary); i++) {
- rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
- }
+ for (i = 0; i < RARRAY_LEN(ary); i++) {
+ rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
+ }
}
else { /* this is the general case */
- volatile VALUE t0;
- long *p = ALLOCV_N(long, t0, r);
- VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
- RBASIC_CLEAR_CLASS(ary0);
+ volatile VALUE t0;
+ long *p = ALLOCV_N(long, t0, r);
+ VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
+ RBASIC_CLEAR_CLASS(ary0);
- rpermute0(n, r, p, ary0); /* compute and yield repeated permutations */
- ALLOCV_END(t0);
- RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
+ rpermute0(n, r, p, ary0); /* compute and yield repeated permutations */
+ ALLOCV_END(t0);
+ RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
}
return ary;
}
@@ -7011,19 +7461,19 @@ rcombinate0(const long n, const long r, long *const p, const long rest, const VA
p[index] = i;
for (;;) {
- if (++index < r-1) {
- p[index] = i;
- continue;
- }
- for (; i < n; ++i) {
- p[index] = i;
- if (!yield_indexed_values(values, r, p)) {
- rb_raise(rb_eRuntimeError, "repeated combination reentered");
- }
- }
- do {
- if (index <= 0) return;
- } while ((i = ++p[--index]) >= n);
+ if (++index < r-1) {
+ p[index] = i;
+ continue;
+ }
+ for (; i < n; ++i) {
+ p[index] = i;
+ if (!yield_indexed_values(values, r, p)) {
+ rb_raise(rb_eRuntimeError, "repeated combination reentered");
+ }
+ }
+ do {
+ if (index <= 0) return;
+ } while ((i = ++p[--index]) >= n);
}
}
@@ -7033,7 +7483,7 @@ rb_ary_repeated_combination_size(VALUE ary, VALUE args, VALUE eobj)
long n = RARRAY_LEN(ary);
long k = NUM2LONG(RARRAY_AREF(args, 0));
if (k == 0) {
- return LONG2FIX(1);
+ return LONG2FIX(1);
}
return binomial_coefficient(k, n + k - 1);
}
@@ -7052,16 +7502,22 @@ rb_ary_repeated_combination_size(VALUE ary, VALUE args, VALUE eobj)
* The number of combinations is <tt>(n+1)(n+2)/2</tt>.
*
* +n+ = 1:
+ *
* a = [0, 1, 2]
* a.repeated_combination(1) {|combination| p combination }
+ *
* Output:
+ *
* [0]
* [1]
* [2]
*
* +n+ = 2:
+ *
* a.repeated_combination(2) {|combination| p combination }
+ *
* Output:
+ *
* [0, 0]
* [0, 1]
* [0, 2]
@@ -7072,14 +7528,17 @@ rb_ary_repeated_combination_size(VALUE ary, VALUE args, VALUE eobj)
* If +n+ is zero, calls the block once with an empty \Array.
*
* If +n+ is negative, does not call the block:
+ *
* a.repeated_combination(-1) {|combination| fail 'Cannot happen' }
*
* Returns a new \Enumerator if no block given:
+ *
* a = [0, 1, 2]
* a.repeated_combination(2) # => #<Enumerator: [0, 1, 2]:combination(2)>
*
* Using Enumerators, it's convenient to show the combinations and counts
* for some values of +n+:
+ *
* e = a.repeated_combination(0)
* e.size # => 1
* e.to_a # => [[]]
@@ -7089,6 +7548,7 @@ rb_ary_repeated_combination_size(VALUE ary, VALUE args, VALUE eobj)
* e = a.repeated_combination(2)
* e.size # => 6
* e.to_a # => [[0, 0], [0, 1], [0, 2], [1, 1], [1, 2], [2, 2]]
+ *
*/
static VALUE
@@ -7100,28 +7560,28 @@ rb_ary_repeated_combination(VALUE ary, VALUE num)
RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_combination_size); /* Return enumerator if no block */
len = RARRAY_LEN(ary);
if (n < 0) {
- /* yield nothing */
+ /* yield nothing */
}
else if (n == 0) {
- rb_yield(rb_ary_new2(0));
+ rb_yield(rb_ary_new2(0));
}
else if (n == 1) {
- for (i = 0; i < RARRAY_LEN(ary); i++) {
- rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
- }
+ for (i = 0; i < RARRAY_LEN(ary); i++) {
+ rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
+ }
}
else if (len == 0) {
- /* yield nothing */
+ /* yield nothing */
}
else {
- volatile VALUE t0;
- long *p = ALLOCV_N(long, t0, n);
- VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
- RBASIC_CLEAR_CLASS(ary0);
+ volatile VALUE t0;
+ long *p = ALLOCV_N(long, t0, n);
+ VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
+ RBASIC_CLEAR_CLASS(ary0);
- rcombinate0(len, n, p, n, ary0); /* compute and yield repeated combinations */
- ALLOCV_END(t0);
- RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
+ rcombinate0(len, n, p, n, ary0); /* compute and yield repeated combinations */
+ ALLOCV_END(t0);
+ RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
}
return ary;
}
@@ -7132,12 +7592,14 @@ rb_ary_repeated_combination(VALUE ary, VALUE num)
* array.product(*other_arrays) {|combination| ... } -> self
*
* Computes and returns or yields all combinations of elements from all the Arrays,
- * including both +self+ and +other_arrays+.
+ * including both +self+ and +other_arrays+:
+ *
* - The number of combinations is the product of the sizes of all the arrays,
* including both +self+ and +other_arrays+.
* - The order of the returned combinations is indeterminate.
*
* When no block is given, returns the combinations as an \Array of Arrays:
+ *
* a = [0, 1, 2]
* a1 = [3, 4]
* a2 = [5, 6]
@@ -7152,11 +7614,15 @@ rb_ary_repeated_combination(VALUE ary, VALUE num)
*
* If no argument is given, returns an \Array of 1-element Arrays,
* each containing an element of +self+:
+ *
* a.product # => [[0], [1], [2]]
*
* When a block is given, yields each combination as an \Array; returns +self+:
+ *
* a.product(a1) {|combination| p combination }
+ *
* Output:
+ *
* [0, 3]
* [0, 4]
* [1, 3]
@@ -7165,21 +7631,26 @@ rb_ary_repeated_combination(VALUE ary, VALUE num)
* [2, 4]
*
* If any argument is an empty \Array, does not call the block:
+ *
* a.product(a1, a2, []) {|combination| fail 'Cannot happen' }
*
* If no argument is given, yields each element of +self+ as a 1-element \Array:
+ *
* a.product {|combination| p combination }
+ *
* Output:
+ *
* [0]
* [1]
* [2]
+ *
*/
static VALUE
rb_ary_product(int argc, VALUE *argv, VALUE ary)
{
int n = argc+1; /* How many arrays we're operating on */
- volatile VALUE t0 = tmpary(n);
+ volatile VALUE t0 = rb_ary_hidden_new(n);
volatile VALUE t1 = Qundef;
VALUE *arrays = RARRAY_PTR(t0); /* The arrays we're computing the product of */
int *counters = ALLOCV_N(int, t1, n); /* The current position in each one */
@@ -7200,64 +7671,64 @@ rb_ary_product(int argc, VALUE *argv, VALUE ary)
/* Otherwise, allocate and fill in an array of results */
if (rb_block_given_p()) {
- /* Make defensive copies of arrays; exit if any is empty */
- for (i = 0; i < n; i++) {
- if (RARRAY_LEN(arrays[i]) == 0) goto done;
- arrays[i] = ary_make_shared_copy(arrays[i]);
- }
+ /* Make defensive copies of arrays; exit if any is empty */
+ for (i = 0; i < n; i++) {
+ if (RARRAY_LEN(arrays[i]) == 0) goto done;
+ arrays[i] = ary_make_shared_copy(arrays[i]);
+ }
}
else {
- /* Compute the length of the result array; return [] if any is empty */
- for (i = 0; i < n; i++) {
- long k = RARRAY_LEN(arrays[i]);
- if (k == 0) {
- result = rb_ary_new2(0);
- goto done;
- }
+ /* Compute the length of the result array; return [] if any is empty */
+ for (i = 0; i < n; i++) {
+ long k = RARRAY_LEN(arrays[i]);
+ if (k == 0) {
+ result = rb_ary_new2(0);
+ goto done;
+ }
if (MUL_OVERFLOW_LONG_P(resultlen, k))
- rb_raise(rb_eRangeError, "too big to product");
- resultlen *= k;
- }
- result = rb_ary_new2(resultlen);
+ rb_raise(rb_eRangeError, "too big to product");
+ resultlen *= k;
+ }
+ result = rb_ary_new2(resultlen);
}
for (;;) {
- int m;
- /* fill in one subarray */
- VALUE subarray = rb_ary_new2(n);
- for (j = 0; j < n; j++) {
- rb_ary_push(subarray, rb_ary_entry(arrays[j], counters[j]));
- }
-
- /* put it on the result array */
- if (NIL_P(result)) {
- FL_SET(t0, FL_USER5);
- rb_yield(subarray);
- if (! FL_TEST(t0, FL_USER5)) {
- rb_raise(rb_eRuntimeError, "product reentered");
- }
- else {
- FL_UNSET(t0, FL_USER5);
- }
- }
- else {
- rb_ary_push(result, subarray);
- }
-
- /*
- * Increment the last counter. If it overflows, reset to 0
- * and increment the one before it.
- */
- m = n-1;
- counters[m]++;
- while (counters[m] == RARRAY_LEN(arrays[m])) {
- counters[m] = 0;
- /* If the first counter overflows, we are done */
- if (--m < 0) goto done;
- counters[m]++;
- }
+ int m;
+ /* fill in one subarray */
+ VALUE subarray = rb_ary_new2(n);
+ for (j = 0; j < n; j++) {
+ rb_ary_push(subarray, rb_ary_entry(arrays[j], counters[j]));
+ }
+
+ /* put it on the result array */
+ if (NIL_P(result)) {
+ FL_SET(t0, RARRAY_SHARED_ROOT_FLAG);
+ rb_yield(subarray);
+ if (!FL_TEST(t0, RARRAY_SHARED_ROOT_FLAG)) {
+ rb_raise(rb_eRuntimeError, "product reentered");
+ }
+ else {
+ FL_UNSET(t0, RARRAY_SHARED_ROOT_FLAG);
+ }
+ }
+ else {
+ rb_ary_push(result, subarray);
+ }
+
+ /*
+ * Increment the last counter. If it overflows, reset to 0
+ * and increment the one before it.
+ */
+ m = n-1;
+ counters[m]++;
+ while (counters[m] == RARRAY_LEN(arrays[m])) {
+ counters[m] = 0;
+ /* If the first counter overflows, we are done */
+ if (--m < 0) goto done;
+ counters[m]++;
+ }
}
+
done:
- tmpary_discard(t0);
ALLOCV_END(t1);
return NIL_P(result) ? ary : result;
@@ -7272,11 +7743,13 @@ done:
* does not modify +self+.
*
* Examples:
+ *
* a = [0, 1, 2, 3, 4, 5]
* a.take(1) # => [0]
* a.take(2) # => [0, 1]
* a.take(50) # => [0, 1, 2, 3, 4, 5]
* a # => [0, 1, 2, 3, 4, 5]
+ *
*/
static VALUE
@@ -7284,7 +7757,7 @@ rb_ary_take(VALUE obj, VALUE n)
{
long len = NUM2LONG(n);
if (len < 0) {
- rb_raise(rb_eArgError, "attempt to take negative size");
+ rb_raise(rb_eArgError, "attempt to take negative size");
}
return rb_ary_subseq(obj, 0, len);
}
@@ -7299,14 +7772,17 @@ rb_ary_take(VALUE obj, VALUE n)
*
* With a block given, calls the block with each successive element of +self+;
* stops if the block returns +false+ or +nil+;
- * returns a new Array containing those elements for which the block returned a truthy value:
+ * returns a new \Array containing those elements for which the block returned a truthy value:
+ *
* a = [0, 1, 2, 3, 4, 5]
* a.take_while {|element| element < 3 } # => [0, 1, 2]
* a.take_while {|element| true } # => [0, 1, 2, 3, 4, 5]
* a # => [0, 1, 2, 3, 4, 5]
*
* With no block given, returns a new \Enumerator:
+ *
* [0, 1].take_while # => #<Enumerator: [0, 1]:take_while>
+ *
*/
static VALUE
@@ -7316,7 +7792,7 @@ rb_ary_take_while(VALUE ary)
RETURN_ENUMERATOR(ary, 0, 0);
for (i = 0; i < RARRAY_LEN(ary); i++) {
- if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
+ if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
}
return rb_ary_take(ary, LONG2FIX(i));
}
@@ -7330,10 +7806,12 @@ rb_ary_take_while(VALUE ary)
* does not modify +self+.
*
* Examples:
+ *
* a = [0, 1, 2, 3, 4, 5]
* a.drop(0) # => [0, 1, 2, 3, 4, 5]
* a.drop(1) # => [1, 2, 3, 4, 5]
* a.drop(2) # => [2, 3, 4, 5]
+ *
*/
static VALUE
@@ -7342,7 +7820,7 @@ rb_ary_drop(VALUE ary, VALUE n)
VALUE result;
long pos = NUM2LONG(n);
if (pos < 0) {
- rb_raise(rb_eArgError, "attempt to drop negative size");
+ rb_raise(rb_eArgError, "attempt to drop negative size");
}
result = rb_ary_subseq(ary, pos, RARRAY_LEN(ary));
@@ -7360,12 +7838,15 @@ rb_ary_drop(VALUE ary, VALUE n)
*
* With a block given, calls the block with each successive element of +self+;
* stops if the block returns +false+ or +nil+;
- * returns a new Array _omitting_ those elements for which the block returned a truthy value:
+ * returns a new \Array _omitting_ those elements for which the block returned a truthy value:
+ *
* a = [0, 1, 2, 3, 4, 5]
* a.drop_while {|element| element < 3 } # => [3, 4, 5]
*
* With no block given, returns a new \Enumerator:
+ *
* [0, 1].drop_while # => # => #<Enumerator: [0, 1]:drop_while>
+ *
*/
static VALUE
@@ -7375,7 +7856,7 @@ rb_ary_drop_while(VALUE ary)
RETURN_ENUMERATOR(ary, 0, 0);
for (i = 0; i < RARRAY_LEN(ary); i++) {
- if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
+ if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
}
return rb_ary_drop(ary, LONG2FIX(i));
}
@@ -7390,17 +7871,20 @@ rb_ary_drop_while(VALUE ary)
*
* With no block given and no argument, returns +true+ if +self+ has any truthy element,
* +false+ otherwise:
+ *
* [nil, 0, false].any? # => true
* [nil, false].any? # => false
* [].any? # => false
*
* With a block given and no argument, calls the block with each element in +self+;
* returns +true+ if the block returns any truthy value, +false+ otherwise:
+ *
* [0, 1, 2].any? {|element| element > 1 } # => true
* [0, 1, 2].any? {|element| element > 2 } # => false
*
* If argument +obj+ is given, returns +true+ if +obj+.<tt>===</tt> any element,
* +false+ otherwise:
+ *
* ['food', 'drink'].any?(/foo/) # => true
* ['food', 'drink'].any?(/bar/) # => false
* [].any?(/foo/) # => false
@@ -7421,9 +7905,9 @@ rb_ary_any_p(int argc, VALUE *argv, VALUE ary)
if (rb_block_given_p()) {
rb_warn("given block not used");
}
- for (i = 0; i < RARRAY_LEN(ary); ++i) {
- if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qtrue;
- }
+ for (i = 0; i < RARRAY_LEN(ary); ++i) {
+ if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qtrue;
+ }
}
else if (!rb_block_given_p()) {
for (i = 0; i < len; ++i) {
@@ -7431,9 +7915,9 @@ rb_ary_any_p(int argc, VALUE *argv, VALUE ary)
}
}
else {
- for (i = 0; i < RARRAY_LEN(ary); ++i) {
- if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qtrue;
- }
+ for (i = 0; i < RARRAY_LEN(ary); ++i) {
+ if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qtrue;
+ }
}
return Qfalse;
}
@@ -7448,16 +7932,19 @@ rb_ary_any_p(int argc, VALUE *argv, VALUE ary)
*
* With no block given and no argument, returns +true+ if +self+ contains only truthy elements,
* +false+ otherwise:
+ *
* [0, 1, :foo].all? # => true
* [0, nil, 2].all? # => false
* [].all? # => true
*
* With a block given and no argument, calls the block with each element in +self+;
* returns +true+ if the block returns only truthy values, +false+ otherwise:
+ *
* [0, 1, 2].all? { |element| element < 3 } # => true
* [0, 1, 2].all? { |element| element < 2 } # => false
*
* If argument +obj+ is given, returns +true+ if <tt>obj.===</tt> every element, +false+ otherwise:
+ *
* ['food', 'fool', 'foot'].all?(/foo/) # => true
* ['food', 'drink'].all?(/bar/) # => false
* [].all?(/foo/) # => true
@@ -7505,16 +7992,19 @@ rb_ary_all_p(int argc, VALUE *argv, VALUE ary)
*
* With no block given and no argument, returns +true+ if +self+ has no truthy elements,
* +false+ otherwise:
+ *
* [nil, false].none? # => true
* [nil, 0, false].none? # => false
* [].none? # => true
*
* With a block given and no argument, calls the block with each element in +self+;
* returns +true+ if the block returns no truthy value, +false+ otherwise:
+ *
* [0, 1, 2].none? {|element| element > 3 } # => true
* [0, 1, 2].none? {|element| element > 1 } # => false
*
* If argument +obj+ is given, returns +true+ if <tt>obj.===</tt> no element, +false+ otherwise:
+ *
* ['food', 'drink'].none?(/bar/) # => true
* ['food', 'drink'].none?(/foo/) # => false
* [].none?(/foo/) # => true
@@ -7562,6 +8052,7 @@ rb_ary_none_p(int argc, VALUE *argv, VALUE ary)
*
* With no block given and no argument, returns +true+ if +self+ has exactly one truthy element,
* +false+ otherwise:
+ *
* [nil, 0].one? # => true
* [0, 0].one? # => false
* [nil, nil].one? # => false
@@ -7569,12 +8060,14 @@ rb_ary_none_p(int argc, VALUE *argv, VALUE ary)
*
* With a block given and no argument, calls the block with each element in +self+;
* returns +true+ if the block a truthy value for exactly one element, +false+ otherwise:
+ *
* [0, 1, 2].one? {|element| element > 0 } # => false
* [0, 1, 2].one? {|element| element > 1 } # => true
* [0, 1, 2].one? {|element| element > 2 } # => false
*
* If argument +obj+ is given, returns +true+ if <tt>obj.===</tt> exactly one element,
* +false+ otherwise:
+ *
* [0, 1, 2].one?(0) # => true
* [0, 0, 1].one?(0) # => false
* [1, 1, 2].one?(0) # => false
@@ -7633,11 +8126,13 @@ rb_ary_one_p(int argc, VALUE *argv, VALUE ary)
* See {Dig Methods}[rdoc-ref:dig_methods.rdoc].
*
* Examples:
+ *
* a = [:foo, [:bar, :baz, [:bat, :bam]]]
* a.dig(1) # => [:bar, :baz, [:bat, :bam]]
* a.dig(1, 2) # => [:bat, :bam]
* a.dig(1, 2, 0) # => :bat
* a.dig(1, 2, 3) # => nil
+ *
*/
static VALUE
@@ -7655,7 +8150,7 @@ finish_exact_sum(long n, VALUE r, VALUE v, int z)
{
if (n != 0)
v = rb_fix_plus(LONG2FIX(n), v);
- if (r != Qundef) {
+ if (!UNDEF_P(r)) {
v = rb_rational_plus(r, v);
}
else if (!n && z) {
@@ -7670,31 +8165,38 @@ finish_exact_sum(long n, VALUE r, VALUE v, int z)
* array.sum(init = 0) {|element| ... } -> object
*
* When no block is given, returns the object equivalent to:
+ *
* sum = init
* array.each {|element| sum += element }
* sum
+ *
* For example, <tt>[e1, e2, e3].sum</tt> returns <tt>init + e1 + e2 + e3</tt>.
*
* Examples:
+ *
* a = [0, 1, 2, 3]
* a.sum # => 6
* a.sum(100) # => 106
*
* The elements need not be numeric, but must be <tt>+</tt>-compatible
* with each other and with +init+:
+ *
* a = ['abc', 'def', 'ghi']
* a.sum('jkl') # => "jklabcdefghi"
*
* When a block is given, it is called with each element
* and the block's return value (instead of the element itself) is used as the addend:
+ *
* a = ['zero', 1, :two]
* s = a.sum('Coerced and concatenated: ') {|element| element.to_s }
* s # => "Coerced and concatenated: zero1two"
*
* Notes:
+ *
* - Array#join and Array#flatten may be faster than Array#sum
* for an \Array of Strings or an \Array of Arrays.
* - Array#sum method may not respect method redefinition of "+" methods such as Integer#+.
+ *
*/
static VALUE
@@ -7727,7 +8229,7 @@ rb_ary_sum(int argc, VALUE *argv, VALUE ary)
else if (RB_BIGNUM_TYPE_P(e))
v = rb_big_plus(e, v);
else if (RB_TYPE_P(e, T_RATIONAL)) {
- if (r == Qundef)
+ if (UNDEF_P(r))
r = e;
else
r = rb_rational_plus(r, e);
@@ -7814,82 +8316,128 @@ rb_ary_deconstruct(VALUE ary)
}
/*
- * An \Array is an ordered, integer-indexed collection of objects,
- * called _elements_. Any object may be an \Array element.
+ * An \Array is an ordered, integer-indexed collection of objects, called _elements_.
+ * Any object (even another array) may be an array element,
+ * and an array can contain objects of different types.
*
* == \Array Indexes
*
* \Array indexing starts at 0, as in C or Java.
*
* A positive index is an offset from the first element:
+ *
* - Index 0 indicates the first element.
* - Index 1 indicates the second element.
* - ...
*
* A negative index is an offset, backwards, from the end of the array:
+ *
* - Index -1 indicates the last element.
* - Index -2 indicates the next-to-last element.
* - ...
*
- * A non-negative index is <i>in range</i> if it is smaller than
+ * A non-negative index is <i>in range</i> if and only if it is smaller than
* the size of the array. For a 3-element array:
+ *
* - Indexes 0 through 2 are in range.
* - Index 3 is out of range.
*
- * A negative index is <i>in range</i> if its absolute value is
+ * A negative index is <i>in range</i> if and only if its absolute value is
* not larger than the size of the array. For a 3-element array:
+ *
* - Indexes -1 through -3 are in range.
* - Index -4 is out of range.
*
- * == Creating Arrays
- *
- * You can create an \Array object explicitly with:
- *
- * - An {array literal}[doc/syntax/literals_rdoc.html#label-Array+Literals].
- *
- * You can convert certain objects to Arrays with:
- *
- * - \Method {Array}[Kernel.html#method-i-Array].
- *
- * An \Array can contain different types of objects. For
- * example, the array below contains an Integer, a String and a Float:
+ * Although the effective index into an array is always an integer,
+ * some methods (both within and outside of class \Array)
+ * accept one or more non-integer arguments that are
+ * {integer-convertible objects}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
*
- * ary = [1, "two", 3.0] #=> [1, "two", 3.0]
*
- * An array can also be created by calling Array.new with zero, one
- * (the initial size of the Array) or two arguments (the initial size and a
- * default object).
- *
- * ary = Array.new #=> []
- * Array.new(3) #=> [nil, nil, nil]
- * Array.new(3, true) #=> [true, true, true]
- *
- * Note that the second argument populates the array with references to the
- * same object. Therefore, it is only recommended in cases when you need to
- * instantiate arrays with natively immutable objects such as Symbols,
- * numbers, true or false.
- *
- * To create an array with separate objects a block can be passed instead.
- * This method is safe to use with mutable objects such as hashes, strings or
- * other arrays:
- *
- * Array.new(4) {Hash.new} #=> [{}, {}, {}, {}]
- * Array.new(4) {|i| i.to_s } #=> ["0", "1", "2", "3"]
- *
- * This is also a quick way to build up multi-dimensional arrays:
- *
- * empty_table = Array.new(3) {Array.new(3)}
- * #=> [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]
+ * == Creating Arrays
*
- * An array can also be created by using the Array() method, provided by
- * Kernel, which tries to call #to_ary, then #to_a on its argument.
+ * You can create an \Array object explicitly with:
*
- * Array({:a => "a", :b => "b"}) #=> [[:a, "a"], [:b, "b"]]
+ * - An {array literal}[rdoc-ref:literals.rdoc@Array+Literals]:
+ *
+ * [1, 'one', :one, [2, 'two', :two]]
+ *
+ * - A {%w or %W: string-array Literal}[rdoc-ref:literals.rdoc@25w+and+-25W-3A+String-Array+Literals]:
+ *
+ * %w[foo bar baz] # => ["foo", "bar", "baz"]
+ * %w[1 % *] # => ["1", "%", "*"]
+ *
+ * - A {%i pr %I: symbol-array Literal}[rdoc-ref:literals.rdoc@25i+and+-25I-3A+Symbol-Array+Literals]:
+ *
+ * %i[foo bar baz] # => [:foo, :bar, :baz]
+ * %i[1 % *] # => [:"1", :%, :*]
+ *
+ * - \Method Kernel#Array:
+ *
+ * Array(["a", "b"]) # => ["a", "b"]
+ * Array(1..5) # => [1, 2, 3, 4, 5]
+ * Array(key: :value) # => [[:key, :value]]
+ * Array(nil) # => []
+ * Array(1) # => [1]
+ * Array({:a => "a", :b => "b"}) # => [[:a, "a"], [:b, "b"]]
+ *
+ * - \Method Array.new:
+ *
+ * Array.new # => []
+ * Array.new(3) # => [nil, nil, nil]
+ * Array.new(4) {Hash.new} # => [{}, {}, {}, {}]
+ * Array.new(3, true) # => [true, true, true]
+ *
+ * Note that the last example above populates the array
+ * with references to the same object.
+ * This is recommended only in cases where that object is a natively immutable object
+ * such as a symbol, a numeric, +nil+, +true+, or +false+.
+ *
+ * Another way to create an array with various objects, using a block;
+ * this usage is safe for mutable objects such as hashes, strings or
+ * other arrays:
+ *
+ * Array.new(4) {|i| i.to_s } # => ["0", "1", "2", "3"]
+ *
+ * Here is a way to create a multi-dimensional array:
+ *
+ * Array.new(3) {Array.new(3)}
+ * # => [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]
+ *
+ * A number of Ruby methods, both in the core and in the standard library,
+ * provide instance method +to_a+, which converts an object to an array.
+ *
+ * - ARGF#to_a
+ * - Array#to_a
+ * - Enumerable#to_a
+ * - Hash#to_a
+ * - MatchData#to_a
+ * - NilClass#to_a
+ * - OptionParser#to_a
+ * - Range#to_a
+ * - Set#to_a
+ * - Struct#to_a
+ * - Time#to_a
+ * - Benchmark::Tms#to_a
+ * - CSV::Table#to_a
+ * - Enumerator::Lazy#to_a
+ * - Gem::List#to_a
+ * - Gem::NameTuple#to_a
+ * - Gem::Platform#to_a
+ * - Gem::RequestSet::Lockfile::Tokenizer#to_a
+ * - Gem::SourceList#to_a
+ * - OpenSSL::X509::Extension#to_a
+ * - OpenSSL::X509::Name#to_a
+ * - Racc::ISet#to_a
+ * - Rinda::RingFinger#to_a
+ * - Ripper::Lexer::Elem#to_a
+ * - RubyVM::InstructionSequence#to_a
+ * - YAML::DBM#to_a
*
* == Example Usage
*
* In addition to the methods it mixes in through the Enumerable module, the
- * Array class has proprietary methods for accessing, searching and otherwise
+ * \Array class has proprietary methods for accessing, searching and otherwise
* manipulating arrays.
*
* Some of the more common ones are illustrated below.
@@ -7937,7 +8485,7 @@ rb_ary_deconstruct(VALUE ary)
*
* arr.drop(3) #=> [4, 5, 6]
*
- * == Obtaining Information about an Array
+ * == Obtaining Information about an \Array
*
* Arrays keep track of their own length at all times. To query an array
* about the number of elements it contains, use #length, #count or #size.
@@ -7975,7 +8523,7 @@ rb_ary_deconstruct(VALUE ary)
* arr.insert(3, 'orange', 'pear', 'grapefruit')
* #=> [0, 1, 2, "orange", "pear", "grapefruit", "apple", 3, 4, 5, 6]
*
- * == Removing Items from an Array
+ * == Removing Items from an \Array
*
* The method #pop removes the last element in an array and returns it:
*
@@ -8017,9 +8565,9 @@ rb_ary_deconstruct(VALUE ary)
*
* == Iterating over Arrays
*
- * Like all classes that include the Enumerable module, Array has an each
+ * Like all classes that include the Enumerable module, \Array has an each
* method, which defines what elements should be iterated over and how. In
- * case of Array's #each, all elements in the Array instance are yielded to
+ * case of Array's #each, all elements in the \Array instance are yielded to
* the supplied block in sequence.
*
* Note that this operation leaves the array unchanged.
@@ -8045,7 +8593,8 @@ rb_ary_deconstruct(VALUE ary)
* arr.map! {|a| a**2} #=> [1, 4, 9, 16, 25]
* arr #=> [1, 4, 9, 16, 25]
*
- * == Selecting Items from an Array
+ *
+ * == Selecting Items from an \Array
*
* Elements can be selected from an array according to criteria defined in a
* block. The selection can happen in a destructive or a non-destructive
@@ -8080,181 +8629,184 @@ rb_ary_deconstruct(VALUE ary)
*
* First, what's elsewhere. \Class \Array:
*
- * - Inherits from {class Object}[Object.html#class-Object-label-What-27s+Here].
- * - Includes {module Enumerable}[Enumerable.html#module-Enumerable-label-What-27s+Here],
+ * - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
+ * - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
* which provides dozens of additional methods.
*
* Here, class \Array provides methods that are useful for:
*
- * - {Creating an Array}[#class-Array-label-Methods+for+Creating+an+Array]
- * - {Querying}[#class-Array-label-Methods+for+Querying]
- * - {Comparing}[#class-Array-label-Methods+for+Comparing]
- * - {Fetching}[#class-Array-label-Methods+for+Fetching]
- * - {Assigning}[#class-Array-label-Methods+for+Assigning]
- * - {Deleting}[#class-Array-label-Methods+for+Deleting]
- * - {Combining}[#class-Array-label-Methods+for+Combining]
- * - {Iterating}[#class-Array-label-Methods+for+Iterating]
- * - {Converting}[#class-Array-label-Methods+for+Converting]
- * - {And more....}[#class-Array-label-Other+Methods]
+ * - {Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array]
+ * - {Querying}[rdoc-ref:Array@Methods+for+Querying]
+ * - {Comparing}[rdoc-ref:Array@Methods+for+Comparing]
+ * - {Fetching}[rdoc-ref:Array@Methods+for+Fetching]
+ * - {Assigning}[rdoc-ref:Array@Methods+for+Assigning]
+ * - {Deleting}[rdoc-ref:Array@Methods+for+Deleting]
+ * - {Combining}[rdoc-ref:Array@Methods+for+Combining]
+ * - {Iterating}[rdoc-ref:Array@Methods+for+Iterating]
+ * - {Converting}[rdoc-ref:Array@Methods+for+Converting]
+ * - {And more....}[rdoc-ref:Array@Other+Methods]
*
- * === Methods for Creating an Array
+ * === Methods for Creating an \Array
*
- * ::[]:: Returns a new array populated with given objects.
- * ::new:: Returns a new array.
- * ::try_convert:: Returns a new array created from a given object.
+ * - ::[]: Returns a new array populated with given objects.
+ * - ::new: Returns a new array.
+ * - ::try_convert: Returns a new array created from a given object.
*
* === Methods for Querying
*
- * #length, #size:: Returns the count of elements.
- * #include?:: Returns whether any element <tt>==</tt> a given object.
- * #empty?:: Returns whether there are no elements.
- * #all?:: Returns whether all elements meet a given criterion.
- * #any?:: Returns whether any element meets a given criterion.
- * #none?:: Returns whether no element <tt>==</tt> a given object.
- * #one?:: Returns whether exactly one element <tt>==</tt> a given object.
- * #count:: Returns the count of elements that meet a given criterion.
- * #find_index, #index:: Returns the index of the first element that meets a given criterion.
- * #rindex:: Returns the index of the last element that meets a given criterion.
- * #hash:: Returns the integer hash code.
+ * - #length, #size: Returns the count of elements.
+ * - #include?: Returns whether any element <tt>==</tt> a given object.
+ * - #empty?: Returns whether there are no elements.
+ * - #all?: Returns whether all elements meet a given criterion.
+ * - #any?: Returns whether any element meets a given criterion.
+ * - #none?: Returns whether no element <tt>==</tt> a given object.
+ * - #one?: Returns whether exactly one element <tt>==</tt> a given object.
+ * - #count: Returns the count of elements that meet a given criterion.
+ * - #find_index, #index: Returns the index of the first element that meets a given criterion.
+ * - #rindex: Returns the index of the last element that meets a given criterion.
+ * - #hash: Returns the integer hash code.
*
* === Methods for Comparing
- * {#<=>}[#method-i-3C-3D-3E]:: Returns -1, 0, or 1
- * as +self+ is less than, equal to, or greater than a given object.
- * {#==}[#method-i-3D-3D]:: Returns whether each element in +self+ is <tt>==</tt> to the
- * corresponding element in a given object.
- * #eql?:: Returns whether each element in +self+ is <tt>eql?</tt> to the corresponding
- * element in a given object.
+ *
+ * - #<=>: Returns -1, 0, or 1 * as +self+ is less than, equal to, or
+ * greater than a given object.
+ * - #==: Returns whether each element in +self+ is <tt>==</tt> to the corresponding element
+ * in a given object.
+ * - #eql?: Returns whether each element in +self+ is <tt>eql?</tt> to the corresponding
+ * element in a given object.
* === Methods for Fetching
*
* These methods do not modify +self+.
*
- * #[]:: Returns one or more elements.
- * #fetch:: Returns the element at a given offset.
- * #first:: Returns one or more leading elements.
- * #last:: Returns one or more trailing elements.
- * #max:: Returns one or more maximum-valued elements,
- * as determined by <tt><=></tt> or a given block.
- * #max:: Returns one or more minimum-valued elements,
- * as determined by <tt><=></tt> or a given block.
- * #minmax:: Returns the minimum-valued and maximum-valued elements,
- * as determined by <tt><=></tt> or a given block.
- * #assoc:: Returns the first element that is an array
- * whose first element <tt>==</tt> a given object.
- * #rassoc:: Returns the first element that is an array
- * whose second element <tt>==</tt> a given object.
- * #at:: Returns the element at a given offset.
- * #values_at:: Returns the elements at given offsets.
- * #dig:: Returns the object in nested objects
- * that is specified by a given index and additional arguments.
- * #drop:: Returns trailing elements as determined by a given index.
- * #take:: Returns leading elements as determined by a given index.
- * #drop_while:: Returns trailing elements as determined by a given block.
- * #take_while:: Returns leading elements as determined by a given block.
- * #slice:: Returns consecutive elements as determined by a given argument.
- * #sort:: Returns all elements in an order determined by <tt><=></tt> or a given block.
- * #reverse:: Returns all elements in reverse order.
- * #compact:: Returns an array containing all non-+nil+ elements.
- * #select, #filter:: Returns an array containing elements selected by a given block.
- * #uniq:: Returns an array containing non-duplicate elements.
- * #rotate:: Returns all elements with some rotated from one end to the other.
- * #bsearch:: Returns an element selected via a binary search
- * as determined by a given block.
- * #bsearch_index:: Returns the index of an element selected via a binary search
- * as determined by a given block.
- * #sample:: Returns one or more random elements.
- * #shuffle:: Returns elements in a random order.
+ * - #[]: Returns one or more elements.
+ * - #fetch: Returns the element at a given offset.
+ * - #first: Returns one or more leading elements.
+ * - #last: Returns one or more trailing elements.
+ * - #max: Returns one or more maximum-valued elements,
+ * as determined by <tt><=></tt> or a given block.
+ * - #min: Returns one or more minimum-valued elements,
+ * as determined by <tt><=></tt> or a given block.
+ * - #minmax: Returns the minimum-valued and maximum-valued elements,
+ * as determined by <tt><=></tt> or a given block.
+ * - #assoc: Returns the first element that is an array
+ * whose first element <tt>==</tt> a given object.
+ * - #rassoc: Returns the first element that is an array
+ * whose second element <tt>==</tt> a given object.
+ * - #at: Returns the element at a given offset.
+ * - #values_at: Returns the elements at given offsets.
+ * - #dig: Returns the object in nested objects
+ * that is specified by a given index and additional arguments.
+ * - #drop: Returns trailing elements as determined by a given index.
+ * - #take: Returns leading elements as determined by a given index.
+ * - #drop_while: Returns trailing elements as determined by a given block.
+ * - #take_while: Returns leading elements as determined by a given block.
+ * - #slice: Returns consecutive elements as determined by a given argument.
+ * - #sort: Returns all elements in an order determined by <tt><=></tt> or a given block.
+ * - #reverse: Returns all elements in reverse order.
+ * - #compact: Returns an array containing all non-+nil+ elements.
+ * - #select, #filter: Returns an array containing elements selected by a given block.
+ * - #uniq: Returns an array containing non-duplicate elements.
+ * - #rotate: Returns all elements with some rotated from one end to the other.
+ * - #bsearch: Returns an element selected via a binary search
+ * as determined by a given block.
+ * - #bsearch_index: Returns the index of an element selected via a binary search
+ * as determined by a given block.
+ * - #sample: Returns one or more random elements.
+ * - #shuffle: Returns elements in a random order.
*
* === Methods for Assigning
*
* These methods add, replace, or reorder elements in +self+.
*
- * #[]=:: Assigns specified elements with a given object.
- * #push, #append, #<<:: Appends trailing elements.
- * #unshift, #prepend:: Prepends leading elements.
- * #insert:: Inserts given objects at a given offset; does not replace elements.
- * #concat:: Appends all elements from given arrays.
- * #fill:: Replaces specified elements with specified objects.
- * #replace:: Replaces the content of +self+ with the content of a given array.
- * #reverse!:: Replaces +self+ with its elements reversed.
- * #rotate!:: Replaces +self+ with its elements rotated.
- * #shuffle!:: Replaces +self+ with its elements in random order.
- * #sort!:: Replaces +self+ with its elements sorted,
- * as determined by <tt><=></tt> or a given block.
- * #sort_by!:: Replaces +self+ with its elements sorted, as determined by a given block.
+ * - #[]=: Assigns specified elements with a given object.
+ * - #push, #append, #<<: Appends trailing elements.
+ * - #unshift, #prepend: Prepends leading elements.
+ * - #insert: Inserts given objects at a given offset; does not replace elements.
+ * - #concat: Appends all elements from given arrays.
+ * - #fill: Replaces specified elements with specified objects.
+ * - #replace: Replaces the content of +self+ with the content of a given array.
+ * - #reverse!: Replaces +self+ with its elements reversed.
+ * - #rotate!: Replaces +self+ with its elements rotated.
+ * - #shuffle!: Replaces +self+ with its elements in random order.
+ * - #sort!: Replaces +self+ with its elements sorted,
+ * as determined by <tt><=></tt> or a given block.
+ * - #sort_by!: Replaces +self+ with its elements sorted, as determined by a given block.
*
* === Methods for Deleting
*
* Each of these methods removes elements from +self+:
*
- * #pop:: Removes and returns the last element.
- * #shift:: Removes and returns the first element.
- * #compact!:: Removes all non-+nil+ elements.
- * #delete:: Removes elements equal to a given object.
- * #delete_at:: Removes the element at a given offset.
- * #delete_if:: Removes elements specified by a given block.
- * #keep_if:: Removes elements not specified by a given block.
- * #reject!:: Removes elements specified by a given block.
- * #select!, #filter!:: Removes elements not specified by a given block.
- * #slice!:: Removes and returns a sequence of elements.
- * #uniq!:: Removes duplicates.
+ * - #pop: Removes and returns the last element.
+ * - #shift: Removes and returns the first element.
+ * - #compact!: Removes all +nil+ elements.
+ * - #delete: Removes elements equal to a given object.
+ * - #delete_at: Removes the element at a given offset.
+ * - #delete_if: Removes elements specified by a given block.
+ * - #keep_if: Removes elements not specified by a given block.
+ * - #reject!: Removes elements specified by a given block.
+ * - #select!, #filter!: Removes elements not specified by a given block.
+ * - #slice!: Removes and returns a sequence of elements.
+ * - #uniq!: Removes duplicates.
*
* === Methods for Combining
*
- * {#&}[#method-i-26]:: Returns an array containing elements found both in +self+ and a given array.
- * #intersection:: Returns an array containing elements found both in +self+
- * and in each given array.
- * #+:: Returns an array containing all elements of +self+ followed by all elements of a given array.
- * #-:: Returns an array containiing all elements of +self+ that are not found in a given array.
- * {#|}[#method-i-7C]:: Returns an array containing all elements of +self+ and all elements of a given array,
- * duplicates removed.
- * #union:: Returns an array containing all elements of +self+ and all elements of given arrays,
- * duplicates removed.
- * #difference:: Returns an array containing all elements of +self+ that are not found
- * in any of the given arrays..
- * #product:: Returns or yields all combinations of elements from +self+ and given arrays.
+ * - #&: Returns an array containing elements found both in +self+ and a given array.
+ * - #intersection: Returns an array containing elements found both in +self+
+ * and in each given array.
+ * - #+: Returns an array containing all elements of +self+ followed by all elements of a given array.
+ * - #-: Returns an array containing all elements of +self+ that are not found in a given array.
+ * - #|: Returns an array containing all elements of +self+ and all elements of a given array,
+ * duplicates removed.
+ * - #union: Returns an array containing all elements of +self+ and all elements of given arrays,
+ * duplicates removed.
+ * - #difference: Returns an array containing all elements of +self+ that are not found
+ * in any of the given arrays..
+ * - #product: Returns or yields all combinations of elements from +self+ and given arrays.
*
* === Methods for Iterating
*
- * #each:: Passes each element to a given block.
- * #reverse_each:: Passes each element, in reverse order, to a given block.
- * #each_index:: Passes each element index to a given block.
- * #cycle:: Calls a given block with each element, then does so again,
- * for a specified number of times, or forever.
- * #combination:: Calls a given block with combinations of elements of +self+;
- * a combination does not use the same element more than once.
- * #permutation:: Calls a given block with permutations of elements of +self+;
- * a permutation does not use the same element more than once.
- * #repeated_combination:: Calls a given block with combinations of elements of +self+;
- * a combination may use the same element more than once.
- * #repeated_permutation:: Calls a given block with permutations of elements of +self+;
- * a permutation may use the same element more than once.
+ * - #each: Passes each element to a given block.
+ * - #reverse_each: Passes each element, in reverse order, to a given block.
+ * - #each_index: Passes each element index to a given block.
+ * - #cycle: Calls a given block with each element, then does so again,
+ * for a specified number of times, or forever.
+ * - #combination: Calls a given block with combinations of elements of +self+;
+ * a combination does not use the same element more than once.
+ * - #permutation: Calls a given block with permutations of elements of +self+;
+ * a permutation does not use the same element more than once.
+ * - #repeated_combination: Calls a given block with combinations of elements of +self+;
+ * a combination may use the same element more than once.
+ * - #repeated_permutation: Calls a given block with permutations of elements of +self+;
+ * a permutation may use the same element more than once.
*
* === Methods for Converting
*
- * #map, #collect:: Returns an array containing the block return-value for each element.
- * #map!, #collect!:: Replaces each element with a block return-value.
- * #flatten:: Returns an array that is a recursive flattening of +self+.
- * #flatten!:: Replaces each nested array in +self+ with the elements from that array.
- * #inspect, #to_s:: Returns a new String containing the elements.
- * #join:: Returns a newsString containing the elements joined by the field separator.
- * #to_a:: Returns +self+ or a new array containing all elements.
- * #to_ary:: Returns +self+.
- * #to_h:: Returns a new hash formed from the elements.
- * #transpose:: Transposes +self+, which must be an array of arrays.
- * #zip:: Returns a new array of arrays containing +self+ and given arrays;
- * follow the link for details.
+ * - #map, #collect: Returns an array containing the block return-value for each element.
+ * - #map!, #collect!: Replaces each element with a block return-value.
+ * - #flatten: Returns an array that is a recursive flattening of +self+.
+ * - #flatten!: Replaces each nested array in +self+ with the elements from that array.
+ * - #inspect, #to_s: Returns a new String containing the elements.
+ * - #join: Returns a newsString containing the elements joined by the field separator.
+ * - #to_a: Returns +self+ or a new array containing all elements.
+ * - #to_ary: Returns +self+.
+ * - #to_h: Returns a new hash formed from the elements.
+ * - #transpose: Transposes +self+, which must be an array of arrays.
+ * - #zip: Returns a new array of arrays containing +self+ and given arrays;
+ * follow the link for details.
*
* === Other Methods
*
- * #*:: Returns one of the following:
- * - With integer argument +n+, a new array that is the concatenation
- * of +n+ copies of +self+.
- * - With string argument +field_separator+, a new string that is equivalent to
- * <tt>join(field_separator)</tt>.
- * #abbrev:: Returns a hash of unambiguous abbreviations for elements.
- * #pack:: Packs the elements into a binary sequence.
- * #sum:: Returns a sum of elements according to either <tt>+</tt> or a given block.
+ * - #*: Returns one of the following:
+ *
+ * - With integer argument +n+, a new array that is the concatenation
+ * of +n+ copies of +self+.
+ * - With string argument +field_separator+, a new string that is equivalent to
+ * <tt>join(field_separator)</tt>.
+ *
+ * - #abbrev: Returns a hash of unambiguous abbreviations for elements.
+ * - #pack: Packs the elements into a binary sequence.
+ * - #sum: Returns a sum of elements according to either <tt>+</tt> or a given block.
*/
void
@@ -8264,6 +8816,7 @@ Init_Array(void)
rb_include_module(rb_cArray, rb_mEnumerable);
rb_define_alloc_func(rb_cArray, empty_ary_alloc);
+ rb_define_singleton_method(rb_cArray, "new", rb_ary_s_new, -1);
rb_define_singleton_method(rb_cArray, "[]", rb_ary_s_create, -1);
rb_define_singleton_method(rb_cArray, "try_convert", rb_ary_s_try_convert, 1);
rb_define_method(rb_cArray, "initialize", rb_ary_initialize, -1);
diff --git a/ast.c b/ast.c
index 466e7a6a2e..adb7287ed3 100644
--- a/ast.c
+++ b/ast.c
@@ -64,8 +64,8 @@ ast_new_internal(rb_ast_t *ast, const NODE *node)
return obj;
}
-static VALUE rb_ast_parse_str(VALUE str, VALUE keep_script_lines);
-static VALUE rb_ast_parse_file(VALUE path, VALUE keep_script_lines);
+static VALUE rb_ast_parse_str(VALUE str, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens);
+static VALUE rb_ast_parse_file(VALUE path, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens);
static VALUE
ast_parse_new(void)
@@ -85,31 +85,33 @@ ast_parse_done(rb_ast_t *ast)
}
static VALUE
-ast_s_parse(rb_execution_context_t *ec, VALUE module, VALUE str, VALUE keep_script_lines)
+ast_s_parse(rb_execution_context_t *ec, VALUE module, VALUE str, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens)
{
- return rb_ast_parse_str(str, keep_script_lines);
+ return rb_ast_parse_str(str, keep_script_lines, error_tolerant, keep_tokens);
}
static VALUE
-rb_ast_parse_str(VALUE str, VALUE keep_script_lines)
+rb_ast_parse_str(VALUE str, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens)
{
rb_ast_t *ast = 0;
StringValue(str);
VALUE vparser = ast_parse_new();
if (RTEST(keep_script_lines)) rb_parser_keep_script_lines(vparser);
+ if (RTEST(error_tolerant)) rb_parser_error_tolerant(vparser);
+ if (RTEST(keep_tokens)) rb_parser_keep_tokens(vparser);
ast = rb_parser_compile_string_path(vparser, Qnil, str, 1);
return ast_parse_done(ast);
}
static VALUE
-ast_s_parse_file(rb_execution_context_t *ec, VALUE module, VALUE path, VALUE keep_script_lines)
+ast_s_parse_file(rb_execution_context_t *ec, VALUE module, VALUE path, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens)
{
- return rb_ast_parse_file(path, keep_script_lines);
+ return rb_ast_parse_file(path, keep_script_lines, error_tolerant, keep_tokens);
}
static VALUE
-rb_ast_parse_file(VALUE path, VALUE keep_script_lines)
+rb_ast_parse_file(VALUE path, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens)
{
VALUE f;
rb_ast_t *ast = 0;
@@ -120,6 +122,8 @@ rb_ast_parse_file(VALUE path, VALUE keep_script_lines)
rb_funcall(f, rb_intern("set_encoding"), 2, rb_enc_from_encoding(enc), rb_str_new_cstr("-"));
VALUE vparser = ast_parse_new();
if (RTEST(keep_script_lines)) rb_parser_keep_script_lines(vparser);
+ if (RTEST(error_tolerant)) rb_parser_error_tolerant(vparser);
+ if (RTEST(keep_tokens)) rb_parser_keep_tokens(vparser);
ast = rb_parser_compile_file_path(vparser, Qnil, f, 1);
rb_io_close(f);
return ast_parse_done(ast);
@@ -139,13 +143,15 @@ lex_array(VALUE array, int index)
}
static VALUE
-rb_ast_parse_array(VALUE array, VALUE keep_script_lines)
+rb_ast_parse_array(VALUE array, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens)
{
rb_ast_t *ast = 0;
array = rb_check_array_type(array);
VALUE vparser = ast_parse_new();
if (RTEST(keep_script_lines)) rb_parser_keep_script_lines(vparser);
+ if (RTEST(error_tolerant)) rb_parser_error_tolerant(vparser);
+ if (RTEST(keep_tokens)) rb_parser_keep_tokens(vparser);
ast = rb_parser_compile_generic(vparser, lex_array, Qnil, array, 1);
return ast_parse_done(ast);
}
@@ -193,9 +199,26 @@ script_lines(VALUE path)
}
static VALUE
-ast_s_of(rb_execution_context_t *ec, VALUE module, VALUE body, VALUE keep_script_lines)
+node_id_for_backtrace_location(rb_execution_context_t *ec, VALUE module, VALUE location)
{
- VALUE path, node, lines = Qnil;
+ int node_id;
+
+ if (!rb_frame_info_p(location)) {
+ rb_raise(rb_eTypeError, "Thread::Backtrace::Location object expected");
+ }
+
+ node_id = rb_get_node_id_from_frame_info(location);
+ if (node_id == -1) {
+ return Qnil;
+ }
+
+ return INT2NUM(node_id);
+}
+
+static VALUE
+ast_s_of(rb_execution_context_t *ec, VALUE module, VALUE body, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens)
+{
+ VALUE node, lines = Qnil;
const rb_iseq_t *iseq;
int node_id;
@@ -215,27 +238,30 @@ ast_s_of(rb_execution_context_t *ec, VALUE module, VALUE body, VALUE keep_script
iseq = rb_method_iseq(body);
}
if (iseq) {
- node_id = iseq->body->location.node_id;
+ node_id = ISEQ_BODY(iseq)->location.node_id;
}
}
if (!iseq) {
return Qnil;
}
- lines = iseq->body->variable.script_lines;
- if (NIL_P(lines) && rb_iseq_from_eval_p(iseq)) {
+ lines = ISEQ_BODY(iseq)->variable.script_lines;
+
+ VALUE path = rb_iseq_path(iseq);
+ int e_option = RSTRING_LEN(path) == 2 && memcmp(RSTRING_PTR(path), "-e", 2) == 0;
+
+ if (NIL_P(lines) && rb_iseq_from_eval_p(iseq) && !e_option) {
rb_raise(rb_eArgError, "cannot get AST for method defined in eval");
}
- path = rb_iseq_path(iseq);
if (!NIL_P(lines) || !NIL_P(lines = script_lines(path))) {
- node = rb_ast_parse_array(lines, keep_script_lines);
+ node = rb_ast_parse_array(lines, keep_script_lines, error_tolerant, keep_tokens);
}
- else if (RSTRING_LEN(path) == 2 && memcmp(RSTRING_PTR(path), "-e", 2) == 0) {
- node = rb_ast_parse_str(rb_e_script, keep_script_lines);
+ else if (e_option) {
+ node = rb_ast_parse_str(rb_e_script, keep_script_lines, error_tolerant, keep_tokens);
}
else {
- node = rb_ast_parse_file(path, keep_script_lines);
+ node = rb_ast_parse_file(path, keep_script_lines, error_tolerant, keep_tokens);
}
return node_find(node, node_id);
@@ -642,6 +668,8 @@ node_children(rb_ast_t *ast, const NODE *node)
NEW_CHILD(ast, node->nd_pkwargs),
kwrest);
}
+ case NODE_ERROR:
+ return rb_ary_new_from_node_args(ast, 0);
case NODE_ARGS_AUX:
case NODE_LAST:
break;
@@ -696,6 +724,15 @@ ast_node_last_column(rb_execution_context_t *ec, VALUE self)
}
static VALUE
+ast_node_all_tokens(rb_execution_context_t *ec, VALUE self)
+{
+ struct ASTNodeData *data;
+ TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
+
+ return rb_ast_tokens(data->ast);
+}
+
+static VALUE
ast_node_inspect(rb_execution_context_t *ec, VALUE self)
{
VALUE str;
diff --git a/ast.rb b/ast.rb
index f866bd23e5..f3f72c747f 100644
--- a/ast.rb
+++ b/ast.rb
@@ -20,21 +20,47 @@
module RubyVM::AbstractSyntaxTree
# call-seq:
- # RubyVM::AbstractSyntaxTree.parse(string) -> RubyVM::AbstractSyntaxTree::Node
+ # RubyVM::AbstractSyntaxTree.parse(string, keep_script_lines: false, error_tolerant: false, keep_tokens: false) -> RubyVM::AbstractSyntaxTree::Node
#
# Parses the given _string_ into an abstract syntax tree,
# returning the root node of that tree.
#
- # SyntaxError is raised if the given _string_ is invalid syntax.
- #
# RubyVM::AbstractSyntaxTree.parse("x = 1 + 2")
# # => #<RubyVM::AbstractSyntaxTree::Node:SCOPE@1:0-1:9>
- def self.parse string, keep_script_lines: false
- Primitive.ast_s_parse string, keep_script_lines
+ #
+ # If <tt>keep_script_lines: true</tt> option is provided, the text of the parsed
+ # source is associated with nodes and is available via Node#script_lines.
+ #
+ # If <tt>keep_tokens: true</tt> option is provided, Node#tokens are populated.
+ #
+ # SyntaxError is raised if the given _string_ is invalid syntax. To overwrite this
+ # behavior, <tt>error_tolerant: true</tt> can be provided. In this case, the parser
+ # will produce a tree where expressions with syntax errors would be represented by
+ # Node with <tt>type=:ERROR</tt>.
+ #
+ # root = RubyVM::AbstractSyntaxTree.parse("x = 1; p(x; y=2")
+ # # <internal:ast>:33:in `parse': syntax error, unexpected ';', expecting ')' (SyntaxError)
+ # # x = 1; p(x; y=2
+ # # ^
+ #
+ # root = RubyVM::AbstractSyntaxTree.parse("x = 1; p(x; y=2", error_tolerant: true)
+ # # (SCOPE@1:0-1:15
+ # # tbl: [:x, :y]
+ # # args: nil
+ # # body: (BLOCK@1:0-1:15 (LASGN@1:0-1:5 :x (LIT@1:4-1:5 1)) (ERROR@1:7-1:11) (LASGN@1:12-1:15 :y (LIT@1:14-1:15 2))))
+ # root.children.last.children
+ # # [(LASGN@1:0-1:5 :x (LIT@1:4-1:5 1)),
+ # # (ERROR@1:7-1:11),
+ # # (LASGN@1:12-1:15 :y (LIT@1:14-1:15 2))]
+ #
+ # Note that parsing continues even after the errored expresion.
+ #
+ def self.parse string, keep_script_lines: false, error_tolerant: false, keep_tokens: false
+ Primitive.ast_s_parse string, keep_script_lines, error_tolerant, keep_tokens
end
# call-seq:
- # RubyVM::AbstractSyntaxTree.parse_file(pathname) -> RubyVM::AbstractSyntaxTree::Node
+ # RubyVM::AbstractSyntaxTree.parse_file(pathname, keep_script_lines: false, error_tolerant: false, keep_tokens: false) -> RubyVM::AbstractSyntaxTree::Node
#
# Reads the file from _pathname_, then parses it like ::parse,
# returning the root node of the abstract syntax tree.
@@ -44,13 +70,15 @@ module RubyVM::AbstractSyntaxTree
#
# RubyVM::AbstractSyntaxTree.parse_file("my-app/app.rb")
# # => #<RubyVM::AbstractSyntaxTree::Node:SCOPE@1:0-31:3>
- def self.parse_file pathname, keep_script_lines: false
- Primitive.ast_s_parse_file pathname, keep_script_lines
+ #
+ # See ::parse for explanation of keyword argument meaning and usage.
+ def self.parse_file pathname, keep_script_lines: false, error_tolerant: false, keep_tokens: false
+ Primitive.ast_s_parse_file pathname, keep_script_lines, error_tolerant, keep_tokens
end
# call-seq:
- # RubyVM::AbstractSyntaxTree.of(proc) -> RubyVM::AbstractSyntaxTree::Node
- # RubyVM::AbstractSyntaxTree.of(method) -> RubyVM::AbstractSyntaxTree::Node
+ # RubyVM::AbstractSyntaxTree.of(proc, keep_script_lines: false, error_tolerant: false, keep_tokens: false) -> RubyVM::AbstractSyntaxTree::Node
+ # RubyVM::AbstractSyntaxTree.of(method, keep_script_lines: false, error_tolerant: false, keep_tokens: false) -> RubyVM::AbstractSyntaxTree::Node
#
# Returns AST nodes of the given _proc_ or _method_.
#
@@ -63,8 +91,25 @@ module RubyVM::AbstractSyntaxTree
#
# RubyVM::AbstractSyntaxTree.of(method(:hello))
# # => #<RubyVM::AbstractSyntaxTree::Node:SCOPE@1:0-3:3>
- def self.of body, keep_script_lines: false
- Primitive.ast_s_of body, keep_script_lines
+ #
+ # See ::parse for explanation of keyword argument meaning and usage.
+ def self.of body, keep_script_lines: false, error_tolerant: false, keep_tokens: false
+ Primitive.ast_s_of body, keep_script_lines, error_tolerant, keep_tokens
+ end
+
+ # call-seq:
+ # RubyVM::AbstractSyntaxTree.node_id_for_backtrace_location(backtrace_location) -> integer
+ #
+ # Returns the node id for the given backtrace location.
+ #
+ # begin
+ # raise
+ # rescue => e
+ # loc = e.backtrace_locations.first
+ # RubyVM::AbstractSyntaxTree.node_id_for_backtrace_location(loc)
+ # end # => 0
+ def self.node_id_for_backtrace_location backtrace_location
+ Primitive.node_id_for_backtrace_location backtrace_location
end
# RubyVM::AbstractSyntaxTree::Node instances are created by parse methods in
@@ -122,6 +167,47 @@ module RubyVM::AbstractSyntaxTree
end
# call-seq:
+ # node.tokens -> array
+ #
+ # Returns tokens corresponding to the location of the node.
+ # Returns +nil+ if +keep_tokens+ is not enabled when #parse method is called.
+ #
+ # root = RubyVM::AbstractSyntaxTree.parse("x = 1 + 2", keep_tokens: true)
+ # root.tokens # => [[0, :tIDENTIFIER, "x", [1, 0, 1, 1]], [1, :tSP, " ", [1, 1, 1, 2]], ...]
+ # root.tokens.map{_1[2]}.join # => "x = 1 + 2"
+ #
+ # Token is an array of:
+ #
+ # - id
+ # - token type
+ # - source code text
+ # - location [ first_lineno, first_column, last_lineno, last_column ]
+ def tokens
+ return nil unless all_tokens
+
+ all_tokens.each_with_object([]) do |token, a|
+ loc = token.last
+ if ([first_lineno, first_column] <=> [loc[0], loc[1]]) <= 0 &&
+ ([last_lineno, last_column] <=> [loc[2], loc[3]]) >= 0
+ a << token
+ end
+ end
+ end
+
+ # call-seq:
+ # node.all_tokens -> array
+ #
+ # Returns all tokens for the input script regardless the receiver node.
+ # Returns +nil+ if +keep_tokens+ is not enabled when #parse method is called.
+ #
+ # root = RubyVM::AbstractSyntaxTree.parse("x = 1 + 2", keep_tokens: true)
+ # root.all_tokens # => [[0, :tIDENTIFIER, "x", [1, 0, 1, 1]], [1, :tSP, " ", [1, 1, 1, 2]], ...]
+ # root.children[-1].all_tokens # => [[0, :tIDENTIFIER, "x", [1, 0, 1, 1]], [1, :tSP, " ", [1, 1, 1, 2]], ...]
+ def all_tokens
+ Primitive.ast_node_all_tokens
+ end
+
+ # call-seq:
# node.children -> array
#
# Returns AST nodes under this one. Each kind of node
diff --git a/basictest/test.rb b/basictest/test.rb
index 52008b78db..95875b52a6 100755
--- a/basictest/test.rb
+++ b/basictest/test.rb
@@ -1960,6 +1960,8 @@ test_ok(p1.call == 5)
test_ok(i7 == nil)
end
+# WASI doesn't support spawning a new process for now.
+unless /wasi/ =~ RUBY_PLATFORM
test_check "system"
test_ok(`echo foobar` == "foobar\n")
test_ok(`./miniruby -e 'print "foobar"'` == 'foobar')
@@ -2010,6 +2012,7 @@ test_ok(done)
File.unlink script_tmp or `/bin/rm -f "#{script_tmp}"`
File.unlink "#{script_tmp}.bak" or `/bin/rm -f "#{script_tmp}.bak"`
+end # not /wasi/ =~ RUBY_PLATFORM
test_check "const"
TEST1 = 1
diff --git a/benchmark/README.md b/benchmark/README.md
index c222164be3..e11381cad9 100644
--- a/benchmark/README.md
+++ b/benchmark/README.md
@@ -28,16 +28,18 @@ See also:
```console
Usage: benchmark-driver [options] RUBY|YAML...
- -r, --runner TYPE Specify runner type: ips, time, memory, once (default: ips)
- -o, --output TYPE Specify output type: compare, simple, markdown, record (default: compare)
+ -r, --runner TYPE Specify runner type: ips, time, memory, once, block (default: ips)
+ -o, --output TYPE Specify output type: compare, simple, markdown, record, all (default: compare)
-e, --executables EXECS Ruby executables (e1::path1 arg1; e2::path2 arg2;...)
--rbenv VERSIONS Ruby executables in rbenv (x.x.x arg1;y.y.y arg2;...)
--repeat-count NUM Try benchmark NUM times and use the fastest result or the worst memory usage
--repeat-result TYPE Yield "best", "average" or "worst" result with --repeat-count (default: best)
+ --alternate Alternate executables instead of running the same executable in a row with --repeat-count
--bundler Install and use gems specified in Gemfile
--filter REGEXP Filter out benchmarks with given regexp
--run-duration SECONDS Warmup estimates loop_count to run for this duration (default: 3)
- -v, --verbose Verbose mode. Multiple -v options increase visibility (max: 2)
+ --timeout SECONDS Timeout ruby command execution with timeout(1)
+ -v, --verbose Verbose mode. Multiple -v options increase visilibity (max: 2)
```
## make benchmark
diff --git a/benchmark/array_sort_int.yml b/benchmark/array_sort_int.yml
new file mode 100644
index 0000000000..7b9027ebf7
--- /dev/null
+++ b/benchmark/array_sort_int.yml
@@ -0,0 +1,15 @@
+prelude: |
+ ary2 = 2.times.to_a.shuffle
+ ary10 = 10.times.to_a.shuffle
+ ary100 = 100.times.to_a.shuffle
+ ary1000 = 1000.times.to_a.shuffle
+ ary10000 = 10000.times.to_a.shuffle
+
+benchmark:
+ ary2.sort: ary2.sort
+ ary10.sort: ary10.sort
+ ary100.sort: ary100.sort
+ ary1000.sort: ary1000.sort
+ ary10000.sort: ary10000.sort
+
+loop_count: 10000
diff --git a/benchmark/buffer_each.yml b/benchmark/buffer_each.yml
new file mode 100644
index 0000000000..417941104e
--- /dev/null
+++ b/benchmark/buffer_each.yml
@@ -0,0 +1,27 @@
+prelude: |
+ # frozen_string_literal: true
+ Warning[:experimental] = false
+ string = "The quick brown fox jumped over the lazy dog."
+ array = string.bytes
+ buffer = IO::Buffer.for(string)
+benchmark:
+ string.each_byte: |
+ upcased = String.new
+ string.each_byte do |byte|
+ upcased << (byte ^ 32)
+ end
+ array.each: |
+ upcased = String.new
+ array.each do |byte|
+ upcased << (byte ^ 32)
+ end
+ buffer.each: |
+ upcased = String.new
+ buffer.each(:U8) do |offset, byte|
+ upcased << (byte ^ 32)
+ end
+ buffer.each_byte: |
+ upcased = String.new
+ buffer.each_byte do |byte|
+ upcased << (byte ^ 32)
+ end
diff --git a/benchmark/buffer_get.yml b/benchmark/buffer_get.yml
index e375dcf85d..9e1f99d64e 100644
--- a/benchmark/buffer_get.yml
+++ b/benchmark/buffer_get.yml
@@ -1,9 +1,25 @@
+prelude: |
+ # frozen_string_literal: true
+ Warning[:experimental] = false
+ string = "The quick brown fox jumped over the lazy dog."
+ buffer = IO::Buffer.for(string)
+ format = [:U32, :U32, :U32, :U32]
benchmark:
- - name: buffer.get
- prelude: buffer = IO::Buffer.new(32, IO::Buffer::MAPPED)
- script: buffer.get(:U32, 0)
- loop_count: 20000000
- - name: string.unpack
- prelude: string = "\0" * 32
- script: string.unpack("C")
- loop_count: 20000000
+ string.unpack1: |
+ [
+ string.unpack1("N"),
+ string.unpack1("N", offset: 4),
+ string.unpack1("N", offset: 8),
+ string.unpack1("N", offset: 12),
+ ]
+ buffer.get_value: |
+ [
+ buffer.get_value(:U32, 0),
+ buffer.get_value(:U32, 4),
+ buffer.get_value(:U32, 8),
+ buffer.get_value(:U32, 12),
+ ]
+ buffer.get_values: |
+ buffer.get_values(format, 0)
+ string.unpack: |
+ string.unpack("NNNN")
diff --git a/benchmark/cgi_escape_html.yml b/benchmark/cgi_escape_html.yml
index af6abd08ac..655be9d7d8 100644
--- a/benchmark/cgi_escape_html.yml
+++ b/benchmark/cgi_escape_html.yml
@@ -1,32 +1,23 @@
-prelude: require 'cgi/escape'
+prelude: |
+ # frozen_string_literal: true
+ require 'cgi/escape'
benchmark:
- - name: escape_html_blank
- prelude: str = ""
- script: CGI.escapeHTML(str)
+ - script: CGI.escapeHTML("")
loop_count: 20000000
- - name: escape_html_short_none
- prelude: str = "abcde"
- script: CGI.escapeHTML(str)
+ - script: CGI.escapeHTML("abcde")
loop_count: 20000000
- - name: escape_html_short_one
- prelude: str = "abcd<"
- script: CGI.escapeHTML(str)
+ - script: CGI.escapeHTML("abcd<")
loop_count: 20000000
- - name: escape_html_short_all
- prelude: str = "'&\"<>"
- script: CGI.escapeHTML(str)
+ - script: CGI.escapeHTML("'&\"<>")
loop_count: 5000000
- - name: escape_html_long_none
- prelude: str = "abcde" * 300
- script: CGI.escapeHTML(str)
+ - prelude: long_no_escape = "abcde" * 300
+ script: CGI.escapeHTML(long_no_escape)
loop_count: 1000000
- - name: escape_html_long_all
- prelude: str = "'&\"<>" * 10
- script: CGI.escapeHTML(str)
+ - prelude: long_all_escape = "'&\"<>" * 10
+ script: CGI.escapeHTML(long_all_escape)
loop_count: 1000000
- - name: escape_html_real
- prelude: | # http://example.com/
- str = <<~HTML
+ - prelude: | # http://example.com/
+ example_html = <<~HTML
<body>
<div>
<h1>Example Domain</h1>
@@ -36,5 +27,5 @@ benchmark:
</div>
</body>
HTML
- script: CGI.escapeHTML(str)
+ script: CGI.escapeHTML(example_html)
loop_count: 1000000
diff --git a/benchmark/constant_invalidation.rb b/benchmark/constant_invalidation.rb
new file mode 100644
index 0000000000..a95ec6f37e
--- /dev/null
+++ b/benchmark/constant_invalidation.rb
@@ -0,0 +1,22 @@
+$VERBOSE = nil
+
+CONSTANT1 = 1
+CONSTANT2 = 1
+CONSTANT3 = 1
+CONSTANT4 = 1
+CONSTANT5 = 1
+
+def constants
+ [CONSTANT1, CONSTANT2, CONSTANT3, CONSTANT4, CONSTANT5]
+end
+
+500_000.times do
+ constants
+
+ # With previous behavior, this would cause all of the constant caches
+ # associated with the constant lookups listed above to invalidate, meaning
+ # they would all have to be fetched again. With current behavior, it only
+ # invalidates when a name matches, so the following constant set shouldn't
+ # impact the constant lookups listed above.
+ INVALIDATE = true
+end
diff --git a/benchmark/enum_minmax.yml b/benchmark/enum_minmax.yml
new file mode 100644
index 0000000000..9d01731abb
--- /dev/null
+++ b/benchmark/enum_minmax.yml
@@ -0,0 +1,25 @@
+prelude: |
+ set2 = 2.times.to_a.shuffle.to_set
+ set10 = 10.times.to_a.shuffle.to_set
+ set100 = 100.times.to_a.shuffle.to_set
+ set1000 = 1000.times.to_a.shuffle.to_set
+ set10000 = 10000.times.to_a.shuffle.to_set
+
+benchmark:
+ set2.min: set2.min
+ set10.min: set10.min
+ set100.min: set100.min
+ set1000.min: set1000.min
+ set10000.min: set10000.min
+ set2.max: set2.max
+ set10.max: set10.max
+ set100.max: set100.max
+ set1000.max: set1000.max
+ set10000.max: set10000.max
+ set2.minmax: set2.minmax
+ set10.minmax: set10.minmax
+ set100.minmax: set100.minmax
+ set1000.minmax: set1000.minmax
+ set10000.minmax: set10000.minmax
+
+loop_count: 10000
diff --git a/benchmark/enum_sort.yml b/benchmark/enum_sort.yml
new file mode 100644
index 0000000000..6f26e748c6
--- /dev/null
+++ b/benchmark/enum_sort.yml
@@ -0,0 +1,15 @@
+prelude: |
+ set2 = 2.times.to_a.shuffle.to_set
+ set10 = 10.times.to_a.shuffle.to_set
+ set100 = 100.times.to_a.shuffle.to_set
+ set1000 = 1000.times.to_a.shuffle.to_set
+ set10000 = 10000.times.to_a.shuffle.to_set
+
+benchmark:
+ set2.sort_by: set2.sort_by { 0 }
+ set10.sort_by: set10.sort_by { 0 }
+ set100.sort_by: set100.sort_by { 0 }
+ set1000.sort_by: set1000.sort_by { 0 }
+ set10000.sort_by: set10000.sort_by { 0 }
+
+loop_count: 10000
diff --git a/benchmark/erb_escape_html.yml b/benchmark/erb_escape_html.yml
new file mode 100644
index 0000000000..ca28d756e7
--- /dev/null
+++ b/benchmark/erb_escape_html.yml
@@ -0,0 +1,31 @@
+prelude: |
+ # frozen_string_literal: true
+ require 'erb'
+benchmark:
+ - script: ERB::Util.html_escape("")
+ loop_count: 20000000
+ - script: ERB::Util.html_escape("abcde")
+ loop_count: 20000000
+ - script: ERB::Util.html_escape("abcd<")
+ loop_count: 20000000
+ - script: ERB::Util.html_escape("'&\"<>")
+ loop_count: 5000000
+ - prelude: long_no_escape = "abcde" * 300
+ script: ERB::Util.html_escape(long_no_escape)
+ loop_count: 1000000
+ - prelude: long_all_escape = "'&\"<>" * 10
+ script: ERB::Util.html_escape(long_all_escape)
+ loop_count: 1000000
+ - prelude: | # http://example.com/
+ example_html = <<~HTML
+ <body>
+ <div>
+ <h1>Example Domain</h1>
+ <p>This domain is established to be used for illustrative examples in documents. You may use this
+ domain in examples without prior coordination or asking for permission.</p>
+ <p><a href="http://www.iana.org/domains/example">More information...</a></p>
+ </div>
+ </body>
+ HTML
+ script: ERB::Util.html_escape(example_html)
+ loop_count: 1000000
diff --git a/benchmark/io_write.rb b/benchmark/io_write.rb
new file mode 100644
index 0000000000..cdb409948b
--- /dev/null
+++ b/benchmark/io_write.rb
@@ -0,0 +1,22 @@
+#!/usr/bin/env ruby
+
+require 'benchmark'
+
+i, o = IO.pipe
+o.sync = true
+
+DOT = ".".freeze
+
+chunks = 100_000.times.collect{DOT}
+
+thread = Thread.new do
+ while i.read(1024)
+ end
+end
+
+100.times do
+ o.write(*chunks)
+end
+
+o.close
+thread.join
diff --git a/benchmark/lib/benchmark_driver/runner/mjit.rb b/benchmark/lib/benchmark_driver/runner/mjit.rb
index 1d4693e8be..3a58a620de 100644
--- a/benchmark/lib/benchmark_driver/runner/mjit.rb
+++ b/benchmark/lib/benchmark_driver/runner/mjit.rb
@@ -16,7 +16,7 @@ class BenchmarkDriver::Runner::Mjit < BenchmarkDriver::Runner::Ips
job.prelude = "#{job.prelude}\n#{<<~EOS}"
if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
__bmdv_ruby_i = 0
- while __bmdv_ruby_i < 10000 # jit_min_calls
+ while __bmdv_ruby_i < 10000 # MJIT call threshold
#{job.script}
__bmdv_ruby_i += 1
end
diff --git a/benchmark/lib/benchmark_driver/runner/mjit_exec.rb b/benchmark/lib/benchmark_driver/runner/mjit_exec.rb
deleted file mode 100644
index eac3dfba84..0000000000
--- a/benchmark/lib/benchmark_driver/runner/mjit_exec.rb
+++ /dev/null
@@ -1,237 +0,0 @@
-require 'benchmark_driver/struct'
-require 'benchmark_driver/metric'
-require 'erb'
-
-# A special runner dedicated for measuring mjit_exec overhead.
-class BenchmarkDriver::Runner::MjitExec
- METRIC = BenchmarkDriver::Metric.new(name: 'Iteration per second', unit: 'i/s')
-
- # JobParser returns this, `BenchmarkDriver::Runner.runner_for` searches "*::Job"
- Job = ::BenchmarkDriver::Struct.new(
- :name, # @param [String] name - This is mandatory for all runner
- :metrics, # @param [Array<BenchmarkDriver::Metric>]
- :num_methods, # @param [Integer] num_methods - The number of methods to be defined
- :loop_count, # @param [Integer] loop_count
- :from_jit, # @param [TrueClass,FalseClass] from_jit - Whether the mjit_exec() is from JIT or not
- :to_jit, # @param [TrueClass,FalseClass] to_jit - Whether the mjit_exec() is to JIT or not
- )
- # Dynamically fetched and used by `BenchmarkDriver::JobParser.parse`
- class << JobParser = Module.new
- # @param [Array,String] num_methods
- # @param [Integer] loop_count
- # @param [TrueClass,FalseClass] from_jit
- # @param [TrueClass,FalseClass] to_jit
- def parse(num_methods:, loop_count:, from_jit:, to_jit:)
- if num_methods.is_a?(String)
- num_methods = eval(num_methods)
- end
-
- num_methods.map do |num|
- if num_methods.size > 1
- suffix = "[#{'%4d' % num}]"
- else
- suffix = "_#{num}"
- end
- Job.new(
- name: "mjit_exec_#{from_jit ? 'JT' : 'VM'}2#{to_jit ? 'JT' : 'VM'}#{suffix}",
- metrics: [METRIC],
- num_methods: num,
- loop_count: loop_count,
- from_jit: from_jit,
- to_jit: to_jit,
- )
- end
- end
- end
-
- # @param [BenchmarkDriver::Config::RunnerConfig] config
- # @param [BenchmarkDriver::Output] output
- # @param [BenchmarkDriver::Context] contexts
- def initialize(config:, output:, contexts:)
- @config = config
- @output = output
- @contexts = contexts
- end
-
- # This method is dynamically called by `BenchmarkDriver::JobRunner.run`
- # @param [Array<BenchmarkDriver::Runner::Peak::Job>] jobs
- def run(jobs)
- @output.with_benchmark do
- jobs.each do |job|
- @output.with_job(name: job.name) do
- @contexts.each do |context|
- result = BenchmarkDriver::Repeater.with_repeat(config: @config, larger_better: true, rest_on_average: :average) do
- run_benchmark(job, context: context)
- end
- value, duration = result.value
- @output.with_context(name: context.name, executable: context.executable, gems: context.gems, prelude: context.prelude) do
- @output.report(values: { METRIC => value }, duration: duration, loop_count: job.loop_count)
- end
- end
- end
- end
- end
- end
-
- private
-
- # @param [BenchmarkDriver::Runner::Ips::Job] job - loop_count is not nil
- # @param [BenchmarkDriver::Context] context
- # @return [BenchmarkDriver::Metrics]
- def run_benchmark(job, context:)
- if job.from_jit
- if job.to_jit
- benchmark = BenchmarkJT2JT.new(num_methods: job.num_methods, loop_count: job.loop_count)
- else
- raise NotImplementedError, "JT2VM is not implemented yet"
- end
- else
- if job.to_jit
- benchmark = BenchmarkVM2JT.new(num_methods: job.num_methods, loop_count: job.loop_count)
- else
- benchmark = BenchmarkVM2VM.new(num_methods: job.num_methods, loop_count: job.loop_count)
- end
- end
-
- duration = Tempfile.open(['benchmark_driver-result', '.txt']) do |f|
- with_script(benchmark.render(result: f.path)) do |path|
- opt = []
- if context.executable.command.any? { |c| c.start_with?('--jit') }
- opt << '--jit-min-calls=2'
- end
- IO.popen([*context.executable.command, '--disable-gems', *opt, path], &:read)
- if $?.success?
- Float(f.read)
- else
- BenchmarkDriver::Result::ERROR
- end
- end
- end
-
- [job.loop_count.to_f / duration, duration]
- end
-
- def with_script(script)
- if @config.verbose >= 2
- sep = '-' * 30
- $stdout.puts "\n\n#{sep}[Script begin]#{sep}\n#{script}#{sep}[Script end]#{sep}\n\n"
- end
-
- Tempfile.open(['benchmark_driver-', '.rb']) do |f|
- f.puts script
- f.close
- return yield(f.path)
- end
- end
-
- # @param [Integer] num_methods
- # @param [Integer] loop_count
- BenchmarkVM2VM = ::BenchmarkDriver::Struct.new(:num_methods, :loop_count) do
- # @param [String] result - A file to write result
- def render(result:)
- ERB.new(<<~EOS, trim_mode: '%').result(binding)
- % num_methods.times do |i|
- def a<%= i %>
- nil
- end
- % end
- RubyVM::MJIT.pause if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
-
- def vm
- t = Process.clock_gettime(Process::CLOCK_MONOTONIC)
- i = 0
- while i < <%= loop_count / 1000 %>
- % 1000.times do |i|
- a<%= i % num_methods %>
- % end
- i += 1
- end
- % (loop_count % 1000).times do |i|
- a<%= i % num_methods %>
- % end
- Process.clock_gettime(Process::CLOCK_MONOTONIC) - t
- end
-
- vm # warmup call cache
- File.write(<%= result.dump %>, vm)
- EOS
- end
- end
- private_constant :BenchmarkVM2VM
-
- # @param [Integer] num_methods
- # @param [Integer] loop_count
- BenchmarkVM2JT = ::BenchmarkDriver::Struct.new(:num_methods, :loop_count) do
- # @param [String] result - A file to write result
- def render(result:)
- ERB.new(<<~EOS, trim_mode: '%').result(binding)
- % num_methods.times do |i|
- def a<%= i %>
- nil
- end
- a<%= i %>
- a<%= i %> # --jit-min-calls=2
- % end
- RubyVM::MJIT.pause if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
-
- def vm
- t = Process.clock_gettime(Process::CLOCK_MONOTONIC)
- i = 0
- while i < <%= loop_count / 1000 %>
- % 1000.times do |i|
- a<%= i % num_methods %>
- % end
- i += 1
- end
- % (loop_count % 1000).times do |i|
- a<%= i % num_methods %>
- % end
- Process.clock_gettime(Process::CLOCK_MONOTONIC) - t
- end
-
- vm # warmup call cache
- File.write(<%= result.dump %>, vm)
- EOS
- end
- end
- private_constant :BenchmarkVM2JT
-
- # @param [Integer] num_methods
- # @param [Integer] loop_count
- BenchmarkJT2JT = ::BenchmarkDriver::Struct.new(:num_methods, :loop_count) do
- # @param [String] result - A file to write result
- def render(result:)
- ERB.new(<<~EOS, trim_mode: '%').result(binding)
- % num_methods.times do |i|
- def a<%= i %>
- nil
- end
- % end
-
- # You may need to:
- # * Increase `JIT_ISEQ_SIZE_THRESHOLD` to 10000000 in mjit.h
- # * Always return false in `inlinable_iseq_p()` of mjit_compile.c
- def jit
- t = Process.clock_gettime(Process::CLOCK_MONOTONIC)
- i = 0
- while i < <%= loop_count / 1000 %>
- % 1000.times do |i|
- a<%= i % num_methods %>
- % end
- i += 1
- end
- % (loop_count % 1000).times do |i|
- a<%= i % num_methods %>
- % end
- Process.clock_gettime(Process::CLOCK_MONOTONIC) - t
- end
-
- jit
- jit
- RubyVM::MJIT.pause if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
- File.write(<%= result.dump %>, jit)
- EOS
- end
- end
- private_constant :BenchmarkJT2JT
-end
diff --git a/benchmark/marshal_dump_load_integer.yml b/benchmark/marshal_dump_load_integer.yml
new file mode 100644
index 0000000000..78ebf823d2
--- /dev/null
+++ b/benchmark/marshal_dump_load_integer.yml
@@ -0,0 +1,22 @@
+prelude: |
+ smallint_array = 1000.times.map { |x| x }
+ bigint32_array = 1000.times.map { |x| x + 2**32 }
+ bigint64_array = 1000.times.map { |x| x + 2**64 }
+
+ smallint_dump = Marshal.dump(smallint_array)
+ bigint32_dump = Marshal.dump(bigint32_array)
+ bigint64_dump = Marshal.dump(bigint64_array)
+benchmark:
+ marshal_dump_integer_small: |
+ Marshal.dump(smallint_array)
+ marshal_dump_integer_over_32_bit: |
+ Marshal.dump(bigint32_array)
+ marshal_dump_integer_over_64_bit: |
+ Marshal.dump(bigint64_array)
+ marshal_load_integer_small: |
+ Marshal.load(smallint_dump)
+ marshal_load_integer_over_32_bit: |
+ Marshal.load(bigint32_dump)
+ marshal_load_integer_over_64_bit: |
+ Marshal.load(bigint64_dump)
+loop_count: 4000
diff --git a/benchmark/masgn.yml b/benchmark/masgn.yml
index 4be9333e23..31cb8ee4a3 100644
--- a/benchmark/masgn.yml
+++ b/benchmark/masgn.yml
@@ -1,7 +1,7 @@
prelude: |
a = [nil] * 3
b = Class.new{attr_writer :a, :b, :c}.new
- c, d, e, f = nil, nil, nil, nil
+ c = d = e = f = g = h = i = nil
benchmark:
array2_2: "c = (a[0], a[1] = 1, 2)"
array2_3: "c = (a[0], a[1] = 1, 2, 3)"
@@ -27,3 +27,27 @@ benchmark:
lvar2_3p: "(d, e = 1, 2, 3; nil)"
lvar3_2p: "(d, e, f = 1, 2; nil)"
lvar3_3p: "(d, e, f = 1, 2, 3; nil)"
+ array2_2lv: "c = (a[0], a[1] = g, h)"
+ array2_ilv: "c = (a[0], a[1] = g, h, i)"
+ arrayi_2lv: "c = (a[0], a[1], a[2] = g, h)"
+ arrayi_ilv: "c = (a[0], a[1], a[2] = g, h, i)"
+ attr2_2lv: "c = (b.a, b.b = g, h)"
+ attr2_ilv: "c = (b.a, b.b = g, h, i)"
+ attri_2lv: "c = (b.a, b.b, b.c = g, h)"
+ attri_ilv: "c = (b.a, b.b, b.c = g, h, i)"
+ lvar2_2lv: "c = (d, e = g, h)"
+ lvar2_ilv: "c = (d, e = g, h, i)"
+ lvari_2lv: "c = (d, e, f = g, h)"
+ lvari_ilv: "c = (d, e, f = g, h, i)"
+ array2_2plv: "(a[0], a[1] = g, h; nil)"
+ array2_iplv: "(a[0], a[1] = g, h, i; nil)"
+ arrayi_2plv: "(a[0], a[1], a[2] = g, h; nil)"
+ arrayi_iplv: "(a[0], a[1], a[2] = g, h, i; nil)"
+ attr2_2plv: "(b.a, b.b = g, h; nil)"
+ attr2_iplv: "(b.a, b.b = g, h, i; nil)"
+ attri_2plv: "(b.a, b.b, b.c = g, h; nil)"
+ attri_iplv: "(b.a, b.b, b.c = g, h, i; nil)"
+ lvar2_2plv: "(d, e = g, h; nil)"
+ lvar2_iplv: "(d, e = g, h, i; nil)"
+ lvari_2plv: "(d, e, f = g, h; nil)"
+ lvari_iplv: "(d, e, f = g, h, i; nil)"
diff --git a/benchmark/mjit_exec_jt2jt.yml b/benchmark/mjit_exec_jt2jt.yml
deleted file mode 100644
index 6c303c7a44..0000000000
--- a/benchmark/mjit_exec_jt2jt.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-type: lib/benchmark_driver/runner/mjit_exec
-num_methods: [1]
-#num_methods: (1..100).to_a + [200, 300, 400, 500, 600, 700, 800, 900, 1000]
-loop_count: 50000000
-from_jit: true
-to_jit: true
diff --git a/benchmark/mjit_exec_vm2jt.yml b/benchmark/mjit_exec_vm2jt.yml
deleted file mode 100644
index 764883f070..0000000000
--- a/benchmark/mjit_exec_vm2jt.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-type: lib/benchmark_driver/runner/mjit_exec
-num_methods: [1]
-#num_methods: (1..100).to_a + [200, 300, 400, 500, 600, 700, 800, 900, 1000]
-loop_count: 50000000
-from_jit: false
-to_jit: true
diff --git a/benchmark/mjit_exec_vm2vm.yml b/benchmark/mjit_exec_vm2vm.yml
deleted file mode 100644
index 030aa76c1c..0000000000
--- a/benchmark/mjit_exec_vm2vm.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-type: lib/benchmark_driver/runner/mjit_exec
-num_methods: [1]
-#num_methods: (1..100).to_a + [200, 300, 400, 500, 600, 700, 800, 900, 1000]
-loop_count: 50000000
-from_jit: false
-to_jit: false
diff --git a/benchmark/module_eqq.yml b/benchmark/module_eqq.yml
new file mode 100644
index 0000000000..a561fb86dc
--- /dev/null
+++ b/benchmark/module_eqq.yml
@@ -0,0 +1,27 @@
+prelude: |
+ class SimpleClass; end
+ class MediumClass
+ 10.times { include Module.new }
+ end
+ class LargeClass
+ 100.times { include Module.new }
+ end
+ class HugeClass
+ 300.times { include Module.new }
+ end
+ SimpleObj = SimpleClass.new
+ MediumObj = MediumClass.new
+ LargeObj = LargeClass.new
+ HugeObj = HugeClass.new
+benchmark:
+ simple_class_eqq_simple_obj: |
+ SimpleClass === SimpleObj
+ medium_class_eqq_simple_obj: |
+ MediumClass === SimpleObj
+ simple_class_eqq_medium_obj: |
+ SimpleClass === MediumObj
+ simple_class_eqq_large_obj: |
+ SimpleClass === LargeObj
+ simple_class_eqq_huge_obj: |
+ SimpleClass === HugeObj
+loop_count: 20000000
diff --git a/benchmark/numeric_methods.yml b/benchmark/numeric_methods.yml
index 433c2268a3..1384902935 100644
--- a/benchmark/numeric_methods.yml
+++ b/benchmark/numeric_methods.yml
@@ -10,4 +10,20 @@ benchmark:
int.finite?
infinite?: |
int.infinite?
+ integer_real: |
+ int.real
+ float_real: |
+ flo.real
+ integr_imag: |
+ int.imag
+ float_imag: |
+ flo.imag
+ integer_conj: |
+ int.conj
+ float_conj: |
+ flo.conj
+ integer_numerator: |
+ int.numerator
+ integer_denominator: |
+ int.denominator
loop_count: 20000000
diff --git a/benchmark/range_min.yml b/benchmark/range_min.yml
new file mode 100644
index 0000000000..9e60dd7308
--- /dev/null
+++ b/benchmark/range_min.yml
@@ -0,0 +1,2 @@
+benchmark:
+ - (1..10).min
diff --git a/benchmark/so_nbody.rb b/benchmark/so_nbody.rb
index d6c5bb9e61..9884fc4edc 100644
--- a/benchmark/so_nbody.rb
+++ b/benchmark/so_nbody.rb
@@ -12,38 +12,38 @@ def _puts *args
end
class Planet
- attr_accessor :x, :y, :z, :vx, :vy, :vz, :mass
+ attr_accessor :x, :y, :z, :vx, :vy, :vz, :mass
- def initialize(x, y, z, vx, vy, vz, mass)
- @x, @y, @z = x, y, z
- @vx, @vy, @vz = vx * DAYS_PER_YEAR, vy * DAYS_PER_YEAR, vz * DAYS_PER_YEAR
- @mass = mass * SOLAR_MASS
- end
-
- def move_from_i(bodies, nbodies, dt, i)
- while i < nbodies
- b2 = bodies[i]
- dx = @x - b2.x
- dy = @y - b2.y
- dz = @z - b2.z
-
- distance = Math.sqrt(dx * dx + dy * dy + dz * dz)
- mag = dt / (distance * distance * distance)
- b_mass_mag, b2_mass_mag = @mass * mag, b2.mass * mag
-
- @vx -= dx * b2_mass_mag
- @vy -= dy * b2_mass_mag
- @vz -= dz * b2_mass_mag
- b2.vx += dx * b_mass_mag
- b2.vy += dy * b_mass_mag
- b2.vz += dz * b_mass_mag
- i += 1
+ def initialize(x, y, z, vx, vy, vz, mass)
+ @x, @y, @z = x, y, z
+ @vx, @vy, @vz = vx * DAYS_PER_YEAR, vy * DAYS_PER_YEAR, vz * DAYS_PER_YEAR
+ @mass = mass * SOLAR_MASS
end
- @x += dt * @vx
- @y += dt * @vy
- @z += dt * @vz
- end
+ def move_from_i(bodies, nbodies, dt, i)
+ while i < nbodies
+ b2 = bodies[i]
+ dx = @x - b2.x
+ dy = @y - b2.y
+ dz = @z - b2.z
+
+ distance = Math.sqrt(dx * dx + dy * dy + dz * dz)
+ mag = dt / (distance * distance * distance)
+ b_mass_mag, b2_mass_mag = @mass * mag, b2.mass * mag
+
+ @vx -= dx * b2_mass_mag
+ @vy -= dy * b2_mass_mag
+ @vz -= dz * b2_mass_mag
+ b2.vx += dx * b_mass_mag
+ b2.vy += dy * b_mass_mag
+ b2.vz += dz * b_mass_mag
+ i += 1
+ end
+
+ @x += dt * @vx
+ @y += dt * @vy
+ @z += dt * @vz
+ end
end
def energy(bodies)
diff --git a/benchmark/string_concat.yml b/benchmark/string_concat.yml
new file mode 100644
index 0000000000..e65c00cca9
--- /dev/null
+++ b/benchmark/string_concat.yml
@@ -0,0 +1,45 @@
+prelude: |
+ CHUNK = "a" * 64
+ UCHUNK = "é" * 32
+ GC.disable # GC causes a lot of variance
+benchmark:
+ binary_concat_7bit: |
+ buffer = String.new(capacity: 4096, encoding: Encoding::BINARY)
+ buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK
+ buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK
+ buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK
+ buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK
+ buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK
+ buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK
+ buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK
+ buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK
+ utf8_concat_7bit: |
+ buffer = String.new(capacity: 4096, encoding: Encoding::UTF_8)
+ buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK
+ buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK
+ buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK
+ buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK
+ buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK
+ buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK
+ buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK
+ buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK
+ utf8_concat_UTF8: |
+ buffer = String.new(capacity: 4096, encoding: Encoding::UTF_8)
+ buffer << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK
+ buffer << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK
+ buffer << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK
+ buffer << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK
+ buffer << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK
+ buffer << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK
+ buffer << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK
+ buffer << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK
+ interpolation: |
+ buffer = "#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}" \
+ "#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}" \
+ "#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}" \
+ "#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}" \
+ "#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}" \
+ "#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}" \
+ "#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}" \
+ "#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}" \
+ "#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}"
diff --git a/benchmark/time_now.yml b/benchmark/time_now.yml
new file mode 100644
index 0000000000..f6d6a31489
--- /dev/null
+++ b/benchmark/time_now.yml
@@ -0,0 +1,3 @@
+benchmark:
+ - 'Time.now'
+ - 'Time.now(in: "+09:00")'
diff --git a/benchmark/time_parse.yml b/benchmark/time_parse.yml
index a6d6948b9c..6060b58bc6 100644
--- a/benchmark/time_parse.yml
+++ b/benchmark/time_parse.yml
@@ -6,3 +6,5 @@ benchmark:
- Time.iso8601(iso8601)
- Time.parse(iso8601)
- Time.parse(inspect)
+ - Time.new(iso8601) rescue Time.iso8601(iso8601)
+ - Time.new(inspect) rescue Time.parse(inspect)
diff --git a/benchmark/vm_const.yml b/benchmark/vm_const.yml
index 6064d4eed0..8939ca0cd3 100644
--- a/benchmark/vm_const.yml
+++ b/benchmark/vm_const.yml
@@ -1,7 +1,13 @@
prelude: |
Const = 1
+ A = B = C = D = E = F = G = H = I = J = K = L = M = N = O = P = Q = R = S = T = U = V = W = X = Y = Z = 1
+ def foo
+ A; B; C; D; E; F; G; H; I; J; K; L; M; N; O; P; Q; R; S; T; U; V; W; X; Y; Z
+ end
benchmark:
vm_const: |
j = Const
k = Const
+ vm_const_many: |
+ foo
loop_count: 30000000
diff --git a/benchmark/vm_freezeobj.yml b/benchmark/vm_freezeobj.yml
new file mode 100644
index 0000000000..69a795a354
--- /dev/null
+++ b/benchmark/vm_freezeobj.yml
@@ -0,0 +1,6 @@
+prelude: |
+ objs = 100000.times.map { Object.new }
+benchmark:
+ vm_freeze_obj: |
+ objs.map(&:freeze)
+loop_count: 600
diff --git a/benchmark/vm_ivar_embedded_obj_init.yml b/benchmark/vm_ivar_embedded_obj_init.yml
new file mode 100644
index 0000000000..74fe20a630
--- /dev/null
+++ b/benchmark/vm_ivar_embedded_obj_init.yml
@@ -0,0 +1,14 @@
+prelude: |
+ class C
+ def set_ivars
+ @a = nil
+ @b = nil
+ @c = nil
+ end
+ end
+
+ c = C.new
+benchmark:
+ vm_ivar_embedded_obj_init: |
+ c.set_ivars
+loop_count: 30000000
diff --git a/benchmark/vm_ivar_init.yml b/benchmark/vm_ivar_extended_obj_init.yml
index c6f1633907..f054bab282 100644
--- a/benchmark/vm_ivar_init.yml
+++ b/benchmark/vm_ivar_extended_obj_init.yml
@@ -1,6 +1,6 @@
prelude: |
class C
- def initialize
+ def set_ivars
@a = nil
@b = nil
@c = nil
@@ -8,7 +8,9 @@ prelude: |
@e = nil
end
end
+
+ c = C.new
benchmark:
- vm_ivar_init: |
- C.new
+ vm_ivar_extended_obj_init: |
+ c.set_ivars
loop_count: 30000000
diff --git a/benchmark/vm_ivar_generic_get.yml b/benchmark/vm_ivar_generic_get.yml
new file mode 100644
index 0000000000..dae2d37671
--- /dev/null
+++ b/benchmark/vm_ivar_generic_get.yml
@@ -0,0 +1,17 @@
+prelude: |
+ class C < Array
+ attr_reader :a, :b, :c
+ def initialize
+ @a = nil
+ @b = nil
+ @c = nil
+ end
+ end
+
+ c = C.new
+benchmark:
+ vm_ivar_generic_get: |
+ c.a
+ c.b
+ c.c
+loop_count: 30000000
diff --git a/benchmark/vm_ivar_generic_set.yml b/benchmark/vm_ivar_generic_set.yml
new file mode 100644
index 0000000000..102a6577fb
--- /dev/null
+++ b/benchmark/vm_ivar_generic_set.yml
@@ -0,0 +1,14 @@
+prelude: |
+ class C < Array
+ def set_ivars
+ @a = nil
+ @b = nil
+ @c = nil
+ end
+ end
+
+ c = C.new
+benchmark:
+ vm_ivar_generic_set: |
+ c.set_ivars
+loop_count: 30000000
diff --git a/benchmark/vm_ivar_get.yml b/benchmark/vm_ivar_get.yml
new file mode 100644
index 0000000000..9174af6965
--- /dev/null
+++ b/benchmark/vm_ivar_get.yml
@@ -0,0 +1,37 @@
+prelude: |
+ class Example
+ def initialize
+ @v0 = 1
+ @v1 = 2
+ @v3 = 3
+ @levar = 1
+ end
+
+ def get_value_loop
+ sum = 0
+
+ i = 0
+ while i < 1000000
+ # 10 times to de-emphasize loop overhead
+ sum += @levar
+ sum += @levar
+ sum += @levar
+ sum += @levar
+ sum += @levar
+ sum += @levar
+ sum += @levar
+ sum += @levar
+ sum += @levar
+ sum += @levar
+ i += 1
+ end
+
+ return sum
+ end
+ end
+
+ obj = Example.new
+benchmark:
+ vm_ivar_get: |
+ obj.get_value_loop
+loop_count: 100
diff --git a/benchmark/vm_ivar_get_unintialized.yml b/benchmark/vm_ivar_get_unintialized.yml
new file mode 100644
index 0000000000..a1ccfb06ce
--- /dev/null
+++ b/benchmark/vm_ivar_get_unintialized.yml
@@ -0,0 +1,12 @@
+prelude: |
+ class Example
+ def read
+ @uninitialized
+ end
+ end
+
+ obj = Example.new
+benchmark:
+ vm_ivar_get_uninitialized: |
+ obj.read
+loop_count: 30000000
diff --git a/benchmark/vm_ivar_lazy_set.yml b/benchmark/vm_ivar_lazy_set.yml
new file mode 100644
index 0000000000..7372ffcfbc
--- /dev/null
+++ b/benchmark/vm_ivar_lazy_set.yml
@@ -0,0 +1,12 @@
+prelude: |
+ class Example
+ def lazy_set
+ @uninitialized ||= 123
+ end
+ end
+
+ objs = 10000000.times.map { Example.new }
+benchmark:
+ vm_ivar_lazy_set: |
+ objs.each(&:lazy_set)
+loop_count: 1
diff --git a/benchmark/vm_ivar_set_on_instance.yml b/benchmark/vm_ivar_set_on_instance.yml
new file mode 100644
index 0000000000..91857b7742
--- /dev/null
+++ b/benchmark/vm_ivar_set_on_instance.yml
@@ -0,0 +1,35 @@
+prelude: |
+ class TheClass
+ def initialize
+ @v0 = 1
+ @v1 = 2
+ @v3 = 3
+ @levar = 1
+ end
+
+ def set_value_loop
+ # 1M
+ i = 0
+ while i < 1000000
+ # 10 times to de-emphasize loop overhead
+ @levar = i
+ @levar = i
+ @levar = i
+ @levar = i
+ @levar = i
+ @levar = i
+ @levar = i
+ @levar = i
+ @levar = i
+ @levar = i
+ i += 1
+ end
+ end
+ end
+
+ obj = TheClass.new
+
+benchmark:
+ vm_ivar_set_on_instance: |
+ obj.set_value_loop
+loop_count: 100
diff --git a/benchmark/vm_ivar_set_subclass.yml b/benchmark/vm_ivar_set_subclass.yml
index 2653d36ded..bc8bf5bf6b 100644
--- a/benchmark/vm_ivar_set_subclass.yml
+++ b/benchmark/vm_ivar_set_subclass.yml
@@ -1,6 +1,6 @@
prelude: |
class A
- def initialize
+ def set_ivars
@a = nil
@b = nil
@c = nil
@@ -10,8 +10,11 @@ prelude: |
end
class B < A; end
class C < A; end
+
+ b = B.new
+ c = C.new
benchmark:
vm_ivar_init_subclass: |
- B.new
- C.new
+ b.set_ivars
+ c.set_ivars
loop_count: 3000000
diff --git a/benchmark/vm_lvar_cond_set.yml b/benchmark/vm_lvar_cond_set.yml
new file mode 100644
index 0000000000..1845f9d12e
--- /dev/null
+++ b/benchmark/vm_lvar_cond_set.yml
@@ -0,0 +1,8 @@
+benchmark:
+ vm_lvar_cond_set: |
+ a ||= 1
+ b ||= 1
+ c ||= 1
+ d ||= 1
+ nil
+loop_count: 30000000
diff --git a/bignum.c b/bignum.c
index f83fbe2c14..cb2c3b6f07 100644
--- a/bignum.c
+++ b/bignum.c
@@ -23,8 +23,14 @@
# include <ieeefp.h>
#endif
+#if !defined(USE_GMP)
#if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H)
-# define USE_GMP
+# define USE_GMP 1
+#else
+# define USE_GMP 0
+#endif
+#endif
+#if USE_GMP
# include <gmp.h>
#endif
@@ -99,8 +105,8 @@ STATIC_ASSERT(sizeof_long_and_sizeof_bdigit, SIZEOF_BDIGIT % SIZEOF_LONG == 0);
#endif
#define BIGZEROP(x) (BIGNUM_LEN(x) == 0 || \
- (BDIGITS(x)[0] == 0 && \
- (BIGNUM_LEN(x) == 1 || bigzero_p(x))))
+ (BDIGITS(x)[0] == 0 && \
+ (BIGNUM_LEN(x) == 1 || bigzero_p(x))))
#define BIGSIZE(x) (BIGNUM_LEN(x) == 0 ? (size_t)0 : \
BDIGITS(x)[BIGNUM_LEN(x)-1] ? \
(size_t)(BIGNUM_LEN(x)*SIZEOF_BDIGIT - nlz(BDIGITS(x)[BIGNUM_LEN(x)-1])/CHAR_BIT) : \
@@ -145,7 +151,7 @@ STATIC_ASSERT(sizeof_long_and_sizeof_bdigit, SIZEOF_BDIGIT % SIZEOF_LONG == 0);
#define GMP_DIV_DIGITS 20
#define GMP_BIG2STR_DIGITS 20
#define GMP_STR2BIG_DIGITS 20
-#ifdef USE_GMP
+#if USE_GMP
# define NAIVE_MUL_DIGITS GMP_MUL_DIGITS
#else
# define NAIVE_MUL_DIGITS KARATSUBA_MUL_DIGITS
@@ -413,9 +419,9 @@ bary_small_lshift(BDIGIT *zds, const BDIGIT *xds, size_t n, int shift)
assert(0 <= shift && shift < BITSPERDIG);
for (i=0; i<n; i++) {
- num = num | (BDIGIT_DBL)*xds++ << shift;
- *zds++ = BIGLO(num);
- num = BIGDN(num);
+ num = num | (BDIGIT_DBL)*xds++ << shift;
+ *zds++ = BIGLO(num);
+ num = BIGDN(num);
}
return BIGLO(num);
}
@@ -431,9 +437,9 @@ bary_small_rshift(BDIGIT *zds, const BDIGIT *xds, size_t n, int shift, BDIGIT hi
num = BIGUP(higher_bdigit);
for (i = 0; i < n; i++) {
BDIGIT x = xds[n - i - 1];
- num = (num | x) >> shift;
+ num = (num | x) >> shift;
zds[n - i - 1] = BIGLO(num);
- num = BIGUP(x);
+ num = BIGUP(x);
}
}
@@ -443,7 +449,7 @@ bary_zero_p(const BDIGIT *xds, size_t xn)
if (xn == 0)
return 1;
do {
- if (xds[--xn]) return 0;
+ if (xds[--xn]) return 0;
} while (xn);
return 1;
}
@@ -971,7 +977,7 @@ integer_unpack_num_bdigits_small(size_t numwords, size_t wordsize, size_t nails,
{
/* nlp_bits stands for number of leading padding bits */
size_t num_bits = (wordsize * CHAR_BIT - nails) * numwords;
- size_t num_bdigits = (num_bits + BITSPERDIG - 1) / BITSPERDIG;
+ size_t num_bdigits = roomof(num_bits, BITSPERDIG);
*nlp_bits_ret = (int)(num_bdigits * BITSPERDIG - num_bits);
return num_bdigits;
}
@@ -981,7 +987,7 @@ integer_unpack_num_bdigits_generic(size_t numwords, size_t wordsize, size_t nail
{
/* BITSPERDIG = SIZEOF_BDIGIT * CHAR_BIT */
/* num_bits = (wordsize * CHAR_BIT - nails) * numwords */
- /* num_bdigits = (num_bits + BITSPERDIG - 1) / BITSPERDIG */
+ /* num_bdigits = roomof(num_bits, BITSPERDIG) */
/* num_bits = CHAR_BIT * (wordsize * numwords) - nails * numwords = CHAR_BIT * num_bytes1 - nails * numwords */
size_t num_bytes1 = wordsize * numwords;
@@ -1344,9 +1350,9 @@ bary_subb(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yd
num = borrow ? -1 : 0;
for (i = 0; i < sn; i++) {
- num += (BDIGIT_DBL_SIGNED)xds[i] - yds[i];
- zds[i] = BIGLO(num);
- num = BIGDN(num);
+ num += (BDIGIT_DBL_SIGNED)xds[i] - yds[i];
+ zds[i] = BIGLO(num);
+ num = BIGDN(num);
}
if (yn <= xn) {
for (; i < xn; i++) {
@@ -1365,7 +1371,7 @@ bary_subb(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yd
}
if (num == 0) goto num_is_zero;
for (; i < zn; i++) {
- zds[i] = BDIGMAX;
+ zds[i] = BDIGMAX;
}
return 1;
@@ -1373,10 +1379,10 @@ bary_subb(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yd
if (xds == zds && xn == zn)
return 0;
for (; i < xn; i++) {
- zds[i] = xds[i];
+ zds[i] = xds[i];
}
for (; i < zn; i++) {
- zds[i] = 0;
+ zds[i] = 0;
}
return 0;
}
@@ -1403,27 +1409,27 @@ bary_addc(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yd
assert(yn <= zn);
if (xn > yn) {
- const BDIGIT *tds;
- tds = xds; xds = yds; yds = tds;
- i = xn; xn = yn; yn = i;
+ const BDIGIT *tds;
+ tds = xds; xds = yds; yds = tds;
+ i = xn; xn = yn; yn = i;
}
num = carry ? 1 : 0;
for (i = 0; i < xn; i++) {
- num += (BDIGIT_DBL)xds[i] + yds[i];
- zds[i] = BIGLO(num);
- num = BIGDN(num);
+ num += (BDIGIT_DBL)xds[i] + yds[i];
+ zds[i] = BIGLO(num);
+ num = BIGDN(num);
}
for (; i < yn; i++) {
if (num == 0) goto num_is_zero;
- num += yds[i];
- zds[i] = BIGLO(num);
- num = BIGDN(num);
+ num += yds[i];
+ zds[i] = BIGLO(num);
+ num = BIGDN(num);
}
for (; i < zn; i++) {
if (num == 0) goto num_is_zero;
- zds[i] = BIGLO(num);
- num = BIGDN(num);
+ zds[i] = BIGLO(num);
+ num = BIGDN(num);
}
return num != 0;
@@ -1431,10 +1437,10 @@ bary_addc(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yd
if (yds == zds && yn == zn)
return 0;
for (; i < yn; i++) {
- zds[i] = yds[i];
+ zds[i] = yds[i];
}
for (; i < zn; i++) {
- zds[i] = 0;
+ zds[i] = 0;
}
return 0;
}
@@ -1573,7 +1579,7 @@ rb_big_mul_normal(VALUE x, VALUE y)
/* efficient squaring (2 times faster than normal multiplication)
* ref: Handbook of Applied Cryptography, Algorithm 14.16
- * http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
+ * https://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
*/
static void
bary_sq_fast(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn)
@@ -1591,30 +1597,30 @@ bary_sq_fast(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn)
return;
for (i = 0; i < xn-1; i++) {
- v = (BDIGIT_DBL)xds[i];
- if (!v)
+ v = (BDIGIT_DBL)xds[i];
+ if (!v)
continue;
- c = (BDIGIT_DBL)zds[i + i] + v * v;
- zds[i + i] = BIGLO(c);
- c = BIGDN(c);
- v *= 2;
+ c = (BDIGIT_DBL)zds[i + i] + v * v;
+ zds[i + i] = BIGLO(c);
+ c = BIGDN(c);
+ v *= 2;
vl = BIGLO(v);
vh = (int)BIGDN(v);
- for (j = i + 1; j < xn; j++) {
- w = (BDIGIT_DBL)xds[j];
- c += (BDIGIT_DBL)zds[i + j] + vl * w;
- zds[i + j] = BIGLO(c);
- c = BIGDN(c);
- if (vh)
+ for (j = i + 1; j < xn; j++) {
+ w = (BDIGIT_DBL)xds[j];
+ c += (BDIGIT_DBL)zds[i + j] + vl * w;
+ zds[i + j] = BIGLO(c);
+ c = BIGDN(c);
+ if (vh)
c += w;
- }
- if (c) {
- c += (BDIGIT_DBL)zds[i + xn];
- zds[i + xn] = BIGLO(c);
- c = BIGDN(c);
+ }
+ if (c) {
+ c += (BDIGIT_DBL)zds[i + xn];
+ zds[i + xn] = BIGLO(c);
+ c = BIGDN(c);
if (c)
zds[i + xn + 1] += (BDIGIT)c;
- }
+ }
}
/* i == xn-1 */
@@ -1639,6 +1645,12 @@ rb_big_sq_fast(VALUE x)
return z;
}
+static inline size_t
+max_size(size_t a, size_t b)
+{
+ return (a > b ? a : b);
+}
+
/* balancing multiplication by slicing larger argument */
static void
bary_mul_balance_with_mulfunc(BDIGIT *const zds, const size_t zn,
@@ -1656,8 +1668,14 @@ bary_mul_balance_with_mulfunc(BDIGIT *const zds, const size_t zn,
BDIGITS_ZERO(zds, xn);
if (wn < xn) {
- const size_t r = (yn % xn) ? (yn % xn) : xn;
- if ((2 * xn + yn + r) > zn) {
+ /* The condition when a new buffer is needed:
+ * 1. (2(xn+r) > zn-(yn-r)) => (2xn+r > zn-yn), at the last
+ * iteration (or r == 0)
+ * 2. (2(xn+xn) > zn-(yn-r-xn)) => (3xn-r > zn-yn), at the
+ * previous iteration.
+ */
+ const size_t r = yn % xn;
+ if (2*xn + yn + max_size(xn-r, r) > zn) {
wn = xn;
wds = ALLOCV_N(BDIGIT, work, wn);
}
@@ -1692,7 +1710,7 @@ bary_mul_balance_with_mulfunc(BDIGIT *const zds, const size_t zn,
zds + n, tn,
wds, xn);
}
- n += r;
+ n += r;
}
BDIGITS_ZERO(zds+xn+yn, zn - (xn+yn));
@@ -2084,21 +2102,21 @@ bary_mul_toom3(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGI
v3n = u3n; v3ds = u3ds; v3p = u3p;
}
else {
- /* v1 <- y0 + y2 */
+ /* v1 <- y0 + y2 */
bary_add(v1ds, v1n, y0ds, y0n, y2ds, y2n);
v1p = 1;
- /* y(-1) : v2 <- v1 - y1 = y0 - y1 + y2 */
+ /* y(-1) : v2 <- v1 - y1 = y0 - y1 + y2 */
v2p = 1;
if (bary_sub(v2ds, v2n, v1ds, v1n, y1ds, y1n)) {
bary_2comp(v2ds, v2n);
v2p = 0;
}
- /* y(1) : v1 <- v1 + y1 = y0 + y1 + y2 */
+ /* y(1) : v1 <- v1 + y1 = y0 + y1 + y2 */
bary_add(v1ds, v1n, v1ds, v1n, y1ds, y1n);
- /* y(-2) : v3 <- 2 * (v2 + y2) - y0 = y0 - 2 * (y1 - 2 * y2) */
+ /* y(-2) : v3 <- 2 * (v2 + y2) - y0 = y0 - 2 * (y1 - 2 * y2) */
v3p = 1;
if (v2p) {
bary_add(v3ds, v3n, v2ds, v2n, y2ds, y2n);
@@ -2291,7 +2309,7 @@ rb_big_mul_toom3(VALUE x, VALUE y)
return z;
}
-#ifdef USE_GMP
+#if USE_GMP
static inline void
bdigits_to_mpz(mpz_t mp, const BDIGIT *digits, size_t len)
{
@@ -2429,8 +2447,8 @@ bary_mul_precheck(BDIGIT **zdsp, size_t *znp, const BDIGIT **xdsp, size_t *xnp,
if (xn > yn) {
const BDIGIT *tds;
size_t tn;
- tds = xds; xds = yds; yds = tds;
- tn = xn; xn = yn; yn = tn;
+ tds = xds; xds = yds; yds = tds;
+ tn = xn; xn = yn; yn = tn;
}
assert(xn <= yn);
@@ -2556,7 +2574,7 @@ bary_mul(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds
}
}
-#ifdef USE_GMP
+#if USE_GMP
bary_mul_gmp(zds, zn, xds, xn, yds, yn);
#else
bary_mul_toom3_start(zds, zn, xds, xn, yds, yn, NULL, 0);
@@ -2580,26 +2598,26 @@ bigdivrem1(void *ptr)
BDIGIT q;
do {
- if (bds->stop) {
- bds->zn = zn;
- return 0;
+ if (bds->stop) {
+ bds->zn = zn;
+ return 0;
}
- if (zds[zn-1] == yds[yn-1]) q = BDIGMAX;
- else q = (BDIGIT)((BIGUP(zds[zn-1]) + zds[zn-2])/yds[yn-1]);
- if (q) {
+ if (zds[zn-1] == yds[yn-1]) q = BDIGMAX;
+ else q = (BDIGIT)((BIGUP(zds[zn-1]) + zds[zn-2])/yds[yn-1]);
+ if (q) {
num = bigdivrem_mulsub(zds+zn-(yn+1), yn+1,
q,
yds, yn);
- while (num) { /* "add back" required */
- q--;
+ while (num) { /* "add back" required */
+ q--;
num = bary_add(zds+zn-(yn+1), yn,
zds+zn-(yn+1), yn,
yds, yn);
num--;
- }
- }
+ }
+ }
zn--;
- zds[zn] = q;
+ zds[zn] = q;
} while (zn > yn);
return 0;
}
@@ -2668,16 +2686,16 @@ bigdivrem_restoring(BDIGIT *zds, size_t zn, BDIGIT *yds, size_t yn)
bds.zn = zn - ynzero;
if (bds.zn > 10000 || bds.yn > 10000) {
retry:
- bds.stop = Qfalse;
+ bds.stop = Qfalse;
rb_nogvl(bigdivrem1, &bds, rb_big_stop, &bds, RB_NOGVL_UBF_ASYNC_SAFE);
- if (bds.stop == Qtrue) {
- /* execute trap handler, but exception was not raised. */
- goto retry;
- }
+ if (bds.stop == Qtrue) {
+ /* execute trap handler, but exception was not raised. */
+ goto retry;
+ }
}
else {
- bigdivrem1(&bds);
+ bigdivrem1(&bds);
}
}
@@ -2776,7 +2794,7 @@ rb_big_divrem_normal(VALUE x, VALUE y)
return rb_assoc_new(q, r);
}
-#ifdef USE_GMP
+#if USE_GMP
static void
bary_divmod_gmp(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
{
@@ -2860,7 +2878,7 @@ rb_big_divrem_gmp(VALUE x, VALUE y)
static void
bary_divmod_branch(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
{
-#ifdef USE_GMP
+#if USE_GMP
if (GMP_DIV_DIGITS < xn) {
bary_divmod_gmp(qds, qn, rds, rn, xds, xn, yds, yn);
return;
@@ -2935,7 +2953,7 @@ int
rb_cmpint(VALUE val, VALUE a, VALUE b)
{
if (NIL_P(val)) {
- rb_cmperr(a, b);
+ rb_cmperr(a, b);
}
if (FIXNUM_P(val)) {
long l = FIX2LONG(val);
@@ -2944,9 +2962,9 @@ rb_cmpint(VALUE val, VALUE a, VALUE b)
return 0;
}
if (RB_BIGNUM_TYPE_P(val)) {
- if (BIGZEROP(val)) return 0;
- if (BIGNUM_SIGN(val)) return 1;
- return -1;
+ if (BIGZEROP(val)) return 0;
+ if (BIGNUM_SIGN(val)) return 1;
+ return -1;
}
if (RTEST(rb_funcall(val, '>', 1, INT2FIX(0)))) return 1;
if (RTEST(rb_funcall(val, '<', 1, INT2FIX(0)))) return -1;
@@ -2956,8 +2974,8 @@ rb_cmpint(VALUE val, VALUE a, VALUE b)
#define BIGNUM_SET_LEN(b,l) \
(BIGNUM_EMBED_P(b) ? \
(void)(RBASIC(b)->flags = \
- (RBASIC(b)->flags & ~BIGNUM_EMBED_LEN_MASK) | \
- ((l) << BIGNUM_EMBED_LEN_SHIFT)) : \
+ (RBASIC(b)->flags & ~BIGNUM_EMBED_LEN_MASK) | \
+ ((l) << BIGNUM_EMBED_LEN_SHIFT)) : \
(void)(RBIGNUM(b)->as.heap.len = (l)))
static void
@@ -2965,33 +2983,33 @@ rb_big_realloc(VALUE big, size_t len)
{
BDIGIT *ds;
if (BIGNUM_EMBED_P(big)) {
- if (BIGNUM_EMBED_LEN_MAX < len) {
- ds = ALLOC_N(BDIGIT, len);
- MEMCPY(ds, RBIGNUM(big)->as.ary, BDIGIT, BIGNUM_EMBED_LEN_MAX);
- RBIGNUM(big)->as.heap.len = BIGNUM_LEN(big);
- RBIGNUM(big)->as.heap.digits = ds;
+ if (BIGNUM_EMBED_LEN_MAX < len) {
+ ds = ALLOC_N(BDIGIT, len);
+ MEMCPY(ds, RBIGNUM(big)->as.ary, BDIGIT, BIGNUM_EMBED_LEN_MAX);
+ RBIGNUM(big)->as.heap.len = BIGNUM_LEN(big);
+ RBIGNUM(big)->as.heap.digits = ds;
FL_UNSET_RAW(big, BIGNUM_EMBED_FLAG);
- }
+ }
}
else {
- if (len <= BIGNUM_EMBED_LEN_MAX) {
- ds = RBIGNUM(big)->as.heap.digits;
+ if (len <= BIGNUM_EMBED_LEN_MAX) {
+ ds = RBIGNUM(big)->as.heap.digits;
FL_SET_RAW(big, BIGNUM_EMBED_FLAG);
- BIGNUM_SET_LEN(big, len);
+ BIGNUM_SET_LEN(big, len);
(void)VALGRIND_MAKE_MEM_UNDEFINED((void*)RBIGNUM(big)->as.ary, sizeof(RBIGNUM(big)->as.ary));
- if (ds) {
- MEMCPY(RBIGNUM(big)->as.ary, ds, BDIGIT, len);
- xfree(ds);
- }
- }
- else {
- if (BIGNUM_LEN(big) == 0) {
- RBIGNUM(big)->as.heap.digits = ALLOC_N(BDIGIT, len);
- }
- else {
- REALLOC_N(RBIGNUM(big)->as.heap.digits, BDIGIT, len);
- }
- }
+ if (ds) {
+ MEMCPY(RBIGNUM(big)->as.ary, ds, BDIGIT, len);
+ xfree(ds);
+ }
+ }
+ else {
+ if (BIGNUM_LEN(big) == 0) {
+ RBIGNUM(big)->as.heap.digits = ALLOC_N(BDIGIT, len);
+ }
+ else {
+ REALLOC_N(RBIGNUM(big)->as.heap.digits, BDIGIT, len);
+ }
+ }
}
}
@@ -3077,7 +3095,7 @@ abs2twocomp(VALUE *xp, long *n_ret)
MEMCPY(BDIGITS(z), ds, BDIGIT, n);
bary_2comp(BDIGITS(z), n);
hibits = BDIGMAX;
- *xp = z;
+ *xp = z;
}
*n_ret = n;
return hibits;
@@ -3101,7 +3119,7 @@ bigtrunc(VALUE x)
if (len == 0) return x;
while (--len && !ds[len]);
if (BIGNUM_LEN(x) > len+1) {
- rb_big_resize(x, len+1);
+ rb_big_resize(x, len+1);
}
return x;
}
@@ -3154,7 +3172,7 @@ static VALUE
bignorm(VALUE x)
{
if (RB_BIGNUM_TYPE_P(x)) {
- x = bigfixize(x);
+ x = bigfixize(x);
}
return x;
}
@@ -3176,8 +3194,8 @@ rb_uint2big(uintptr_t n)
digits[0] = n;
#else
for (i = 0; i < bdigit_roomof(SIZEOF_VALUE); i++) {
- digits[i] = BIGLO(n);
- n = BIGDN(n);
+ digits[i] = BIGLO(n);
+ n = BIGDN(n);
}
#endif
@@ -3196,14 +3214,14 @@ rb_int2big(intptr_t n)
if (n < 0) {
u = 1 + (VALUE)(-(n + 1)); /* u = -n avoiding overflow */
- neg = 1;
+ neg = 1;
}
else {
u = n;
}
big = rb_uint2big(u);
if (neg) {
- BIGNUM_SET_NEGATIVE_SIGN(big);
+ BIGNUM_SET_NEGATIVE_SIGN(big);
}
return big;
}
@@ -3362,7 +3380,7 @@ absint_numwords_generic(size_t numbytes, int nlz_bits_in_msbyte, size_t word_num
if (sign == 2) {
#if defined __GNUC__ && (__GNUC__ == 4 && __GNUC_MINOR__ == 4)
- *nlz_bits_ret = 0;
+ *nlz_bits_ret = 0;
#endif
return (size_t)-1;
}
@@ -3682,7 +3700,7 @@ rb_integer_unpack(const void *words, size_t numwords, size_t wordsize, size_t na
}
else if (num_bdigits == numberof(fixbuf)) {
val = bignew((long)num_bdigits+1, 0);
- MEMCPY(BDIGITS(val), fixbuf, BDIGIT, num_bdigits);
+ MEMCPY(BDIGITS(val), fixbuf, BDIGIT, num_bdigits);
BDIGITS(val)[num_bdigits++] = 1;
}
else {
@@ -3694,9 +3712,9 @@ rb_integer_unpack(const void *words, size_t numwords, size_t wordsize, size_t na
BDIGIT_DBL u = fixbuf[0] + BIGUP(fixbuf[1]);
if (u == 0)
return LONG2FIX(0);
- if (0 < sign && POSFIXABLE(u))
+ if (0 < sign && POSFIXABLE(u))
return LONG2FIX((long)u);
- if (sign < 0 && BDIGIT_MSB(fixbuf[1]) == 0 &&
+ if (sign < 0 && BDIGIT_MSB(fixbuf[1]) == 0 &&
NEGFIXABLE(-(BDIGIT_DBL_SIGNED)u))
return LONG2FIX((long)-(BDIGIT_DBL_SIGNED)u);
val = bignew((long)num_bdigits, 0 <= sign);
@@ -3748,41 +3766,41 @@ str2big_scan_digits(const char *s, const char *str, int base, int badcheck, size
int c;
if (!len) {
- *num_digits_p = 0;
- *len_p = 0;
- return TRUE;
+ *num_digits_p = 0;
+ *len_p = 0;
+ return TRUE;
}
if (badcheck && *str == '_') return FALSE;
while ((c = *str++) != 0) {
- if (c == '_') {
- if (nondigit) {
+ if (c == '_') {
+ if (nondigit) {
if (badcheck) return FALSE;
- break;
- }
- nondigit = (char) c;
- }
- else if ((c = conv_digit(c)) < 0 || c >= base) {
- break;
- }
- else {
- nondigit = 0;
- num_digits++;
- digits_end = str;
- }
- if (len > 0 && !--len) break;
+ break;
+ }
+ nondigit = (char) c;
+ }
+ else if ((c = conv_digit(c)) < 0 || c >= base) {
+ break;
+ }
+ else {
+ nondigit = 0;
+ num_digits++;
+ digits_end = str;
+ }
+ if (len > 0 && !--len) break;
}
if (badcheck && nondigit) return FALSE;
if (badcheck && len) {
- str--;
- while (*str && ISSPACE(*str)) {
- str++;
- if (len > 0 && !--len) break;
- }
- if (len && *str) {
- return FALSE;
- }
+ str--;
+ while (*str && ISSPACE(*str)) {
+ str++;
+ if (len > 0 && !--len) break;
+ }
+ if (len && *str) {
+ return FALSE;
+ }
}
*num_digits_p = num_digits;
*len_p = digits_end - digits_start;
@@ -3957,7 +3975,7 @@ str2big_karatsuba(
return z;
}
-#ifdef USE_GMP
+#if USE_GMP
static VALUE
str2big_gmp(
int sign,
@@ -4024,8 +4042,8 @@ rb_cstr_to_inum(const char *str, int base, int badcheck)
char *end;
VALUE ret = rb_cstr_parse_inum(str, -1, (badcheck ? NULL : &end), base);
if (NIL_P(ret)) {
- if (badcheck) rb_invalid_str(str, "Integer()");
- ret = INT2FIX(0);
+ if (badcheck) rb_invalid_str(str, "Integer()");
+ ret = INT2FIX(0);
}
return ret;
}
@@ -4049,7 +4067,7 @@ rb_cstr_to_inum(const char *str, int base, int badcheck)
VALUE
rb_int_parse_cstr(const char *str, ssize_t len, char **endp, size_t *ndigits,
- int base, int flags)
+ int base, int flags)
{
const char *const s = str;
char sign = 1;
@@ -4066,82 +4084,82 @@ rb_int_parse_cstr(const char *str, ssize_t len, char **endp, size_t *ndigits,
const int badcheck = !endp;
#define ADV(n) do {\
- if (len > 0 && len <= (n)) goto bad; \
- str += (n); \
- len -= (n); \
+ if (len > 0 && len <= (n)) goto bad; \
+ str += (n); \
+ len -= (n); \
} while (0)
#define ASSERT_LEN() do {\
- assert(len != 0); \
- if (len0 >= 0) assert(s + len0 == str + len); \
+ assert(len != 0); \
+ if (len0 >= 0) assert(s + len0 == str + len); \
} while (0)
if (!str) {
goto bad;
}
if (len && (flags & RB_INT_PARSE_SIGN)) {
- while (ISSPACE(*str)) ADV(1);
+ while (ISSPACE(*str)) ADV(1);
- if (str[0] == '+') {
- ADV(1);
- }
- else if (str[0] == '-') {
- ADV(1);
- sign = 0;
- }
- ASSERT_LEN();
+ if (str[0] == '+') {
+ ADV(1);
+ }
+ else if (str[0] == '-') {
+ ADV(1);
+ sign = 0;
+ }
+ ASSERT_LEN();
}
if (base <= 0) {
- if (str[0] == '0' && len > 1) {
- switch (str[1]) {
- case 'x': case 'X':
- base = 16;
- ADV(2);
- break;
- case 'b': case 'B':
- base = 2;
- ADV(2);
- break;
- case 'o': case 'O':
- base = 8;
- ADV(2);
- break;
- case 'd': case 'D':
- base = 10;
- ADV(2);
- break;
- default:
- base = 8;
- }
- }
- else if (base < -1) {
- base = -base;
- }
- else {
- base = 10;
- }
+ if (str[0] == '0' && len > 1) {
+ switch (str[1]) {
+ case 'x': case 'X':
+ base = 16;
+ ADV(2);
+ break;
+ case 'b': case 'B':
+ base = 2;
+ ADV(2);
+ break;
+ case 'o': case 'O':
+ base = 8;
+ ADV(2);
+ break;
+ case 'd': case 'D':
+ base = 10;
+ ADV(2);
+ break;
+ default:
+ base = 8;
+ }
+ }
+ else if (base < -1) {
+ base = -base;
+ }
+ else {
+ base = 10;
+ }
}
else if (len == 1 || !(flags & RB_INT_PARSE_PREFIX)) {
- /* no prefix */
+ /* no prefix */
}
else if (base == 2) {
- if (str[0] == '0' && (str[1] == 'b'||str[1] == 'B')) {
- ADV(2);
- }
+ if (str[0] == '0' && (str[1] == 'b'||str[1] == 'B')) {
+ ADV(2);
+ }
}
else if (base == 8) {
- if (str[0] == '0' && (str[1] == 'o'||str[1] == 'O')) {
- ADV(2);
- }
+ if (str[0] == '0' && (str[1] == 'o'||str[1] == 'O')) {
+ ADV(2);
+ }
}
else if (base == 10) {
- if (str[0] == '0' && (str[1] == 'd'||str[1] == 'D')) {
- ADV(2);
- }
+ if (str[0] == '0' && (str[1] == 'd'||str[1] == 'D')) {
+ ADV(2);
+ }
}
else if (base == 16) {
- if (str[0] == '0' && (str[1] == 'x'||str[1] == 'X')) {
- ADV(2);
- }
+ if (str[0] == '0' && (str[1] == 'x'||str[1] == 'X')) {
+ ADV(2);
+ }
}
if (!valid_radix_p(base)) {
invalid_radix(base);
@@ -4149,80 +4167,79 @@ rb_int_parse_cstr(const char *str, ssize_t len, char **endp, size_t *ndigits,
if (!len) goto bad;
num_digits = str - s;
if (*str == '0' && len != 1) { /* squeeze preceding 0s */
- int us = 0;
- const char *end = len < 0 ? NULL : str + len;
- ++num_digits;
- while ((c = *++str) == '0' ||
- ((flags & RB_INT_PARSE_UNDERSCORE) && c == '_')) {
- if (c == '_') {
- if (++us >= 2)
- break;
- }
- else {
- ++num_digits;
- us = 0;
- }
- if (str == end) break;
- }
- if (!c || ISSPACE(c)) --str;
- if (end) len = end - str;
- ASSERT_LEN();
+ int us = 0;
+ const char *end = len < 0 ? NULL : str + len;
+ ++num_digits;
+ while ((c = *++str) == '0' ||
+ ((flags & RB_INT_PARSE_UNDERSCORE) && c == '_')) {
+ if (c == '_') {
+ if (++us >= 2)
+ break;
+ }
+ else {
+ ++num_digits;
+ us = 0;
+ }
+ if (str == end) break;
+ }
+ if (!c || ISSPACE(c)) --str;
+ if (end) len = end - str;
}
c = *str;
c = conv_digit(c);
if (c < 0 || c >= base) {
- if (!badcheck && num_digits) z = INT2FIX(0);
- goto bad;
+ if (!badcheck && num_digits) z = INT2FIX(0);
+ goto bad;
}
if (ndigits) *ndigits = num_digits;
val = ruby_scan_digits(str, len, base, &num_digits, &ov);
if (!ov) {
- const char *end = &str[num_digits];
- if (num_digits > 0 && *end == '_' && (flags & RB_INT_PARSE_UNDERSCORE))
- goto bigparse;
- if (endp) *endp = (char *)end;
- if (ndigits) *ndigits += num_digits;
- if (badcheck) {
- if (num_digits == 0) return Qnil; /* no number */
- while (len < 0 ? *end : end < str + len) {
- if (!ISSPACE(*end)) return Qnil; /* trailing garbage */
- end++;
- }
- }
-
- if (POSFIXABLE(val)) {
- if (sign) return LONG2FIX(val);
- else {
- long result = -(long)val;
- return LONG2FIX(result);
- }
- }
- else {
- VALUE big = rb_uint2big(val);
- BIGNUM_SET_SIGN(big, sign);
- return bignorm(big);
- }
+ const char *end = &str[num_digits];
+ if (num_digits > 0 && *end == '_' && (flags & RB_INT_PARSE_UNDERSCORE))
+ goto bigparse;
+ if (endp) *endp = (char *)end;
+ if (ndigits) *ndigits += num_digits;
+ if (badcheck) {
+ if (num_digits == 0) return Qnil; /* no number */
+ while (len < 0 ? *end : end < str + len) {
+ if (!ISSPACE(*end)) return Qnil; /* trailing garbage */
+ end++;
+ }
+ }
+
+ if (POSFIXABLE(val)) {
+ if (sign) return LONG2FIX(val);
+ else {
+ long result = -(long)val;
+ return LONG2FIX(result);
+ }
+ }
+ else {
+ VALUE big = rb_uint2big(val);
+ BIGNUM_SET_SIGN(big, sign);
+ return bignorm(big);
+ }
}
bigparse:
digits_start = str;
if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &len))
- goto bad;
+ goto bad;
if (endp) *endp = (char *)(str + len);
if (ndigits) *ndigits += num_digits;
digits_end = digits_start + len;
if (POW2_P(base)) {
z = str2big_poweroftwo(sign, digits_start, digits_end, num_digits,
- bit_length(base-1));
+ bit_length(base-1));
}
else {
int digits_per_bdigits_dbl;
maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
-#ifdef USE_GMP
+#if USE_GMP
if (GMP_STR2BIG_DIGITS < num_bdigits) {
z = str2big_gmp(sign, digits_start, digits_end, num_digits,
num_bdigits, base);
@@ -4251,7 +4268,7 @@ static VALUE
rb_cstr_parse_inum(const char *str, ssize_t len, char **endp, int base)
{
return rb_int_parse_cstr(str, len, endp, NULL, base,
- RB_INT_PARSE_DEFAULT);
+ RB_INT_PARSE_DEFAULT);
}
VALUE
@@ -4300,14 +4317,14 @@ rb_str2big_poweroftwo(VALUE arg, int base, int badcheck)
s = str = StringValueCStr(arg);
len = RSTRING_LEN(arg);
if (*str == '-') {
- len--;
+ len--;
str++;
positive_p = 0;
}
digits_start = str;
if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &len))
- invalid_integer(arg);
+ invalid_integer(arg);
digits_end = digits_start + len;
z = str2big_poweroftwo(positive_p, digits_start, digits_end, num_digits,
@@ -4339,14 +4356,14 @@ rb_str2big_normal(VALUE arg, int base, int badcheck)
s = str = StringValuePtr(arg);
len = RSTRING_LEN(arg);
if (len > 0 && *str == '-') {
- len--;
+ len--;
str++;
positive_p = 0;
}
digits_start = str;
if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &len))
- invalid_integer(arg);
+ invalid_integer(arg);
digits_end = digits_start + len;
maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
@@ -4381,14 +4398,14 @@ rb_str2big_karatsuba(VALUE arg, int base, int badcheck)
s = str = StringValuePtr(arg);
len = RSTRING_LEN(arg);
if (len > 0 && *str == '-') {
- len--;
+ len--;
str++;
positive_p = 0;
}
digits_start = str;
if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &len))
- invalid_integer(arg);
+ invalid_integer(arg);
digits_end = digits_start + len;
maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
@@ -4402,7 +4419,7 @@ rb_str2big_karatsuba(VALUE arg, int base, int badcheck)
return bignorm(z);
}
-#ifdef USE_GMP
+#if USE_GMP
VALUE
rb_str2big_gmp(VALUE arg, int base, int badcheck)
{
@@ -4424,14 +4441,14 @@ rb_str2big_gmp(VALUE arg, int base, int badcheck)
s = str = StringValuePtr(arg);
len = RSTRING_LEN(arg);
if (len > 0 && *str == '-') {
- len--;
+ len--;
str++;
positive_p = 0;
}
digits_start = str;
if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &len))
- invalid_integer(arg);
+ invalid_integer(arg);
digits_end = digits_start + len;
maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
@@ -4458,8 +4475,8 @@ rb_ull2big(unsigned LONG_LONG n)
digits[0] = n;
#else
for (i = 0; i < bdigit_roomof(SIZEOF_LONG_LONG); i++) {
- digits[i] = BIGLO(n);
- n = BIGDN(n);
+ digits[i] = BIGLO(n);
+ n = BIGDN(n);
}
#endif
@@ -4478,14 +4495,14 @@ rb_ll2big(LONG_LONG n)
if (n < 0) {
u = 1 + (unsigned LONG_LONG)(-(n + 1)); /* u = -n avoiding overflow */
- neg = 1;
+ neg = 1;
}
else {
u = n;
}
big = rb_ull2big(u);
if (neg) {
- BIGNUM_SET_NEGATIVE_SIGN(big);
+ BIGNUM_SET_NEGATIVE_SIGN(big);
}
return big;
}
@@ -4515,7 +4532,7 @@ rb_uint128t2big(uint128_t n)
BDIGIT *digits = BDIGITS(big);
for (i = 0; i < bdigit_roomof(SIZEOF_INT128_T); i++) {
- digits[i] = BIGLO(RSHIFT(n ,BITSPERDIG*i));
+ digits[i] = BIGLO(RSHIFT(n ,BITSPERDIG*i));
}
i = bdigit_roomof(SIZEOF_INT128_T);
@@ -4533,14 +4550,14 @@ rb_int128t2big(int128_t n)
if (n < 0) {
u = 1 + (uint128_t)(-(n + 1)); /* u = -n avoiding overflow */
- neg = 1;
+ neg = 1;
}
else {
u = n;
}
big = rb_uint128t2big(u);
if (neg) {
- BIGNUM_SET_NEGATIVE_SIGN(big);
+ BIGNUM_SET_NEGATIVE_SIGN(big);
}
return big;
}
@@ -4569,11 +4586,14 @@ big_shift3(VALUE x, int lshift_p, size_t shift_numdigits, int shift_numbits)
if (lshift_p) {
if (LONG_MAX < shift_numdigits) {
- rb_raise(rb_eArgError, "too big number");
+ too_big:
+ rb_raise(rb_eRangeError, "shift width too big");
}
s1 = shift_numdigits;
s2 = shift_numbits;
+ if ((size_t)s1 != shift_numdigits) goto too_big;
xn = BIGNUM_LEN(x);
+ if (LONG_MAX/SIZEOF_BDIGIT <= xn+s1) goto too_big;
z = bignew(xn+s1+1, BIGNUM_SIGN(x));
zds = BDIGITS(z);
BDIGITS_ZERO(zds, s1);
@@ -4703,7 +4723,7 @@ power_cache_get_power(int base, int power_level, size_t *numdigits_ret)
rb_obj_hide(power);
base36_power_cache[base - 2][power_level] = power;
base36_numdigits_cache[base - 2][power_level] = numdigits;
- rb_gc_register_mark_object(power);
+ rb_gc_register_mark_object(power);
}
if (numdigits_ret)
*numdigits_ret = base36_numdigits_cache[base - 2][power_level];
@@ -4754,7 +4774,7 @@ big2str_2bdigits(struct big2str_struct *b2s, BDIGIT *xds, size_t xn, size_t tail
} while (num);
len = sizeof(buf) - j;
big2str_alloc(b2s, len + taillen);
- MEMCPY(b2s->ptr, buf + j, char, len);
+ MEMCPY(b2s->ptr, buf + j, char, len);
}
else {
p = b2s->ptr;
@@ -4771,7 +4791,7 @@ big2str_2bdigits(struct big2str_struct *b2s, BDIGIT *xds, size_t xn, size_t tail
static void
big2str_karatsuba(struct big2str_struct *b2s, BDIGIT *xds, size_t xn, size_t wn,
- int power_level, size_t taillen)
+ int power_level, size_t taillen)
{
VALUE b;
size_t half_numdigits, lower_numdigits;
@@ -4801,17 +4821,17 @@ big2str_karatsuba(struct big2str_struct *b2s, BDIGIT *xds, size_t xn, size_t wn,
*/
if (xn == 0 || bary_zero_p(xds, xn)) {
- if (b2s->ptr) {
+ if (b2s->ptr) {
/* When x is zero, power_cache_get_power(base, power_level) should be cached already. */
power_cache_get_power(b2s->base, power_level, &len);
- memset(b2s->ptr, '0', len);
+ memset(b2s->ptr, '0', len);
b2s->ptr += len;
- }
+ }
return;
}
if (power_level == 0) {
- big2str_2bdigits(b2s, xds, xn, taillen);
+ big2str_2bdigits(b2s, xds, xn, taillen);
return;
}
@@ -4839,7 +4859,7 @@ big2str_karatsuba(struct big2str_struct *b2s, BDIGIT *xds, size_t xn, size_t wn,
memset(b2s->ptr, '0', len);
b2s->ptr += len;
}
- big2str_2bdigits(b2s, xds, xn, taillen);
+ big2str_2bdigits(b2s, xds, xn, taillen);
}
else {
BDIGIT *qds, *rds;
@@ -4943,11 +4963,11 @@ big2str_generic(VALUE x, int base)
BARY_TRUNC(xds, xn);
if (xn == 0) {
- return rb_usascii_str_new2("0");
+ return rb_usascii_str_new2("0");
}
if (!valid_radix_p(base))
- invalid_radix(base);
+ invalid_radix(base);
if (xn >= LONG_MAX/BITSPERDIG) {
rb_raise(rb_eRangeError, "bignum too big to convert into `string'");
@@ -4984,7 +5004,7 @@ big2str_generic(VALUE x, int base)
b2s_data.ptr = NULL;
if (power_level == 0) {
- big2str_2bdigits(&b2s_data, xds, xn, 0);
+ big2str_2bdigits(&b2s_data, xds, xn, 0);
}
else {
VALUE tmpw = 0;
@@ -4993,7 +5013,7 @@ big2str_generic(VALUE x, int base)
wn = power_level * BIGDIVREM_EXTRA_WORDS + BIGNUM_LEN(power);
wds = ALLOCV_N(BDIGIT, tmpw, xn + wn);
MEMCPY(wds, xds, BDIGIT, xn);
- big2str_karatsuba(&b2s_data, wds, xn, wn, power_level, 0);
+ big2str_karatsuba(&b2s_data, wds, xn, wn, power_level, 0);
if (tmpw)
ALLOCV_END(tmpw);
}
@@ -5012,7 +5032,7 @@ rb_big2str_generic(VALUE x, int base)
return big2str_generic(x, base);
}
-#ifdef USE_GMP
+#if USE_GMP
static VALUE
big2str_gmp(VALUE x, int base)
{
@@ -5059,7 +5079,7 @@ rb_big2str1(VALUE x, int base)
size_t xn;
if (FIXNUM_P(x)) {
- return rb_fix2str(x, base);
+ return rb_fix2str(x, base);
}
bigtrunc(x);
@@ -5068,11 +5088,11 @@ rb_big2str1(VALUE x, int base)
BARY_TRUNC(xds, xn);
if (xn == 0) {
- return rb_usascii_str_new2("0");
+ return rb_usascii_str_new2("0");
}
if (!valid_radix_p(base))
- invalid_radix(base);
+ invalid_radix(base);
if (xn >= LONG_MAX/BITSPERDIG) {
rb_raise(rb_eRangeError, "bignum too big to convert into `string'");
@@ -5083,7 +5103,7 @@ rb_big2str1(VALUE x, int base)
return big2str_base_poweroftwo(x, base);
}
-#ifdef USE_GMP
+#if USE_GMP
if (GMP_BIG2STR_DIGITS < xn) {
return big2str_gmp(x, base);
}
@@ -5119,7 +5139,7 @@ big2ulong(VALUE x, const char *type)
#else
num = 0;
for (i = 0; i < len; i++) {
- num <<= BITSPERDIG;
+ num <<= BITSPERDIG;
num += (unsigned long)ds[len - i - 1]; /* overflow is already checked */
}
#endif
@@ -5172,13 +5192,13 @@ big2ull(VALUE x, const char *type)
if (len == 0)
return 0;
if (BIGSIZE(x) > SIZEOF_LONG_LONG)
- rb_raise(rb_eRangeError, "bignum too big to convert into `%s'", type);
+ rb_raise(rb_eRangeError, "bignum too big to convert into `%s'", type);
#if SIZEOF_LONG_LONG <= SIZEOF_BDIGIT
num = (unsigned LONG_LONG)ds[0];