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)
18 struct _EXCEPTION_POINTERS;
19 #endif
20 
21 namespace v8 {
22 
23 template <typename T>
24 class FunctionCallbackInfo;
25 class Isolate;
26 class Message;
27 class Module;
28 class Object;
29 class Promise;
30 class ScriptOrModule;
31 class String;
32 class UnboundScript;
33 class 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  */
40 struct 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  */
127 enum 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  */
138 using 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  */
149 enum GCType {
150   kGCTypeScavenge = 1 << 0,
151   kGCTypeMarkSweepCompact = 1 << 1,
152   kGCTypeIncrementalMarking = 1 << 2,
153   kGCTypeProcessWeakCallbacks = 1 << 3,
154   kGCTypeAll = kGCTypeScavenge | kGCTypeMarkSweepCompact |
155                kGCTypeIncrementalMarking | kGCTypeProcessWeakCallbacks
156 };
157 
158 /**
159  * GCCallbackFlags is used to notify additional information about the GC
160  * callback.
161  *   - kGCCallbackFlagConstructRetainedObjectInfos: The GC callback is for
162  *     constructing retained object infos.
163  *   - kGCCallbackFlagForced: The GC callback is for a forced GC for testing.
164  *   - kGCCallbackFlagSynchronousPhantomCallbackProcessing: The GC callback
165  *     is called synchronously without getting posted to an idle task.
166  *   - kGCCallbackFlagCollectAllAvailableGarbage: The GC callback is called
167  *     in a phase where V8 is trying to collect all available garbage
168  *     (e.g., handling a low memory notification).
169  *   - kGCCallbackScheduleIdleGarbageCollection: The GC callback is called to
170  *     trigger an idle garbage collection.
171  */
172 enum GCCallbackFlags {
173   kNoGCCallbackFlags = 0,
174   kGCCallbackFlagConstructRetainedObjectInfos = 1 << 1,
175   kGCCallbackFlagForced = 1 << 2,
176   kGCCallbackFlagSynchronousPhantomCallbackProcessing = 1 << 3,
177   kGCCallbackFlagCollectAllAvailableGarbage = 1 << 4,
178   kGCCallbackFlagCollectAllExternalMemory = 1 << 5,
179   kGCCallbackScheduleIdleGarbageCollection = 1 << 6,
180 };
181 
182 using GCCallback = void (*)(GCType type, GCCallbackFlags flags);
183 
184 using InterruptCallback = void (*)(Isolate* isolate, void* data);
185 
186 /**
187  * This callback is invoked when the heap size is close to the heap limit and
188  * V8 is likely to abort with out-of-memory error.
189  * The callback can extend the heap limit by returning a value that is greater
190  * than the current_heap_limit. The initial heap limit is the limit that was
191  * set after heap setup.
192  */
193 using NearHeapLimitCallback = size_t (*)(void* data, size_t current_heap_limit,
194                                          size_t initial_heap_limit);
195 
196 /**
197  * Callback function passed to SetUnhandledExceptionCallback.
198  */
199 #if defined(V8_OS_WIN)
200 using UnhandledExceptionCallback =
201     int (*)(_EXCEPTION_POINTERS* exception_pointers);
202 #endif
203 
204 // --- Counters Callbacks ---
205 
206 using CounterLookupCallback = int* (*)(const char* name);
207 
208 using CreateHistogramCallback = void* (*)(const char* name, int min, int max,
209                                           size_t buckets);
210 
211 using AddHistogramSampleCallback = void (*)(void* histogram, int sample);
212 
213 // --- Exceptions ---
214 
215 using FatalErrorCallback = void (*)(const char* location, const char* message);
216 
217 using OOMErrorCallback = void (*)(const char* location, bool is_heap_oom);
218 
219 using MessageCallback = void (*)(Local<Message> message, Local<Value> data);
220 
221 // --- Tracing ---
222 
223 enum LogEventStatus : int { kStart = 0, kEnd = 1, kStamp = 2 };
224 using LogEventCallback = void (*)(const char* name,
225                                   int /* LogEventStatus */ status);
226 
227 // --- Crashkeys Callback ---
228 enum class CrashKeyId {
229   kIsolateAddress,
230   kReadonlySpaceFirstPageAddress,
231   kMapSpaceFirstPageAddress,
232   kCodeSpaceFirstPageAddress,
233   kDumpType,
234 };
235 
236 using AddCrashKeyCallback = void (*)(CrashKeyId id, const std::string& value);
237 
238 // --- Enter/Leave Script Callback ---
239 using BeforeCallEnteredCallback = void (*)(Isolate*);
240 using CallCompletedCallback = void (*)(Isolate*);
241 
242 // --- AllowCodeGenerationFromStrings callbacks ---
243 
244 /**
245  * Callback to check if code generation from strings is allowed. See
246  * Context::AllowCodeGenerationFromStrings.
247  */
248 using AllowCodeGenerationFromStringsCallback = bool (*)(Local<Context> context,
249                                                         Local<String> source);
250 
251 struct ModifyCodeGenerationFromStringsResult {
252   // If true, proceed with the codegen algorithm. Otherwise, block it.
253   bool codegen_allowed = false;
254   // Overwrite the original source with this string, if present.
255   // Use the original source if empty.
256   // This field is considered only if codegen_allowed is true.
257   MaybeLocal<String> modified_source;
258 };
259 
260 /**
261  * Access type specification.
262  */
263 enum AccessType {
264   ACCESS_GET,
265   ACCESS_SET,
266   ACCESS_HAS,
267   ACCESS_DELETE,
268   ACCESS_KEYS
269 };
270 
271 // --- Failed Access Check Callback ---
272 
273 using FailedAccessCheckCallback = void (*)(Local<Object> target,
274                                            AccessType type, Local<Value> data);
275 
276 /**
277  * Callback to check if codegen is allowed from a source object, and convert
278  * the source to string if necessary. See: ModifyCodeGenerationFromStrings.
279  */
280 using ModifyCodeGenerationFromStringsCallback =
281     ModifyCodeGenerationFromStringsResult (*)(Local<Context> context,
282                                               Local<Value> source);
283 using ModifyCodeGenerationFromStringsCallback2 =
284     ModifyCodeGenerationFromStringsResult (*)(Local<Context> context,
285                                               Local<Value> source,
286                                               bool is_code_like);
287 
288 // --- WebAssembly compilation callbacks ---
289 using ExtensionCallback = bool (*)(const FunctionCallbackInfo<Value>&);
290 
291 using AllowWasmCodeGenerationCallback = bool (*)(Local<Context> context,
292                                                  Local<String> source);
293 
294 // --- Callback for APIs defined on v8-supported objects, but implemented
295 // by the embedder. Example: WebAssembly.{compile|instantiate}Streaming ---
296 using ApiImplementationCallback = void (*)(const FunctionCallbackInfo<Value>&);
297 
298 // --- Callback for WebAssembly.compileStreaming ---
299 using WasmStreamingCallback = void (*)(const FunctionCallbackInfo<Value>&);
300 
301 // --- Callback for loading source map file for Wasm profiling support
302 using WasmLoadSourceMapCallback = Local<String> (*)(Isolate* isolate,
303                                                     const char* name);
304 
305 // --- Callback for checking if WebAssembly Simd is enabled ---
306 using WasmSimdEnabledCallback = bool (*)(Local<Context> context);
307 
308 // --- Callback for checking if WebAssembly exceptions are enabled ---
309 using WasmExceptionsEnabledCallback = bool (*)(Local<Context> context);
310 
311 // --- Callback for checking if WebAssembly dynamic tiering is enabled ---
312 using WasmDynamicTieringEnabledCallback = bool (*)(Local<Context> context);
313 
314 // --- Callback for checking if the SharedArrayBuffer constructor is enabled ---
315 using SharedArrayBufferConstructorEnabledCallback =
316     bool (*)(Local<Context> context);
317 
318 /**
319  * HostImportModuleDynamicallyWithImportAssertionsCallback is called when we
320  * require the embedder to load a module. This is used as part of the dynamic
321  * import syntax.
322  *
323  * The referrer contains metadata about the script/module that calls
324  * import.
325  *
326  * The specifier is the name of the module that should be imported.
327  *
328  * The import_assertions are import assertions for this request in the form:
329  * [key1, value1, key2, value2, ...] where the keys and values are of type
330  * v8::String. Note, unlike the FixedArray passed to ResolveModuleCallback and
331  * returned from ModuleRequest::GetImportAssertions(), this array does not
332  * contain the source Locations of the assertions.
333  *
334  * The embedder must compile, instantiate, evaluate the Module, and
335  * obtain its namespace object.
336  *
337  * The Promise returned from this function is forwarded to userland
338  * JavaScript. The embedder must resolve this promise with the module
339  * namespace object. In case of an exception, the embedder must reject
340  * this promise with the exception. If the promise creation itself
341  * fails (e.g. due to stack overflow), the embedder must propagate
342  * that exception by returning an empty MaybeLocal.
343  */
344 using HostImportModuleDynamicallyWithImportAssertionsCallback =
345     MaybeLocal<Promise> (*)(Local<Context> context,
346                             Local<ScriptOrModule> referrer,
347                             Local<String> specifier,
348                             Local<FixedArray> import_assertions);
349 
350 /**
351  * HostInitializeImportMetaObjectCallback is called the first time import.meta
352  * is accessed for a module. Subsequent access will reuse the same value.
353  *
354  * The method combines two implementation-defined abstract operations into one:
355  * HostGetImportMetaProperties and HostFinalizeImportMeta.
356  *
357  * The embedder should use v8::Object::CreateDataProperty to add properties on
358  * the meta object.
359  */
360 using HostInitializeImportMetaObjectCallback = void (*)(Local<Context> context,
361                                                         Local<Module> module,
362                                                         Local<Object> meta);
363 
364 /**
365  * PrepareStackTraceCallback is called when the stack property of an error is
366  * first accessed. The return value will be used as the stack value. If this
367  * callback is registed, the |Error.prepareStackTrace| API will be disabled.
368  * |sites| is an array of call sites, specified in
369  * https://v8.dev/docs/stack-trace-api
370  */
371 using PrepareStackTraceCallback = MaybeLocal<Value> (*)(Local<Context> context,
372                                                         Local<Value> error,
373                                                         Local<Array> sites);
374 
375 }  // namespace v8
376 
377 #endif  // INCLUDE_V8_ISOLATE_CALLBACKS_H_
378