Skip to content

Commit 3e12201

Browse files
committed
feat(globals): add CompilerGlobals
1 parent 96555c4 commit 3e12201

File tree

4 files changed

+106
-4
lines changed

4 files changed

+106
-4
lines changed

allowed_bindings.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ bind! {
2626
_efree,
2727
_emalloc,
2828
_zend_executor_globals,
29+
_zend_compiler_globals,
2930
_sapi_globals_struct,
3031
_sapi_module_struct,
3132
_zend_expected_type,
@@ -41,6 +42,7 @@ bind! {
4142
_zval_struct__bindgen_ty_2,
4243
_zend_known_string_id,
4344
// ext_php_rs_executor_globals,
45+
// ext_php_rs_compiler_globals,
4446
// ext_php_rs_php_build_id,
4547
// ext_php_rs_zend_object_alloc,
4648
// ext_php_rs_zend_object_release,
@@ -252,6 +254,7 @@ bind! {
252254
zend_class_serialize_deny,
253255
zend_class_unserialize_deny,
254256
zend_executor_globals,
257+
zend_compiler_globals,
255258
sapi_module_struct,
256259
zend_objects_store_del,
257260
zend_hash_move_forward_ex,
@@ -263,6 +266,7 @@ bind! {
263266
gc_possible_root,
264267
ZEND_ACC_NOT_SERIALIZABLE,
265268
executor_globals,
269+
compiler_globals,
266270
php_core_globals,
267271
core_globals,
268272
sapi_globals_struct,
@@ -272,6 +276,7 @@ bind! {
272276
__zend_malloc,
273277
tsrm_get_ls_cache,
274278
executor_globals_offset,
279+
compiler_globals_offset,
275280
core_globals_offset,
276281
sapi_globals_offset,
277282
php_file_globals,

src/ffi.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ extern "C" {
2626
pub fn ext_php_rs_zend_object_alloc(obj_size: usize, ce: *mut zend_class_entry) -> *mut c_void;
2727
pub fn ext_php_rs_zend_object_release(obj: *mut zend_object);
2828
pub fn ext_php_rs_executor_globals() -> *mut zend_executor_globals;
29+
pub fn ext_php_rs_compiler_globals() -> *mut zend_compiler_globals;
2930
pub fn ext_php_rs_process_globals() -> *mut php_core_globals;
3031
pub fn ext_php_rs_sapi_globals() -> *mut sapi_globals_struct;
3132
pub fn ext_php_rs_file_globals() -> *mut php_file_globals;

src/wrapper.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,18 @@ zend_executor_globals *ext_php_rs_executor_globals() {
4040
#endif
4141
}
4242

43+
zend_compiler_globals *ext_php_rs_compiler_globals() {
44+
#ifdef ZTS
45+
#ifdef ZEND_ENABLE_STATIC_TSRMLS_CACHE
46+
return TSRMG_FAST_BULK_STATIC(compiler_globals_offset, zend_compiler_globals);
47+
#else
48+
return TSRMG_FAST_BULK(compiler_globals_offset, zend_compiler_globals *);
49+
#endif
50+
#else
51+
return &compiler_globals;
52+
#endif
53+
}
54+
4355
php_core_globals *ext_php_rs_process_globals() {
4456
#ifdef ZTS
4557
#ifdef ZEND_ENABLE_STATIC_TSRMLS_CACHE

src/zend/globals.rs

Lines changed: 88 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ use crate::exception::PhpResult;
1313
#[cfg(php82)]
1414
use crate::ffi::zend_atomic_bool_store;
1515
use crate::ffi::{
16-
_sapi_module_struct, _zend_executor_globals, ext_php_rs_executor_globals,
16+
_sapi_module_struct, _zend_executor_globals, _zend_compiler_globals,
17+
ext_php_rs_executor_globals, ext_php_rs_compiler_globals,
1718
ext_php_rs_file_globals, ext_php_rs_process_globals, ext_php_rs_sapi_globals,
1819
ext_php_rs_sapi_module, php_core_globals, php_file_globals, sapi_globals_struct,
1920
sapi_header_struct, sapi_headers_struct, sapi_request_info, zend_ini_entry,
@@ -35,9 +36,6 @@ use super::linked_list::ZendLinkedListIterator;
3536
/// Stores global variables used in the PHP executor.
3637
pub type ExecutorGlobals = _zend_executor_globals;
3738

38-
/// Stores the SAPI module used in the PHP executor.
39-
pub type SapiModule = _sapi_module_struct;
40-
4139
impl ExecutorGlobals {
4240
/// Returns a reference to the PHP executor globals.
4341
///
@@ -226,6 +224,69 @@ impl ExecutorGlobals {
226224
}
227225
}
228226

227+
pub type CompilerGlobals = _zend_compiler_globals;
228+
229+
impl CompilerGlobals {
230+
/// Returns a reference to the PHP compiler globals.
231+
///
232+
/// The compiler globals are guarded by a [`RwLock`]. There can be multiple
233+
/// immutable references at one time but only ever one mutable reference.
234+
/// Attempting to retrieve the globals while already holding the global
235+
/// guard will lead to a deadlock. Dropping the globals guard will release
236+
/// the lock.
237+
///
238+
/// # Panics
239+
///
240+
/// * If static executor globals are not set
241+
pub fn get() -> GlobalReadGuard<Self> {
242+
// SAFETY: PHP compiler globals are statically declared therefore should never
243+
// return an invalid pointer.
244+
let globals = unsafe { ext_php_rs_compiler_globals().as_ref() }
245+
.expect("Static compiler globals were invalid");
246+
247+
cfg_if::cfg_if! {
248+
if #[cfg(php_zts)] {
249+
let guard = lock::GLOBALS_LOCK.with(|l| l.read_arc());
250+
} else {
251+
let guard = lock::GLOBALS_LOCK.read_arc();
252+
}
253+
}
254+
255+
GlobalReadGuard { globals, guard }
256+
}
257+
258+
/// Returns a mutable reference to the PHP compiler globals.
259+
///
260+
/// The compiler globals are guarded by a [`RwLock`]. There can be multiple
261+
/// immutable references at one time but only ever one mutable reference.
262+
/// Attempting to retrieve the globals while already holding the global
263+
/// guard will lead to a deadlock. Dropping the globals guard will release
264+
/// the lock.
265+
///
266+
/// # Panics
267+
///
268+
/// * If static compiler globals are not set
269+
pub fn get_mut() -> GlobalWriteGuard<Self> {
270+
// SAFETY: PHP compiler globals are statically declared therefore should never
271+
// return an invalid pointer.
272+
let globals = unsafe { ext_php_rs_compiler_globals().as_mut() }
273+
.expect("Static compiler globals were invalid");
274+
275+
cfg_if::cfg_if! {
276+
if #[cfg(php_zts)] {
277+
let guard = lock::GLOBALS_LOCK.with(|l| l.write_arc());
278+
} else {
279+
let guard = lock::GLOBALS_LOCK.write_arc();
280+
}
281+
}
282+
283+
GlobalWriteGuard { globals, guard }
284+
}
285+
}
286+
287+
/// Stores the SAPI module used in the PHP executor.
288+
pub type SapiModule = _sapi_module_struct;
289+
229290
impl SapiModule {
230291
/// Returns a reference to the PHP SAPI module.
231292
///
@@ -835,3 +896,26 @@ impl<T> DerefMut for GlobalWriteGuard<T> {
835896
self.globals
836897
}
837898
}
899+
900+
#[cfg(test)]
901+
mod tests {
902+
use super::*;
903+
904+
#[test]
905+
fn test_executor_globals() {
906+
let state = ExecutorGlobals::get().active;
907+
ExecutorGlobals::get_mut().active = !state;
908+
let changed = ExecutorGlobals::get().active;
909+
ExecutorGlobals::get_mut().active = state;
910+
assert_eq!(changed, !state);
911+
}
912+
913+
#[test]
914+
fn test_compiler_globals() {
915+
let state = CompilerGlobals::get().in_compilation;
916+
CompilerGlobals::get_mut().in_compilation = !state;
917+
let changed = CompilerGlobals::get().in_compilation;
918+
CompilerGlobals::get_mut().in_compilation = state;
919+
assert_eq!(changed, !state);
920+
}
921+
}

0 commit comments

Comments
 (0)