Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - Redesign native functions and closures API #2499

Closed
wants to merge 4 commits into from

Conversation

jedel1043
Copy link
Member

This PR is a complete redesign of our current native functions and closures API.

I was a bit dissatisfied with our previous design (even though I created it 😆), because it had a lot of superfluous traits, a forced usage of Gc<GcCell<T>> and an overly restrictive NativeObject bound. This redesign, on the other hand, simplifies a lot our public API, with a simple NativeCallable struct that has several constructors for each type of required native function.

This new design doesn't require wrapping every capture type with Gc<GcCell<T>>, relaxes the trait requirement to Trace + 'static for captures, can be reused in both JsObject functions and (soonish) host defined functions, and is (in my opinion) a bit cleaner than the previous iteration. It also offers an unsafe API as an escape hatch for users that want to pass non-Copy closures which don't capture traceable types.

Would ask for bikeshedding about the names though, because I don't know if NativeCallable is the most precise name for this. Same about the constructor names; I added the from prefix to all of them because it's the "standard" practice, but seeing the API doesn't have any other method aside from call, it may be better to just remove the prefix altogether.

Let me know what you think :)

@jedel1043 jedel1043 added execution Issues or PRs related to code execution API run-benchmark Label used to run banchmarks on PRs labels Dec 20, 2022
@jedel1043 jedel1043 added this to the v0.17.0 milestone Dec 20, 2022
@github-actions
Copy link

github-actions bot commented Dec 20, 2022

Test262 conformance changes

Test result main count PR count difference
Total 94,188 94,188 0
Passed 70,214 70,214 0
Ignored 18,605 18,605 0
Failed 5,369 5,369 0
Panics 0 0 0
Conformance 74.55% 74.55% 0.00%

@codecov
Copy link

codecov bot commented Dec 20, 2022

Codecov Report

Merging #2499 (24d7e04) into main (082d362) will increase coverage by 0.14%.
The diff coverage is 31.94%.

@@            Coverage Diff             @@
##             main    #2499      +/-   ##
==========================================
+ Coverage   51.50%   51.64%   +0.14%     
==========================================
  Files         358      356       -2     
  Lines       35755    35766      +11     
==========================================
+ Hits        18414    18473      +59     
+ Misses      17341    17293      -48     
Impacted Files Coverage Δ
boa_engine/src/builtins/async_generator/mod.rs 8.04% <0.00%> (-0.05%) ⬇️
boa_engine/src/builtins/proxy/mod.rs 13.84% <0.00%> (-0.22%) ⬇️
boa_engine/src/class.rs 0.00% <ø> (ø)
boa_engine/src/lib.rs 100.00% <ø> (ø)
boa_engine/src/object/builtins/jsproxy.rs 0.00% <0.00%> (ø)
boa_engine/src/vm/opcode/await_stm/mod.rs 0.00% <0.00%> (ø)
boa_gc/src/internals/gc_box.rs 78.68% <ø> (ø)
boa_gc/src/lib.rs 100.00% <ø> (ø)
boa_gc/src/trace.rs 60.00% <0.00%> (-9.57%) ⬇️
boa_engine/src/builtins/promise/mod.rs 20.76% <11.61%> (+0.07%) ⬆️
... and 37 more

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

@github-actions
Copy link

Benchmark for 7e18e7a

