Presentation is loading. Please wait.

Presentation is loading. Please wait.

Method Shelters: Avoiding Conflicts among Class Extensions Caused by Local Rebinding Shumpei Akai, Shigeru Chiba Tokyo Institute of Technology 1.

Similar presentations


Presentation on theme: "Method Shelters: Avoiding Conflicts among Class Extensions Caused by Local Rebinding Shumpei Akai, Shigeru Chiba Tokyo Institute of Technology 1."— Presentation transcript:

1 Method Shelters: Avoiding Conflicts among Class Extensions Caused by Local Rebinding Shumpei Akai, Shigeru Chiba Tokyo Institute of Technology 1

2 Class Extensions Destructively change method definitions in the existing classes ◦ Write new definitions in a separate file Available in ◦ Smalltalk, Objective-C, AspectJ … ◦ and Ruby  (called Open Class) 2

3 Class Extensions are popular in Ruby Ruby on Rails aggressively adds methods to built-in classes ◦ Class extensions are used in real applications ◦ e.g. 10.kilobytes # => NoMethodError: undefined method require “active_record” #load rails’ lib 10.kilobytes # => 10240 10.kilobytes # => NoMethodError: undefined method require “active_record” #load rails’ lib 10.kilobytes # => 10240 3

4 Conflicts among Class Extensions Class extensions are dangerous ◦ Cause conflicts, of course Ruby allows class extensions ◦ Ruby on Rails aggressively use ◦ Serious issue in Ruby ◦ Scope of class extensions are needed 4

5 What is the appropriate scope of class extensions? Global? ◦ Same as Ruby Lexical? ◦ Redefinitions are available in a lexical scope Local rebinding property (of Classbox *)? ◦ Redefine methods in another module by importing ◦ Redefinition is limited in imported module 5 * [‘05 Bergel et al.]

6 Global Scopes 6 List avg(): average of elems using div Integer div(): return rational Integer div(): return integer plus(): … minus(): … 1.div(2) #=> (1/2) Redefine destructively Module 1 Module 2 Module 3 No one can use original div()

7 Lexical Scopes 7 List avg(): average of elems using div Integer div(): return rational Integer div(): return integer plus(): … minus(): … Redefinition in Lexical scope Module 1 Module 2 Module 3 Cannot reuse redefined div() [1, 2].avg() #=> (3/2) 1.div(2) #=> 0 [1, 2].avg() #=> (3/2) 1.div(2) #=> 0 [1, 2].avg() #=> (3/2) 1.div(2) #=> 0 [1, 2].avg() #=> (3/2) 1.div(2) #=> 0

8 Local rebinding (Classbox) 8 List avg(): average of elems using div Integer div(): return rational Integer div(): return integer plus(): … minus(): … 1.div(2) #=> 0 Module 1 Module 2 Module 3 import [1, 2].avg() #=> (3/2) 1.div(2) #=> (1/2) [1, 2].avg() #=> (3/2) 1.div(2) #=> (1/2) Module 4 Redefinition in importing chain Original div() Redefined div()

9 Local rebinding (Classbox) 9 List avg(): average of elems using div Integer div(): return rational Integer div(): return integer plus(): … minus(): … [1, 2].avg() #=> (3/2) 1.div(2) #=> Conflicts [1, 2].avg() #=> (3/2) 1.div(2) #=> Conflicts Module 1 Module 2 Module 3 1.div(2) #=> (1/2) [1, 2].avg() #=> (3/2) 1.div(2) #=> (1/2) [1, 2].avg() #=> (3/2) Module 4

10 Our proposal: Method Shelters A method shelter is a module which provides a way to control scopes of class extensions ◦ 2 mechanisms  Preserves local rebinding  Or redefine methods in limited scope Based on Ruby 10

11 A Code with Method Shelters shelter :MathN do class Fixnum # fixed size integer in Ruby def /(x) Rational(self,x) end shelter :Average do class Array def avg sum = self.inject(0){|r,i|r+i} sum / self.size end hide import :MathN end shelter :MathN do class Fixnum # fixed size integer in Ruby def /(x) Rational(self,x) end shelter :Average do class Array def avg sum = self.inject(0){|r,i|r+i} sum / self.size end hide import :MathN end 11

12 Chambers in a method shelter A method shelter has two parts ◦ An exposed chamber and a hidden chamber ◦ Each chamber contains methods and “import”s ◦ Exposed : for public APIs (similar to public) ◦ Hidden : for internal use (similar to protected) - Obj#m0 S0 Exposed Hidden 12 Import

