Skip to content

Commit 177f200

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

File tree

1 file changed

+128
-0
lines changed

1 file changed

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

0 commit comments

Comments
 (0)