summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gdbinit2
-rw-r--r--NEWS.md5
-rw-r--r--configure.ac15
-rw-r--r--depend3
-rw-r--r--doc/string/hash.rdoc19
-rw-r--r--gc.c2
-rw-r--r--imemo.c3
-rw-r--r--internal/class.h2
-rw-r--r--math.c71
-rw-r--r--ractor.c8
-rw-r--r--string.c4
-rw-r--r--test/ruby/test_math.rb20
-rw-r--r--test/ruby/test_variable.rb13
-rw-r--r--variable.c2
-rw-r--r--vcpkg.json4
-rw-r--r--vm_method.c9
-rw-r--r--zjit/src/codegen.rs28
17 files changed, 148 insertions, 62 deletions
diff --git a/.gdbinit b/.gdbinit
index f624456d04..f204b3a235 100644
--- a/.gdbinit
+++ b/.gdbinit
@@ -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
diff --git a/NEWS.md b/NEWS.md
index 288f7d97de..964bafacd6 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -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(
diff --git a/depend b/depend
index 0fcf5ce652..334bab5684 100644
--- a/depend
+++ b/depend
@@ -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].
diff --git a/gc.c b/gc.c
index c2fc681253..686e727521 100644
--- a/gc.c
+++ b/gc.c
@@ -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)
{
diff --git a/imemo.c b/imemo.c
index fde5b15ad6..2fde22a3db 100644
--- a/imemo.c
+++ b/imemo.c
@@ -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
diff --git a/math.c b/math.c
index a95919e342..9e96f3666a 100644
--- a/math.c
+++ b/math.c
@@ -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);
diff --git a/ractor.c b/ractor.c
index 096bda5df6..c4d748e69c 100644
--- a/ractor.c
+++ b/ractor.c
@@ -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)
{
diff --git a/string.c b/string.c
index d9d8678c71..0329d2845a 100644
--- a/string.c
+++ b/string.c
@@ -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