• 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 using OOMErrorCallback = void (*)(const char* location, bool is_heap_oom);
220 
221 using MessageCallback = void (*)(Local<Message> message, Local<Value> data);
222 
223 // --- Tracing ---
224 
225 enum LogEventStatus : int { kStart = 0, kEnd = 1, kStamp = 2 };
226 using LogEventCallback = void (*)(const char* name,
227                                   int /* LogEventStatus */ status);
228 
229 // --- Crashkeys Callback ---
230 enum class CrashKeyId {
231   kIsolateAddress,
232   kReadonlySpaceFirstPageAddress,
233   kMapSpaceFirstPageAddress,
234   kCodeSpaceFirstPageAddress,
235   kDumpType,
236 };
237 
238 using AddCrashKeyCallback = void (*)(CrashKeyId id, const std::string& value);
239 
240 // --- Enter/Leave Script Callback ---
241 using BeforeCallEnteredCallback = void (*)(Isolate*);
242 using 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  */
250 using AllowCodeGenerationFromStringsCallback = bool (*)(Local<Context> context,
251                                                         Local<String> source);
252 
253 struct 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  */
265 enum AccessType {
266   ACCESS_GET,
267   ACCESS_SET,
268   ACCESS_HAS,
269   ACCESS_DELETE,
270   ACCESS_KEYS
271 };
272 
273 // --- Failed Access Check Callback ---
274 
275 using 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  */
282 using ModifyCodeGenerationFromStringsCallback =
283     ModifyCodeGenerationFromStringsResult (*)(Local<Context> context,
284                                               Local<Value> source);
285 using ModifyCodeGenerationFromStringsCallback2 =
286     ModifyCodeGenerationFromStringsResult (*)(Local<Context> context,
287                                               Local<Value> source,
288                                               bool is_code_like);
289 
290 // --- WebAssembly compilation callbacks ---
291 using ExtensionCallback = bool (*)(const FunctionCallbackInfo<Value>&);
292 
293 using 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 ---
298 using ApiImplementationCallback = void (*)(const FunctionCallbackInfo<Value>&);
299 
300 // --- Callback for WebAssembly.compileStreaming ---
301 using WasmStreamingCallback = void (*)(const FunctionCallbackInfo<Value>&);
302 
303 // --- Callback for loading source map file for Wasm profiling support
304 using WasmLoadSourceMapCallback = Local<String> (*)(Isolate* isolate,
305                                                     const char* name);
306 
307 // --- Callback for checking if WebAssembly Simd is enabled ---
308 using WasmSimdEnabledCallback = bool (*)(Local<Context> context);
309 
310 // --- Callback for checking if WebAssembly exceptions are enabled ---
311 using WasmExceptionsEnabledCallback = bool (*)(Local<Context> context);
312 
313 // --- Callback for checking if WebAssembly dynamic tiering is enabled ---
314 using WasmDynamicTieringEnabledCallback = bool (*)(Local<Context> context);
315 
316 // --- Callback for checking if the SharedArrayBuffer constructor is enabled ---
317 using 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  */
346 using HostImportModuleDynamicallyWithImportAssertionsCallback =
347     MaybeLocal<Promise> (*)(Local<Context> context,
348                             Local<ScriptOrModule> referrer,
349                             Local<String> specifier,
350                             Local<FixedArray> import_assertions);
351 using 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  */
366 using 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  */
381 using 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  */
391 using 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