-
-
Notifications
You must be signed in to change notification settings - Fork 939
Description
Ruby classes with instance variables will attempt to pick the right "shape" on first allocation, by statically analyzing all methods in the class hierarchy and looking for variable accesses or accessors. These variables will then be stored in specialized Java fields rather than in the varTable array, improving locality.
When previously-undetected instance variables are assigned after this first instantiation, the varTable is used as a spill location to store those variables. However there are a few performance problems with how this is handled:
- The varTable size is calculated based on the total number of variables at that point (including statically-detected variables), leaving slots empty and unused.
- The index into the varTable for a new dynamic instance variable also reflects this total number of variables, rather than just the additional number of dynamic variables needed.
For a class with two statically-detected variables and two more dynamically allocated variables, this results in using an object with two fields (RubyObject2) with a varTable large enough for four values but only holding two non-null values.
This has greater impact for large and complex classes that have many statically-detected variables, since the size of the dynamic varTable array will waste 4 or 8 bytes per variable.
The correct logic would be that any spilled variables to go in varTable are indexed independently of the statically-detected field-based variables, and the array is allocated to hold exactly that many values.