Upgrade to Pro — share decks privately, control downloads, hide ads and more …

The Journey of Box Building

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

The Journey of Box Building

RubyKaigi 2026 Opening Keynote, talking about Ruby Box and the story behind it.
https://rubykaigi.org/2026/presentations/tagomoris.html

Avatar for Satoshi Tagomori

Satoshi Tagomori

April 21, 2026

More Decks by Satoshi Tagomori

Other Decks in Technology

Transcript

  1. ా᝷ ૱ (Satoshi Tagomori) @tagomoris SAKURA internet (2024.08ʙ) Cloud Business

    Strategy Division Maintainer/Founder: OSS: Ruby, Fluentd, MessagePack, 
 Norikra, Woothee, …
 Event: ISUCON Service: Pathtraq
  2. ˒ What’s “Ruby Box”? ˒ Tour of Ruby Box ˒

    Road to Box Building The Journey of Box Building
  3. ˒ An experimental feature, introduced in Ruby 4.0 ˒ Renamed

    from “Namespace” after RubyKaigi 2025 ˒ Accessed as Ruby::Box ˒ Enabled by an ENV value RUBY_BOX=1 What’s “Ruby Box”?
  4. ˒ Separating apps/libs/monkey-patches into isolated spaces ˒ Load apps/libs in

    a space ˒ Hide changes of apps/libs in the space from other spaces ˒ Run methods de fi ned in the space with the de fi nitions Ruby Box: Feature
  5. Before Ruby Box: Global Only All classes/modules are shared in

    the entire Ruby process Ruby Process Application Code App::Func User Library Code DB::Client (v2) Library Code ActiveSupport (v7)
  6. Before Ruby Box: Global Only Monkey patches overwrite things globally

    Ruby Process Application Code App::Func User Library Code DB::Client (v2) Library Code ActiveSupport (v7) class String def +(other) = “self:#{other}” User Library Code
  7. Ruby Process Application Code App::Func User Library Code DB::Client (v2)

    Library Code ActiveSupport (v7) 😵 😵 😵 Before Ruby Box: Global Only Monkey patches overwrite things globally class String def +(other) = “self:#{other}” User Library Code
  8. Ruby Process Ruby Box Ruby Box Using Ruby Box Ruby

    Box provides separation for funky monkey patches! Application Code App::Func User Library Code DB::Client (v2) Library Code ActiveSupport (v7) class String def +(other) = “self:#{other}” User Library Code 😀 😀 😀
  9. Testing in Boxes With world-breaking monkey patches for mocking Ruby

    Process Application Code Test Case ( _test.rb) Monkey Patches Test Runner Application Code Monkey Patches Application Code Test Case ( _test.rb) Test Case ( _test.rb) Test Case ( _test.b.rb) Test Case ( _test.b.rb) “.b.rb” su ff ix is just my idea - there should be be tt er rules.
  10. Ruby Process Ruby Box Running 2 Apps in Boxes With

    the di ff erent sets of apps/libraries Application Code (v1) App::Func User Library Code DB::Client (v2) Library Code ActiveSupport (v7) Ruby Box Application Code (v2) App::Func User Library Code DB::Client (v3) Library Code ActiveSupport (v8) "QQWXJUI 0MEFSMJCWFSTJPOT "QQWXJUI /FXFSMJCWFSTJPOT For example, LFA is an app server, runs AWS Lambda functions. Application Server supporting Ruby Box
  11. ˒ Updated “Packaging” Feature Idea from Matz ˒ Loading packages

    in box, then pulling public APIs from the box ˒ Packages never break other packages or libraries ˒ Many things to be solved to realize this idea ˒ ActiveSupport? Hook points? Memory usage? Packaging w/ Underlying Boxes
  12. ˒ Per-box Class/Method De fi nitions ˒ Scripts(.rb) and Extensions(.so)

    Loading in Boxes ˒ Current Box Management/Detection RUBY BOX INGREDIENTS
  13. ˒ Per-box Class/Method De fi nitions “Namespace, What and Why”

    h tt ps://rubykaigi.org/2024/presentations/tagomoris.html ˒ Scripts(.rb) and Extensions(.so) Loading in Boxes “State of Namespace” h tt ps://rubykaigi.org/2025/presentations/tagomoris.html ˒ Current Box Management/Detection This Talk RUBY BOX INGREDIENTS class.c load.c vm.c
  14. ˒ Box separates class/method de fi nitions ˒ Ruby programs

    can de fi ne/refer classes/methods anytime ˒ Current box should be determined whenever Ruby runs (and then, classes/methods for the box will be fetched) Current Box Management/Detection
  15. # main.rb …… … require_relative(“app”) … p App.foo #=> [“foo”,

    “bar”] Ruby Code Example # app.rb p 1 module App def self.foo(x=:bar) [:foo, x].map{ it.to_s } end p 2 end
  16. # main.rb w/ RUBY_BOX=1 …… b1 = Ruby::Box.new p b1

    # #<Ruby::Box:3,user,optional> … b1.require_relative(“app”) … p b1::App.foo Ruby Code using Ruby Box # app.rb p 1 module App def self.foo(x=:bar) [:foo, x].map{ it.to_s } end p 2 end
  17. ˒ Ruby Box Switching happens only on some Ruby::Box methods

    ˒ #require, #require_relative, #load (and #eval) ˒ The target code is required/loaded in the receiver box ˒ Box boundary is fi le, but fi le doesn’t determine its box ˒ A fi le can be loaded in 2 boxes Current Box: Dynamic File Scope?
  18. # main.rb w/ RUBY_BOX=1 …… b1 = Ruby::Box.new … b1.require_relative(“app”)

    … p b1::App.foo Ruby Code using Ruby Box (revisit) b1 # app.rb p 1 module App def self.foo(x=:bar) [:foo, x].map{ it.to_s } end p 2 end
  19. In File: Immediately or Later # main.rb w/ RUBY_BOX=1 ……

    b1 = Ruby::Box.new … b1.require_relative(“app”) … p b1::App.foo Evaluated immediately De fi nition created De fi nition created Evaluated when called # app.rb p 1 module App def self.foo(x=:bar) [:foo, x].map{ it.to_s } end p 2 end
  20. app.rb:9:in '<module:App>': yay (RuntimeError) from app.rb:3:in '<top (required)>' from main.rb:5:in

    'Ruby::Box#require_relative' from main.rb:5:in '<main>' Where is it now? (Using Exception) # app.rb p 1 module App def self.foo(x=:bar) [:foo, x].map{ it.to_s } end raise “yay” end
  21. app.rb:9: [BUG] o.o ruby 4.1.0dev (2026-04-10T21:09:30Z master 044a43f42b) +PRISM [arm64-darwin24]

    -- Crash Report log information -------------------------------------------- See Crash Report log file in one of the following locations: * ~/Library/Logs/DiagnosticReports * /Library/Logs/DiagnosticReports for more details. Don't forget to include the above Crash Report log file in bug reports. -- Control frame information ----------------------------------------------- c:0006 p:---- s:0022 e:000021 l:y b:---- r:0x0 CFUNC :bug! c:0005 p:0007 s:0018 e:000017 l:y b:0003 r:0x0 CLASS /Users/s-tagomori/oss/talk_demo/rubykaigi2026/app.rb:9 c:0004 p:0007 s:0015 e:000014 l:y b:0003 r:0x0 TOP /Users/s-tagomori/oss/talk_demo/rubykaigi2026/app.rb:3 [FINISH] c:0003 p:---- s:0012 e:000011 l:y b:---- r:0x0 CFUNC :require_relative c:0002 p:0023 s:0007 E:000de0 l:n b:---- r:0x0 EVAL main.rb:5 [FINISH] c:0001 p:0000 s:0003 E:000888 l:y b:---- r:0x0 DUMMY [FINISH] -- Ruby level backtrace information ---------------------------------------- main.rb:5:in '<main>' main.rb:5:in 'require_relative' /Users/s-tagomori/oss/talk_demo/rubykaigi2026/app.rb:3:in '<top (required)>' /Users/s-tagomori/oss/talk_demo/rubykaigi2026/app.rb:9:in '<module:App>' /Users/s-tagomori/oss/talk_demo/rubykaigi2026/app.rb:9:in 'bug!' -- Threading information --------------------------------------------------- Total ractor count: 1 Ruby thread count for this ractor: 1 -- C level backtrace information ------------------------------------------- /Users/s-tagomori/oss/ruby/build/ruby(rb_print_backtrace+0x24) [0x103421e3c] /Users/s-tagomori/oss/ruby/build/../vm_dump.c:1108 /Users/s-tagomori/oss/ruby/build/ruby(rb_print_backtrace) (null):0 /Users/s-tagomori/oss/ruby/build/ruby(rb_vm_bugreport+0x2f8) [0x103422154] /Users/s-tagomori/oss/ruby/build/../vm_dump.c:1456 Where is it now? (Using BUG) # app.rb p 1 module App def self.foo(x=:bar) [:foo, x].map{ it.to_s } end bug! #only on my Ruby end
  22. ˒ The execution status in Ruby VM ˒ Control Frames

    are stack Control Frames (rb_control_frame_t) struct rb_control_frame_struct { const VALUE *pc; VALUE *sp; const rb_iseq_t *_iseq; VALUE self; const VALUE *ep; const void *block_code; void *jit_return; }; -- Control frame information ----------------------------------------- c:0006 p:---- s:0022 e:000021 l:y b:---- r:0x0 CFUNC :bug! c:0005 p:0007 s:0018 e:000017 l:y b:0003 r:0x0 CLASS ……/app.rb:9 c:0004 p:0007 s:0015 e:000014 l:y b:0003 r:0x0 TOP ……/app.rb:3 [FINISH] c:0003 p:---- s:0012 e:000011 l:y b:---- r:0x0 CFUNC :require_relative c:0002 p:0023 s:0007 E:000de0 l:n b:---- r:0x0 EVAL main.rb:5 [FINISH] c:0001 p:0000 s:0003 E:000888 l:y b:---- r:0x0 DUMMY [FINISH]
  23. ˒ Backtrace: “Ruby Level Backtrace” ˒ Translated & fi ltered

    control frames ˒ Hide C-level informations (show them just like Ruby-level one) ˒ Hide internal frames (DUMMY, IFUNC, etc) Backtrace and Control Frames
  24. Finding Current Box # app.rb a = 1 module App

    b = 1 def self.foo(x=:bar) c = 1 [:foo, x].map{ it.to_s } end p b end p a # main.rb w/ RUBY_BOX=1 …… b1 = Ruby::Box.new … b1.require_relative(“app”) … p b1::App.foo
  25. # app.rb a = 1 module App b = 1

    def self.foo(x=:bar) c = 1 [:foo, x].map{ it.to_s } end p b end p a # main.rb w/ RUBY_BOX=1 …… b1 = Ruby::Box.new … b1.require_relative(“app”) … p b1::App.foo main Finding Current Box
  26. # app.rb a = 1 module App b = 1

    def self.foo(x=:bar) c = 1 [:foo, x].map{ it.to_s } end p b end p a # main.rb w/ RUBY_BOX=1 …… b1 = Ruby::Box.new … b1.require_relative(“app”) … p b1::App.foo main Finding Current Box
  27. # app.rb a = 1 module App b = 1

    def self.foo(x=:bar) c = 1 [:foo, x].map{ it.to_s } end p b end p a # main.rb w/ RUBY_BOX=1 …… b1 = Ruby::Box.new … b1.require_relative(“app”) … p b1::App.foo b1 Finding Current Box
  28. # app.rb a = 1 module App b = 1

    def self.foo(x=:bar) c = 1 [:foo, x].map{ it.to_s } end p b end p a # main.rb w/ RUBY_BOX=1 …… b1 = Ruby::Box.new … b1.require_relative(“app”) … p b1::App.foo b1 Finding Current Box
  29. # app.rb a = 1 module App b = 1

    def self.foo(x=:bar) c = 1 [:foo, x].map{ it.to_s } end p b end p a # main.rb w/ RUBY_BOX=1 …… b1 = Ruby::Box.new … b1.require_relative(“app”) … p b1::App.foo b1 Finding Current Box
  30. # app.rb a = 1 module App b = 1

    def self.foo(x=:bar) c = 1 [:foo, x].map{ it.to_s } end p b end p a # main.rb w/ RUBY_BOX=1 …… b1 = Ruby::Box.new … b1.require_relative(“app”) … p b1::App.foo b1 Finding Current Box
  31. # app.rb a = 1 module App b = 1

    def self.foo(x=:bar) c = 1 [:foo, x].map{ it.to_s } end p b end p a # main.rb w/ RUBY_BOX=1 …… b1 = Ruby::Box.new … b1.require_relative(“app”) … p b1::App.foo b1 Finding Current Box
  32. # app.rb a = 1 module App b = 1

    def self.foo(x=:bar) c = 1 [:foo, x].map{ it.to_s } end p b end p a # main.rb w/ RUBY_BOX=1 …… b1 = Ruby::Box.new … b1.require_relative(“app”) … p b1::App.foo b1 Finding Current Box
  33. # app.rb a = 1 module App b = 1

    def self.foo(x=:bar) c = 1 [:foo, x].map{ it.to_s } end p b end p a # main.rb w/ RUBY_BOX=1 …… b1 = Ruby::Box.new … b1.require_relative(“app”) … p b1::App.foo main Finding Current Box
  34. # app.rb a = 1 module App b = 1

    def self.foo(x=:bar) c = 1 [:foo, x].map{ it.to_s } end p b end p a # main.rb w/ RUBY_BOX=1 …… b1 = Ruby::Box.new … b1.require_relative(“app”) … p b1::App.foo b1 Finding Current Box
  35. # app.rb a = 1 module App b = 1

    def self.foo(x=:bar) c = 1 [:foo, x].map{ it.to_s } end p b end p a # main.rb w/ RUBY_BOX=1 …… b1 = Ruby::Box.new … b1.require_relative(“app”) … p b1::App.foo b1 Finding Current Box
  36. # app.rb a = 1 module App b = 1

    def self.foo(x=:bar) c = 1 [:foo, x].map{ it.to_s } end p b end p a # main.rb w/ RUBY_BOX=1 …… b1 = Ruby::Box.new … b1.require_relative(“app”) … p b1::App.foo b1 Finding Current Box
  37. # app.rb a = 1 module App b = 1

    def self.foo(x=:bar) c = 1 [:foo, x].map{ it.to_s } end p b end p a # main.rb w/ RUBY_BOX=1 …… b1 = Ruby::Box.new … b1.require_relative(“app”) … p b1::App.foo b1 Finding Current Box
  38. # app.rb a = 1 module App b = 1

    def self.foo(x=:bar) c = 1 [:foo, x].map{ it.to_s } end p b end p a # main.rb w/ RUBY_BOX=1 …… b1 = Ruby::Box.new … b1.require_relative(“app”) … p b1::App.foo main Finding Current Box
  39. Finding Current Box ˒ Rules to detect current box ˒

    Find the closest Ruby frame ˒ If it’s running a C func, trace back to the closest Ruby frame ˒ Find the “LOCAL” variable scope from the Ruby frame ˒ Check the box of the LOCAL env
  40. ˒ The fl ag about local variable scope ˒ LOCAL:

    File, Class/Module, Method ˒ Non-LOCAL: Block, Eval, Rescue ˒ “env” fl ag ˒ Control frames and these environments are marked “LOCAL”?
  41. ˒ “env” is not “ENV”ironment variable ˒ Frame environment ˒

    ep: env pointer Control Frame and Environment struct rb_control_frame_struct { const VALUE *pc; VALUE *sp; const rb_iseq_t *_iseq; VALUE self; const VALUE *ep; const void *block_code; void *jit_return; }; typedef struct rb_control_frame_struct rb_control_frame_t; rb_control_frame_t env VALUE LVAR … VALUE LAST_LVAR VALUE ME_CREF // ep[-2] VALUE SPECVAL // ep[-1] VALUE FLAGS // ep[0] VALUE ENV // rb_env_t*
  42. ˒ Local variables are listed in the tail of env

    Control Frame and Environment env VALUE d VALUE c VALUE x VALUE ME_CREF // ep[-2] VALUE SPECVAL // ep[-1] VALUE FLAGS // ep[0] VALUE ENV // rb_env_t* def self.foo(x=:bar) c = 1 [:foo, x].map{ it.to_s } d = 2 end
  43. ENVs Referenced from Control Frames rb_control_frame_t rb_control_frame_t rb_control_frame_t rb_control_frame_t rb_control_frame_t

    current cfp ˒ rb_control_frame_t *cfp (control frame pointer) ˒ cfp->ep ˒ ENV size depends on # of local variables ENV ENV ENV ENV ENV ep ep ep ep ep
  44. Ruby’s Stack Memory Space ˒ From head: control frames ˒

    From tail: ENVs ˒ ENV members are accessed using negative index as ep[-1] Stack Memory Space in CRuby rb_control_frame_t ENV ENV rb_control_frame_t
  45. Ruby’s Stack Memory Space Stack in CRuby rb_control_frame_t ENV ENV

    ENV ENV rb_control_frame_t rb_control_frame_t rb_control_frame_t ˒ From head: control frames ˒ From tail: ENVs
  46. Ruby’s Stack Memory Space Stack in CRuby rb_control_frame_t ENV ENV

    ENV ENV rb_control_frame_t rb_control_frame_t rb_control_frame_t rb_control_frame_t ENV ˒ From head: control frames ˒ From tail: ENVs
  47. Ruby’s Stack Memory Space Stack in CRuby rb_control_frame_t ENV ENV

    ENV ENV rb_control_frame_t rb_control_frame_t rb_control_frame_t rb_control_frame_t rb_control_frame_t ENV ENV Stack Over fl ow!! ˒ From head: control frames ˒ From tail: ENVs
  48. ˒ M: Frame Magic / Frame Type (15bits + check)

    METHOD, BLOCK, CLASS, TOP, CFUNC, IFUNC, EVAL, RESCUE, DUMMY ˒ F: Frame Flags (8bits) FINISH, CFRAME, LAMBDA, … ˒ E: Env Flags (4bits) LOCAL, ESCAPED, WB_REQUIRED, ISOLATED ˒ X: Tag for GC marking (to mimic Fixnum) Frame/Env Flags struct rb_control_frame_struct { // …… const VALUE *ep; // …… }; ————————————————————- VALUE ME_CREF // ep[-2] VALUE SPECVAL // ep[-1] VALUE FLAGS // ep[0] M M M M M M M M M M M M M M M M _ _ _ F F F F F F F F E E E E X
  49. Frame Types and Env Values (3.4) 'SBNFUZQF 7.@&/7@'-"(@-0$"- 41&$7"- .&@$3&'

    .&5)0% 0O #) #MPDL)BOEMFS .& .FUIPE&OUSZ #-0$,  1SFW&1 $3&' $-"44 0O #) $3&' 501 0O #) $3&' $'6/$ 0O #) .& *'6/$  1SFW&1 $3&' &7"-  1SFW&1 $3&' 3&4$6&  1SFW&1 $3&' %6..: 0O #) $3&'
  50. ˒ ME: Method Entry fl ags, de fi ned_class, method_de

    fi nition, called_id, owner ˒ Method De fi nition (mdef) (rb_method_definition_struct) can have box (rb_box_t *box) ˒ BH: Block Handler ˒ CREF: Class REFerence fl ags, re fi nements, klass_of_self, next, scope_visibility ˒ Prev EP: Previous Env Pointer ENV Values a = 1 PROC1 = ->(){ a * 2 } module App def self.foo c = 2 [:foo, :bar].map{ s = it.to_s ->(){ s * c } } end end env1 env2 env3 env4 env5 env6
  51. ˒ ME: Method Entry fl ags, de fi ned_class, method_de

    fi nition, called_id, owner ˒ Method De fi nition (mdef) (rb_method_definition_struct) can have box (rb_box_t *box) ˒ BH: Block Handler ˒ CREF: Class REFerence fl ags, re fi nements, klass_of_self, next, scope_visibility ˒ Prev EP: Previous Env Pointer ENV Values a = 1 PROC1 = ->(){ a * 2 } module App def self.foo c = 2 [:foo, :bar].map{ s = it.to_s ->(){ s * c } } end end env1 env2 env3 env4 env5 env6
  52. ˒ ME: Method Entry fl ags, de fi ned_class, method_de

    fi nition, called_id, owner ˒ Method De fi nition (mdef) (rb_method_definition_struct) can have box (rb_box_t *box) ˒ BH: Block Handler ˒ CREF: Class REFerence fl ags, re fi nements, klass_of_self, next, scope_visibility ˒ Prev EP: Previous Env Pointer ENV Values a = 1 PROC1 = ->(){ a * 2 } module App def self.foo c = 2 [:foo, :bar].map{ s = it.to_s ->(){ s * c } } end end env1 env2 env3 env4 env5 env6
  53. ˒ ME: Method Entry fl ags, de fi ned_class, method_de

    fi nition, called_id, owner ˒ Method De fi nition (mdef) (rb_method_definition_struct) can have box (rb_box_t *box) ˒ BH: Block Handler ˒ CREF: Class REFerence fl ags, re fi nements, klass_of_self, next, scope_visibility ˒ Prev EP: Previous Env Pointer ENV Values a = 1 PROC1 = ->(){ a * 2 } module App def self.foo c = 2 [:foo, :bar].map{ s = it.to_s ->(){ s * c } } end end env1 env2 env3 env4 env5 env6
  54. Frame Types and Env Values Finding the current box 'SBNFUZQF

    7.@&/7@'-"(@-0$"- 41&$7"- .&@$3&' .&5)0% 0O #) #MPDL)BOEMFS .& .FUIPE&OUSZ #-0$,  1SFW&1 $3&' $-"44 0O #) $3&' 501 0O #) $3&' $'6/$ 0O #) .& *'6/$  1SFW&1 $3&' &7"-  1SFW&1 $3&' 3&4$6&  1SFW&1 $3&' %6..: 0O #) $3&' Check MDef Check MDef
  55. Frame Types and Env Values Finding the current box 'SBNFUZQF

    7.@&/7@'-"(@-0$"- 41&$7"- .&@$3&' .&5)0% 0O #) #MPDL)BOEMFS .& .FUIPE&OUSZ #-0$,  1SFW&1 $3&' $-"44 0O #) $3&' 501 0O #) $3&' $'6/$ 0O #) .& *'6/$  1SFW&1 $3&' &7"-  1SFW&1 $3&' 3&4$6&  1SFW&1 $3&' %6..: 0O #) $3&' Check Prev EP Check Prev EP Check Prev EP Check MDef Check MDef
  56. Frame Types and Env Values Finding the current box 'SBNFUZQF

    7.@&/7@'-"(@-0$"- 41&$7"- .&@$3&' .&5)0% 0O #) #MPDL)BOEMFS .& .FUIPE&OUSZ #-0$,  1SFW&1 $3&' $-"44 0O #) $3&' 501 0O #) $3&' $'6/$ 0O #) .& *'6/$  1SFW&1 $3&' &7"-  1SFW&1 $3&' 3&4$6&  1SFW&1 $3&' %6..: 0O #) $3&' Check Prev EP Check CFUNC Check Prev EP Check Prev EP Check MDef Check MDef Always main
  57. Frame Types and Env Values Finding the current box 'SBNFUZQF

    7.@&/7@'-"(@-0$"- 41&$7"- .&@$3&' .&5)0% 0O #) #MPDL)BOEMFS .& .FUIPE&OUSZ #-0$,  1SFW&1 $3&' $-"44 0O #) $3&' 501 0O #) $3&' $'6/$ 0O #) .& *'6/$  1SFW&1 $3&' &7"-  1SFW&1 $3&' 3&4$6&  1SFW&1 $3&' %6..: 0O #) $3&' Check Prev EP Check Prev EP Check Prev EP Check MDef Check MDef 🤔 🤔 Check CFUNC Always main
  58. Frame Types and Env Values Finding the current box 'SBNFUZQF

    7.@&/7@'-"(@-0$"- 41&$7"- .&@$3&' .&5)0% 0O #) #MPDL)BOEMFS .& .FUIPE&OUSZ #-0$,  1SFW&1 $3&' $-"44 0O #) $3&' 501 0O #) $3&' $'6/$ 0O #) .& *'6/$  1SFW&1 $3&' &7"-  1SFW&1 $3&' 3&4$6&  1SFW&1 $3&' %6..: 0O #) $3&' Check Prev EP Check Prev EP Check Prev EP Check MDef Check MDef 🤔 🤔 😳 😳 CLASS/TOP frames never receive blocks! Check CFUNC Always main
  59. Frame Types and Env Values (4.0) Finding the Current Box

    'SBNFUZQF 7.@&/7@'-"(@-0$"- 41&$7"- .&@$3&' .&5)0% 0O #) #MPDL)BOEMFS .& .FUIPE&OUSZ #-0$,  1SFW&1 $3&' $-"44 0O #PY SC@CPY@U $3&' 501 0O #PY SC@CPY@U $3&' $'6/$ 0O #) .& *'6/$  1SFW&1 $3&' &7"-  1SFW&1 $3&' 3&4$6&  1SFW&1 $3&' %6..: 0O #) $3&' Check Prev EP Check Prev EP Check Prev EP Check MDef Check MDef Check SPECVAL Check SPECVAL Check CFUNC Always main
  60. Finding Current Box: Revisit ˒ Rules to identify current box

    ˒ Find the closest Ruby frame ˒ If it’s running a C func, trace back to the closest Ruby frame ˒ Find the “LOCAL” variable scope from the Ruby frame ˒ Check the box of the LOCAL env ˒ SPECVAL or ME_CREF->mdef
  61. ˒ Method de fi nitions can be marked with its

    box ˒ In Class/Top frames ˒ Class de fi nition frame can be marked with its box ˒ In Top frames ˒ How can we mark the Top frames? Bootstrapping Problem
  62. ˒ Ruby Box switching happens only on some Ruby::Box methods

    ˒ #require, #require_relative, #load (and #eval) ˒ The target code is required/loaded in the receiver box ˒ The pushed (TOP) control frame is marked with the loading box Bootstrapping Box: Box#require -- Control frame information ------------------------------------------- c:0005 p:---- s:0019 e:000018 l:y b:---- r:0x0 CFUNC :bug! c:0004 p:0003 s:0015 e:000014 l:y b:0003 r:0x0 TOP ……/app.rb:2 [FINISH] c:0003 p:---- s:0012 e:000011 l:y b:---- r:0x0 CFUNC :require_relative c:0002 p:0023 s:0007 E:000030 l:n b:---- r:0x0 EVAL ./main.rb:5 [FINISH] c:0001 p:0000 s:0003 E:000738 l:y b:---- r:0x0 DUMMY [FINISH]
  63. ˒ The box to be used on loading fi les,

    marking TOP frame ˒ $LOAD_PATH is to resolve fi le paths BEFORE loading fi les ˒ Global variables for loading should switch the e ff ective boxes earlier than the current box (after red, before green line frame) The “Loading” Box? -- Control frame information ------------------------------------------- c:0005 p:---- s:0019 e:000018 l:y b:---- r:0x0 CFUNC :bug! c:0004 p:0003 s:0015 e:000014 l:y b:0003 r:0x0 TOP ……/app.rb:2 [FINISH] c:0003 p:---- s:0012 e:000011 l:y b:---- r:0x0 CFUNC :require_relative c:0002 p:0023 s:0007 E:000030 l:n b:---- r:0x0 EVAL ./main.rb:5 [FINISH] c:0001 p:0000 s:0003 E:000738 l:y b:---- r:0x0 DUMMY [FINISH]
  64. ˒ When calling Box#require (etc) ˒ Marking the current frame

    with VM_FRAME_FLAG_BOX_REQUIRE ˒ Finding the loading box ˒ Find the VM_FRAME_FLAG_BOX_REQUIRE frame ˒ Fetch cfp->self to get the receiver Ruby::Box instance Or the current box on the cfp (if the self is missing) A New Frame Flag: BOX_REQUIRE
  65. -- Control frame information ----------------------------------------------- c:0012 (snip) l:y b:---- r:0x0

    CFUNC :bug! c:0011 (snip) l:y b:0003 r:0x0 CLASS …/app2.rb:3 c:0010 (snip) l:y b:0003 r:0x0 CLASS …/app2.rb:2 c:0009 (snip) l:y b:0003 r:0x0 TOP …/app2.rb:1 [FINISH] c:0008 (snip) l:y b:---- r:0x0 CFUNC :require c:0007 (snip) l:y b:0001 r:0x0 METHOD <internal:…/rubygems/core_ext/kernel_require.rb>:139 [FINISH] c:0005 (snip) l:y b:0003 r:0x0 CLASS …/app.rb:9 c:0004 (snip) l:y b:0003 r:0x0 TOP …/app.rb:3 [FINISH] c:0003 (snip) l:y b:---- r:0x0 CFUNC :require_relative c:0002 (snip) l:n b:---- r:0x0 EVAL ./main.rb:5 [FINISH] c:0001 (snip) l:y b:---- r:0x0 DUMMY [FINISH] ˒ cfp->self is missing in this case ˒ Kernel#require (etc) is overrided by RubyGems, in the root box ˒ The loading box must be marked near the line calling #require Calling Kernel#require in box
  66. ˒ In boxes, Object includes Box::Loader having #require (etc) ˒

    Box::Loader#require marks its cfp with BOX_REQUIRE ˒ The current box (calling #require on .rb) will be the loading box Inserting Ruby::Box::Loader -- Control frame information ----------------------------------------------- c:0012 (snip) l:y b:---- r:0x0 CFUNC :bug! c:0011 (snip) l:y b:0003 r:0x0 CLASS …/app2.rb:3 c:0010 (snip) l:y b:0003 r:0x0 CLASS …/app2.rb:2 c:0009 (snip) l:y b:0003 r:0x0 TOP …/app2.rb:1 [FINISH] c:0008 (snip) l:y b:---- r:0x0 CFUNC :require c:0007 (snip) l:y b:0001 r:0x0 METHOD <internal:…/rubygems/core_ext/kernel_require.rb>:139 [FINIS c:0006 (snip) l:y b:---- r:0x0 CFUNC :require c:0005 (snip) l:y b:0003 r:0x0 CLASS …/app.rb:9 c:0004 (snip) l:y b:0003 r:0x0 TOP …/app.rb:3 [FINISH] c:0003 (snip) l:y b:---- r:0x0 CFUNC :require_relative c:0002 (snip) l:n b:---- r:0x0 EVAL ./main.rb:5 [FINISH]
  67. ˒ Ruby Box has many details on various spots of

    Ruby VM ˒ De fi ning things in box: Class/Method/etc de fi nitions (class.c) ˒ Loading things in box: Evaluating scripts / Loading binaries (load.c) ˒ Finding boxes: Executing Ruby programs (vm.c) ˒ Tour must be pleasure, probably……? 🤔 Tour of Ruby Box ≒ Tour of (a part of) Ruby VM
  68. Before RubyKaigi 2023 No future for me to develop Ruby

    language or runtime… I have nothing to add to Ruby.
  69. ˒ tagomoris/LFA: App server, wri tt en in 2022 Winter

    ˒ loads multi AWS Lambda functions in a process ˒ separates them incompletely ˒ A blog post about its feature and my motivation ˒ h tt ps://tagomoris.hatenablog.com/entry/2022/12/15/133450 ˒ … then, I forgot the motivation ˒ “Multiverse Ruby” “Yes! I have the motivation on that problem!” “Multiverse Ruby” Shock
  70. ˒ Day 11: The 1st commit of Namespace PoC ˒

    Day 46: The proposal #19744 “Namespace on read” ˒ Day 78: My 1st talk about this idea at MatueRubyKaigi ˒ Day 166: Ruby Association Grant selected my project ˒ 1Y1D: My talk “Namespace, What and Why” in RubyKaigi 2024 ˒ 1Y3D: Matz “Ruby 4.0 with Packaging based on Namespace” Timeline 1
  71. ˒ 2Y-26D: My talk “State of Namespace” in RubyKaigi 2025

    ˒ 2Y-24D: Matz “Ruby 4.0 with (experimental) Namespace and ZJIT” ˒ 2Y-12D: Pull request submi tt ed ˒ 2Y-1D: Pull request merged (by myself) ˒ 2Y179D: Renamed Namespace to Ruby Box ˒ 2Y227D: Ruby 4.0 Timeline 2
  72. ˒ 3Y-20D: Opening Keynote in RubyKaigi 2026 ˒ Day 0:

    Multiverse Ruby ˒ Day -1: “I have nothing to add to Ruby” Timeline 3
  73. @tagomoris @shioyama Let’s name it as “Hako” (meaning “Box”), …

    and then, sometimes later, Let’s have RubyKaigi at Hakodate. Wow, it’s Hako-Kaigi!
  74. Big Thank You @shioyama -san, Ruby Box and This Talk

    Can’t Be Without You. @shioyama