Skip to content

Trivial functions optimizations#4918

Open
hansl wants to merge 10 commits intoboa-dev:mainfrom
hansl:pure-function
Open

Trivial functions optimizations#4918
hansl wants to merge 10 commits intoboa-dev:mainfrom
hansl:pure-function

Conversation

@hansl
Copy link
Contributor

@hansl hansl commented Mar 7, 2026

3 optimizations:


Inline immediately invoked function expressions (IIFEs) at compile time,
eliminating function object allocation, call frame creation, and
environment setup overhead. Supports arrow functions and function
expressions with simple parameters, handling expression bodies,
void/side-effect bodies (no return), and bodies with a trailing return.


Skip frame creation for empty functions (e.g., function f() {}) by
detecting them at compile time and using CallValue::Complete at runtime,
similar to native function calls.


Skip frame creation for empty constructors (e.g., function Foo() {})
that have no fields or private methods and are not derived. Creates the
object and returns it directly via CallValue::Complete, avoiding the
full frame push/pop cycle.


This brings the call.js benchmark to within 1.9x of QuickJS:

Benchmark 1: ./target/release/boa /Users/hansl/call.js
  Time (mean ± σ):     578.9 ms ±   1.8 ms    [User: 570.3 ms, System: 4.7 ms]
  Range (min … max):   577.2 ms … 583.3 ms    10 runs

Benchmark 2: qjs /Users/hansl/call.js
  Time (mean ± σ):     307.6 ms ±   0.3 ms    [User: 304.1 ms, System: 2.2 ms]
  Range (min … max):   307.1 ms … 308.1 ms    10 runs

Summary
  qjs /Users/hansl/call.js ran
    1.88 ± 0.01 times faster than ./target/release/boa /Users/hansl/call.js

hansl and others added 3 commits March 6, 2026 15:12
Inline immediately invoked function expressions (IIFEs) at compile time,
eliminating function object allocation, call frame creation, and
environment setup overhead. Supports arrow functions and function
expressions with simple parameters, handling expression bodies,
void/side-effect bodies (no return), and bodies with a trailing return.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Skip frame creation for empty functions (e.g., `function f() {}`) by
detecting them at compile time and using CallValue::Complete at runtime,
similar to native function calls.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Skip frame creation for empty constructors (e.g., `function Foo() {}`)
that have no fields or private methods and are not derived. Creates the
object and returns it directly via CallValue::Complete, avoiding the
full frame push/pop cycle.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@hansl hansl requested a review from a team as a code owner March 7, 2026 05:18
@github-actions
Copy link

github-actions bot commented Mar 7, 2026

Test262 conformance changes

Test result main count PR count difference
Total 52,963 52,963 0
Passed 49,687 49,687 0
Ignored 2,262 2,262 0
Failed 1,014 1,014 0
Panics 0 0 0
Conformance 93.81% 93.81% 0.00%

Tested main commit: 34ca7f1f404c2712d6897c3e39e5f5e981ce9ed6
Tested PR commit: 823dbde37ef5d718f9ea8ab626c936b803af6979
Compare commits: 34ca7f1...823dbde

@hansl hansl marked this pull request as draft March 7, 2026 05:34
@codecov
Copy link

codecov bot commented Mar 7, 2026

Codecov Report

❌ Patch coverage is 78.70370% with 46 lines in your changes missing coverage. Please review.
✅ Project coverage is 58.05%. Comparing base (6ddc2b4) to head (823dbde).
⚠️ Report is 779 commits behind head on main.

Files with missing lines Patch % Lines
core/engine/src/bytecompiler/inline.rs 72.61% 46 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##             main    #4918       +/-   ##
===========================================
+ Coverage   47.24%   58.05%   +10.80%     
===========================================
  Files         476      558       +82     
  Lines       46892    61174    +14282     
===========================================
+ Hits        22154    35514    +13360     
- Misses      24738    25660      +922     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

hansl and others added 5 commits March 6, 2026 22:21
…ions

Functions with var-scoped declarations (hoisted functions, var
statements) or Annex B block-scoped function declarations require
function_declaration_instantiation setup that IIFE inlining skips.
Add checks for both to prevent incorrect inlining.

Fixes 417 test262 regressions in annexB/language/function-code/.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
The `arguments` object is created by function_declaration_instantiation
which IIFE inlining skips. Functions that access `arguments` must not
be inlined.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Function expressions have their own `this` binding which differs from
the caller's. Reject inlining when the body references `this`, when
the function's strictness differs from the caller, and when call
arguments contain spread syntax (which the inliner cannot handle).

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@hansl hansl marked this pull request as ready for review March 8, 2026 04:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant