A call site is a specific location in source code where a method or function is invoked. In virtual machines like YARV, each call site is tracked and associated with metadata about how the method should be called.
What is a Call Site?
def greet(name)
puts "Hello, #{name}"
end
greet("Alice") # ← This is a call site
greet("Bob") # ← This is another call site
Each call site represents:
- The location where a method is invoked
- The context of the invocation (caller and callee)
- Arguments being passed
- Expected return value handling
Call Site in Virtual Machines
In YARV and similar VMs, call sites are optimized through several mechanisms:
Call Data Structure: Call sites store information that persists across invocations:
- Method name being called
- Number and types of arguments
- Receiver type information (for optimization)
- Cached method lookup results
# YARV creates call data for this site:
object.method_name(arg1, arg2)
# Call data includes:
# - method_name: :method_name
# - argc: 2
# - flags: (keyword args, blocks, etc.)
Inline Caching
Call sites are prime candidates for inline caching optimization. The VM can cache method lookups at each call site:
# First call at this site
user.name # VM: lookup 'name' method, cache result
# Subsequent calls at same site
user.name # VM: use cached lookup (if user is same class)
Call Site vs Call Stack
Important distinction:
- Call site: The static location in code where a call happens
- call stack: The runtime stack of active method calls
def a
b() # Call site for 'b'
end
def b
c() # Call site for 'c'
end
def c
# When executing here, call stack is: [a, b, c]
# But we have three different call sites total
end
Caller and Callee Relationship
Every call site establishes a relationship:
def caller_method
callee_method() # Call site establishes caller/callee relationship
end
def callee_method
# ...
end
Dynamic vs Static Call Sites
Static call sites (compile-time known):
object.known_method # Method name determined at compile time
Dynamic call sites (runtime determined):
object.send(method_name) # Method name only known at runtime
Dynamic call sites are harder to optimize because the VM can’t predict which method will be called. This is why send
is typically slower than direct method calls in YARV.
Call Site Profiling
Modern VMs profile call sites to guide optimization:
# Hot call site (called many times)
1000000.times { object.method } # VM may JIT compile this
# Cold call site (rarely called)
if rare_condition
object.other_method # Stays interpreted
end
JIT compilers use call site frequency to decide what to optimize. See JIT compilation threshold for Ruby’s approach.
In YARV Bytecode
YARV represents call sites with instructions that include call data:
# Ruby code:
obj.foo(42)
# YARV bytecode (simplified):
getlocal obj # Push receiver
putobject 42 # Push argument
opt_send_without_block <call_data> # Call with site metadata
The <call_data>
includes all the call site information needed for method dispatch and optimization.