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] - Refactor mapped Arguments object #1849

Closed
wants to merge 2 commits into from

Conversation

raskad
Copy link
Member

@raskad raskad commented Feb 20, 2022

This refactors the representation of the [[ParameterMap]] internal slot on the Arguments exotic object to be faster at runtime.

Previously [[ParameterMap]] was a JsObject like the spec describes. This can be pretty slow a runtime, because the argument getters and setters must be represented as function objects on the [[ParameterMap]] object. In addition to the time spend on creation and calling of those functions, every getter/setter needs a cloned gc reference to the function environment to access the bindings. This adds to the gc overhead.

The spec states that the [[ParameterMap]] internal slot doesn't have to be a JsObject. See NOTE 3 here: https://tc39.es/ecma262/#sec-arguments-exotic-objects
Leveraging this freedom, we can use a more optimized representation, that avoids any JsObject usage and only needs one clone of the function environment.

@raskad raskad added performance Performance related changes and issues execution Issues or PRs related to code execution Internal Category for changelog labels Feb 20, 2022
@raskad raskad added this to the v0.14.0 milestone Feb 20, 2022
@github-actions
Copy link

Test262 conformance changes

VM implementation

Test result main count PR count difference
Total 87,912 87,912 0
Passed 41,366 41,366 0
Ignored 21,153 21,153 0
Failed 25,393 25,393 0
Panics 0 0 0
Conformance 47.05% 47.05% 0.00%

@codecov
Copy link

codecov bot commented Feb 20, 2022

Codecov Report

Merging #1849 (28d10b7) into main (29cd909) will decrease coverage by 0.02%.
The diff coverage is 30.88%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1849      +/-   ##
==========================================
- Coverage   55.57%   55.55%   -0.03%     
==========================================
  Files         199      199              
  Lines       17756    17768      +12     
