@@ -26,15 +26,8 @@ for example, they may not trigger garbage collection.
26
26
in a snapshot (either the built-in or a user-land one). Please refer to the
27
27
[ binding functions documentation] ( ../../src/README.md#binding-functions ) for more
28
28
information.
29
- * To test fast APIs, make sure to run the tests in a loop with a decent
30
- iterations count to trigger relevant optimizations that prefer the fast API
31
- over the slow one.
32
- * In debug mode (` --debug ` or ` --debug-node ` flags), the fast API calls can be
33
- tracked using the ` TRACK_V8_FAST_API_CALL("key") ` macro. This can be used to
34
- count how many times fast paths are taken during tests. The key is a global
35
- identifier and should be unique across the codebase.
36
- Use ` "binding_name.function_name" ` or ` "binding_name.function_name.suffix" ` to
37
- ensure uniqueness.
29
+ * Fast API functions must be tested following the example in
30
+ [ Test with Fast API path] ( #test-with-fast-api-path ) .
38
31
* The fast callback must be idempotent up to the point where error and fallback
39
32
conditions are checked, because otherwise executing the slow callback might
40
33
produce visible side effects twice.
@@ -175,40 +168,47 @@ A typical function that communicates between JavaScript and C++ is as follows.
175
168
v8::FastApiCallbackOptions& options);
176
169
```
177
170
178
- * In the unit tests:
179
-
180
- Since the fast API function uses ` TRACK_V8_FAST_API_CALL ` , we can ensure that
181
- the fast paths are taken and test them by writing tests that force
182
- V8 optimizations and check the counters.
183
-
184
- ``` js
185
- // Flags: --expose-internals --no-warnings --allow-natives-syntax
186
- ' use strict' ;
187
- const common = require (' ../common' );
188
-
189
- const { internalBinding } = require (' internal/test/binding' );
190
- // We could also require a function that uses the internal binding internally.
191
- const { divide } = internalBinding (' custom_namespace' );
192
-
193
- // The function that will be optimized. It has to be a function written in
194
- // JavaScript. Since `divide` comes from the C++ side, we need to wrap it.
195
- function testFastPath (a , b ) {
196
- return divide (a, b);
197
- }
198
-
199
- eval (' %PrepareFunctionForOptimization(testFastPath)' );
200
- // This call will let V8 know about the argument types that the function expects.
201
- assert .strictEqual (testFastPath (6 , 3 ), 2 );
202
-
203
- eval (' %OptimizeFunctionOnNextCall(testFastPath)' );
204
- assert .strictEqual (testFastPath (8 , 2 ), 4 );
205
- assert .throws (() => testFastPath (1 , 0 ), {
206
- code: ' ERR_INVALID_STATE' ,
207
- });
208
-
209
- if (common .isDebug ) {
210
- const { getV8FastApiCallCount } = internalBinding (' debug' );
211
- assert .strictEqual (getV8FastApiCallCount (' custom_namespace.divide.ok' ), 1 );
212
- assert .strictEqual (getV8FastApiCallCount (' custom_namespace.divide.error' ), 1 );
213
- }
214
- ```
171
+ ### Test with Fast API path
172
+
173
+ In debug mode (` ./configure --debug ` or ` ./configure --debug-node ` flags), the
174
+ fast API calls can be tracked using the ` TRACK_V8_FAST_API_CALL("key") ` macro.
175
+ This can be used to count how many times fast paths are taken during tests. The
176
+ key is a global identifier and should be unique across the codebase.
177
+ Use ` "binding_name.function_name" ` or ` "binding_name.function_name.suffix" ` to
178
+ ensure uniqueness.
179
+
180
+ In the unit tests, since the fast API function uses ` TRACK_V8_FAST_API_CALL ` ,
181
+ we can ensure that the fast paths are taken and test them by writing tests that
182
+ force V8 optimizations and check the counters.
183
+
184
+ ``` js
185
+ // Flags: --expose-internals --no-warnings --allow-natives-syntax
186
+ ' use strict' ;
187
+ const common = require (' ../common' );
188
+
189
+ const { internalBinding } = require (' internal/test/binding' );
190
+ // We could also require a function that uses the internal binding internally.
191
+ const { divide } = internalBinding (' custom_namespace' );
192
+
193
+ // The function that will be optimized. It has to be a function written in
194
+ // JavaScript. Since `divide` comes from the C++ side, we need to wrap it.
195
+ function testFastPath (a , b ) {
196
+ return divide (a, b);
197
+ }
198
+
199
+ eval (' %PrepareFunctionForOptimization(testFastPath)' );
200
+ // This call will let V8 know about the argument types that the function expects.
201
+ assert .strictEqual (testFastPath (6 , 3 ), 2 );
202
+
203
+ eval (' %OptimizeFunctionOnNextCall(testFastPath)' );
204
+ assert .strictEqual (testFastPath (8 , 2 ), 4 );
205
+ assert .throws (() => testFastPath (1 , 0 ), {
206
+ code: ' ERR_INVALID_STATE' ,
207
+ });
208
+
209
+ if (common .isDebug ) {
210
+ const { getV8FastApiCallCount } = internalBinding (' debug' );
211
+ assert .strictEqual (getV8FastApiCallCount (' custom_namespace.divide.ok' ), 1 );
212
+ assert .strictEqual (getV8FastApiCallCount (' custom_namespace.divide.error' ), 1 );
213
+ }
214
+ ```
0 commit comments