1// Copyright 2021 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef INCLUDE_V8_ISOLATE_CALLBACKS_H_
6#define INCLUDE_V8_ISOLATE_CALLBACKS_H_
7
8#include <stddef.h>
9
10#include <string>
11
12#include "cppgc/common.h"
13#include "v8-data.h"          // NOLINT(build/include_directory)
14#include "v8-local-handle.h"  // NOLINT(build/include_directory)
15#include "v8config.h"         // NOLINT(build/include_directory)
16
17#if defined(V8_OS_WIN)
18struct _EXCEPTION_POINTERS;
19#endif
20
21namespace v8 {
22
23template <typename T>
24class FunctionCallbackInfo;
25class Isolate;
26class Message;
27class Module;
28class Object;
29class Promise;
30class ScriptOrModule;
31class String;
32class UnboundScript;
33class Value;
34
35/**
36 * A JIT code event is issued each time code is added, moved or removed.
37 *
38 * \note removal events are not currently issued.
39 */
40struct JitCodeEvent {
41  enum EventType {
42    CODE_ADDED,
43    CODE_MOVED,
44    CODE_REMOVED,
45    CODE_ADD_LINE_POS_INFO,
46    CODE_START_LINE_INFO_RECORDING,
47    CODE_END_LINE_INFO_RECORDING
48  };
49  // Definition of the code position type. The "POSITION" type means the place
50  // in the source code which are of interest when making stack traces to
51  // pin-point the source location of a stack frame as close as possible.
52  // The "STATEMENT_POSITION" means the place at the beginning of each
53  // statement, and is used to indicate possible break locations.
54  enum PositionType { POSITION, STATEMENT_POSITION };
55
56  // There are three different kinds of CodeType, one for JIT code generated
57  // by the optimizing compiler, one for byte code generated for the
58  // interpreter, and one for code generated from Wasm. For JIT_CODE and
59  // WASM_CODE, |code_start| points to the beginning of jitted assembly code,
60  // while for BYTE_CODE events, |code_start| points to the first bytecode of
61  // the interpreted function.
62  enum CodeType { BYTE_CODE, JIT_CODE, WASM_CODE };
63
64  // Type of event.
65  EventType type;
66  CodeType code_type;
67  // Start of the instructions.
68  void* code_start;
69  // Size of the instructions.
70  size_t code_len;
71  // Script info for CODE_ADDED event.
72  Local<UnboundScript> script;
73  // User-defined data for *_LINE_INFO_* event. It's used to hold the source
74  // code line information which is returned from the
75  // CODE_START_LINE_INFO_RECORDING event. And it's passed to subsequent
76  // CODE_ADD_LINE_POS_INFO and CODE_END_LINE_INFO_RECORDING events.
77  void* user_data;
78
79  struct name_t {
80    // Name of the object associated with the code, note that the string is not
81    // zero-terminated.
82    const char* str;
83    // Number of chars in str.
84    size_t len;
85  };
86
87  struct line_info_t {
88    // PC offset
89    size_t offset;
90    // Code position
91    size_t pos;
92    // The position type.
93    PositionType position_type;
94  };
95
96  struct wasm_source_info_t {
97    // Source file name.
98    const char* filename;
99    // Length of filename.
100    size_t filename_size;
101    // Line number table, which maps offsets of JITted code to line numbers of
102    // source file.
103    const line_info_t* line_number_table;
104    // Number of entries in the line number table.
105    size_t line_number_table_size;
106  };
107
108  wasm_source_info_t* wasm_source_info;
109
110  union {
111    // Only valid for CODE_ADDED.
112    struct name_t name;
113
114    // Only valid for CODE_ADD_LINE_POS_INFO
115    struct line_info_t line_info;
116
117    // New location of instructions. Only valid for CODE_MOVED.
118    void* new_code_start;
119  };
120
121  Isolate* isolate;
122};
123
124/**
125 * Option flags passed to the SetJitCodeEventHandler function.
126 */
127enum JitCodeEventOptions {
128  kJitCodeEventDefault = 0,
129  // Generate callbacks for already existent code.
130  kJitCodeEventEnumExisting = 1
131};
132
133/**
134 * Callback function passed to SetJitCodeEventHandler.
135 *
136 * \param event code add, move or removal event.
137 */
138using JitCodeEventHandler = void (*)(const JitCodeEvent* event);
139
140// --- Garbage Collection Callbacks ---
141
142/**
143 * Applications can register callback functions which will be called before and
144 * after certain garbage collection operations.  Allocations are not allowed in
145 * the callback functions, you therefore cannot manipulate objects (set or
146 * delete properties for example) since it is possible such operations will
147 * result in the allocation of objects.
148 */
149enum GCType {
150  kGCTypeScavenge = 1 << 0,
151  kGCTypeMinorMarkCompact = 1 << 1,
152  kGCTypeMarkSweepCompact = 1 << 2,
153  kGCTypeIncrementalMarking = 1 << 3,
154  kGCTypeProcessWeakCallbacks = 1 << 4,
155  kGCTypeAll = kGCTypeScavenge | kGCTypeMinorMarkCompact |
156               kGCTypeMarkSweepCompact | kGCTypeIncrementalMarking |
157               kGCTypeProcessWeakCallbacks
158};
159
160/**
161 * GCCallbackFlags is used to notify additional information about the GC
162 * callback.
163 *   - kGCCallbackFlagConstructRetainedObjectInfos: The GC callback is for
164 *     constructing retained object infos.
165 *   - kGCCallbackFlagForced: The GC callback is for a forced GC for testing.
166 *   - kGCCallbackFlagSynchronousPhantomCallbackProcessing: The GC callback
167 *     is called synchronously without getting posted to an idle task.
168 *   - kGCCallbackFlagCollectAllAvailableGarbage: The GC callback is called
169 *     in a phase where V8 is trying to collect all available garbage
170 *     (e.g., handling a low memory notification).
171 *   - kGCCallbackScheduleIdleGarbageCollection: The GC callback is called to
172 *     trigger an idle garbage collection.
173 */
174enum GCCallbackFlags {
175  kNoGCCallbackFlags = 0,
176  kGCCallbackFlagConstructRetainedObjectInfos = 1 << 1,
177  kGCCallbackFlagForced = 1 << 2,
178  kGCCallbackFlagSynchronousPhantomCallbackProcessing = 1 << 3,
179  kGCCallbackFlagCollectAllAvailableGarbage = 1 << 4,
180  kGCCallbackFlagCollectAllExternalMemory = 1 << 5,
181  kGCCallbackScheduleIdleGarbageCollection = 1 << 6,
182};
183
184using GCCallback = void (*)(GCType type, GCCallbackFlags flags);
185
186using InterruptCallback = void (*)(Isolate* isolate, void* data);
187
188/**
189 * This callback is invoked when the heap size is close to the heap limit and
190 * V8 is likely to abort with out-of-memory error.
191 * The callback can extend the heap limit by returning a value that is greater
192 * than the current_heap_limit. The initial heap limit is the limit that was
193 * set after heap setup.
194 */
195using NearHeapLimitCallback = size_t (*)(void* data, size_t current_heap_limit,
196                                         size_t initial_heap_limit);
197
198/**
199 * Callback function passed to SetUnhandledExceptionCallback.
200 */
201#if defined(V8_OS_WIN)
202using UnhandledExceptionCallback =
203    int (*)(_EXCEPTION_POINTERS* exception_pointers);
204#endif
205
206// --- Counters Callbacks ---
207
208using CounterLookupCallback = int* (*)(const char* name);
209
210using CreateHistogramCallback = void* (*)(const char* name, int min, int max,
211                                          size_t buckets);
212
213using AddHistogramSampleCallback = void (*)(void* histogram, int sample);
214
215// --- Exceptions ---
216
217using FatalErrorCallback = void (*)(const char* location, const char* message);
218
219using OOMErrorCallback = void (*)(const char* location, bool is_heap_oom);
220
221using MessageCallback = void (*)(Local<Message> message, Local<Value> data);
222
223// --- Tracing ---
224
225enum LogEventStatus : int { kStart = 0, kEnd = 1, kStamp = 2 };
226using LogEventCallback = void (*)(const char* name,
227                                  int /* LogEventStatus */ status);
228
229// --- Crashkeys Callback ---
230enum class CrashKeyId {
231  kIsolateAddress,
232  kReadonlySpaceFirstPageAddress,
233  kMapSpaceFirstPageAddress,
234  kCodeSpaceFirstPageAddress,
235  kDumpType,
236};
237
238using AddCrashKeyCallback = void (*)(CrashKeyId id, const std::string& value);
239
240// --- Enter/Leave Script Callback ---
241using BeforeCallEnteredCallback = void (*)(Isolate*);
242using CallCompletedCallback = void (*)(Isolate*);
243
244// --- AllowCodeGenerationFromStrings callbacks ---
245
246/**
247 * Callback to check if code generation from strings is allowed. See
248 * Context::AllowCodeGenerationFromStrings.
249 */
250using AllowCodeGenerationFromStringsCallback = bool (*)(Local<Context> context,
251                                                        Local<String> source);
252
253struct ModifyCodeGenerationFromStringsResult {
254  // If true, proceed with the codegen algorithm. Otherwise, block it.
255  bool codegen_allowed = false;
256  // Overwrite the original source with this string, if present.
257  // Use the original source if empty.
258  // This field is considered only if codegen_allowed is true.
259  MaybeLocal<String> modified_source;
260};
261
262/**
263 * Access type specification.
264 */
265enum AccessType {
266  ACCESS_GET,
267  ACCESS_SET,
268  ACCESS_HAS,
269  ACCESS_DELETE,
270  ACCESS_KEYS
271};
272
273// --- Failed Access Check Callback ---
274
275using FailedAccessCheckCallback = void (*)(Local<Object> target,
276                                           AccessType type, Local<Value> data);
277
278/**
279 * Callback to check if codegen is allowed from a source object, and convert
280 * the source to string if necessary. See: ModifyCodeGenerationFromStrings.
281 */
282using ModifyCodeGenerationFromStringsCallback =
283    ModifyCodeGenerationFromStringsResult (*)(Local<Context> context,
284                                              Local<Value> source);
285using ModifyCodeGenerationFromStringsCallback2 =
286    ModifyCodeGenerationFromStringsResult (*)(Local<Context> context,
287                                              Local<Value> source,
288                                              bool is_code_like);
289
290// --- WebAssembly compilation callbacks ---
291using ExtensionCallback = bool (*)(const FunctionCallbackInfo<Value>&);
292
293using AllowWasmCodeGenerationCallback = bool (*)(Local<Context> context,
294                                                 Local<String> source);
295
296// --- Callback for APIs defined on v8-supported objects, but implemented
297// by the embedder. Example: WebAssembly.{compile|instantiate}Streaming ---
298using ApiImplementationCallback = void (*)(const FunctionCallbackInfo<Value>&);
299
300// --- Callback for WebAssembly.compileStreaming ---
301using WasmStreamingCallback = void (*)(const FunctionCallbackInfo<Value>&);
302
303// --- Callback for loading source map file for Wasm profiling support
304using WasmLoadSourceMapCallback = Local<String> (*)(Isolate* isolate,
305                                                    const char* name);
306
307// --- Callback for checking if WebAssembly Simd is enabled ---
308using WasmSimdEnabledCallback = bool (*)(Local<Context> context);
309
310// --- Callback for checking if WebAssembly exceptions are enabled ---
311using WasmExceptionsEnabledCallback = bool (*)(Local<Context> context);
312
313// --- Callback for checking if WebAssembly dynamic tiering is enabled ---
314using WasmDynamicTieringEnabledCallback = bool (*)(Local<Context> context);
315
316// --- Callback for checking if the SharedArrayBuffer constructor is enabled ---
317using SharedArrayBufferConstructorEnabledCallback =
318    bool (*)(Local<Context> context);
319
320/**
321 * HostImportModuleDynamicallyCallback is called when we
322 * require the embedder to load a module. This is used as part of the dynamic
323 * import syntax.
324 *
325 * The referrer contains metadata about the script/module that calls
326 * import.
327 *
328 * The specifier is the name of the module that should be imported.
329 *
330 * The import_assertions are import assertions for this request in the form:
331 * [key1, value1, key2, value2, ...] where the keys and values are of type
332 * v8::String. Note, unlike the FixedArray passed to ResolveModuleCallback and
333 * returned from ModuleRequest::GetImportAssertions(), this array does not
334 * contain the source Locations of the assertions.
335 *
336 * The embedder must compile, instantiate, evaluate the Module, and
337 * obtain its namespace object.
338 *
339 * The Promise returned from this function is forwarded to userland
340 * JavaScript. The embedder must resolve this promise with the module
341 * namespace object. In case of an exception, the embedder must reject
342 * this promise with the exception. If the promise creation itself
343 * fails (e.g. due to stack overflow), the embedder must propagate
344 * that exception by returning an empty MaybeLocal.
345 */
346using HostImportModuleDynamicallyWithImportAssertionsCallback =
347    MaybeLocal<Promise> (*)(Local<Context> context,
348                            Local<ScriptOrModule> referrer,
349                            Local<String> specifier,
350                            Local<FixedArray> import_assertions);
351using HostImportModuleDynamicallyCallback = MaybeLocal<Promise> (*)(
352    Local<Context> context, Local<Data> host_defined_options,
353    Local<Value> resource_name, Local<String> specifier,
354    Local<FixedArray> import_assertions);
355
356/**
357 * HostInitializeImportMetaObjectCallback is called the first time import.meta
358 * is accessed for a module. Subsequent access will reuse the same value.
359 *
360 * The method combines two implementation-defined abstract operations into one:
361 * HostGetImportMetaProperties and HostFinalizeImportMeta.
362 *
363 * The embedder should use v8::Object::CreateDataProperty to add properties on
364 * the meta object.
365 */
366using HostInitializeImportMetaObjectCallback = void (*)(Local<Context> context,
367                                                        Local<Module> module,
368                                                        Local<Object> meta);
369
370/**
371 * HostCreateShadowRealmContextCallback is called each time a ShadowRealm is
372 * being constructed in the initiator_context.
373 *
374 * The method combines Context creation and implementation defined abstract
375 * operation HostInitializeShadowRealm into one.
376 *
377 * The embedder should use v8::Context::New or v8::Context:NewFromSnapshot to
378 * create a new context. If the creation fails, the embedder must propagate
379 * that exception by returning an empty MaybeLocal.
380 */
381using HostCreateShadowRealmContextCallback =
382    MaybeLocal<Context> (*)(Local<Context> initiator_context);
383
384/**
385 * PrepareStackTraceCallback is called when the stack property of an error is
386 * first accessed. The return value will be used as the stack value. If this
387 * callback is registed, the |Error.prepareStackTrace| API will be disabled.
388 * |sites| is an array of call sites, specified in
389 * https://v8.dev/docs/stack-trace-api
390 */
391using PrepareStackTraceCallback = MaybeLocal<Value> (*)(Local<Context> context,
392                                                        Local<Value> error,
393                                                        Local<Array> sites);
394
395}  // namespace v8
396
397#endif  // INCLUDE_V8_ISOLATE_CALLBACKS_H_
398