13 Exposed Chambers for public API ◦ Local rebinding Methods ◦ Visible from importer Import ◦ Imported methods are also visible from importer - Obj#m0 S0 S1 S2 import 13 Call/redefine

14 Hidden chamber for internally used methods ◦ Not called/redefined from importer Method ◦ Visible only from the same shelter Import ◦ Imported methods are not visible from importer - Obj#m1 - Obj#m0 S0 S1 S2 14 Call import

15 Method Lookup Algorithm Contexts : ◦ (class, method name, current shelter) Search for methods as follows: ◦ 1. look up the current shelter’s hidden- chamber and its importing shelters ◦ 2. look up the current shelter’s exposed- chamber and its importing shelters ◦ 3.If not found, go to the superclass 15

16 - m1 - m0 current First, look up this group Second, 16 *Look up from importer

17 Detect Ambiguity If you use exposed chambers, it may cause conflicts ◦ Detects and raises an error S0 - C#m0 S1 S2 Error! - C#m0 S3 17

18 Syntax We have not modified syntax ◦ Ruby has powerful syntax ◦ Use ordinal methods with a block shelter :ShelterName do class Foo def hoge # <- defined in the method shelter end shelter :ShelterName do class Foo def hoge # <- defined in the method shelter end 18

19 Syntax: Import shelter :ShelterName do import :AnotherShelterName end shelter :ShelterName do import :AnotherShelterName end 19

20 Syntax: hide “hide” method switches a chamber ◦ Methods and imports below “hide” are in the hidden chamber shelter :ShelterName do # exposed chamber hide # hidden chamber end shelter :ShelterName do # exposed chamber hide # hidden chamber end 20

21 Example of method shelters 21 List avg(): average of elems using div Integer div(): return rational Integer div(): return integer plus(): … minus(): … Shelter1 Sheleter 2 Sheleter 3 [1, 2].avg() #=> (3/2) 1.div(2) #=> 0 [1, 2].avg() #=> (3/2) 1.div(2) #=> 0 Shelter 4

22 Example of method shelters 22 List avg(): average of elems using div Integer div(): return rational Integer div(): return integer plus(): … minus(): … Shelter1 Sheleter 2 Sheleter 3 [1, 2].avg() #=> (3/2) 1.div(2) #=> (1/2) [1, 2].avg() #=> (3/2) 1.div(2) #=> (1/2) Shelter 4

23 Implementation Based on Ruby 1.9.2 Add one implicit argument to method: ◦ Current method shelter Optimize method-lookup caches ◦ Shelter node cache  Caches method body in a shelter ◦ Extend inline cache  Stores the found shelter  Size of an inline cache : 3 word -> 4word (per method call) 23

24 Micro benchmark : empty methods Micro benchmark : empty methods Call an empty method in shelter 10,000,000 times ◦ Less than 5% overhead when shelters are used 24

25 Micro benchmark : Ruby on Rails Enabled shelters in an action method ◦ Numeric#kilobytes method in a shelter In the action method ◦ 1. Call kilobytes method in shelter ◦ 2. One access to SQLite 4% overhead 25

26 Related Work Refinements (for Ruby) ◦ Provide a scope of methods ◦ Redefined methods are available in lexical scope  No local rebinding Classboxes [‘05 Bergel et al.] ◦ A classbox provides the scope of class extensions ◦ Introduce Local rebinding property 26

27 Conclusion Method shelters provide 2 mechanisms for implementing scope of class extensions ◦ Exposed and Hidden ◦ You can control scopes of class extensions by combining them ◦ Avoid conflicts Implementation on Ruby ◦ reasonable overhead by caches 27

28 Evaluate Should specify the initial method shelter ◦ Evaluate within a shelter shelter_eval :ShelterName do #shelter is enabled end shelter_eval :ShelterName do #shelter is enabled end 28

29 Global Methods Methods not in shelters ◦ Callable from any shelter ◦ Global methods can call methods in a shelter if the caller is in the shelter  To preserve local rebinding obj.g0() S0 - Obj#g0 Global 29


Download ppt "Method Shelters: Avoiding Conflicts among Class Extensions Caused by Local Rebinding Shumpei Akai, Shigeru Chiba Tokyo Institute of Technology 1."

Similar presentations


Ads by Google