rusty_v8/
isolate_create_params.rs1use crate::array_buffer;
2use crate::array_buffer::Allocator as ArrayBufferAllocator;
3use crate::support::char;
4use crate::support::int;
5use crate::support::intptr_t;
6use crate::support::Allocated;
7use crate::support::Allocation;
8use crate::support::Opaque;
9use crate::support::SharedPtr;
10
11use std::any::Any;
12use std::convert::TryFrom;
13use std::iter::once;
14use std::mem::size_of;
15use std::mem::MaybeUninit;
16use std::os::raw::c_char;
17use std::ptr::null;
18
19pub type CounterLookupCallback = extern "C" fn(name: *const c_char) -> *mut i32;
22
23#[must_use]
25#[derive(Debug, Default)]
26pub struct CreateParams {
27 raw: raw::CreateParams,
28 allocations: CreateParamAllocations,
29}
30
31impl CreateParams {
32 pub fn counter_lookup_callback(
35 mut self,
36 callback: CounterLookupCallback,
37 ) -> Self {
38 self.raw.counter_lookup_callback = Some(callback);
39 self
40 }
41
42 pub fn snapshot_blob(mut self, data: impl Allocated<[u8]>) -> Self {
44 let data = Allocation::of(data);
45 let header = Allocation::of(raw::StartupData::boxed_header(&data));
46 self.raw.snapshot_blob = &*header;
47 self.allocations.snapshot_blob_data = Some(data);
48 self.allocations.snapshot_blob_header = Some(header);
49 self
50 }
51
52 pub fn array_buffer_allocator(
55 mut self,
56 array_buffer_allocator: impl Into<SharedPtr<ArrayBufferAllocator>>,
57 ) -> Self {
58 self.raw.array_buffer_allocator_shared = array_buffer_allocator.into();
59 self
60 }
61
62 pub fn external_references(
67 mut self,
68 ext_refs: impl Allocated<[intptr_t]>,
69 ) -> Self {
70 let last_non_null = ext_refs
71 .iter()
72 .cloned()
73 .enumerate()
74 .rev()
75 .find_map(|(idx, value)| if value != 0 { Some(idx) } else { None });
76 let first_null = ext_refs
77 .iter()
78 .cloned()
79 .enumerate()
80 .find_map(|(idx, value)| if value == 0 { Some(idx) } else { None });
81 match (last_non_null, first_null) {
82 (None, _) => {
83 self.raw.external_references = null();
85 self.allocations.external_references = None;
86 }
87 (_, None) => {
88 let ext_refs =
90 ext_refs.iter().cloned().chain(once(0)).collect::<Vec<_>>();
91 let ext_refs = Allocation::of(ext_refs);
92 self.raw.external_references = &ext_refs[0];
93 self.allocations.external_references = Some(ext_refs);
94 }
95 (Some(idx1), Some(idx2)) if idx1 + 1 == idx2 => {
96 let ext_refs = Allocation::of(ext_refs);
98 self.raw.external_references = &ext_refs[0];
99 self.allocations.external_references = Some(ext_refs);
100 }
101 _ => panic!("unexpected null pointer in external references list"),
102 }
103 self
104 }
105
106 pub fn allow_atomics_wait(mut self, value: bool) -> Self {
109 self.raw.allow_atomics_wait = value;
110 self
111 }
112
113 pub fn only_terminate_in_safe_scope(mut self, value: bool) -> Self {
115 self.raw.only_terminate_in_safe_scope = value;
116 self
117 }
118
119 pub fn embedder_wrapper_type_info_offsets(
123 mut self,
124 embedder_wrapper_type_index: int,
125 embedder_wrapper_object_index: int,
126 ) -> Self {
127 self.raw.embedder_wrapper_type_index = embedder_wrapper_type_index;
128 self.raw.embedder_wrapper_object_index = embedder_wrapper_object_index;
129 self
130 }
131
132 pub fn heap_limits(mut self, initial: usize, max: usize) -> Self {
154 self
155 .raw
156 .constraints
157 .configure_defaults_from_heap_size(initial, max);
158 self
159 }
160
161 pub(crate) fn finalize(mut self) -> (raw::CreateParams, Box<dyn Any>) {
162 if self.raw.array_buffer_allocator_shared.is_null() {
163 self = self.array_buffer_allocator(array_buffer::new_default_allocator());
164 }
165 let Self { raw, allocations } = self;
166 (raw, Box::new(allocations))
167 }
168}
169
170#[derive(Debug, Default)]
171struct CreateParamAllocations {
172 snapshot_blob_data: Option<Allocation<[u8]>>,
174 snapshot_blob_header: Option<Allocation<raw::StartupData>>,
178 external_references: Option<Allocation<[intptr_t]>>,
179}
180
181#[test]
182fn create_param_defaults() {
183 let params = CreateParams::default();
184 assert_eq!(params.raw.embedder_wrapper_type_index, -1);
185 assert_eq!(params.raw.embedder_wrapper_object_index, -1);
186 assert!(!params.raw.only_terminate_in_safe_scope);
187 assert!(params.raw.allow_atomics_wait);
188}
189
190pub(crate) mod raw {
191 use super::*;
192
193 #[repr(C)]
194 #[derive(Debug)]
195 pub(crate) struct CreateParams {
196 pub code_event_handler: *const Opaque, pub constraints: ResourceConstraints,
198 pub snapshot_blob: *const StartupData,
199 pub counter_lookup_callback: Option<CounterLookupCallback>,
200 pub create_histogram_callback: *const Opaque, pub add_histogram_sample_callback: *const Opaque, pub array_buffer_allocator: *mut ArrayBufferAllocator,
203 pub array_buffer_allocator_shared: SharedPtr<ArrayBufferAllocator>,
204 pub external_references: *const intptr_t,
205 pub allow_atomics_wait: bool,
206 pub only_terminate_in_safe_scope: bool,
207 pub embedder_wrapper_type_index: int,
208 pub embedder_wrapper_object_index: int,
209 pub supported_import_assertions: [usize; 8],
213 }
214
215 extern "C" {
216 fn v8__Isolate__CreateParams__CONSTRUCT(
217 buf: *mut MaybeUninit<CreateParams>,
218 );
219 fn v8__Isolate__CreateParams__SIZEOF() -> usize;
220 }
221
222 impl Default for CreateParams {
223 fn default() -> Self {
224 let size = unsafe { v8__Isolate__CreateParams__SIZEOF() };
225 assert!(size <= size_of::<Self>());
226 let mut buf = MaybeUninit::<Self>::uninit();
227 unsafe { v8__Isolate__CreateParams__CONSTRUCT(&mut buf) };
228 unsafe { buf.assume_init() }
229 }
230 }
231
232 #[repr(C)]
233 #[derive(Debug)]
234 pub(crate) struct StartupData {
235 pub data: *const char,
236 pub raw_size: int,
237 }
238
239 impl StartupData {
240 pub(super) fn boxed_header(data: &Allocation<[u8]>) -> Box<Self> {
241 Box::new(Self {
242 data: &data[0] as *const _ as *const char,
243 raw_size: int::try_from(data.len()).unwrap(),
244 })
245 }
246 }
247
248 #[repr(C)]
249 #[derive(Debug)]
250 pub(crate) struct ResourceConstraints {
251 code_range_size_: usize,
252 max_old_generation_size_: usize,
253 max_young_generation_size_: usize,
254 initial_old_generation_size_: usize,
255 initial_young_generation_size_: usize,
256 stack_limit_: *mut u32,
257 }
258
259 extern "C" {
260 fn v8__ResourceConstraints__ConfigureDefaultsFromHeapSize(
261 constraints: *mut ResourceConstraints,
262 initial_heap_size_in_bytes: usize,
263 maximum_heap_size_in_bytes: usize,
264 );
265 }
266
267 impl ResourceConstraints {
268 pub fn configure_defaults_from_heap_size(
269 &mut self,
270 initial_heap_size_in_bytes: usize,
271 maximum_heap_size_in_bytes: usize,
272 ) {
273 unsafe {
274 v8__ResourceConstraints__ConfigureDefaultsFromHeapSize(
275 self,
276 initial_heap_size_in_bytes,
277 maximum_heap_size_in_bytes,
278 )
279 };
280 }
281 }
282}