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