Slide 1

Slide 1 text

RE: POWER ASSERT IN RUBY Kazuki Tsujimoto

Slide 2

Slide 2 text

ࣗݾ঺հ • “VM Bug Hunter” • ॳAsakusa.rb

Slide 3

Slide 3 text

• Ξαʔγϣϯϝιου/Ϛονϟͷ࢖͍෼͚ʹ೰·ͣʹ ςετΛॻ͚ΔΑ͏ʹ͢ΔͨΊpower_assertΛ࡞ͬͨ • assert {expr}͚͍֮ͩ͑ͯΕ͹Α͍ • 1==3ͷ໭Γ஋͕දࣔ͞Ε͍ͯͳ͍ͱ͍͏໰୊͕͋Δ $ ruby test_example.rb assert { [0, 1, 2].find {|i| i.odd? } == 3 } | 1 POWER ASSERT IN RUBY

Slide 4

Slide 4 text

• ࣮૷ʹ࢖͍ͬͯΔTracePointͷ੍໿ • ϝιουݺͼग़͠ͷ࠷దԽʹΑͬͯɺΠϕϯτ͕ىಈ ͞Εͳ͘ͳ͍ͬͯΔ • ࣄલʹpower_assertΛrequireͯ͠࠷దԽΛແޮԽ͢Ε ͹Α͍͕ɺ͜Ε͸खؒ $ ruby -rpoewr_assert test_example.rb assert { [0, 1, 2].find {|i| i.odd? } == 3 } | | | false 1 POWER ASSERT IN RUBY

Slide 5

Slide 5 text

• akr͞Μ͔Β࠷దԽର৅ͱͳΔϝιουΛʮ͜ ͱ͝ͱ͘࠶ఆٛͯ͠ݩʹ໭ͯ͠͠·ʯ͑͹Α ͍ͷͰ͸ͳ͍͔ͱͷࢦఠ • ࣄલrequireΛෆཁʹ͢Δ͜ͱ͸Ͱ͖Δͷ͔ POWER ASSERT IN RUBY

Slide 6

Slide 6 text

໰୊ • 1 == 3ͷ==ϝιουݺͼग़͠ͷΠϕϯτ͕र ͑ͳ͍ trace = TracePoint.new(:return, :c_return) {|tp| p tp.method_id } trace.enable { 1 == 3 }

Slide 7

Slide 7 text

ݪҼ • Fixnum#==ͳͲͷجຊతͳϝιου͸ಛघ έʔεѻ͍Ͱ؆ུԽͨ͠ॲཧΛ͍ͯ͠ΔͨΊ if (FIXNUM_2_P(recv, obj) && BASIC_OP_UNREDEFINED_P(BOP_EQ, FIXNUM_REDEFINED_OP_FLAG)) { return (recv == obj) ? Qtrue : Qfalse; } else if(...) { ... } ... CALL_SIMPLE_METHOD(recv); ಛघέʔε(1) ಛघέʔε(..N) Ұൠέʔεɹ

Slide 8

Slide 8 text

ରࡦ • ૉ௚ͳΞϓϩʔν(࠶ఆٛͰϑϥάΛཱͯΔ) • Fixnum.method_addedΛϢʔβ͕ఆٛͯ͠ ͍Δ৔߹ͳͲʹӨڹ͕ग़Δ class Fixnum alias eq_orig == def ==(other) eq_orig(other) end alias == eq_orig end

Slide 9

Slide 9 text

ରࡦ • ࠾༻ͨ͠Ξϓϩʔν(࠶ఆٛҎ֎ͰϑϥάΛཱͯΔ) • ՄࢹੑΛ໌ࣔతʹઃఆ͢Δ(Ruby 2.0ʙ2.2) • refine͢Δ(Ruby 2.0ʙ2.3dev) class Fixnum public :== end module M refine Fixnum do def ==; end end end

Slide 10

Slide 10 text

ଓɾ໰୊ • C.new == C.newͷ==ϝιουݺͼग़͠ͷΠ ϕϯτ͕र͑ͳ͍ trace = TracePoint.new(:return, :c_return) {|tp| p tp.method_id } class C; end trace.enable { C.new == C.new }

Slide 11

Slide 11 text

ଓɾݪҼ • ϝιουͷ࣮ମ͕ಛఆͷCؔ਺(rb_obj_equal) ͩͬͨͱ͖͸ಛघέʔεѻ͍Ͱ؆ུԽͨ͠ॲ ཧΛ͍ͯ͠ΔͨΊ ... vm_search_method(ci, cc, recv); if (check_cfunc(cc->me, rb_obj_equal)) { return recv == obj ? Qtrue : Qfalse; } ... CALL_SIMPLE_METHOD(recv);

Slide 12

Slide 12 text

ଓɾରࡦ • ૉ௚ͳΞϓϩʔν • ϝιουΛ࠶ఆٛͯ͠ݩʹ໭͞ͳ͍ • BasicObject.method_added(ུ) • ϞϯΩʔύον͕ద༻͞Εͨঢ়ଶͰϢʔβίʔυ͕࣮ߦ͞ Εͯ͠·͏ class BasicObject alias eq_orig == def ==(other); eq_orig(other); end alias == eq_orig end

Slide 13

Slide 13 text

ଓɾରࡦ • ࠾༻ͨ͠Ξϓϩʔν • refine͢Δ(refine͞Ε͍ͯΔ͜ͱΛࣔ͢ಛघͳϝιου ΤϯτϦΛrb_obj_equalͷલʹૠೖ͢Δ) • ͲͪΒͷΞϓϩʔνͰ΋Rubyͷඪ४Ϋϥεʹ͍ͭͯ͸ࣄલʹ ରԠ͓ͯ͘͜͠ͱ͕Մೳ͕ͩɺC֦ுͰ࡞੒ͨ͠Ϣʔβఆٛ Ϋϥε·Ͱ͸ٹ͑ͳ͍ͱ͍͏՝୊͸࢒Δ module M refine BasicObject do def ==; end end end

Slide 14

Slide 14 text

ଓʑɾ໰୊ • C.new == C.newͷ==ϝιουݺͼग़͠ͷΠ ϕϯτ͕1ճ͔͠र͑ͳ͍ trace = TracePoint.new(:return, :c_return) {|tp| p tp.method_id } class C; end trace.enable { loop { C.new == C.new } }

Slide 15

Slide 15 text

ଓʑɾݪҼ • 1ճ໨ͷݺͼग़࣌͠ʹʮ࠷ऴతʹrb_obj_equalΛݺͿʯ ͱ͍͏৘ใΛΠϯϥΠϯΩϟογϡʹ࣋ͬͯ͠·͏ͨΊ Lightweight Method Dispatch on MRI(Koichi Sasada)͔ΒҾ༻

Slide 16

Slide 16 text

ଓʑɾରࡦ • దٓΩϟογϡΛΫϦΞ͢Ε͹Α͍ • power_assertͰ͸assertʹ౉͞ΕͨϒϩοΫΛݺ ͼग़͢λΠϛϯάͰΫϦΞ • ΩϟογϡͷΫϦΞʹ΋RefinementsΛར༻ • ۭϞδϡʔϧΛusing

Slide 17

Slide 17 text

·ͱΊ • power_assertͷࣄલrequire͸΄΅ෆཁʹ • ׬શͰ͸ͳ͍͕௨ৗͷϢʔεέʔε͸Χόʔ • Rubyͷ಺෦࣮૷ʹڧ͘ґଘ͓ͯ͠Γࠓޙ΋ಈ࡞ ͢Δ͔͸ෆಁ໌ • Ҿ͖ଓ͖ࣄલrequireΛਪ঑