Skip to content

Commit 944a88a

Browse files
authored
refactor: optimizing extends and implements (#193)
1 parent 58fef19 commit 944a88a

File tree

1 file changed

+55
-40
lines changed

1 file changed

+55
-40
lines changed

phper/src/classes.rs

Lines changed: 55 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,7 @@ use std::{
3030
marker::PhantomData,
3131
mem::{ManuallyDrop, replace, size_of, transmute, zeroed},
3232
os::raw::c_int,
33-
ptr,
34-
ptr::null_mut,
33+
ptr::{self, null, null_mut},
3534
rc::Rc,
3635
slice,
3736
};
@@ -233,6 +232,12 @@ fn find_global_class_entry_ptr(name: impl AsRef<str>) -> *mut zend_class_entry {
233232
}
234233
}
235234

235+
#[derive(Clone)]
236+
enum InnerClassEntry {
237+
Ptr(*const zend_class_entry),
238+
Name(String),
239+
}
240+
236241
/// The [StateClass] holds [zend_class_entry] and inner state, created by
237242
/// [Module::add_class](crate::modules::Module::add_class) or
238243
/// [ClassEntity::bound_class].
@@ -273,45 +278,55 @@ fn find_global_class_entry_ptr(name: impl AsRef<str>) -> *mut zend_class_entry {
273278
/// module
274279
/// }
275280
/// ```
276-
pub struct StateClass<T> {
277-
inner: Rc<RefCell<*mut zend_class_entry>>,
278-
name: Option<String>,
281+
pub struct StateClass<T: ?Sized> {
282+
inner: Rc<RefCell<InnerClassEntry>>,
279283
_p: PhantomData<T>,
280284
}
281285

282-
impl StateClass<()> {
286+
impl StateClass<[()]> {
283287
/// Create from name, which will be looked up from globals.
284288
pub fn from_name(name: impl Into<String>) -> Self {
285289
Self {
286-
inner: Rc::new(RefCell::new(null_mut())),
287-
name: Some(name.into()),
290+
inner: Rc::new(RefCell::new(InnerClassEntry::Name(name.into()))),
288291
_p: PhantomData,
289292
}
290293
}
291294
}
292295

293-
impl<T> StateClass<T> {
296+
impl<T: ?Sized> StateClass<T> {
294297
fn null() -> Self {
295298
Self {
296-
inner: Rc::new(RefCell::new(null_mut())),
297-
name: None,
299+
inner: Rc::new(RefCell::new(InnerClassEntry::Ptr(null()))),
298300
_p: PhantomData,
299301
}
300302
}
301303

302304
fn bind(&self, ptr: *mut zend_class_entry) {
303-
*self.inner.borrow_mut() = ptr;
305+
match &mut *self.inner.borrow_mut() {
306+
InnerClassEntry::Ptr(p) => {
307+
*p = ptr;
308+
}
309+
InnerClassEntry::Name(_) => {
310+
unreachable!("Cannot bind() an StateClass created with from_name()");
311+
}
312+
}
304313
}
305314

306315
/// Converts to class entry.
307316
pub fn as_class_entry(&self) -> &ClassEntry {
308-
if let Some(name) = &self.name {
309-
ClassEntry::from_globals(name).unwrap()
310-
} else {
311-
unsafe { ClassEntry::from_mut_ptr(*self.inner.borrow()) }
317+
let inner = self.inner.borrow().clone();
318+
match inner {
319+
InnerClassEntry::Ptr(ptr) => unsafe { ClassEntry::from_ptr(ptr) },
320+
InnerClassEntry::Name(name) => {
321+
let entry = ClassEntry::from_globals(name).unwrap();
322+
*self.inner.borrow_mut() = InnerClassEntry::Ptr(entry.as_ptr());
323+
entry
324+
}
312325
}
313326
}
327+
}
314328

329+
impl<T: 'static> StateClass<T> {
315330
/// Create the object from class and call `__construct` with arguments.
316331
///
317332
/// If the `__construct` is private, or protected and the called scope isn't
@@ -338,7 +353,6 @@ impl<T> Clone for StateClass<T> {
338353
fn clone(&self) -> Self {
339354
Self {
340355
inner: self.inner.clone(),
341-
name: self.name.clone(),
342356
_p: self._p,
343357
}
344358
}
@@ -381,39 +395,44 @@ impl<T> Clone for StateClass<T> {
381395
/// ```
382396
#[derive(Clone)]
383397
pub struct Interface {
384-
inner: Rc<RefCell<*mut zend_class_entry>>,
385-
name: Option<String>,
398+
inner: Rc<RefCell<InnerClassEntry>>,
386399
}
387400

388401
impl Interface {
389402
fn null() -> Self {
390403
Self {
391-
inner: Rc::new(RefCell::new(null_mut())),
392-
name: None,
404+
inner: Rc::new(RefCell::new(InnerClassEntry::Ptr(null()))),
393405
}
394406
}
395407

396408
/// Create a new interface from global name (eg "Stringable", "ArrayAccess")
397409
pub fn from_name(name: impl Into<String>) -> Self {
398410
Self {
399-
inner: Rc::new(RefCell::new(null_mut())),
400-
name: Some(name.into()),
411+
inner: Rc::new(RefCell::new(InnerClassEntry::Name(name.into()))),
401412
}
402413
}
403414

404415
fn bind(&self, ptr: *mut zend_class_entry) {
405-
if self.name.is_some() {
406-
panic!("Cannot bind() an Interface created with from_name()");
416+
match &mut *self.inner.borrow_mut() {
417+
InnerClassEntry::Ptr(p) => {
418+
*p = ptr;
419+
}
420+
InnerClassEntry::Name(_) => {
421+
unreachable!("Cannot bind() an Interface created with from_name()");
422+
}
407423
}
408-
*self.inner.borrow_mut() = ptr;
409424
}
410425

411426
/// Converts to class entry.
412427
pub fn as_class_entry(&self) -> &ClassEntry {
413-
if let Some(name) = &self.name {
414-
ClassEntry::from_globals(name).unwrap()
415-
} else {
416-
unsafe { ClassEntry::from_mut_ptr(*self.inner.borrow()) }
428+
let inner = self.inner.borrow().clone();
429+
match inner {
430+
InnerClassEntry::Ptr(ptr) => unsafe { ClassEntry::from_ptr(ptr) },
431+
InnerClassEntry::Name(name) => {
432+
let entry = ClassEntry::from_globals(name).unwrap();
433+
*self.inner.borrow_mut() = InnerClassEntry::Ptr(entry.as_ptr());
434+
entry
435+
}
417436
}
418437
}
419438
}
@@ -433,7 +452,7 @@ pub struct ClassEntity<T: 'static> {
433452
state_constructor: Rc<StateConstructor>,
434453
method_entities: Vec<MethodEntity>,
435454
property_entities: Vec<PropertyEntity>,
436-
parent: Option<StateClass<()>>,
455+
parent: Option<StateClass<[()]>>,
437456
interfaces: Vec<Interface>,
438457
constants: Vec<ConstantEntity>,
439458
bound_class: StateClass<T>,
@@ -588,8 +607,8 @@ impl<T: 'static> ClassEntity<T> {
588607
/// module
589608
/// }
590609
/// ```
591-
pub fn extends<S: 'static>(&mut self, parent: StateClass<S>) {
592-
self.parent = Some(unsafe { transmute::<StateClass<S>, StateClass<()>>(parent) });
610+
pub fn extends<S: ?Sized>(&mut self, parent: StateClass<S>) {
611+
self.parent = Some(unsafe { transmute::<StateClass<S>, StateClass<[()]>>(parent) });
593612
}
594613

595614
/// Register class to `implements` the interface, due to the class can
@@ -793,7 +812,7 @@ pub struct InterfaceEntity {
793812
interface_name: CString,
794813
method_entities: Vec<MethodEntity>,
795814
constants: Vec<ConstantEntity>,
796-
extends: Vec<Box<dyn Fn() -> &'static ClassEntry>>,
815+
extends: Vec<Interface>,
797816
bound_interface: Interface,
798817
}
799818

@@ -840,11 +859,7 @@ impl InterfaceEntity {
840859
/// interface.extends(Interface::from_name("Stringable"));
841860
/// ```
842861
pub fn extends(&mut self, interface: Interface) {
843-
self.extends.push(Box::new(move || {
844-
let entry: &'static ClassEntry =
845-
unsafe { std::mem::transmute(interface.as_class_entry()) };
846-
entry
847-
}));
862+
self.extends.push(interface);
848863
}
849864

850865
#[allow(clippy::useless_conversion)]
@@ -861,7 +876,7 @@ impl InterfaceEntity {
861876
self.bound_interface.bind(class_ce);
862877

863878
for interface in &self.extends {
864-
let interface_ce = interface().as_ptr();
879+
let interface_ce = interface.as_class_entry().as_ptr();
865880
zend_class_implements(class_ce, 1, interface_ce);
866881
}
867882

0 commit comments

Comments
 (0)