Builtins, Torque & CSA
Array.prototype.map, JSON.parse, the + operator's slow path, even the
Ignition bytecode handlers — these are builtins:
precompiled functions shipped inside V8. This page explains how they are written:
in C++, in hand-written CodeStubAssembler (CSA), or — increasingly — in
Torque, V8's typed DSL that compiles to CSA. If you want to contribute to
V8's standard library, this is the toolchain you will use.
::: info Ubiquitous language
Builtin: a precompiled function bundled with V8. CSA (CodeStubAssembler):
a portable, typed macro-assembler over TurboFan's backend.
Torque (.tq): a higher-level typed language that compiles to CSA.
:::
What a builtin is
Builtins are enumerated and bundled at build time:
enum class Builtin : int32_t {
kNoBuiltinId = -1,
// … one entry per builtin, generated from BUILTIN_LIST …
};
— src/builtins/builtins.h#L56-L150
They come in several kinds, documented where the list is defined:
// CPP: Builtin in C++. Entered via BUILTIN_EXIT frame.
// TFJ: Turbofan, with JS linkage (a JS-callable function).
// TFS: Turbofan, with CodeStub linkage (an internal stub).
// TFC: Turbofan, CodeStub linkage + custom descriptor.
// TFH: Turbofan handlers (IC handlers).
// BCH: Bytecode handlers.
// ASM: hand-written platform assembly.
— src/builtins/builtins-definitions.h#L29-L52
::: details Embedded builtins Builtins are compiled once and packed into an embedded blob baked into the V8 binary, shared across all isolates. That means zero per-isolate cost to "have" the standard library, and the code is position-independent so it can be mapped once. This pairs with snapshots to make isolate startup cheap. :::
CSA: a portable assembler that the optimizer compiles
Hand-writing builtins in raw assembly for every CPU would be unmaintainable. CSA solves this: it is a C++ API for emitting TurboFan IR that the existing backend then turns into optimized machine code for each target. You write architecture-independent code; you get x64/arm64/… out.
// Provides JavaScript-specific "macro-assembler" functionality on top of the
// CodeAssembler. …
class V8_EXPORT_PRIVATE CodeStubAssembler
: public compiler::CodeAssembler,
public TorqueGeneratedExportedMacrosAssembler { … };
— src/codegen/code-stub-assembler.h#L65-L79
CSA gives you typed nodes (TNode<Smi>, TNode<JSObject>), the
tagged/untagged
distinction, label-based control flow, and exception scopes — but it is still
low-level and easy to get wrong (forget a Smi untag, mishandle a HeapNumber,
and you have a security bug).
Torque: types and safety on top of CSA
Torque is V8's answer to "CSA is too sharp." It is a typed, higher-level
language (.tq files) that compiles to CSA, so the common builtin patterns are
expressed safely and the dangerous boilerplate is generated. Here is a real
builtin in Torque:
transitioning builtin ArrayFindLoopContinuation(
implicit context: Context)(_receiver: JSReceiver, callbackfn: Callable,
thisArg: JSAny, o: JSReceiver, initialK: Number, length: Number): JSAny {
for (let k: Number = initialK; k < length; k++) {
const value: JSAny = GetProperty(o, k);
const testResult: JSAny = Call(context, callbackfn, thisArg, value, k, o);
if (ToBoolean(testResult)) { return value; }
}
return Undefined;
}
— src/builtins/array-find.tq#L6-L80
What Torque buys:
A strict type system (
JSAny,JSReceiver,Callable,Number, …) that catches type-confusion bugs at compile time — directly relevant to security, since builtins are a classic exploitation surface.transitioningannotations that make side effects (and thus possible deopt/GC points) explicit.Generated object accessors: many object layouts are declared in
.tqand generate the C++ field offsets and verification code (this is theTorqueGenerated…base class you meet in the C++ primer).
Torque files compile to generated C++/CSA under torque-generated/, which
TurboFan's backend then turns into the embedded builtin code.
::: tip Why this matters to a contributor
Most standard-library work in modern V8 means writing or editing .tq. The
progression CPP → CSA → Torque is V8 deliberately trading raw control for
safety and portability without giving up performance — the generated code still
goes through TurboFan's optimizer. If you build a runtime with a big native
standard library, a typed DSL that lowers to your optimizer is a pattern worth
studying.
:::
See also
Ignition — its bytecode handlers are builtins (BCH).
TurboFan — the backend CSA/Torque compile through.
C++ primer — reading Torque-generated classes.
Build system — where Torque runs in the build.