diff --git a/gc/default/default.c b/gc/default/default.c index fa39ecc83217a1..e51331b8bdbb58 100644 --- a/gc/default/default.c +++ b/gc/default/default.c @@ -96,15 +96,6 @@ # include #endif -#ifndef VM_CHECK_MODE -# define VM_CHECK_MODE RUBY_DEBUG -#endif - -// From ractor_core.h -#ifndef RACTOR_CHECK_MODE -# define RACTOR_CHECK_MODE (VM_CHECK_MODE || RUBY_DEBUG) && (SIZEOF_UINT64_T == SIZEOF_VALUE) -#endif - #ifndef RUBY_DEBUG_LOG # define RUBY_DEBUG_LOG(...) #endif @@ -691,10 +682,10 @@ typedef struct rb_objspace { #define HEAP_PAGE_ALIGN_LOG 16 #endif -#if RACTOR_CHECK_MODE || GC_DEBUG +#if RB_GC_OBJ_HAS_SUFFIX || GC_DEBUG struct rvalue_overhead { -# if RACTOR_CHECK_MODE - uint32_t _ractor_belonging_id; +# ifdef RB_GC_OBJ_HAS_SUFFIX + struct rb_gc_obj_suffix suffix; # endif # if GC_DEBUG const char *file; diff --git a/gc/gc.h b/gc/gc.h index 2809c7a128b824..ce67d0da672f44 100644 --- a/gc/gc.h +++ b/gc/gc.h @@ -10,9 +10,32 @@ * first introduced for [Feature #20470]. */ #include "ruby/ruby.h" +#include "ruby/assert.h" #include "ruby/thread_native.h" +#ifndef VM_CHECK_MODE +# define VM_CHECK_MODE RUBY_DEBUG +#endif + +// From ractor_core.h +#ifndef RACTOR_CHECK_MODE +# define RACTOR_CHECK_MODE (VM_CHECK_MODE || RUBY_DEBUG) && (SIZEOF_UINT64_T == SIZEOF_VALUE) +#endif + +#if RACTOR_CHECK_MODE +void rb_ractor_setup_belonging(VALUE obj); + +struct rb_gc_obj_suffix { + uint32_t _ractor_belonging_id; +}; + +# define RB_GC_OBJ_HAS_SUFFIX 1 +# define RB_GC_OBJ_SUFFIX_SIZE (sizeof(struct rb_gc_obj_suffix)) +#else +# define RB_GC_OBJ_SUFFIX_SIZE 0 +#endif + struct rb_gc_vm_context { rb_nativethread_lock_t lock; diff --git a/pathname.c b/pathname.c index ec026c133344e0..b12f64037392da 100644 --- a/pathname.c +++ b/pathname.c @@ -156,13 +156,14 @@ path_root_p(VALUE self) * * Returns whether +self+ contains an absolute path: * - * Pathname.new('/home').absolute? # => true - * Pathname.new('lib').absolute? # => false + * Pathname('/home').absolute? # => true + * Pathname('lib').absolute? # => false * - * OS-dependent for some paths: + * The result is OS-dependent for some paths: + * + * Pathname('C:/').absolute? # => true # On Windows. + * Pathname('C:/').absolute? # => false # Elsewhere. * - * Pathname.new('C:/').absolute? # => true # On Windows. - * Pathname.new('C:/').absolute? # => false # Elsewhere. */ static VALUE path_absolute_p(VALUE self) diff --git a/pathname_builtin.rb b/pathname_builtin.rb index 446c52f0d958e7..e24b892b16b7f6 100644 --- a/pathname_builtin.rb +++ b/pathname_builtin.rb @@ -1040,26 +1040,54 @@ def binwrite(...) File.binwrite(@path, ...) end # See {File System Timestamps}[rdoc-ref:file/timestamps.md]. def atime() File.atime(@path) end + # :markup: markdown + # # call-seq: # birthtime -> new_time # # Returns a new Time object containing the create time of the entry # represented by +self+: # - # filepath = 't.tmp' - # pn = Pathname.new(filepath) - # pn.birthtime # Raises Errno::ENOENT: No such file or directory - # file = File.open(filepath, 'w') - # pn.birthtime # => 2026-04-14 16:14:47.494846 -0500 - # file.birthtime # => 2026-04-14 16:14:47.494846 -0500 - # file.write('foo') - # pn.birthtime # => 2026-04-14 16:14:47.494846 -0500 - # file.close - # pn.birthtime # => 2026-04-14 16:14:47.494846 -0500 - # File.delete(filepath) - # pn.birthtime # Raises Errno::ENOENT: No such file or directory + # ```ruby + # # Work in a temporary directory. + # Pathname.mktmpdir do |tmpdirpath| + # # A subdirectory therein, and its Pathname. + # dirpath = File.join(tmpdirpath, 'subdir') + # dir_pn = Pathname(dirpath) + # puts "Create directory; directory birthtime established." + # dir_pn.mkdir + # puts " Directory birthtime: #{dir_pn.birthtime}" + # sleep(1) + # + # # A file in the subdirectory, and its Pathname. + # filepath = File.join(dirpath, 't.txt') + # file_pn = Pathname(filepath) + # puts "Create file; file birthtime established; directory birthtime not updated." + # file_pn.write('foo') + # puts " File birthtime: #{file_pn.birthtime}" + # puts " Directory birthtime: #{dir_pn.birthtime}" + # sleep(1) + # puts "Write file; neither birthtime updated." + # file_pn.write('bar') + # puts " File birthtime: #{file_pn.birthtime}" + # puts " Directory birthtime: #{dir_pn.birthtime}" + # end + # ``` # - # See {File System Timestamps}[rdoc-ref:file/timestamps.md]. + # Output: + # + # ```text + # Create directory; directory birthtime established. + # Directory birthtime: 2026-05-14 23:41:12 +0100 + # Create file; file birthtime established; directory birthtime not updated. + # File birthtime: 2026-05-14 23:41:13 +0100 + # Directory birthtime: 2026-05-14 23:41:12 +0100 + # Write file; neither birthtime updated. + # File birthtime: 2026-05-14 23:41:13 +0100 + # Directory birthtime: 2026-05-14 23:41:12 +0100 + # ``` + # + # See [File System Timestamps](rdoc-ref:file/timestamps.md). def birthtime() File.birthtime(@path) end # See File.ctime. Returns last (directory entry, not file) change time. diff --git a/test/ruby/test_refinement.rb b/test/ruby/test_refinement.rb index daff07ecb0abff..c3ded524fc891d 100644 --- a/test/ruby/test_refinement.rb +++ b/test/ruby/test_refinement.rb @@ -1035,6 +1035,43 @@ def ===(other) RUBY end + def test_prohibit_super_in_refined_module_method + assert_separately([], <<-"end;") + bug22071 = '[ruby-core:125511] [Bug #22071]' + class BasicObject + def a; "B" end + end + + module G + def a; "G" + super end + end + + module F + include G + def a; "F" + super end + end + + class A + def a; "A" + super end + end + + class B < A + include F + end + + module R + refine F do + def a; "R"+super end + end + end + using R + + msg = "super in a method in a module that has been refined and that is called via super" + + " from a refinement method is not supported." + assert_raise(NoMethodError, msg, bug22071) { B.new.a } + end; + end + def test_refine_after_using assert_separately([], <<-"end;") bug8880 = '[ruby-core:57079] [Bug #8880]' diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 84daaa85a54830..92091216f41ff8 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -5061,6 +5061,13 @@ vm_search_super_method(const rb_control_frame_t *reg_cfp, struct rb_call_data *c cc = vm_cc_new(Qundef, NULL, vm_call_method_missing, cc_type_super); RB_OBJ_WRITE(iseq, &cd->cc, cc); } + else if (klass == rb_cBasicObject && + RB_TYPE_P(me->defined_class, T_ICLASS) && + RCLASS_INCLUDER(me->defined_class) == 0) { + rb_raise(rb_eNoMethodError, + "super in a method in a module that has been refined and that is called via super" + " from a refinement method is not supported."); + } else { cc = vm_search_method_fastpath(reg_cfp, cd, klass); const rb_callable_method_entry_t *cached_cme = vm_cc_cme(cc); diff --git a/zjit/src/codegen.rs b/zjit/src/codegen.rs index efcc11a5e43300..acc5002a2a267c 100644 --- a/zjit/src/codegen.rs +++ b/zjit/src/codegen.rs @@ -492,8 +492,6 @@ fn gen_function(cb: &mut CodeBlock, iseq: IseqPtr, version: IseqVersionRef, func debug!("ZJIT: gen_function: Failed to compile insn: {insn_id} {insn}. Generating side-exit."); gen_incr_counter(&mut asm, exit_counter_for_unhandled_hir_insn(&insn)); let reason = match insn { - Insn::ArrayMax { .. } => SideExitReason::UnhandledHIRArrayMax, - Insn::FixnumDiv { .. } => SideExitReason::UnhandledHIRFixnumDiv, Insn::Throw { .. } => SideExitReason::UnhandledHIRThrow, Insn::InvokeBuiltin { .. } => SideExitReason::UnhandledHIRInvokeBuiltin, _ => SideExitReason::UnhandledHIRUnknown(insn_id), diff --git a/zjit/src/hir.rs b/zjit/src/hir.rs index e7ed3faf9c1050..e350387dc27999 100644 --- a/zjit/src/hir.rs +++ b/zjit/src/hir.rs @@ -504,8 +504,6 @@ pub enum SideExitReason { UnhandledNewarraySend(vm_opt_newarray_send_type), UnhandledDuparraySend(u64), UnknownSpecialVariable(u64), - UnhandledHIRArrayMax, - UnhandledHIRFixnumDiv, UnhandledHIRThrow, UnhandledHIRInvokeBuiltin, UnhandledHIRUnknown(InsnId), diff --git a/zjit/src/stats.rs b/zjit/src/stats.rs index 587dde06603bab..22fbb2b23fc20f 100644 --- a/zjit/src/stats.rs +++ b/zjit/src/stats.rs @@ -584,8 +584,6 @@ pub fn side_exit_counter(reason: crate::hir::SideExitReason) -> Counter { UnhandledCallType(Splat) => exit_unhandled_splat, UnhandledCallType(Kwarg) => exit_unhandled_kwarg, UnknownSpecialVariable(_) => exit_unknown_special_variable, - UnhandledHIRArrayMax => exit_unhandled_hir_insn, - UnhandledHIRFixnumDiv => exit_unhandled_hir_insn, UnhandledHIRThrow => exit_unhandled_hir_insn, UnhandledHIRInvokeBuiltin => exit_unhandled_hir_insn, UnhandledHIRUnknown(_) => exit_unhandled_hir_insn,