Click to view benchmark
Test Base PR %
Arithmetic operations (Compiler) 583.6±31.92ns 574.5±23.40ns -1.56%
Arithmetic operations (Execution) 558.9±50.01ns 554.7±34.73ns -0.75%
Arithmetic operations (Parser) 7.1±0.38µs 7.2±0.49µs +1.41%
Array access (Compiler) 1649.4±83.92ns 1638.1±105.20ns -0.69%
Array access (Execution) 10.1±0.49µs 10.1±0.41µs 0.00%
Array access (Parser) 14.7±0.63µs 14.6±0.50µs -0.68%
Array creation (Compiler) 2.5±0.11µs 2.4±0.13µs -4.00%
Array creation (Execution) 1324.7±80.95µs 1311.9±61.23µs -0.97%
Array creation (Parser) 17.5±0.80µs 18.6±1.52µs +6.29%
Array pop (Compiler) 4.4±0.19µs 4.2±0.24µs -4.55%
Array pop (Execution) 769.8±22.93µs 794.1±35.02µs +3.16%
Array pop (Parser) 167.2±11.18µs 167.1±9.90µs -0.06%
Boolean Object Access (Compiler) 1272.7±50.13ns 1280.1±98.66ns +0.58%
Boolean Object Access (Execution) 5.9±0.43µs 5.7±0.35µs -3.39%
Boolean Object Access (Parser) 18.3±1.10µs 18.1±0.91µs -1.09%
Clean js (Compiler) 5.8±0.45µs 5.2±0.31µs -10.34%
Clean js (Execution) 792.7±49.52µs 802.4±53.41µs +1.22%
Clean js (Parser) 36.1±1.50µs 37.4±2.57µs +3.60%
Create Realm 297.4±16.30ns 297.5±23.92ns +0.03%
Dynamic Object Property Access (Compiler) 1896.2±96.04ns 1865.1±89.84ns -1.64%
Dynamic Object Property Access (Execution) 5.8±0.35µs 6.0±0.26µs +3.45%
Dynamic Object Property Access (Parser) 13.4±0.81µs 13.5±0.60µs +0.75%
Fibonacci (Compiler) 2.9±0.13µs 2.9±0.15µs 0.00%
Fibonacci (Execution) 1221.4±49.17µs 1309.6±65.32µs +7.22%
Fibonacci (Parser) 20.6±1.94µs 21.5±2.97µs +4.37%
For loop (Compiler) 2.9±0.25µs 2.9±0.15µs 0.00%
For loop (Execution) 17.8±0.70µs 18.7±1.74µs +5.06%
For loop (Parser) 17.8±0.68µs 18.4±1.52µs +3.37%
Mini js (Compiler) 4.6±0.24µs 4.5±0.25µs -2.17%
Mini js (Execution) 696.4±45.21µs 725.0±84.61µs +4.11%
Mini js (Parser) 31.7±1.71µs 31.8±1.72µs +0.32%
Number Object Access (Compiler) 1154.1±81.51ns 1129.1±69.15ns -2.17%
Number Object Access (Execution) 4.5±0.33µs 4.3±0.24µs -4.44%
Number Object Access (Parser) 13.7±0.75µs 13.7±0.47µs 0.00%
Object Creation (Compiler) 1814.2±122.32ns 1696.3±119.44ns -6.50%
Object Creation (Execution) 5.6±0.37µs 5.9±0.46µs +5.36%
Object Creation (Parser) 11.6±0.70µs 12.6±2.02µs +8.62%
RegExp (Compiler) 1953.4±136.24ns 1894.3±160.32ns -3.03%
RegExp (Execution) 15.1±0.78µs 15.4±0.85µs +1.99%
RegExp (Parser) 12.6±1.49µs 12.7±0.72µs +0.79%
RegExp Creation (Compiler) 1710.1±72.78ns 1657.2±69.90ns -3.09%
RegExp Creation (Execution) 10.4±1.03µs 10.7±0.88µs +2.88%
RegExp Creation (Parser) 10.7±0.64µs 11.0±0.69µs +2.80%
RegExp Literal (Compiler) 2.0±0.18µs 1899.3±122.72ns -5.04%
RegExp Literal (Execution) 15.0±0.54µs 15.3±0.80µs +2.00%
RegExp Literal (Parser) 10.3±0.51µs 10.7±0.75µs +3.88%
RegExp Literal Creation (Compiler) 1712.0±81.50ns 1666.1±82.09ns -2.68%
RegExp Literal Creation (Execution) 10.1±0.49µs 10.5±0.52µs +3.96%
RegExp Literal Creation (Parser) 8.2±0.60µs 8.3±0.53µs +1.22%
Static Object Property Access (Compiler) 1757.4±116.97ns 1773.6±136.59ns +0.92%
Static Object Property Access (Execution) 5.8±0.27µs 5.8±0.42µs 0.00%
Static Object Property Access (Parser) 12.5±0.81µs 13.1±1.10µs +4.80%
String Object Access (Compiler) 1522.9±66.05ns 1546.3±79.86ns +1.54%
String Object Access (Execution) 8.0±0.45µs 8.0±0.40µs 0.00%
String Object Access (Parser) 17.6±1.26µs 17.3±0.69µs -1.70%
String comparison (Compiler) 2.5±0.14µs 2.5±0.10µs 0.00%
String comparison (Execution) 5.0±0.22µs 5.2±0.39µs +4.00%
String comparison (Parser) 13.7±0.66µs 14.3±0.88µs +4.38%
String concatenation (Compiler) 1999.2±119.09ns 1949.5±85.33ns -2.49%
String concatenation (Execution) 4.8±0.36µs 4.8±0.28µs 0.00%
String concatenation (Parser) 9.5±0.45µs 9.8±0.73µs +3.16%
String copy (Compiler) 1631.3±86.21ns 1569.5±94.62ns -3.79%
String copy (Execution) 4.5±0.28µs 4.5±0.35µs 0.00%
String copy (Parser) 7.2±0.39µs 7.3±0.52µs +1.39%
Symbols (Compiler) 1220.7±74.85ns 1159.9±53.39ns -4.98%
Symbols (Execution) 4.8±0.16µs 4.8±0.37µs 0.00%
Symbols (Parser) 5.8±0.36µs 6.1±0.57µs +5.17%