==========================================
+ Hits         9868     9871       +3     
- Misses       7888     7897       +9     
Impacted Files Coverage Δ
boa/src/object/mod.rs 29.19% <0.00%> (+0.09%) ⬆️
boa/src/object/internal_methods/arguments.rs 27.11% <19.51%> (-0.47%) ⬇️
boa/src/builtins/function/arguments.rs 88.67% <68.42%> (-3.92%) ⬇️
boa/src/string.rs 84.39% <0.00%> (-0.28%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 29cd909...28d10b7. Read the comment docs.

@github-actions
Copy link

Benchmark for 507f73e

Click to view benchmark
Test Base PR %
Arithmetic operations (Compiler) 467.0±1.28ns 462.4±1.04ns -0.99%
Arithmetic operations (Execution) 1944.4±2.25ns 2.0±0.00µs +2.86%
Arithmetic operations (Parser) 5.5±0.01µs 5.5±0.01µs 0.00%
Array access (Compiler) 1181.7±1.79ns 1162.8±6.00ns -1.60%
Array access (Execution) 10.6±0.03µs 10.3±0.06µs -2.83%
Array access (Parser) 11.9±0.02µs 12.0±0.01µs +0.84%
Array creation (Compiler) 1767.1±15.30ns 1702.4±6.34ns -3.66%
Array creation (Execution) 3.1±0.01ms 3.2±0.01ms +3.23%
Array creation (Parser) 13.3±0.02µs 13.4±0.03µs +0.75%
Array pop (Compiler) 3.5±0.01µs 3.4±0.04µs -2.86%
Array pop (Execution) 1361.1±3.30µs 1346.5±4.34µs -1.07%
Array pop (Parser) 136.9±0.07µs 137.4±0.24µs +0.37%
Boolean Object Access (Compiler) 1029.0±3.05ns 1014.6±2.84ns -1.40%
Boolean Object Access (Execution) 5.5±0.02µs 5.6±0.04µs +1.82%
Boolean Object Access (Parser) 14.0±0.03µs 14.1±0.08µs +0.71%
Clean js (Compiler) 3.3±0.01µs 3.2±0.02µs -3.03%
Clean js (Execution) 1089.0±11.11µs 1094.8±7.86µs +0.53%
Clean js (Parser) 28.7±0.04µs 28.6±0.07µs -0.35%
Create Realm 266.5±0.27ns 286.9±0.38ns +7.65%
Dynamic Object Property Access (Compiler) 1550.7±4.22ns 1525.8±10.20ns -1.61%
Dynamic Object Property Access (Execution) 7.0±0.02µs 6.7±0.03µs -4.29%
Dynamic Object Property Access (Parser) 10.6±0.02µs 10.6±0.01µs 0.00%
Fibonacci (Compiler) 2.2±0.01µs 2.1±0.01µs -4.55%
Fibonacci (Execution) 2.7±0.00ms 1758.4±2.14µs -34.87%
Fibonacci (Parser) 15.9±0.03µs 15.9±0.03µs 0.00%
For loop (Compiler) 1847.5±4.28ns 1838.0±10.17ns -0.51%
For loop (Execution) 41.5±0.15µs 42.9±0.15µs +3.37%
For loop (Parser) 13.8±0.03µs 13.9±0.07µs +0.72%
Mini js (Compiler) 3.2±0.01µs 3.1±0.01µs -3.13%
Mini js (Execution) 1004.4±6.22µs 1007.2±6.42µs +0.28%
Mini js (Parser) 25.1±0.02µs 25.0±0.07µs -0.40%
Number Object Access (Compiler) 984.4±1.06ns 968.7±1.71ns -1.59%
Number Object Access (Execution) 4.3±0.01µs 4.4±0.01µs +2.33%
Number Object Access (Parser) 11.0±0.01µs 11.2±0.13µs +1.82%
Object Creation (Compiler) 1289.0±6.74ns 1298.9±7.97ns +0.77%
Object Creation (Execution) 6.3±0.03µs 6.0±0.02µs -4.76%
Object Creation (Parser) 9.1±0.01µs 9.3±0.09µs +2.20%
RegExp (Compiler) 1523.6±3.93ns 1491.8±2.83ns -2.09%
RegExp (Execution) 12.8±0.02µs 12.4±0.06µs -3.13%
RegExp (Parser) 10.1±0.06µs 10.0±0.03µs -0.99%
RegExp Creation (Compiler) 1304.2±17.63ns 1294.8±2.45ns -0.72%
RegExp Creation (Execution) 9.7±0.04µs 9.5±0.09µs -2.06%
RegExp Creation (Parser) 8.4±0.02µs 8.4±0.09µs 0.00%
RegExp Literal (Compiler) 1528.5±10.59ns 1513.2±3.07ns -1.00%
RegExp Literal (Execution) 12.9±0.03µs 12.4±0.06µs -3.88%
RegExp Literal (Parser) 8.0±0.01µs 8.1±0.01µs +1.25%
RegExp Literal Creation (Compiler) 1347.8±12.88ns 1296.9±2.79ns -3.78%
RegExp Literal Creation (Execution) 9.7±0.06µs 9.4±0.04µs -3.09%
RegExp Literal Creation (Parser) 6.4±0.06µs 6.4±0.02µs 0.00%
Static Object Property Access (Compiler) 1334.8±4.00ns 1335.7±9.68ns +0.07%
Static Object Property Access (Execution) 6.6±0.03µs 6.3±0.02µs -4.55%
Static Object Property Access (Parser) 9.8±0.01µs 9.9±0.01µs +1.02%
String Object Access (Compiler) 1366.4±3.50ns 1346.3±4.17ns -1.47%
String Object Access (Execution) 7.2±0.02µs 7.4±0.02µs +2.78%
String Object Access (Parser) 13.7±0.02µs 13.9±0.04µs +1.46%
String comparison (Compiler) 2.0±0.01µs 1984.0±6.19ns -0.80%
String comparison (Execution) 6.2±0.02µs 5.9±0.01µs -4.84%
String comparison (Parser) 10.9±0.03µs 11.0±0.02µs +0.92%
String concatenation (Compiler) 1571.4±10.37ns 1556.3±2.81ns -0.96%
String concatenation (Execution) 5.6±0.02µs 5.3±0.02µs -5.36%
String concatenation (Parser) 7.5±0.02µs 7.5±0.02µs 0.00%
String copy (Compiler) 1230.3±11.96ns 1221.3±2.17ns -0.73%
String copy (Execution) 5.1±0.01µs 4.7±0.01µs -7.84%
String copy (Parser) 5.7±0.02µs 5.7±0.02µs 0.00%
Symbols (Compiler) 839.9±2.11ns 821.9±5.57ns -2.14%
Symbols (Execution) 4.8±0.03µs 4.5±0.01µs -6.25%
Symbols (Parser) 4.2±0.01µs 4.4±0.01µs +4.76%

Copy link
Member

@Razican Razican left a comment

Choose a reason for hiding this comment

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

Looks good to me :) I think it could use some better documentation in some functions, though.

}

