Skip to main content

v8/
platform.rs

1use crate::Isolate;
2use crate::isolate::RealIsolate;
3use crate::support::int;
4
5use crate::support::Opaque;
6use crate::support::Shared;
7use crate::support::SharedPtrBase;
8use crate::support::SharedRef;
9use crate::support::UniquePtr;
10use crate::support::UniqueRef;
11use crate::support::long;
12
13unsafe extern "C" {
14  fn v8__Platform__NewDefaultPlatform(
15    thread_pool_size: int,
16    idle_task_support: bool,
17  ) -> *mut Platform;
18  fn v8__Platform__NewUnprotectedDefaultPlatform(
19    thread_pool_size: int,
20    idle_task_support: bool,
21  ) -> *mut Platform;
22  fn v8__Platform__NewSingleThreadedDefaultPlatform(
23    idle_task_support: bool,
24  ) -> *mut Platform;
25  fn v8__Platform__DELETE(this: *mut Platform);
26
27  fn v8__Platform__PumpMessageLoop(
28    platform: *mut Platform,
29    isolate: *mut RealIsolate,
30    wait_for_work: bool,
31  ) -> bool;
32
33  fn v8__Platform__RunIdleTasks(
34    platform: *mut Platform,
35    isolate: *mut RealIsolate,
36    idle_time_in_seconds: f64,
37  );
38
39  fn v8__Platform__NotifyIsolateShutdown(
40    platform: *mut Platform,
41    isolate: *mut RealIsolate,
42  );
43
44  fn std__shared_ptr__v8__Platform__CONVERT__std__unique_ptr(
45    unique_ptr: UniquePtr<Platform>,
46  ) -> SharedPtrBase<Platform>;
47  fn std__shared_ptr__v8__Platform__get(
48    ptr: *const SharedPtrBase<Platform>,
49  ) -> *mut Platform;
50  fn std__shared_ptr__v8__Platform__COPY(
51    ptr: *const SharedPtrBase<Platform>,
52  ) -> SharedPtrBase<Platform>;
53  fn std__shared_ptr__v8__Platform__reset(ptr: *mut SharedPtrBase<Platform>);
54  fn std__shared_ptr__v8__Platform__use_count(
55    ptr: *const SharedPtrBase<Platform>,
56  ) -> long;
57}
58
59#[repr(C)]
60#[derive(Debug)]
61pub struct Platform(Opaque);
62
63/// Returns a new instance of the default v8::Platform implementation.
64///
65/// |thread_pool_size| is the number of worker threads to allocate for
66/// background jobs. If a value of zero is passed, a suitable default
67/// based on the current number of processors online will be chosen.
68/// If |idle_task_support| is enabled then the platform will accept idle
69/// tasks (IdleTasksEnabled will return true) and will rely on the embedder
70/// calling v8::platform::RunIdleTasks to process the idle tasks.
71///
72/// The default platform for v8 may include restrictions and caveats on thread
73/// creation and initialization. This platform should only be used in cases
74/// where v8 can be reliably initialized on the application's main thread, or
75/// the parent thread to all threads in the system that will use v8.
76///
77/// One example of a restriction is the use of Memory Protection Keys (pkeys) on
78/// modern Linux systems using modern Intel/AMD processors. This particular
79/// technology requires that all threads using v8 are created as descendent
80/// threads of the thread that called `v8::Initialize`.
81#[inline(always)]
82pub fn new_default_platform(
83  thread_pool_size: u32,
84  idle_task_support: bool,
85) -> UniqueRef<Platform> {
86  Platform::new(thread_pool_size, idle_task_support)
87}
88
89/// Creates a platform that is identical to the default platform, but does not
90/// enforce thread-isolated allocations. This may reduce security in some cases,
91/// so this method should be used with caution in cases where the threading
92/// guarantees of `new_default_platform` cannot be upheld (generally for tests).
93#[inline(always)]
94pub fn new_unprotected_default_platform(
95  thread_pool_size: u32,
96  idle_task_support: bool,
97) -> UniqueRef<Platform> {
98  Platform::new_unprotected(thread_pool_size, idle_task_support)
99}
100
101/// The same as new_default_platform() but disables the worker thread pool.
102/// It must be used with the --single-threaded V8 flag.
103///
104/// If |idle_task_support| is enabled then the platform will accept idle
105/// tasks (IdleTasksEnabled will return true) and will rely on the embedder
106/// calling v8::platform::RunIdleTasks to process the idle tasks.
107#[inline(always)]
108pub fn new_single_threaded_default_platform(
109  idle_task_support: bool,
110) -> UniqueRef<Platform> {
111  Platform::new_single_threaded(idle_task_support)
112}
113
114impl Platform {
115  /// Returns a new instance of the default v8::Platform implementation.
116  ///
117  /// |thread_pool_size| is the number of worker threads to allocate for
118  /// background jobs. If a value of zero is passed, a suitable default
119  /// based on the current number of processors online will be chosen.
120  /// If |idle_task_support| is enabled then the platform will accept idle
121  /// tasks (IdleTasksEnabled will return true) and will rely on the embedder
122  /// calling v8::platform::RunIdleTasks to process the idle tasks.
123  ///
124  /// The default platform for v8 may include restrictions and caveats on thread
125  /// creation and initialization. This platform should only be used in cases
126  /// where v8 can be reliably initialized on the application's main thread, or
127  /// the parent thread to all threads in the system that will use v8.
128  ///
129  /// One example of a restriction is the use of Memory Protection Keys (pkeys)
130  /// on modern Linux systems using modern Intel/AMD processors. This particular
131  /// technology requires that all threads using v8 are created as descendent
132  /// threads of the thread that called `v8::Initialize`.
133  #[inline(always)]
134  pub fn new(
135    thread_pool_size: u32,
136    idle_task_support: bool,
137  ) -> UniqueRef<Self> {
138    unsafe {
139      UniqueRef::from_raw(v8__Platform__NewDefaultPlatform(
140        thread_pool_size.min(16) as i32,
141        idle_task_support,
142      ))
143    }
144  }
145
146  /// Creates a platform that is identical to the default platform, but does not
147  /// enforce thread-isolated allocations. This may reduce security in some
148  /// cases, so this method should be used with caution in cases where the
149  /// threading guarantees of `new_default_platform` cannot be upheld (generally
150  /// for tests).
151  #[inline(always)]
152  pub fn new_unprotected(
153    thread_pool_size: u32,
154    idle_task_support: bool,
155  ) -> UniqueRef<Self> {
156    unsafe {
157      UniqueRef::from_raw(v8__Platform__NewUnprotectedDefaultPlatform(
158        thread_pool_size.min(16) as i32,
159        idle_task_support,
160      ))
161    }
162  }
163
164  /// The same as new() but disables the worker thread pool.
165  /// It must be used with the --single-threaded V8 flag.
166  ///
167  /// If |idle_task_support| is enabled then the platform will accept idle
168  /// tasks (IdleTasksEnabled will return true) and will rely on the embedder
169  /// calling v8::platform::RunIdleTasks to process the idle tasks.
170  #[inline(always)]
171  pub fn new_single_threaded(idle_task_support: bool) -> UniqueRef<Self> {
172    unsafe {
173      UniqueRef::from_raw(v8__Platform__NewSingleThreadedDefaultPlatform(
174        idle_task_support,
175      ))
176    }
177  }
178}
179
180impl Platform {
181  /// Pumps the message loop for the given isolate.
182  ///
183  /// The caller has to make sure that this is called from the right thread.
184  /// Returns true if a task was executed, and false otherwise. If the call to
185  /// PumpMessageLoop is nested within another call to PumpMessageLoop, only
186  /// nestable tasks may run. Otherwise, any task may run. Unless requested through
187  /// the |wait_for_work| parameter, this call does not block if no task is pending.
188  #[inline(always)]
189  pub fn pump_message_loop(
190    platform: &SharedRef<Self>,
191    isolate: &Isolate,
192    wait_for_work: bool,
193  ) -> bool {
194    unsafe {
195      v8__Platform__PumpMessageLoop(
196        &**platform as *const Self as *mut _,
197        isolate.as_real_ptr(),
198        wait_for_work,
199      )
200    }
201  }
202
203  /// Runs pending idle tasks for at most |idle_time_in_seconds| seconds.
204  ///
205  /// The caller has to make sure that this is called from the right thread.
206  /// This call does not block if no task is pending.
207  #[inline(always)]
208  pub fn run_idle_tasks(
209    platform: &SharedRef<Self>,
210    isolate: &Isolate,
211    idle_time_in_seconds: f64,
212  ) {
213    unsafe {
214      v8__Platform__RunIdleTasks(
215        &**platform as *const Self as *mut _,
216        isolate.as_real_ptr(),
217        idle_time_in_seconds,
218      );
219    }
220  }
221
222  /// Notifies the given platform about the Isolate getting deleted soon. Has to
223  /// be called for all Isolates which are deleted - unless we're shutting down
224  /// the platform.
225  ///
226  /// The |platform| has to be created using |NewDefaultPlatform|.
227  #[inline(always)]
228  pub(crate) unsafe fn notify_isolate_shutdown(
229    platform: &SharedRef<Self>,
230    isolate: &Isolate,
231  ) {
232    unsafe {
233      v8__Platform__NotifyIsolateShutdown(
234        &**platform as *const Self as *mut _,
235        isolate.as_real_ptr(),
236      );
237    }
238  }
239}
240
241impl Shared for Platform {
242  fn from_unique_ptr(unique_ptr: UniquePtr<Self>) -> SharedPtrBase<Self> {
243    unsafe {
244      std__shared_ptr__v8__Platform__CONVERT__std__unique_ptr(unique_ptr)
245    }
246  }
247  fn get(ptr: &SharedPtrBase<Self>) -> *const Self {
248    unsafe { std__shared_ptr__v8__Platform__get(ptr) }
249  }
250  fn clone(ptr: &SharedPtrBase<Self>) -> SharedPtrBase<Self> {
251    unsafe { std__shared_ptr__v8__Platform__COPY(ptr) }
252  }
253  fn reset(ptr: &mut SharedPtrBase<Self>) {
254    unsafe { std__shared_ptr__v8__Platform__reset(ptr) }
255  }
256  fn use_count(ptr: &SharedPtrBase<Self>) -> long {
257    unsafe { std__shared_ptr__v8__Platform__use_count(ptr) }
258  }
259}
260
261impl Drop for Platform {
262  fn drop(&mut self) {
263    unsafe { v8__Platform__DELETE(self) };
264  }
265}