Context: on script-heavy pages, property access, calls and GC dominate well
before any JIT question, which matches the conclusion in #4487 that bytecode
dispatch is not the main cost. I'd like to contribute performance work in
mergeable increments, and I'd rather align with you before writing code.
Reading 0.22, the property-access side is further along than I expected:
vm/inline_cache already has 4-way polymorphic ICs keyed on Shape, wired
into GetPropertyByName / SetPropertyByName. What I did not find is any
form of lazy function compilation: bytecompiler::function() compiles
every nested function through FunctionCompiler::compile while compiling
its parent, so a multi-megabyte bundle is fully parsed and compiled to
bytecode before the first instruction runs. On page bundles most functions
are never called during load, so this is startup time, not execution time.
Four questions:
- Lazy compilation. Since the source text of each function is already
kept (SpannedSourceText) and parse_function_body exists for
new Function, one design is: at compile time, store the source span plus
the parent scopes instead of a CodeBlock; on first call, parse that span
and compile it. The hard part is scope_analyzer, which would need to
accept an existing parent scope chain instead of a fresh global scope.
Would you consider this, and is that analyzer change acceptable — or do
you see a better way?
- Inline caches. Is there a plan or branch for computed-key access and
method-call sites, or is the current coverage what you intend for 1.0?
- Call path. Is there appetite for a fast path for the common case (no
rest/spread, no arguments, known arity), or is that gated on the IR work
described in Boa and JIT #4487?
- GC. Is a generational or nursery collector on the table before 1.0, or
is the current mark-sweep considered good enough until then?
I'll post parse+compile timings of a real bundle measured with boa_cli
here, and bring a first PR sized for review on whichever item you'd look at
first.
Context: on script-heavy pages, property access, calls and GC dominate well
before any JIT question, which matches the conclusion in #4487 that bytecode
dispatch is not the main cost. I'd like to contribute performance work in
mergeable increments, and I'd rather align with you before writing code.
Reading 0.22, the property-access side is further along than I expected:
vm/inline_cachealready has 4-way polymorphic ICs keyed onShape, wiredinto
GetPropertyByName/SetPropertyByName. What I did not find is anyform of lazy function compilation:
bytecompiler::function()compilesevery nested function through
FunctionCompiler::compilewhile compilingits parent, so a multi-megabyte bundle is fully parsed and compiled to
bytecode before the first instruction runs. On page bundles most functions
are never called during load, so this is startup time, not execution time.
Four questions:
kept (
SpannedSourceText) andparse_function_bodyexists fornew Function, one design is: at compile time, store the source span plusthe parent scopes instead of a
CodeBlock; on first call, parse that spanand compile it. The hard part is
scope_analyzer, which would need toaccept an existing parent scope chain instead of a fresh global scope.
Would you consider this, and is that analyzer change acceptable — or do
you see a better way?
method-call sites, or is the current coverage what you intend for 1.0?
rest/spread, no
arguments, known arity), or is that gated on the IR workdescribed in Boa and JIT #4487?
is the current mark-sweep considered good enough until then?
I'll post parse+compile timings of a real bundle measured with
boa_clihere, and bring a first PR sized for review on whichever item you'd look at
first.