Re: Power Assert in Ruby

303dd57f37d64288bb4f0336332a8882?s=47 k_tsj
November 08, 2015

Re: Power Assert in Ruby

303dd57f37d64288bb4f0336332a8882?s=128

k_tsj

November 08, 2015
Tweet

Transcript

  1. RE: POWER ASSERT IN RUBY Kazuki Tsujimoto

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

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

    test_example.rb assert { [0, 1, 2].find {|i| i.odd? } == 3 } | 1 POWER ASSERT IN RUBY
  4. • ࣮૷ʹ࢖͍ͬͯΔ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
  5. • akr͞Μ͔Β࠷దԽର৅ͱͳΔϝιουΛʮ͜ ͱ͝ͱ͘࠶ఆٛͯ͠ݩʹ໭ͯ͠͠·ʯ͑͹Α ͍ͷͰ͸ͳ͍͔ͱͷࢦఠ • ࣄલrequireΛෆཁʹ͢Δ͜ͱ͸Ͱ͖Δͷ͔ POWER ASSERT IN RUBY

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

    {|tp| p tp.method_id } trace.enable { 1 == 3 }
  7. ݪҼ • 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) Ұൠέʔεɹ
  8. ରࡦ • ૉ௚ͳΞϓϩʔν(࠶ఆٛͰϑϥάΛཱͯΔ) • Fixnum.method_addedΛϢʔβ͕ఆٛͯ͠ ͍Δ৔߹ͳͲʹӨڹ͕ग़Δ class Fixnum alias eq_orig

    == def ==(other) eq_orig(other) end alias == eq_orig end
  9. ରࡦ • ࠾༻ͨ͠Ξϓϩʔν(࠶ఆٛҎ֎ͰϑϥάΛཱͯΔ) • ՄࢹੑΛ໌ࣔతʹઃఆ͢Δ(Ruby 2.0ʙ2.2) • refine͢Δ(Ruby 2.0ʙ2.3dev) class

    Fixnum public :== end module M refine Fixnum do def ==; end end end
  10. ଓɾ໰୊ • C.new == C.newͷ==ϝιουݺͼग़͠ͷΠ ϕϯτ͕र͑ͳ͍ trace = TracePoint.new(:return, :c_return)

    {|tp| p tp.method_id } class C; end trace.enable { C.new == C.new }
  11. ଓɾݪҼ • ϝιουͷ࣮ମ͕ಛఆͷ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);
  12. ଓɾରࡦ • ૉ௚ͳΞϓϩʔν • ϝιουΛ࠶ఆٛͯ͠ݩʹ໭͞ͳ͍ • BasicObject.method_added(ུ) • ϞϯΩʔύον͕ద༻͞Εͨঢ়ଶͰϢʔβίʔυ͕࣮ߦ͞ Εͯ͠·͏

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

    module M refine BasicObject do def ==; end end end
  14. ଓʑɾ໰୊ • 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 } }
  15. ଓʑɾݪҼ • 1ճ໨ͷݺͼग़࣌͠ʹʮ࠷ऴతʹrb_obj_equalΛݺͿʯ ͱ͍͏৘ใΛΠϯϥΠϯΩϟογϡʹ࣋ͬͯ͠·͏ͨΊ Lightweight Method Dispatch on MRI(Koichi Sasada)͔ΒҾ༻

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

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