impl ParameterMap {
pub(crate) fn delete(&mut self, index: usize) {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
pub(crate) fn delete(&mut self, index: usize) {
/// Deletes the binding with the given index from the parameter map.
pub(crate) fn delete(&mut self, index: usize) {

Comment on lines 30 to 31
// 10.4.4.7.1 MakeArgGetter ( name, env )
// https://tc39.es/ecma262/#sec-makearggetter
Copy link
Member

Choose a reason for hiding this comment

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

Could we use documentation comments here?

Comment on lines 39 to 40
// 10.4.4.7.2 MakeArgSetter ( name, env )
// https://tc39.es/ecma262/#sec-makeargsetter
Copy link
Member

Choose a reason for hiding this comment

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

Here also, we should use documentation comments, and add a bit of explanation.

@github-actions
Copy link

Benchmark for 7ee330e

Click to view benchmark
Test Base PR %
Arithmetic operations (Compiler) 509.9±17.72ns 502.8±15.54ns -1.39%
Arithmetic operations (Execution) 2.3±0.07µs 2.2±0.10µs -4.35%
Arithmetic operations (Parser) 5.5±0.20µs 5.8±0.18µs +5.45%
Array access (Compiler) 1299.8±41.86ns 1332.7±57.40ns +2.53%
Array access (Execution) 11.9±0.83µs 11.4±0.39µs -4.20%
Array access (Parser) 12.0±0.35µs 12.5±0.51µs +4.17%
Array creation (Compiler) 1838.9±53.67ns 1961.1±144.02ns +6.65%
Array creation (Execution) 3.5±0.10ms 3.5±0.10ms 0.00%
Array creation (Parser) 13.4±0.40µs 13.4±0.41µs 0.00%
Array pop (Compiler) 3.7±0.12µs 3.8±0.14µs +2.70%
Array pop (Execution) 1496.8±40.77µs 1512.5±45.44µs +1.05%
Array pop (Parser) 146.7±4.81µs 145.3±5.61µs -0.95%
Boolean Object Access (Compiler) 1001.5±33.08ns 984.2±36.22ns -1.73%
Boolean Object Access (Execution) 6.5±0.18µs 6.2±0.19µs -4.62%
Boolean Object Access (Parser) 14.2±0.49µs 14.7±0.53µs +3.52%
Clean js (Compiler) 3.5±0.09µs 3.5±0.13µs 0.00%
Clean js (Execution) 1254.5±46.01µs 1204.2±60.75µs -4.01%
Clean js (Parser) 28.5±1.06µs 28.8±1.03µs +1.05%
Create Realm 305.9±10.96ns 302.9±11.08ns -0.98%
Dynamic Object Property Access (Compiler) 1694.0±49.84ns 1725.3±57.92ns +1.85%
Dynamic Object Property Access (Execution) 7.7±0.24µs 7.4±0.23µs -3.90%
Dynamic Object Property Access (Parser) 10.6±0.41µs 10.9±0.28µs +2.83%
Fibonacci (Compiler) 2.4±0.07µs 2.4±0.06µs 0.00%
Fibonacci (Execution) 3.0±0.09ms 1988.9±58.54µs -33.70%
Fibonacci (Parser) 16.5±0.50µs 17.0±0.88µs +3.03%
For loop (Compiler) 2.0±0.12µs 2.0±0.06µs 0.00%
For loop (Execution) 48.1±1.48µs 47.5±1.50µs -1.25%
For loop (Parser) 14.3±0.42µs 14.3±0.97µs 0.00%
Mini js (Compiler) 3.4±0.12µs 3.4±0.12µs 0.00%
Mini js (Execution) 1176.8±24.30µs 1143.2±30.47µs -2.86%
Mini js (Parser) 25.1±0.75µs 25.3±0.89µs +0.80%
Number Object Access (Compiler) 952.0±38.03ns 964.4±32.66ns +1.30%
Number Object Access (Execution) 4.9±0.17µs 4.8±0.17µs -2.04%
Number Object Access (Parser) 11.2±0.42µs 11.3±0.47µs +0.89%
Object Creation (Compiler) 1414.2±48.80ns 1500.8±45.37ns +6.12%
Object Creation (Execution) 6.8±0.24µs 6.7±0.19µs -1.47%
Object Creation (Parser) 9.1±0.28µs 9.3±0.46µs +2.20%
RegExp (Compiler) 1645.5±62.68ns 1681.1±64.83ns +2.16%
RegExp (Execution) 13.6±0.56µs 13.5±0.50µs -0.74%
RegExp (Parser) 10.3±0.32µs 10.4±0.18µs +0.97%
RegExp Creation (Compiler) 1464.1±52.22ns 1421.3±42.78ns -2.92%
RegExp Creation (Execution) 10.2±0.37µs 9.9±0.31µs -2.94%
RegExp Creation (Parser) 8.5±0.31µs 8.5±0.19µs 0.00%
RegExp Literal (Compiler) 1736.7±66.71ns 1731.1±114.13ns -0.32%
RegExp Literal (Execution) 13.4±0.41µs 13.4±0.53µs 0.00%
RegExp Literal (Parser) 7.9±0.25µs 8.5±0.22µs +7.59%
RegExp Literal Creation (Compiler) 1467.4±48.74ns 1440.1±53.17ns -1.86%
RegExp Literal Creation (Execution) 10.0±0.32µs 10.0±0.32µs 0.00%
RegExp Literal Creation (Parser) 6.3±0.22µs 6.6±0.22µs +4.76%
Static Object Property Access (Compiler) 1439.3±55.43ns 1449.9±58.33ns +0.74%
Static Object Property Access (Execution) 7.2±0.21µs 7.2±0.24µs 0.00%
Static Object Property Access (Parser) 9.8±0.35µs 9.9±0.26µs +1.02%
String Object Access (Compiler) 1379.8±44.99ns 1396.0±44.45ns +1.17%
String Object Access (Execution) 8.2±0.32µs 8.2±0.28µs 0.00%
String Object Access (Parser) 14.2±0.44µs 14.4±0.44µs +1.41%
String comparison (Compiler) 2.2±0.06µs 2.3±0.07µs +4.55%
String comparison (Execution) 6.8±0.26µs 6.5±0.18µs -4.41%
String comparison (Parser) 11.0±0.34µs 11.3±0.39µs +2.73%
String concatenation (Compiler) 1673.9±65.58ns 1714.6±66.02ns +2.43%
String concatenation (Execution) 6.2±0.20µs 5.9±0.20µs -4.84%
String concatenation (Parser) 7.5±0.21µs 7.7±0.26µs +2.67%
String copy (Compiler) 1318.6±39.54ns 1351.3±47.89ns +2.48%
String copy (Execution) 5.5±0.18µs 5.3±0.19µs -3.64%
String copy (Parser) 5.5±0.18µs 5.6±0.18µs +1.82%
Symbols (Compiler) 902.2±27.79ns 916.6±26.81ns +1.60%
Symbols (Execution) 5.3±0.14µs 4.9±0.17µs -7.55%
Symbols (Parser) 4.2±0.17µs 4.2±0.14µs 0.00%

Copy link
Member

@jedel1043 jedel1043 left a comment

Choose a reason for hiding this comment

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

Benchmarks look good! Especially the Fibonacci benchmark with a 30+% reduction in runtime. That's probably because the engine doesn't need to slowly create the mapped arguments object on each recursive call, right?

Copy link
Member

@HalidOdat HalidOdat left a comment

Choose a reason for hiding this comment

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

Looks good to me :)

@Razican
Copy link
Member

Razican commented Feb 21, 2022

bors r+

bors bot pushed a commit that referenced this pull request Feb 21, 2022
This refactors the representation of the `[[ParameterMap]]` internal slot on the `Arguments` exotic object to be faster at runtime.

Previously `[[ParameterMap]]` was a `JsObject` like the spec describes. This can be pretty slow a runtime, because the argument getters and setters must be represented as function objects on the `[[ParameterMap]]` object. In addition to the time spend on creation and calling of those functions, every getter/setter needs a cloned gc reference to the function environment to access the bindings. This adds to the gc overhead.

The spec states that the `[[ParameterMap]]` internal slot doesn't have to be a `JsObject`. See NOTE 3 here: https://tc39.es/ecma262/#sec-arguments-exotic-objects
Leveraging this freedom, we can use a more optimized representation, that avoids any `JsObject` usage and only needs one clone of the function environment.
@bors
Copy link

bors bot commented Feb 21, 2022

Pull request successfully merged into main.

Build succeeded:

@bors bors bot changed the title Refactor mapped Arguments object [Merged by Bors] - Refactor mapped Arguments object Feb 21, 2022
@bors bors bot closed this Feb 21, 2022
@bors bors bot deleted the mapped-arguments-refactor branch February 21, 2022 12:04
Razican pushed a commit that referenced this pull request Feb 21, 2022
This refactors the representation of the `[[ParameterMap]]` internal slot on the `Arguments` exotic object to be faster at runtime.

Previously `[[ParameterMap]]` was a `JsObject` like the spec describes. This can be pretty slow a runtime, because the argument getters and setters must be represented as function objects on the `[[ParameterMap]]` object. In addition to the time spend on creation and calling of those functions, every getter/setter needs a cloned gc reference to the function environment to access the bindings. This adds to the gc overhead.

The spec states that the `[[ParameterMap]]` internal slot doesn't have to be a `JsObject`. See NOTE 3 here: https://tc39.es/ecma262/#sec-arguments-exotic-objects
Leveraging this freedom, we can use a more optimized representation, that avoids any `JsObject` usage and only needs one clone of the function environment.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
execution Issues or PRs related to code execution Internal Category for changelog performance Performance related changes and issues
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants