artichoke
artichoke copied to clipboard
Eagerly evaluate const functions at parse time
Ruby has literals. Simple, like Integer
, Float
, String
, Range
and aggregate like Hash
, Array
.
Simple literals like:
def foo
"abc"
end
can be evaluated at parse time and stored as shared data in the interpreter.
Some functions on literals can also be computed at parse time. Such functions are called const
and pre-computing values is called const evaluation.
a = 'a' * 1024
b = [nil] * 100
c = { foo: ["bar".delete_prefix('b')] }
d = 1 + 2 * 3
The preceding are all const
if String#*
, Array#*
, String#delete_prefix
, Integer#+
and Integer#*
are not redefined. I consider this unlikely, so it is worthwhile to precompute these literals at parse time. Then as this code is executed in the bytecode loop, validate that the "const functions" have not been tainted since ??? (interpreter init most likely) and either return a Cow
to the eagerly parsed literal or shell out to a funcall via the VM.
A further optimization that may fall out of this work is to inline functions that return const literals.
We'd probably require custom opcodes on top of MRI to accomplish this.
@jamatthews does this seem feasible?
Supporting something like this will also influence the heap design. Rather than pass around RBasic
s I was considering passing around usize
object ID, resolving objects through the heap via the ID, and doing GC coloring of object IDs.
It'd be useful to mark object ids as Cow
s of some other interpreter lifetime (template) object id.
Oh cool! I'm working on constant evaluation at the moment. There's a lot to consider here. Have you read through https://github.com/ruby/ruby/pull/1419 ?
Thanks for the link to that PR 🙏