• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   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  */
174 enum 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 
184 using GCCallback = void (*)(GCType type, GCCallbackFlags flags);
185 
186 using 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  */
195 using 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)
202 using UnhandledExceptionCallback =
203     int (*)(_EXCEPTION_POINTERS* exception_pointers);
204 #endif
205 
206 // --- Counters Callbacks ---
207 
208 using CounterLookupCallback = int* (*)(const char* name);
209 
210 using CreateHistogramCallback = void* (*)(const char* name, int min, int max,
211                                           size_t buckets);
212 
213 using AddHistogramSampleCallback = void (*)(void* histogram, int sample);
214 
215 // --- Exceptions ---
216 
217 using FatalErrorCallback = void (*)(const char* location, const char* message);
218 
219 
220 struct OOMDetails {
221  bool is_heap_oom = false;
222  const char* detail = nullptr;
223 };
224 
225 using OOMErrorCallback = void (*)(const char* location, bool is_heap_oom);
226 
227 using MessageCallback = void (*)(Local<Message> message, Local<Value> data);
228 
229 // --- Tracing ---
230 
231 enum LogEventStatus : int { kStart = 0, kEnd = 1, kStamp = 2 };
232 using LogEventCallback = void (*)(const char* name,
233                                   int /* LogEventStatus */ status);
234 
235 // --- Crashkeys Callback ---
236 enum class CrashKeyId {
237   kIsolateAddress,
238   kReadonlySpaceFirstPageAddress,
239   kMapSpaceFirstPageAddress,
240   kCodeSpaceFirstPageAddress,
241   kDumpType,
242 };
243 
244 using AddCrashKeyCallback = void (*)(CrashKeyId id, const std::string& value);
245 
246 // --- Enter/Leave Script Callback ---
247 using BeforeCallEnteredCallback = void (*)(Isolate*);
248 using CallCompletedCallback = void (*)(Isolate*);
249 
250 // --- AllowCodeGenerationFromStrings callbacks ---
251 
252 /**
253  * Callback to check if code generation from strings is allowed. See
254  * Context::AllowCodeGenerationFromStrings.
255  */
256 using AllowCodeGenerationFromStringsCallback = bool (*)(Local<Context> context,
257                                                         Local<String> source);
258 
259 struct ModifyCodeGenerationFromStringsResult {
260   // If true, proceed with the codegen algorithm. Otherwise, block it.
261   bool codegen_allowed = false;
262   // Overwrite the original source with this string, if present.
263   // Use the original source if empty.
264   // This field is considered only if codegen_allowed is true.
265   MaybeLocal<String> modified_source;
266 };
267 
268 /**
269  * Access type specification.
270  */
271 enum AccessType {
272   ACCESS_GET,
273   ACCESS_SET,
274   ACCESS_HAS,
275   ACCESS_DELETE,
276   ACCESS_KEYS
277 };
278 
279 // --- Failed Access Check Callback ---
280 
281 using FailedAccessCheckCallback = void (*)(Local<Object> target,
282                                            AccessType type, Local<Value> data);
283 
284 /**
285  * Callback to check if codegen is allowed from a source object, and convert
286  * the source to string if necessary. See: ModifyCodeGenerationFromStrings.
287  */
288 using ModifyCodeGenerationFromStringsCallback =
289     ModifyCodeGenerationFromStringsResult (*)(Local<Context> context,
290                                               Local<Value> source);
291 using ModifyCodeGenerationFromStringsCallback2 =
292     ModifyCodeGenerationFromStringsResult (*)(Local<Context> context,
293                                               Local<Value> source,
294                                               bool is_code_like);
295 
296 // --- WebAssembly compilation callbacks ---
297 using ExtensionCallback = bool (*)(const FunctionCallbackInfo<Value>&);
298 
299 using AllowWasmCodeGenerationCallback = bool (*)(Local<Context> context,
300                                                  Local<String> source);
301 
302 // --- Callback for APIs defined on v8-supported objects, but implemented
303 // by the embedder. Example: WebAssembly.{compile|instantiate}Streaming ---
304 using ApiImplementationCallback = void (*)(const FunctionCallbackInfo<Value>&);
305 
306 // --- Callback for WebAssembly.compileStreaming ---
307 using WasmStreamingCallback = void (*)(const FunctionCallbackInfo<Value>&);
308 
309 // --- Callback for loading source map file for Wasm profiling support
310 using WasmLoadSourceMapCallback = Local<String> (*)(Isolate* isolate,
311                                                     const char* name);
312 
313 // --- Callback for checking if WebAssembly Simd is enabled ---
314 using WasmSimdEnabledCallback = bool (*)(Local<Context> context);
315 
316 // --- Callback for checking if WebAssembly exceptions are enabled ---
317 using WasmExceptionsEnabledCallback = bool (*)(Local<Context> context);
318 
319 // --- Callback for checking if WebAssembly dynamic tiering is enabled ---
320 using WasmDynamicTieringEnabledCallback = bool (*)(Local<Context> context);
321 
322 // --- Callback for checking if the SharedArrayBuffer constructor is enabled ---
323 using SharedArrayBufferConstructorEnabledCallback =
324     bool (*)(Local<Context> context);
325 
326 /**
327  * HostImportModuleDynamicallyCallback is called when we
328  * require the embedder to load a module. This is used as part of the dynamic
329  * import syntax.
330  *
331  * The referrer contains metadata about the script/module that calls
332  * import.
333  *
334  * The specifier is the name of the module that should be imported.
335  *
336  * The import_assertions are import assertions for this request in the form:
337  * [key1, value1, key2, value2, ...] where the keys and values are of type
338  * v8::String. Note, unlike the FixedArray passed to ResolveModuleCallback and
339  * returned from ModuleRequest::GetImportAssertions(), this array does not
340  * contain the source Locations of the assertions.
341  *
342  * The embedder must compile, instantiate, evaluate the Module, and
343  * obtain its namespace object.
344  *
345  * The Promise returned from this function is forwarded to userland
346  * JavaScript. The embedder must resolve this promise with the module
347  * namespace object. In case of an exception, the embedder must reject
348  * this promise with the exception. If the promise creation itself
349  * fails (e.g. due to stack overflow), the embedder must propagate
350  * that exception by returning an empty MaybeLocal.
351  */
352 using HostImportModuleDynamicallyWithImportAssertionsCallback =
353     MaybeLocal<Promise> (*)(Local<Context> context,
354                             Local<ScriptOrModule> referrer,
355                             Local<String> specifier,
356                             Local<FixedArray> import_assertions);
357 using HostImportModuleDynamicallyCallback = MaybeLocal<Promise> (*)(
358     Local<Context> context, Local<Data> host_defined_options,
359     Local<Value> resource_name, Local<String> specifier,
360     Local<FixedArray> import_assertions);
361 
362 /**
363  * HostInitializeImportMetaObjectCallback is called the first time import.meta
364  * is accessed for a module. Subsequent access will reuse the same value.
365  *
366  * The method combines two implementation-defined abstract operations into one:
367  * HostGetImportMetaProperties and HostFinalizeImportMeta.
368  *
369  * The embedder should use v8::Object::CreateDataProperty to add properties on
370  * the meta object.
371  */
372 using HostInitializeImportMetaObjectCallback = void (*)(Local<Context> context,
373                                                         Local<Module> module,
374                                                         Local<Object> meta);
375 
376 /**
377  * HostCreateShadowRealmContextCallback is called each time a ShadowRealm is
378  * being constructed in the initiator_context.
379  *
380  * The method combines Context creation and implementation defined abstract
381  * operation HostInitializeShadowRealm into one.
382  *
383  * The embedder should use v8::Context::New or v8::Context:NewFromSnapshot to
384  * create a new context. If the creation fails, the embedder must propagate
385  * that exception by returning an empty MaybeLocal.
386  */
387 using HostCreateShadowRealmContextCallback =
388     MaybeLocal<Context> (*)(Local<Context> initiator_context);
389 
390 /**
391  * PrepareStackTraceCallback is called when the stack property of an error is
392  * first accessed. The return value will be used as the stack value. If this
393  * callback is registed, the |Error.prepareStackTrace| API will be disabled.
394  * |sites| is an array of call sites, specified in
395  * https://v8.dev/docs/stack-trace-api
396  */
397 using PrepareStackTraceCallback = MaybeLocal<Value> (*)(Local<Context> context,
398                                                         Local<Value> error,
399                                                         Local<Array> sites);
400 
401 }  // namespace v8
402 
403 #endif  // INCLUDE_V8_ISOLATE_CALLBACKS_H_
404