1use js::jsapi::JSObject;
6use script_bindings::proxyhandler;
7use servo_config::pref;
8
9use crate::dom::bindings::codegen::RegisterBindings;
10use crate::dom::bindings::conversions::is_dom_proxy;
11use crate::dom::bindings::utils::is_platform_object_static;
12use crate::engine::handle::JSEngineSetup;
13
14#[cfg(target_os = "linux")]
15#[expect(unsafe_code)]
16fn perform_platform_specific_initialization() {
17 const MAX_FILE_LIMIT: libc::rlim_t = 4096;
19
20 unsafe {
23 let mut rlim = libc::rlimit {
24 rlim_cur: 0,
25 rlim_max: 0,
26 };
27 match libc::getrlimit(libc::RLIMIT_NOFILE, &mut rlim) {
28 0 => {
29 if rlim.rlim_cur >= MAX_FILE_LIMIT {
30 return;
32 }
33
34 rlim.rlim_cur = match rlim.rlim_max {
35 libc::RLIM_INFINITY => MAX_FILE_LIMIT,
36 _ => {
37 if rlim.rlim_max < MAX_FILE_LIMIT {
38 rlim.rlim_max
39 } else {
40 MAX_FILE_LIMIT
41 }
42 },
43 };
44 match libc::setrlimit(libc::RLIMIT_NOFILE, &rlim) {
45 0 => (),
46 _ => warn!("Failed to set file count limit"),
47 };
48 },
49 _ => warn!("Failed to get file count limit"),
50 };
51 }
52}
53
54#[cfg(not(target_os = "linux"))]
55fn perform_platform_specific_initialization() {}
56
57#[expect(unsafe_code)]
58unsafe extern "C" fn is_dom_object(obj: *mut JSObject) -> bool {
59 !obj.is_null() && (is_platform_object_static(obj) || unsafe { is_dom_proxy(obj) })
60}
61
62#[cfg(target_env = "ohos")]
70#[expect(unsafe_code)]
71fn jit_forbidden() -> bool {
72 debug!("Testing if JIT is allowed.");
73
74 fn mem_is_writable(ptr: *mut core::ffi::c_void) -> std::io::Result<bool> {
75 debug!("Testing if ptr {ptr:?} is writable");
76 #[expect(unsafe_code)]
81 unsafe {
82 let fd = libc::open(c"/dev/zero".as_ptr(), libc::O_RDONLY);
83 if fd < 0 {
84 return Err(std::io::Error::last_os_error());
85 }
86 let writable = libc::read(fd, ptr, 1) > 0;
87 if !writable {
88 debug!(
89 "addr is not writable. Error: {}",
90 std::io::Error::last_os_error()
91 );
92 }
93 libc::close(fd);
94 Ok(writable)
95 }
96 }
97
98 let map_size: libc::size_t = unsafe { libc::sysconf(libc::_SC_PAGESIZE) as libc::size_t };
100 let flags = libc::MAP_NORESERVE | libc::MAP_PRIVATE | libc::MAP_ANON;
101 let first_mmap = unsafe {
104 libc::mmap(
105 core::ptr::null_mut(),
106 map_size,
107 libc::PROT_NONE,
108 flags,
109 -1,
110 0,
111 )
112 };
113 assert_ne!(first_mmap, libc::MAP_FAILED, "mmap not allowed?");
114
115 let remap_flags =
116 libc::MAP_ANONYMOUS | libc::MAP_FIXED | libc::MAP_PRIVATE | libc::MAP_EXECUTABLE;
117 let second_mmap = unsafe {
119 libc::mmap(
120 first_mmap,
121 map_size,
122 libc::PROT_READ | libc::PROT_EXEC,
123 remap_flags,
124 -1,
125 0,
126 )
127 };
128 let mut jit_forbidden = second_mmap == libc::MAP_FAILED;
129 if !jit_forbidden {
130 let res =
134 unsafe { libc::mprotect(first_mmap, map_size, libc::PROT_READ | libc::PROT_WRITE) };
135 if res != 0 {
136 jit_forbidden = true;
138 } else {
139 let is_writable = mem_is_writable(first_mmap)
143 .inspect_err(|_e| {
144 debug!("Failed to determine if JIT is allowed. Conservatively assuming it is forbidden.");
145 })
146 .unwrap_or(false); jit_forbidden = !is_writable;
148 }
149 }
150 let _ = unsafe { libc::munmap(first_mmap, map_size) };
154
155 jit_forbidden
156}
157
158#[cfg(not(target_env = "ohos"))]
159fn jit_forbidden() -> bool {
160 false
161}
162
163#[expect(unsafe_code)]
164#[servo_tracing::instrument(name = "script::init")]
165pub fn init() -> JSEngineSetup {
166 if pref!(js_disable_jit) || jit_forbidden() {
167 let reason = if pref!(js_disable_jit) {
168 "preference `js_disable_jit` is set to true"
169 } else {
170 "runtime test determined JIT is forbidden on this system"
171 };
172 warn!("Disabling JIT for Javascript, since {reason}. This may cause subpar performance");
173 unsafe {
175 js::jsapi::DisableJitBackend();
176 }
177 }
178 proxyhandler::init();
179
180 RegisterBindings::RegisterProxyHandlers::<crate::DomTypeHolder>();
183 RegisterBindings::InitAllStatics::<crate::DomTypeHolder>();
184
185 unsafe {
186 js::glue::InitializeMemoryReporter(Some(is_dom_object));
187 }
188
189 perform_platform_specific_initialization();
190
191 JSEngineSetup::default()
192}