Skip to content

Commit a2251da

Browse files
committed
doc: add v8 fast api contribution guidelines
1 parent f5dc92c commit a2251da

File tree

1 file changed

+120
-0
lines changed

1 file changed

+120
-0
lines changed
+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
# Adding V8 Fast API
2+
3+
Node.js uses [V8](https://github.com/v8/v8) as the JavaScript engine.
4+
In order to provide fast paths for functions that are called quite often,
5+
V8 proposes the usage of `fast api calls` that does not use any of the V8
6+
internals, but uses internal C functions.
7+
8+
## Limitations
9+
10+
- Fast api calls can not use `V8` internals inside the fast path.
11+
- Not all parameter and return types are supported in fast api calls.
12+
For a full list, please look into [`v8-fast-api-calls.h`](/deps/v8/include/v8-fast-api-calls.h) file.
13+
14+
## Requirements
15+
- Each unique fast path function signature should be defined inside
16+
[`node_external_reference.h`](/src/node_external_reference.h) file.
17+
- In order to test fast paths, make sure to run the tests in a loop
18+
with more than 1000 iterations to force V8 to optimize and prefer the
19+
fast api over slow path.
20+
21+
## Fallback to slow path
22+
23+
Fast apis support fallback to slow path (implementation that uses V8 internals)
24+
in case logically it is wise to do so, for example when providing a more detailed error.
25+
Fallback mechanism can be enabled, and changed from both caller JavaScript function
26+
or from the fast api function declaration.
27+
28+
Every fast api function accessible from JavaScript side, can pass an object
29+
consisting of fallback key, with a boolean value as the last parameter
30+
(or the first parameter, if no parameters of the function exist).
31+
32+
In V8 the options fallback is defined as `FastApiCallbackOptions` inside
33+
[`v8-fast-api-calls.h`](/deps/v8/include/v8-fast-api-calls.h) file.
34+
35+
- JavaScript land
36+
37+
Example of a JavaScript:
38+
39+
```javascript
40+
// Let calculateX be a function that provides fast api calls.
41+
const { calculateX } = internalBinding('custom_namespace');
42+
43+
function conditionallyGetX(useSlowPath) {
44+
return calculateX({ fallback: useSlowPath })
45+
}
46+
```
47+
48+
- C++ land
49+
50+
Example of a conditional fast path on C++
51+
52+
```c++
53+
// Anywhere in the execution flow, you can set fallback and stop the execution.
54+
static void FastCalculateX(const v8::FastApiCallbackOptions& options) {
55+
if (true) {
56+
options.fallback = true;
57+
}
58+
}
59+
```
60+
61+
## Example
62+
63+
A typical function that communicates between JavaScript and C++ is as follows.
64+
65+
- On the JavaScript side:
66+
67+
```javascript
68+
const { calculateX } = internalBinding('custom_namespace');
69+
```
70+
71+
- On the C++ side:
72+
73+
```c++
74+
namespace node {
75+
namespace custom_namespace {
76+
77+
#define PREFER_FALLBACK = false;
78+
79+
static void CalculateX(const FunctionCallbackInfo<Value>& args) {
80+
int calculated_x = 5;
81+
args.GetReturnValue().Set(calculated_x);
82+
}
83+
84+
static int FastCalculateX(const v8::FastApiCallbackOptions& options) {
85+
if (PREFER_FALLBACK) {
86+
options.fallback = true;
87+
return;
88+
}
89+
return 5;
90+
}
91+
92+
CFunction fast_calculate_x_(CFunction::Make(FastCalculateX));
93+
94+
static void Initialize(Local<Object> target, Local<Value> unused, Local<Context> context, void* priv) {
95+
SetFastMethod(context, target, "calculateX", CalculateX, &calculate_x_);
96+
}
97+
98+
void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
99+
registry->Register(CalculateX);
100+
registry->Register(FastCalculateX);
101+
registry->Register(fast_calculate_x_.GetTypeInfo());
102+
}
103+
104+
} // namespace custom_namespace
105+
} // namespace node
106+
107+
NODE_BINDING_CONTEXT_AWARE_INTERNAL(custom_namespace, node::custom_namespace::Initialize)
108+
NODE_BINDING_EXTERNAL_REFERENCE(custom_namespace, node::custom_namespace::RegisterExternalReferences)
109+
```
110+
111+
- Update external references ([`node_external_reference.h`](/src/node_external_reference.h))
112+
113+
Since our implementation used `int(const v8::FastApiCallbackOptions& options)` signature,
114+
we need to add it to external references.
115+
116+
Example declaration:
117+
118+
```c++
119+
using CFunctionCallbackReturningInt = int (*)(const v8::FastApiCallbackOptions& options);
120+
```

0 commit comments

Comments
 (0)