Skip to content

Commit

Permalink
update fast api docs
Browse files Browse the repository at this point in the history
  • Loading branch information
targos committed Aug 11, 2024
1 parent 1cfced7 commit 9a9d4e7
Showing 1 changed file with 42 additions and 0 deletions.
42 changes: 42 additions & 0 deletions doc/contributing/adding-v8-fast-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ A typical function that communicates between JavaScript and C++ is as follows.
* On the C++ side:

```cpp
#include "node_debug.h"
#include "v8-fast-api-calls.h"

namespace node {
Expand All @@ -102,9 +103,11 @@ A typical function that communicates between JavaScript and C++ is as follows.
const int32_t b,
v8::FastApiCallbackOptions& options) {
if (b == 0) {
TRACK_V8_FAST_API_CALL("custom_namespace.divide.error");
options.fallback = true;
return 0;
} else {
TRACK_V8_FAST_API_CALL("custom_namespace.divide.ok");
return a / b;
}
}
Expand Down Expand Up @@ -148,3 +151,42 @@ A typical function that communicates between JavaScript and C++ is as follows.
const int32_t b,
v8::FastApiCallbackOptions& options);
```

* In the unit tests:

Since the fast API function uses `TRACK_V8_FAST_API_CALL`, we can ensure that
the fast paths are taken and test them by writing tests that force
V8 optimizations and check the counters.

```js
// Flags: --expose-internals --no-warnings --allow-natives-syntax
'use strict';
const common = require('../common');

const { internalBinding } = require('internal/test/binding');
// We could also require a function that uses the internal binding internally.
const { divide } = internalBinding('custom_namespace');

if (common.isDebug) {
const { getV8FastApiCallCount } = internalBinding('debug');

// The function that will be optimized. It has to be a function written in
// JavaScript. Since `divide` comes from the C++ side, we need to wrap it.
function testFastPath(a, b) {
return divide(a, b);
}

eval('%PrepareFunctionForOptimization(testFastPath)');
// This call will let V8 know about the argument types that the function expects.
assert.strictEqual(testFastPath(6, 3), 2);

eval('%OptimizeFunctionOnNextCall(testFastPath)');
assert.strictEqual(testFastPath(8, 2), 4);
assert.throws(() => testFastPath(1, 0), {
code: 'ERR_INVALID_STATE',
});

assert.strictEqual(getV8FastApiCallCount('custom_namespace.divide.ok'), 1);
assert.strictEqual(getV8FastApiCallCount('custom_namespace.divide.error'), 1);
}
```

0 comments on commit 9a9d4e7

Please sign in to comment.