@jedel1043
Copy link
Member Author

Will disable the benchmark, since everything looks good.

@jedel1043 jedel1043 removed the run-benchmark Label used to run banchmarks on PRs label Dec 20, 2022
@jedel1043 jedel1043 force-pushed the new-functions branch 2 times, most recently from 609a24f to 1d18d8f Compare December 21, 2022 19:05
Copy link
Member

@nekevss nekevss left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A lot of this looks good to me. NativeCallable makes sense the more I think about it. Maybe, NativeCallableFn to be a bit more specific. I'm not entirely sure about it being in the function module, and after looking at this, I'm also a bit curious about FunctionBuilder too, as we use the term function in a lot of different contexts that it may be ambiguous at times. Maybe function -> native_function/native_fn and FunctionBuilder -> FunctionObjectBuilder.

@jedel1043
Copy link
Member Author

jedel1043 commented Dec 28, 2022

Maybe function -> native_function/native_fn and FunctionBuilder -> FunctionObjectBuilder.

Sounds good! Though, if we're changing function to native_function I'd also change NativeCallable to NativeFunction, since NativeCallableFunction sounds a bit redundant.

Copy link
Member

@nekevss nekevss left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me 😄

Copy link
Member

@raskad raskad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice changes. Great work on the docs too!

@raskad
Copy link
Member

raskad commented Jan 8, 2023

bors r+

bors bot pushed a commit that referenced this pull request Jan 8, 2023
This PR is a complete redesign of our current native functions and closures API.

I was a bit dissatisfied with our previous design (even though I created it 😆), because it had a lot of superfluous traits, a forced usage of `Gc<GcCell<T>>` and an overly restrictive `NativeObject` bound. This redesign, on the other hand, simplifies a lot our public API, with a simple `NativeCallable` struct that has several constructors for each type of required native function.

This new design doesn't require wrapping every capture type with `Gc<GcCell<T>>`, relaxes the trait requirement to `Trace + 'static` for captures, can be reused in both `JsObject` functions and (soonish) host defined functions, and is (in my opinion) a bit cleaner than the previous iteration. It also offers an `unsafe` API as an escape hatch for users that want to pass non-Copy closures which don't capture traceable types.

Would ask for bikeshedding about the names though, because I don't know if `NativeCallable` is the most precise name for this. Same about the constructor names; I added the `from` prefix to all of them because it's the "standard" practice, but seeing the API doesn't have any other method aside from `call`, it may be better to just remove the prefix altogether.

Let me know what you think :)
@bors
Copy link

bors bot commented Jan 8, 2023

Pull request successfully merged into main.

Build succeeded:

@bors bors bot changed the title Redesign native functions and closures API [Merged by Bors] - Redesign native functions and closures API Jan 8, 2023
@bors bors bot closed this Jan 8, 2023
@bors bors bot deleted the new-functions branch January 8, 2023 19:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
API execution Issues or PRs related to code execution
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants