1use crate::ExternalReference;
2use crate::array_buffer;
3use crate::array_buffer::Allocator as ArrayBufferAllocator;
4use crate::cppgc::Heap;
5use crate::snapshot::RawStartupData;
6use crate::snapshot::StartupData;
7use crate::support::Opaque;
8use crate::support::SharedPtr;
9use crate::support::UniqueRef;
10use crate::support::char;
11use crate::support::intptr_t;
12
13use std::any::Any;
14use std::borrow::Cow;
15use std::iter::once;
16use std::mem::MaybeUninit;
17use std::mem::size_of;
18use std::ptr::null;
19
20pub type CounterLookupCallback =
23 unsafe extern "C" fn(name: *const char) -> *mut i32;
24
25#[must_use]
27#[derive(Debug, Default)]
28pub struct CreateParams {
29 raw: raw::CreateParams,
30 allocations: CreateParamAllocations,
31}
32
33impl CreateParams {
34 pub fn counter_lookup_callback(
37 mut self,
38 callback: CounterLookupCallback,
39 ) -> Self {
40 self.raw.counter_lookup_callback = Some(callback);
41 self
42 }
43
44 pub fn snapshot_blob(mut self, data: StartupData) -> Self {
46 let header = Box::new(RawStartupData {
47 data: data.as_ptr() as _,
48 raw_size: data.len() as _,
49 });
50 self.raw.snapshot_blob = &*header;
51 self.allocations.snapshot_blob_data = Some(data);
52 self.allocations.snapshot_blob_header = Some(header);
53 self
54 }
55
56 pub fn array_buffer_allocator(
59 mut self,
60 array_buffer_allocator: impl Into<SharedPtr<ArrayBufferAllocator>>,
61 ) -> Self {
62 self.raw.array_buffer_allocator_shared = array_buffer_allocator.into();
63 self
64 }
65
66 pub fn has_set_array_buffer_allocator(&self) -> bool {
70 !self.raw.array_buffer_allocator_shared.is_null()
71 }
72
73 pub fn external_references(
78 mut self,
79 ext_refs: Cow<'static, [ExternalReference]>,
80 ) -> Self {
81 let ext_refs = if ext_refs.last()
82 == Some(&ExternalReference {
83 pointer: std::ptr::null_mut(),
84 }) {
85 ext_refs
86 } else {
87 Cow::from(
88 ext_refs
89 .into_owned()
90 .into_iter()
91 .chain(once(ExternalReference {
92 pointer: std::ptr::null_mut(),
93 }))
94 .collect::<Vec<_>>(),
95 )
96 };
97
98 self.allocations.external_references = Some(ext_refs);
99 self.raw.external_references = self
100 .allocations
101 .external_references
102 .as_ref()
103 .map(|c| c.as_ptr() as _)
104 .unwrap_or_else(null);
105
106 self
107 }
108
109 pub fn allow_atomics_wait(mut self, value: bool) -> Self {
112 self.raw.allow_atomics_wait = value;
113 self
114 }
115
116 pub fn heap_limits(mut self, initial: usize, max: usize) -> Self {
138 self
139 .raw
140 .constraints
141 .configure_defaults_from_heap_size(initial, max);
142 self
143 }
144
145 pub fn heap_limits_from_system_memory(
165 mut self,
166 physical_memory: u64,
167 virtual_memory_limit: u64,
168 ) -> Self {
169 self
170 .raw
171 .constraints
172 .configure_defaults(physical_memory, virtual_memory_limit);
173 self
174 }
175
176 pub fn max_old_generation_size_in_bytes(&self) -> usize {
178 self.raw.constraints.max_old_generation_size_in_bytes()
179 }
180
181 pub fn set_max_old_generation_size_in_bytes(mut self, limit: usize) -> Self {
185 self
186 .raw
187 .constraints
188 .set_max_old_generation_size_in_bytes(limit);
189 self
190 }
191
192 pub fn max_young_generation_size_in_bytes(&self) -> usize {
194 self.raw.constraints.max_young_generation_size_in_bytes()
195 }
196
197 pub fn set_max_young_generation_size_in_bytes(
201 mut self,
202 limit: usize,
203 ) -> Self {
204 self
205 .raw
206 .constraints
207 .set_max_young_generation_size_in_bytes(limit);
208 self
209 }
210
211 pub fn code_range_size_in_bytes(&self) -> usize {
213 self.raw.constraints.code_range_size_in_bytes()
214 }
215
216 pub fn set_code_range_size_in_bytes(mut self, limit: usize) -> Self {
220 self.raw.constraints.set_code_range_size_in_bytes(limit);
221 self
222 }
223
224 pub fn stack_limit(&self) -> *mut u32 {
227 self.raw.constraints.stack_limit()
228 }
229
230 pub unsafe fn set_stack_limit(mut self, value: *mut u32) -> Self {
237 self.raw.constraints.set_stack_limit(value);
238 self
239 }
240
241 pub fn initial_old_generation_size_in_bytes(&self) -> usize {
243 self.raw.constraints.initial_old_generation_size_in_bytes()
244 }
245
246 pub fn set_initial_old_generation_size_in_bytes(
250 mut self,
251 initial_size: usize,
252 ) -> Self {
253 self
254 .raw
255 .constraints
256 .set_initial_old_generation_size_in_bytes(initial_size);
257 self
258 }
259
260 pub fn initial_young_generation_size_in_bytes(&self) -> usize {
262 self
263 .raw
264 .constraints
265 .initial_young_generation_size_in_bytes()
266 }
267
268 pub fn set_initial_young_generation_size_in_bytes(
270 mut self,
271 initial_size: usize,
272 ) -> Self {
273 self
274 .raw
275 .constraints
276 .set_initial_young_generation_size_in_bytes(initial_size);
277 self
278 }
279
280 pub fn cpp_heap(mut self, heap: UniqueRef<Heap>) -> Self {
283 self.raw.cpp_heap = heap.into_raw();
284 self
285 }
286
287 pub(crate) fn finalize(mut self) -> (raw::CreateParams, Box<dyn Any>) {
288 if self.raw.array_buffer_allocator_shared.is_null() {
289 self = self.array_buffer_allocator(array_buffer::new_default_allocator());
290 }
291 let Self { raw, allocations } = self;
292 (raw, Box::new(allocations))
293 }
294}
295
296#[derive(Debug, Default)]
297struct CreateParamAllocations {
298 snapshot_blob_data: Option<StartupData>,
300 snapshot_blob_header: Option<Box<RawStartupData>>,
304 external_references: Option<Cow<'static, [ExternalReference]>>,
305}
306
307#[test]
308fn create_param_defaults() {
309 let params = CreateParams::default();
310 assert!(params.raw.allow_atomics_wait);
311}
312
313pub(crate) mod raw {
314 use super::*;
315
316 #[repr(C)]
317 #[derive(Debug)]
318 pub(crate) struct CreateParams {
319 pub code_event_handler: *const Opaque, pub constraints: ResourceConstraints,
321 pub snapshot_blob: *const RawStartupData,
322 pub counter_lookup_callback: Option<CounterLookupCallback>,
323 pub create_histogram_callback: *const Opaque, pub add_histogram_sample_callback: *const Opaque, pub array_buffer_allocator: *mut ArrayBufferAllocator,
326 pub array_buffer_allocator_shared: SharedPtr<ArrayBufferAllocator>,
327 pub external_references: *const intptr_t,
328 pub allow_atomics_wait: bool,
329 _fatal_error_handler: *const Opaque, _oom_error_handler: *const Opaque, pub cpp_heap: *const Heap,
332 }
333
334 unsafe extern "C" {
335 fn v8__Isolate__CreateParams__CONSTRUCT(
336 buf: *mut MaybeUninit<CreateParams>,
337 );
338 fn v8__Isolate__CreateParams__SIZEOF() -> usize;
339 }
340
341 impl Default for CreateParams {
342 fn default() -> Self {
343 let size = unsafe { v8__Isolate__CreateParams__SIZEOF() };
344 assert_eq!(size, size_of::<Self>());
345 let mut buf = MaybeUninit::<Self>::uninit();
346 unsafe { v8__Isolate__CreateParams__CONSTRUCT(&mut buf) };
347 unsafe { buf.assume_init() }
348 }
349 }
350
351 #[repr(C)]
352 #[derive(Debug)]
353 pub(crate) struct ResourceConstraints {
354 code_range_size_: usize,
355 max_old_generation_size_: usize,
356 max_young_generation_size_: usize,
357 initial_old_generation_size_: usize,
358 initial_young_generation_size_: usize,
359 physical_memory_size_: u64,
360 stack_limit_: *mut u32,
361 }
362
363 unsafe extern "C" {
364 fn v8__ResourceConstraints__ConfigureDefaultsFromHeapSize(
365 constraints: *mut ResourceConstraints,
366 initial_heap_size_in_bytes: usize,
367 maximum_heap_size_in_bytes: usize,
368 );
369 fn v8__ResourceConstraints__ConfigureDefaults(
370 constraints: *mut ResourceConstraints,
371 physical_memory: u64,
372 virtual_memory_limit: u64,
373 );
374 fn v8__ResourceConstraints__max_old_generation_size_in_bytes(
375 constraints: *const ResourceConstraints,
376 ) -> usize;
377 fn v8__ResourceConstraints__set_max_old_generation_size_in_bytes(
378 constraints: *mut ResourceConstraints,
379 limit: usize,
380 );
381 fn v8__ResourceConstraints__max_young_generation_size_in_bytes(
382 constraints: *const ResourceConstraints,
383 ) -> usize;
384 fn v8__ResourceConstraints__set_max_young_generation_size_in_bytes(
385 constraints: *mut ResourceConstraints,
386 limit: usize,
387 );
388 fn v8__ResourceConstraints__code_range_size_in_bytes(
389 constraints: *const ResourceConstraints,
390 ) -> usize;
391 fn v8__ResourceConstraints__set_code_range_size_in_bytes(
392 constraints: *mut ResourceConstraints,
393 limit: usize,
394 );
395 fn v8__ResourceConstraints__stack_limit(
396 constraints: *const ResourceConstraints,
397 ) -> *mut u32;
398 fn v8__ResourceConstraints__set_stack_limit(
399 constraints: *mut ResourceConstraints,
400 value: *mut u32,
401 );
402 fn v8__ResourceConstraints__initial_old_generation_size_in_bytes(
403 constraints: *const ResourceConstraints,
404 ) -> usize;
405 fn v8__ResourceConstraints__set_initial_old_generation_size_in_bytes(
406 constraints: *mut ResourceConstraints,
407 initial_size: usize,
408 );
409 fn v8__ResourceConstraints__initial_young_generation_size_in_bytes(
410 constraints: *const ResourceConstraints,
411 ) -> usize;
412 fn v8__ResourceConstraints__set_initial_young_generation_size_in_bytes(
413 constraints: *mut ResourceConstraints,
414 initial_size: usize,
415 );
416 }
417
418 impl ResourceConstraints {
419 pub fn configure_defaults_from_heap_size(
420 &mut self,
421 initial_heap_size_in_bytes: usize,
422 maximum_heap_size_in_bytes: usize,
423 ) {
424 unsafe {
425 v8__ResourceConstraints__ConfigureDefaultsFromHeapSize(
426 self,
427 initial_heap_size_in_bytes,
428 maximum_heap_size_in_bytes,
429 );
430 };
431 }
432
433 pub fn configure_defaults(
434 &mut self,
435 physical_memory: u64,
436 virtual_memory_limit: u64,
437 ) {
438 unsafe {
439 v8__ResourceConstraints__ConfigureDefaults(
440 self,
441 physical_memory,
442 virtual_memory_limit,
443 );
444 }
445 }
446
447 pub fn max_old_generation_size_in_bytes(&self) -> usize {
448 unsafe { v8__ResourceConstraints__max_old_generation_size_in_bytes(self) }
449 }
450
451 pub fn set_max_old_generation_size_in_bytes(&mut self, limit: usize) {
452 unsafe {
453 v8__ResourceConstraints__set_max_old_generation_size_in_bytes(
454 self, limit,
455 );
456 }
457 }
458
459 pub fn max_young_generation_size_in_bytes(&self) -> usize {
460 unsafe {
461 v8__ResourceConstraints__max_young_generation_size_in_bytes(self)
462 }
463 }
464
465 pub fn set_max_young_generation_size_in_bytes(&mut self, limit: usize) {
466 unsafe {
467 v8__ResourceConstraints__set_max_young_generation_size_in_bytes(
468 self, limit,
469 );
470 }
471 }
472
473 pub fn code_range_size_in_bytes(&self) -> usize {
474 unsafe { v8__ResourceConstraints__code_range_size_in_bytes(self) }
475 }
476
477 pub fn set_code_range_size_in_bytes(&mut self, limit: usize) {
478 unsafe {
479 v8__ResourceConstraints__set_code_range_size_in_bytes(self, limit);
480 }
481 }
482
483 pub fn stack_limit(&self) -> *mut u32 {
484 unsafe { v8__ResourceConstraints__stack_limit(self) }
485 }
486
487 pub fn set_stack_limit(&mut self, value: *mut u32) {
488 unsafe {
489 v8__ResourceConstraints__set_stack_limit(self, value);
490 }
491 }
492
493 pub fn initial_old_generation_size_in_bytes(&self) -> usize {
494 unsafe {
495 v8__ResourceConstraints__initial_old_generation_size_in_bytes(self)
496 }
497 }
498
499 pub fn set_initial_old_generation_size_in_bytes(
500 &mut self,
501 initial_size: usize,
502 ) {
503 unsafe {
504 v8__ResourceConstraints__set_initial_old_generation_size_in_bytes(
505 self,
506 initial_size,
507 );
508 }
509 }
510
511 pub fn initial_young_generation_size_in_bytes(&self) -> usize {
512 unsafe {
513 v8__ResourceConstraints__initial_young_generation_size_in_bytes(self)
514 }
515 }
516
517 pub fn set_initial_young_generation_size_in_bytes(
518 &mut self,
519 initial_size: usize,
520 ) {
521 unsafe {
522 v8__ResourceConstraints__set_initial_young_generation_size_in_bytes(
523 self,
524 initial_size,
525 );
526 }
527 }
528 }
529}