diff options
-rw-r--r-- | .gdbinit | 2 | ||||
-rw-r--r-- | NEWS.md | 5 | ||||
-rw-r--r-- | configure.ac | 15 | ||||
-rw-r--r-- | depend | 3 | ||||
-rw-r--r-- | doc/string/hash.rdoc | 19 | ||||
-rw-r--r-- | gc.c | 2 | ||||
-rw-r--r-- | imemo.c | 3 | ||||
-rw-r--r-- | internal/class.h | 2 | ||||
-rw-r--r-- | math.c | 71 | ||||
-rw-r--r-- | ractor.c | 8 | ||||
-rw-r--r-- | string.c | 4 | ||||
-rw-r--r-- | test/ruby/test_math.rb | 20 | ||||
-rw-r--r-- | test/ruby/test_variable.rb | 13 | ||||
-rw-r--r-- | variable.c | 2 | ||||
-rw-r--r-- | vcpkg.json | 4 | ||||
-rw-r--r-- | vm_method.c | 9 | ||||
-rw-r--r-- | zjit/src/codegen.rs | 28 |
17 files changed, 148 insertions, 62 deletions
@@ -51,7 +51,7 @@ define rp printf "%sT_OBJECT%s: ", $color_type, $color_end print ((struct RObject *)($arg0))->basic if ($flags & ROBJECT_EMBED) - print/x *((VALUE*)((struct RObject*)($arg0))->as.ary) @ (rb_shape_get_shape($arg0)->capacity) + print/x *((VALUE*)((struct RObject*)($arg0))->as.ary) @ (RSHAPE_CAPACITY(rb_obj_shape_id($arg0))) else print (((struct RObject *)($arg0))->as.heap) if (((struct RObject*)($arg0))->as.heap.numiv) > 0 @@ -47,6 +47,10 @@ Note: We're only listing outstanding class updates. * `IO.select` accepts +Float::INFINITY+ as a timeout argument. [[Feature #20610]] +* Math + + * `Math.log1p` and `Math.expm1` are added. [[Feature #21527]] + * Socket * `Socket.tcp` & `TCPSocket.new` accepts `open_timeout` as a keyword argument to specify @@ -254,3 +258,4 @@ The following bundled gems are updated. [Feature #21287]: https://bugs.ruby-lang.org/issues/21287 [Feature #21347]: https://bugs.ruby-lang.org/issues/21347 [Feature #21360]: https://bugs.ruby-lang.org/issues/21360 +[Feature #21527]: https://bugs.ruby-lang.org/issues/21527 diff --git a/configure.ac b/configure.ac index fdff2469cb..82f144a8bb 100644 --- a/configure.ac +++ b/configure.ac @@ -1680,21 +1680,6 @@ AS_IF([test "$rb_cv_func_weak" != x], [ AC_DEFINE(HAVE_FUNC_WEAK) ]) -AC_CACHE_CHECK([for __attribute__((__deprecated__(msg))) in C++], - rb_cv_CentOS6_CXX_workaround, - RUBY_WERROR_FLAG([ - AC_LANG_PUSH([C++]) - AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM( - [], - [__attribute__((__deprecated__("message"))) int conftest(...);])], - [rb_cv_CentOS6_CXX_workaround=yes], - [rb_cv_CentOS6_CXX_workaround=no]) - AC_LANG_POP()])) -AS_IF([test "$rb_cv_CentOS6_CXX_workaround" != no],[ - AC_DEFINE([RUBY_CXX_DEPRECATED(msg)], - [__attribute__((__deprecated__(msg)))])]) - AC_CACHE_CHECK([for std::nullptr_t], rb_cv_CXX_nullptr, [ AC_LANG_PUSH([C++]) AC_COMPILE_IFELSE( @@ -6306,6 +6306,7 @@ imemo.$(OBJEXT): $(top_srcdir)/internal/compilers.h imemo.$(OBJEXT): $(top_srcdir)/internal/gc.h imemo.$(OBJEXT): $(top_srcdir)/internal/imemo.h imemo.$(OBJEXT): $(top_srcdir)/internal/namespace.h +imemo.$(OBJEXT): $(top_srcdir)/internal/object.h imemo.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h imemo.$(OBJEXT): $(top_srcdir)/internal/serial.h imemo.$(OBJEXT): $(top_srcdir)/internal/set_table.h @@ -7159,7 +7160,6 @@ iseq.$(OBJEXT): $(top_srcdir)/prism/pack.h iseq.$(OBJEXT): $(top_srcdir)/prism/parser.h iseq.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h iseq.$(OBJEXT): $(top_srcdir)/prism/prism.h -iseq.$(OBJEXT): $(top_srcdir)/prism/prism.h iseq.$(OBJEXT): $(top_srcdir)/prism/regexp.h iseq.$(OBJEXT): $(top_srcdir)/prism/static_literals.h iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h @@ -11676,7 +11676,6 @@ prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h prism/prism.$(OBJEXT): $(top_srcdir)/prism/version.h -prism/prism.$(OBJEXT): $(top_srcdir)/prism/version.h prism/regexp.$(OBJEXT): $(top_srcdir)/prism/ast.h prism/regexp.$(OBJEXT): $(top_srcdir)/prism/defines.h prism/regexp.$(OBJEXT): $(top_srcdir)/prism/encoding.h diff --git a/doc/string/hash.rdoc b/doc/string/hash.rdoc new file mode 100644 index 0000000000..fe94770ed9 --- /dev/null +++ b/doc/string/hash.rdoc @@ -0,0 +1,19 @@ +Returns the integer hash value for +self+. + +Two \String objects that have identical content and compatible encodings +also have the same hash value; +see Object#hash and {Encodings}[rdoc-ref:encodings.rdoc]: + + s = 'foo' + h = s.hash # => -569050784 + h == 'foo'.hash # => true + h == 'food'.hash # => false + h == 'FOO'.hash # => false + + s0 = "äöü" + s1 = s0.encode(Encoding::ISO_8859_1) + s0.encoding # => #<Encoding:UTF-8> + s1.encoding # => #<Encoding:ISO-8859-1> + s0.hash == s1.hash # => false + +Related: see {Querying}[rdoc-ref:String@Querying]. @@ -332,8 +332,6 @@ rb_gc_multi_ractor_p(void) return rb_multi_ractor_p(); } -bool rb_obj_is_main_ractor(VALUE gv); - bool rb_gc_shutdown_call_finalizer_p(VALUE obj) { @@ -3,6 +3,7 @@ #include "id_table.h" #include "internal.h" #include "internal/imemo.h" +#include "internal/object.h" #include "internal/st.h" #include "vm_callinfo.h" @@ -208,6 +209,8 @@ rb_imemo_fields_clear(VALUE fields_obj) else { RBASIC_SET_SHAPE_ID(fields_obj, ROOT_SHAPE_ID); } + // Invalidate the ec->gen_fields_cache. + RBASIC_CLEAR_CLASS(fields_obj); } /* ========================================================================= diff --git a/internal/class.h b/internal/class.h index db4ae2ada1..bed69adef7 100644 --- a/internal/class.h +++ b/internal/class.h @@ -630,7 +630,7 @@ RCLASS_WRITE_CALLABLE_M_TBL(VALUE klass, struct rb_id_table *table) static inline void RCLASS_WRITE_CC_TBL(VALUE klass, VALUE table) { - RB_OBJ_WRITE(klass, &RCLASSEXT_CC_TBL(RCLASS_EXT_WRITABLE(klass)), table); + RB_OBJ_ATOMIC_WRITE(klass, &RCLASSEXT_CC_TBL(RCLASS_EXT_WRITABLE(klass)), table); } static inline void @@ -457,6 +457,34 @@ math_exp(VALUE unused_obj, VALUE x) return DBL2NUM(exp(Get_Double(x))); } +/* + * call-seq: + * Math.expm1(x) -> float + * + * Returns "exp(x) - 1", +e+ raised to the +x+ power, minus 1. + * + * + * - Domain: <tt>[-INFINITY, INFINITY]</tt>. + * - Range: <tt>[-1.0, INFINITY]</tt>. + * + * Examples: + * + * expm1(-INFINITY) # => 0.0 + * expm1(-1.0) # => -0.6321205588285577 # 1.0/E - 1 + * expm1(0.0) # => 0.0 + * expm1(0.5) # => 0.6487212707001282 # sqrt(E) - 1 + * expm1(1.0) # => 1.718281828459045 # E - 1 + * expm1(2.0) # => 6.38905609893065 # E**2 - 1 + * expm1(INFINITY) # => Infinity + * + */ + +static VALUE +math_expm1(VALUE unused_obj, VALUE x) +{ + return DBL2NUM(expm1(Get_Double(x))); +} + #if defined __CYGWIN__ # include <cygwin/version.h> # if CYGWIN_VERSION_DLL_MAJOR < 1005 @@ -646,6 +674,47 @@ math_log10(VALUE unused_obj, VALUE x) return DBL2NUM(log10(d) + numbits * log10(2)); /* log10(d * 2 ** numbits) */ } +/* + * call-seq: + * Math.log1p(x) -> float + * + * Returns "log(x + 1)", the base E {logarithm}[https://en.wikipedia.org/wiki/Logarithm] of (+x+ + 1). + * + * - Domain: <tt>[-1, INFINITY]</tt>. + * - Range: <tt>[-INFINITY, INFINITY]</tt>. + * + * Examples: + * + * log1p(-1.0) # => -Infinity + * log1p(0.0) # => 0.0 + * log1p(E - 1) # => 1.0 + * log1p(INFINITY) # => Infinity + * + */ + +static VALUE +math_log1p(VALUE unused_obj, VALUE x) +{ + size_t numbits; + double d = get_double_rshift(x, &numbits); + + if (numbits != 0) { + x = rb_big_plus(x, INT2FIX(1)); + d = math_log_split(x, &numbits); + /* check for pole error */ + if (d == 0.0) return DBL2NUM(-HUGE_VAL); + d = log(d); + d += numbits * M_LN2; + return DBL2NUM(d); + } + + domain_check_min(d, -1.0, "log1p"); + /* check for pole error */ + if (d == -1.0) return DBL2NUM(-HUGE_VAL); + + return DBL2NUM(log1p(d)); /* log10(d * 2 ** numbits) */ +} + static VALUE rb_math_sqrt(VALUE x); /* @@ -1120,9 +1189,11 @@ InitVM_Math(void) rb_define_module_function(rb_mMath, "atanh", math_atanh, 1); rb_define_module_function(rb_mMath, "exp", math_exp, 1); + rb_define_module_function(rb_mMath, "expm1", math_expm1, 1); rb_define_module_function(rb_mMath, "log", math_log, -1); rb_define_module_function(rb_mMath, "log2", math_log2, 1); rb_define_module_function(rb_mMath, "log10", math_log10, 1); + rb_define_module_function(rb_mMath, "log1p", math_log1p, 1); rb_define_module_function(rb_mMath, "sqrt", math_sqrt, 1); rb_define_module_function(rb_mMath, "cbrt", math_cbrt, 1); @@ -585,14 +585,6 @@ rb_ractor_main_p_(void) return rb_ec_ractor_ptr(ec) == rb_ec_vm_ptr(ec)->ractor.main_ractor; } -bool -rb_obj_is_main_ractor(VALUE gv) -{ - if (!rb_ractor_p(gv)) return false; - rb_ractor_t *r = DATA_PTR(gv); - return r == GET_VM()->ractor.main_ractor; -} - int rb_ractor_living_thread_num(const rb_ractor_t *r) { @@ -4133,10 +4133,8 @@ rb_str_hash_cmp(VALUE str1, VALUE str2) * call-seq: * hash -> integer * - * Returns the integer hash value for +self+. - * The value is based on the length, content and encoding of +self+. + * :include: doc/string/hash.rdoc * - * Related: Object#hash. */ static VALUE diff --git a/test/ruby/test_math.rb b/test/ruby/test_math.rb index 6e67099c6b..a676bb5cd9 100644 --- a/test/ruby/test_math.rb +++ b/test/ruby/test_math.rb @@ -147,6 +147,13 @@ class TestMath < Test::Unit::TestCase check(Math::E ** 2, Math.exp(2)) end + def test_expm1 + check(0, Math.expm1(0)) + check(Math.sqrt(Math::E) - 1, Math.expm1(0.5)) + check(Math::E - 1, Math.expm1(1)) + check(Math::E ** 2 - 1, Math.expm1(2)) + end + def test_log check(0, Math.log(1)) check(1, Math.log(Math::E)) @@ -201,6 +208,19 @@ class TestMath < Test::Unit::TestCase assert_nothing_raised { assert_infinity(-Math.log10(0)) } end + def test_log1p + check(0, Math.log1p(0)) + check(1, Math.log1p(Math::E - 1)) + check(Math.log(2.0 ** 64 + 1), Math.log1p(1 << 64)) + check(Math.log(2) * 1024.0, Math.log1p(2 ** 1024)) + assert_nothing_raised { assert_infinity(Math.log1p(1.0/0)) } + assert_nothing_raised { assert_infinity(-Math.log1p(-1.0)) } + assert_raise_with_message(Math::DomainError, /\blog1p\b/) { Math.log1p(-1.1) } + assert_raise_with_message(Math::DomainError, /\blog1p\b/) { Math.log1p(-Float::EPSILON-1) } + assert_nothing_raised { assert_nan(Math.log1p(Float::NAN)) } + assert_nothing_raised { assert_infinity(-Math.log1p(-1)) } + end + def test_sqrt check(0, Math.sqrt(0)) check(1, Math.sqrt(1)) diff --git a/test/ruby/test_variable.rb b/test/ruby/test_variable.rb index cc784e7644..3504b9b7dc 100644 --- a/test/ruby/test_variable.rb +++ b/test/ruby/test_variable.rb @@ -447,6 +447,19 @@ class TestVariable < Test::Unit::TestCase assert_equal(%i[α b], b.local_variables) end + def test_genivar_cache + bug21547 = '[Bug #21547]' + klass = Class.new(Array) + instance = klass.new + instance.instance_variable_set(:@a1, 1) + instance.instance_variable_set(:@a2, 2) + Fiber.new do + instance.instance_variable_set(:@a3, 3) + instance.instance_variable_set(:@a4, 4) + end.resume + assert_equal 4, instance.instance_variable_get(:@a4) + end + private def with_kwargs_11(v1:, v2:, v3:, v4:, v5:, v6:, v7:, v8:, v9:, v10:, v11:) local_variables diff --git a/variable.c b/variable.c index 4f0f83d203..1cd1c604c3 100644 --- a/variable.c +++ b/variable.c @@ -1247,7 +1247,7 @@ rb_obj_fields(VALUE obj, ID field_name) generic_fields: { rb_execution_context_t *ec = GET_EC(); - if (ec->gen_fields_cache.obj == obj) { + if (ec->gen_fields_cache.obj == obj && rb_imemo_fields_owner(ec->gen_fields_cache.fields_obj) == obj) { fields_obj = ec->gen_fields_cache.fields_obj; } else { diff --git a/vcpkg.json b/vcpkg.json index 16415dece1..efd356e814 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -7,5 +7,5 @@ "openssl", "zlib" ], - "builtin-baseline": "65be7019941e1401e02daaba0738cab2c8a4a355" -} + "builtin-baseline": "dd3097e305afa53f7b4312371f62058d2e665320" +}
\ No newline at end of file diff --git a/vm_method.c b/vm_method.c index 73a431ce93..241e4cacef 100644 --- a/vm_method.c +++ b/vm_method.c @@ -1786,7 +1786,14 @@ cache_callable_method_entry(VALUE klass, ID mid, const rb_callable_method_entry_ #endif } else { - vm_ccs_create(klass, cc_tbl, mid, cme); + if (rb_multi_ractor_p()) { + VALUE new_cc_tbl = rb_vm_cc_table_dup(cc_tbl); + vm_ccs_create(klass, new_cc_tbl, mid, cme); + RB_OBJ_ATOMIC_WRITE(klass, &RCLASSEXT_CC_TBL(RCLASS_EXT_WRITABLE(klass)), new_cc_tbl); + } + else { + vm_ccs_create(klass, cc_tbl, mid, cme); + } } } diff --git a/zjit/src/codegen.rs b/zjit/src/codegen.rs index db56db0927..f502801aff 100644 --- a/zjit/src/codegen.rs +++ b/zjit/src/codegen.rs @@ -1005,35 +1005,11 @@ fn gen_new_hash( pairs.push(val); } - let n = pairs.len(); - - // Calculate the compile-time NATIVE_STACK_PTR offset from NATIVE_BASE_PTR - // At this point, frame_setup(&[], jit.c_stack_slots) has been called, - // which allocated aligned_stack_bytes(jit.c_stack_slots) on the stack - let frame_size = aligned_stack_bytes(jit.c_stack_slots); - let allocation_size = aligned_stack_bytes(n); - - asm_comment!(asm, "allocate {} bytes on C stack for {} hash elements", allocation_size, n); - asm.sub_into(NATIVE_STACK_PTR, allocation_size.into()); - - // Calculate the total offset from NATIVE_BASE_PTR to our buffer - let total_offset_from_base = (frame_size + allocation_size) as i32; - - for (idx, &pair_opnd) in pairs.iter().enumerate() { - let slot_offset = -total_offset_from_base + (idx as i32 * SIZEOF_VALUE_I32); - asm.mov( - Opnd::mem(VALUE_BITS, NATIVE_BASE_PTR, slot_offset), - pair_opnd - ); - } - - let argv = asm.lea(Opnd::mem(64, NATIVE_BASE_PTR, -total_offset_from_base)); - + let argv = gen_push_opnds(jit, asm, &pairs); let argc = (elements.len() * 2) as ::std::os::raw::c_long; asm_ccall!(asm, rb_hash_bulk_insert, lir::Opnd::Imm(argc), argv, new_hash); - asm_comment!(asm, "restore C stack pointer"); - asm.add_into(NATIVE_STACK_PTR, allocation_size.into()); + gen_pop_opnds(asm, &pairs); } new_hash |