Skip to content

Commit 3b0777d

Browse files
committed
Reworked call site, inline cache mechanism.
A CallSite is an abstraction of the point of call & return for another procedure. An InlineCache is an abstraction of a particular instance of an executable at a CallSite. In a 'statically typed' (or early bound) language, the executable at the call site is known 'statically', via textual analysis of the program text. In a 'dynamically-typed' (or late bound) language, the particular executable is not known until the program is executed. Consequently, in a late-bound language, a call site must permit dynamic reconfiguration based on the program's execution. This dynamic reconfiguration requires prediction: when this kind of object is seen, we predict we will see it again. The cost of finding the executable in the first place can then be reduced by caching the previous result of looking up the executable. When we see this kind of object, we can retrieve the executable from the cache at less cost than looking it up. If our predictions are correct, and the mechanism of creating and retrieving items from the cache is actually less than searching for the item, we can execute the program more efficiently. However, predictions can be wrong. If they are wrong, the cache mechanism can become pure overhead, work done that produces no value. In this case, the caching mechanism will make the program *less* efficient rather than more efficient. The number of cached items is typically limited because as the number grows, the cost of retrieving items typically grows. Ideally, the first cached item would always be the desired one. When that is not true, some (hopefully less costly than lookup) search mechanism is required. Contiguous structures that permit linear probing and are CPU cache-efficient usually perform very well. If the number of entries grows, the algorithm needs to change from on O(n) complexity to something closer to O(1), or the extra work of the caching mechanism will be a cost increase instead of a cost reduction. To account for our predictions being wrong, we need to be able to update, replace, or even discard previous predictions. In same cases, we may need to disable the caching mechanism completely. This latter case is true when the types of objects seen at a call site vary widely. This change also adds some new metrics for understanding how a program is performing from the perspective of the call sites and inline caches. The next mechanism to add is diagnostics to see the operation of individual caches instead of the aggregate values that the metrics provide. Another improvement that is needed is to cache `#method_missing`, `#respond_to?` and `#send` call sites.
1 parent 54bed47 commit 3b0777d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+1084
-2023
lines changed

core/call_site.rb

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,35 @@
11
module Rubinius
22
class CallSite
33
attr_reader :name
4-
attr_reader :executable
5-
6-
def hits
7-
0
8-
end
4+
attr_reader :cache
95

106
def ip
117
Rubinius.primitive :call_site_ip
128
raise PrimitiveFailure, "CallSite#ip primitive failed"
139
end
1410

15-
def location
16-
"#{@executable.file}:#{@executable.line_from_ip(ip)}"
11+
def depth
12+
Rubinius.primitive :call_site_depth
13+
raise PrimitiveFailure, "CallSite#depth primitive failed"
14+
end
15+
16+
def invokes
17+
Rubinius.primitive :call_site_invokes
18+
raise PrimitiveFailure, "CallSite#invokes primitive failed"
19+
end
20+
21+
def hits
22+
Rubinius.primitive :call_site_hits
23+
raise PrimitiveFailure, "CallSite#hits primitive failed"
24+
end
25+
26+
def misses
27+
Rubinius.primitive :call_site_misses
28+
raise PrimitiveFailure, "CallSite#misses primitive failed"
1729
end
1830

1931
def inspect
20-
"#<#{self.class.name}:0x#{self.object_id.to_s(16)} #{location}##{@name}(#{hits})>"
32+
"#<#{self.class.name}:0x#{self.object_id.to_s(16)} name=#{@name} ip=#{ip} depth=#{depth} invokes=#{invokes} hits=#{hits} misses=#{misses}>"
2133
end
2234
end
2335
end

core/load_order.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ metrics.rb
7777
mirror.rb
7878
missing_method.rb
7979
module.rb
80-
mono_inline_cache.rb
8180
mutex.rb
8281
native_method.rb
8382
nil.rb
@@ -88,7 +87,6 @@ options.rb
8887
pack.rb
8988
pointer.rb
9089
pointer_accessors.rb
91-
poly_inline_cache.rb
9290
proc.rb
9391
proc_mirror.rb
9492
process.rb

core/mono_inline_cache.rb

Lines changed: 0 additions & 25 deletions
This file was deleted.

core/poly_inline_cache.rb

Lines changed: 0 additions & 52 deletions
This file was deleted.

library/rubinius/configuration.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,16 @@
168168
c.vm_variable "profiler.threshold", 1000000,
169169
"The minimum number of nanoseconds a profiler node must have to be reported"
170170

171+
c.section "machine" do |s|
172+
s.section "call_site" do |cs|
173+
cs.vm_variable "cache", true,
174+
"Cache executables at call sites"
175+
176+
cs.vm_variable "limit", 3,
177+
"Maximum number of caches at call sites"
178+
end
179+
end
180+
171181
c.section "system" do |s|
172182
s.vm_variable "tmp", "$TMPDIR",
173183
"Default temp/fallback directory for the process"

0 commit comments

Comments
 (0)