tfpt review “/shelveset:Precompilation5;REDMOND\tomat”
Mostly Ruby changes, one simple DLR change.
Implements precompilation of simple Ruby method invocations. Adds
pre-generated rules for call sites that are
-
context bound
-
without a block, splat or RHS argument
-
with self of runtime type RubyObject strongly typed to Object in
the call site
-
the method is resolved to an existing Ruby method or an "empty"
library method
-
no context class checks are needed due to protected visibility
-
the method doesn't have optional or unsplatted parameters and
the number of mandatory parameters matches the call site
-
the method has at most 5 parameters
The rules are generated to MethodDispatcher.Generated.cs by
MethodDispatcher.Generator.rb. The generator finds blocks in C# code
that match this pattern:
#if GENERATOR
#else
<C# template>
#end
#region Generated by …
#endregion
It creates a new class G < Generator for each such block end
module-eval’s in that class. Then it calls G.new.generate.
The default implementation takes the <C# template> and replaces each
occurrence of /$MethodName/ or /$MethodName{/ … /}/ in the
template by a value returned by a call to MethodName on the generator
class. The generator replaces the content of “Generated by” region by
the resulting code. The <C# template> is optional - the #else block can
be omitted.
There could be multiple templates in a single file. The generator also
searches the file for /$$/ comments before evaluating them. Text in
between such comment and following semicolon is evaluated as a Ruby
global variable definition. For example,
internal const int /$$/PrecompiledParameterCount = 5;
sets a global variable $PrecompiledParameterCount to 5.
The shelveset also moves event sites (method added/removed/undefined,
…) to RubyModule and RubyClass so that they don’t become megamorphic.
Encapsulates class version into VersionHandle class.
Changes RubyObject.ToString to detect that it’s called by rule
expression writer in DEBUG builds. We shouldn’t call to_s dynamically in
that case since it would recursively call the writer leading to a stack
overflow.
Changes perf stats output writer to a file instead of a console: if
-X:TrackPerformance -X:PerfStats is passed on command line
“perfstats.log” file is created in the current directory.
Adds perf-counters for Ruby rules. For example, for “mspec ci library”
we get the following numbers below. “Bind” means that a rule is
generated in runtime, “BindDelegate” that a site is being bound. The
number of sites bound to pregenerated rules can be calculated by
subtracting Bind from BindDelegate. In this case we saved generating 30%
of RubyCallAction rules (1 - 153k/219k) by using precompiled rules.
Ruby:
RubyCallAction(S,2=):
BindDelegate
1
Ruby:
RubyCallAction(.S,16):
Bind
1
Ruby:
RubyCallAction(S,2=):
Bind
1
Ruby:
ConvertToIntAction(.C,0):
Bind
1
Ruby:
ConvertToIntAction:
BindDelegate
1
Ruby:
ConvertToHashAction(.C,0):
Bind
1
Ruby:
ConvertToHashAction:
BindDelegate
1
Ruby:
ConvertToArrayAction(.C,0):
Bind
1
Ruby:
RubyCallAction(.S,16):
BindDelegate
1
Ruby:
ConvertToArrayAction:
BindDelegate
1
Ruby:
RubyCallAction(S,10):
Bind
1
Ruby:
RubyCallAction(S,10):
BindDelegate
1
Ruby:
RubyCallAction(.C,3):
Bind
1
Ruby:
RubyCallAction(.C,3):
BindDelegate
1
Ruby:
RubyCallAction(S,7):
BindDelegate
2
Ruby:
SuperCallAction(.S,3&):
Bind
2
Ruby:
ConvertToSymbolAction:
BindDelegate
2
Ruby:
RubyCallAction(S,7):
Bind
2
Ruby:
ConvertToSymbolAction(.C,0):
Bind
2
Ruby:
RubyCallAction(.S,4&):
BindDelegate
3
Ruby:
ConvertToProcAction:
BindDelegate
3
Ruby:
ConvertToProcAction(.C,0):
Bind
3
Ruby:
RubyCallAction(.S,4&):
Bind
3
Ruby:
TryConvertToStrAction(.C,0):
Bind
3
Ruby:
TryConvertToStrAction:
BindDelegate
3
Ruby:
RubyCallAction(S,4&):
Bind
3
Ruby:
RubyCallAction(S,4&):
BindDelegate
3
Ruby:
RubyCallAction(.S,7):
Bind
4
Ruby:
RubyCallAction(.S,7):
BindDelegate
4
Ruby:
SuperCallAction(.S,6&):
Bind
5
Ruby:
RubyCallAction(.S,3&):
BindDelegate
7
Ruby:
RubyCallAction(.S,3&):
Bind
7
Ruby:
RubyCallAction(.S,1*):
BindDelegate
11
Ruby:
RubyCallAction(.S,1*):
Bind
11
Ruby:
RubyCallAction(.S,5):
Bind
11
Ruby:
RubyCallAction(S,2*):
Bind
11
Ruby:
RubyCallAction(S,2*):
BindDelegate
11
Ruby:
RubyCallAction(.S,8):
Bind
11
Ruby:
RubyCallAction(.S,8):
BindDelegate
11
Ruby:
RubyCallAction(.S,6):
Bind
12
Ruby:
RubyCallAction(.S,6):
BindDelegate
12
Ruby:
RubyCallAction(.S,5):
BindDelegate
12
Ruby:
ConvertToFixnumAction:
BindDelegate
13
Ruby:
ConvertToFixnumAction(.C,0):
Bind
13
Ruby:
RubyCallAction(S,3&):
BindDelegate
14
Ruby:
SuperCallAction(.S,5&):
Bind
14
Ruby:
RubyCallAction(S,3&):
Bind
14
Ruby:
RubyCallAction(S,1*&):
BindDelegate
15
Ruby:
RubyCallAction(S,1*&):
Bind
15
Ruby:
ConvertToStrAction:
BindDelegate
16
Ruby:
ConvertToStrAction(.C,0):
Bind
16
Ruby:
RubyCallAction(S,5):
BindDelegate
25
Ruby:
RubyCallAction(S,5):
Bind
25
Ruby:
RubyCallAction(S,6):
BindDelegate
26
Ruby:
RubyCallAction(S,6):
Bind
26
Ruby:
RubyCallAction(S,9):
BindDelegate
38
Ruby:
RubyCallAction(S,9):
Bind
38
Ruby:
ConvertToRegexAction(.C,0):
Bind
44
Ruby:
ConvertToRegexAction:
BindDelegate
44
Ruby:
RubyCallAction(S,2*&):
BindDelegate
45
Ruby:
RubyCallAction(S,2*&):
Bind
45
Ruby:
RubyCallAction(.C,2):
BindDelegate
46
Ruby:
RubyCallAction(.C,2):
Bind
46
Ruby:
ConvertToFAction:
BindDelegate
46
Ruby:
ConvertToFAction(.C,0):
Bind
46
Ruby:
RubyCallAction(.S,0*&):
Bind
55
Ruby:
RubyCallAction(.S,0*&):
BindDelegate
55
Ruby:
SuperCallAction(.S,2&):
Bind
57
Ruby:
RubyCallAction(.S,1=):
Bind
59
Ruby:
RubyCallAction(.S,1=):
BindDelegate
59
Ruby:
SuperCallAction(.S,0&):
Bind
121
Ruby:
RubyCallAction(S,4):
Bind
128
Ruby:
RubyCallAction(S,4):
BindDelegate
130
Ruby:
SuperCallAction(.S,0*&):
Bind
137
Ruby:
RubyCallAction(.S,4):
Bind
146
Ruby:
RubyCallAction(.S,4):
BindDelegate
154
Ruby:
CompositeConversionAction(.C,0):
Bind
315
Ruby:
CompositeConversionAction:
BindDelegate
315
Ruby:
RubyCallAction(.S,2&):
BindDelegate
439
Ruby:
SuperCallAction(.S,1&):
Bind
439
Ruby:
RubyCallAction(.S,2&):
Bind
439
Ruby:
RubyCallAction(.S,0=):
Bind
460
Ruby:
RubyCallAction(.S,0=):
BindDelegate
460
Ruby:
TryConvertToAAction(.C,0):
Bind
1241
Ruby:
TryConvertToAAction:
BindDelegate
1241
Ruby:
TryConvertToArrayAction:
BindDelegate
1262
Ruby:
TryConvertToArrayAction(.C,0):
Bind
1262
Ruby:
RubyCallAction(.S,3):
Bind
1432
Ruby:
RubyCallAction(.S,0*):
Bind
1456
Ruby:
RubyCallAction(.S,0*):
BindDelegate
1456
Ruby:
RubyCallAction(.S,3):
BindDelegate
1468
Ruby:
RubyCallAction(.C,0&):
Bind
1510
Ruby:
RubyCallAction(.C,0&):
BindDelegate
1510
Ruby:
RubyCallAction(.S,0&):
Bind
1686
Ruby:
RubyCallAction(.S,0&):
BindDelegate
1686
Ruby:
ConvertToSAction:
BindDelegate
1737
Ruby:
ConvertToSAction(.C,0):
Bind
1737
Ruby:
RubyCallAction(S,2&):
Bind
1896
Ruby:
RubyCallAction(.C,0):
Bind
2096
Ruby:
RubyCallAction(S,0=):
Bind
2136
Ruby:
RubyCallAction(S,3):
Bind
2717
Ruby:
RubyCallAction(S,1=):
Bind
2729
Ruby:
RubyCallAction(.S,2):
Bind
4756
Ruby:
RubyCallAction(S,2):
Bind
4865
Ruby:
RubyCallAction(.S,1&):
Bind
4992
Ruby:
RubyCallAction(S,0*):
Bind
5508
Ruby:
RubyCallAction(S,1&):
Bind
5724
Ruby:
RubyCallAction(.S,0):
Bind
7159
Ruby:
RubyCallAction(S,1*):
Bind
7351
Ruby:
RubyCallAction(.S,1):
Bind
10717
Ruby:
RubyCallAction(.C,1):
Bind
11999
Ruby:
RubyCallAction(S,0&):
Bind
12303
Ruby:
RubyCallAction(S,0):
Bind
26073
Ruby:
RubyCallAction(S,1):
Bind
38619
153377
Ruby:
RubyCallAction(S,2&):
BindDelegate
1896
Ruby:
RubyCallAction(.C,0):
BindDelegate
2105
Ruby:
RubyCallAction(S,0=):
BindDelegate
2136
Ruby:
RubyCallAction(S,1=):
BindDelegate
2729
Ruby:
RubyCallAction(S,3):
BindDelegate
2760
Ruby:
RubyCallAction(.S,1&):
BindDelegate
4992
Ruby:
RubyCallAction(S,0*):
BindDelegate
5508
Ruby:
RubyCallAction(S,1&):
BindDelegate
5724
Ruby:
RubyCallAction(S,1*):
BindDelegate
7351
Ruby:
RubyCallAction(S,2):
BindDelegate
7882
Ruby:
RubyCallAction(.S,2):
BindDelegate
8695
Ruby:
RubyCallAction(S,0&):
BindDelegate
12303
Ruby:
RubyCallAction(.C,1):
BindDelegate
14264
Ruby:
RubyCallAction(.S,1):
BindDelegate
19195
Ruby:
RubyCallAction(.S,0):
BindDelegate
26125
Ruby:
RubyCallAction(S,0):
BindDelegate
44212
Ruby:
RubyCallAction(S,1):
BindDelegate
51343
219220
0.3004
Tomas