PyInterned

This commit is contained in:
Jeong Yunwon committed 2022-05-22 14:19:11 +09:00
1 parent 370b2b3f99
commit bbc31364bb
7 files changed
+93 -77

No files matched your search

+1 -1
View File
@@ -683,7 +683,7 @@ mod array {
fn typecode(&self, vm: &VirtualMachine) -> PyStrRef {
vm.ctx
.intern_str(self.read().typecode().to_string())
.to_str()
.to_owned()
}
#[pyproperty]
-1
View File
@@ -117,7 +117,6 @@ impl PyBool {
vm.ctx.false_str
}
.to_owned()
.into_pyref()
}
#[pymethod(magic)]
+1 -1
View File
@@ -104,7 +104,7 @@ impl ConstantBag for PyObjBag<'_> {
}
fn make_name(&self, name: &str) -> PyStrRef {
self.0.intern_str(name).to_str()
self.0.intern_str(name).to_owned()
}
}
+1 -1
View File
@@ -230,7 +230,7 @@ impl IntoPyStrRef for &str {
impl IntoPyStrRef for &'static crate::intern::PyStrInterned {
#[inline]
fn into_pystr_ref(self, _vm: &VirtualMachine) -> PyRef<PyStr> {
self.to_str()
self.to_owned()
}
}
+86 -68
View File
@@ -2,7 +2,7 @@ use crate::{
builtins::{PyStr, PyTypeRef},
common::lock::PyRwLock,
convert::ToPyObject,
AsObject, Py, PyExact, PyObject, PyObjectRef, PyRef, PyRefExact,
AsObject, Py, PyExact, PyObject, PyObjectRef, PyPayload, PyRef, PyRefExact, VirtualMachine,
};
use std::{
borrow::{Borrow, ToOwned},
@@ -113,11 +113,84 @@ impl CachedPyStrRef {
}
}
pub struct PyInterned<T>
where
T: PyPayload,
{
inner: Py<T>,
}
impl<T: PyPayload> PyInterned<T> {
#[inline]
pub fn leak(cache: PyRef<T>) -> &'static Self {
unsafe { std::mem::transmute(cache) }
}
#[inline]
fn as_ptr(&self) -> *const Py<T> {
self as *const _ as *const _
}
#[inline]
pub fn to_owned(&'static self) -> PyRef<T> {
unsafe { (*(&self as *const _ as *const PyRef<T>)).clone() }
}
#[inline]
pub fn to_object(&'static self) -> PyObjectRef {
self.to_owned().into()
}
}
impl<T: PyPayload> Borrow<PyObject> for PyInterned<T> {
#[inline(always)]
fn borrow(&self) -> &PyObject {
self.inner.borrow()
}
}
// NOTE: std::hash::Hash of Self and Self::Borrowed *must* be the same
// This is ok only because PyObject doesn't implement Hash
impl<T: PyPayload> std::hash::Hash for PyInterned<T> {
#[inline(always)]
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.get_id().hash(state)
}
}
impl<T: PyPayload> Deref for PyInterned<T> {
type Target = Py<T>;
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<T: PyPayload> PartialEq for PyInterned<T> {
#[inline(always)]
fn eq(&self, other: &Self) -> bool {
std::ptr::eq(self, other)
}
}
impl<T: PyPayload> Eq for PyInterned<T> {}
impl<T: PyPayload + std::fmt::Debug> std::fmt::Debug for PyInterned<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(&**self, f)?;
write!(f, "@{:p}", self.as_ptr())
}
}
impl<T: PyPayload> ToPyObject for &'static PyInterned<T> {
fn to_pyobject(self, _vm: &VirtualMachine) -> PyObjectRef {
self.to_owned().into()
}
}
/// The unique reference of interned PyStr
/// Always intended to be used as a static reference
pub struct PyStrInterned {
inner: Py<PyStr>,
}
pub type PyStrInterned = PyInterned<PyStr>;
impl PyStrInterned {
/// # Safety
@@ -128,70 +201,8 @@ impl PyStrInterned {
}
#[inline]
fn as_ptr(&self) -> *const Py<PyStr> {
self as *const _ as *const _
}
#[inline]
pub fn to_owned(&'static self) -> PyRefExact<PyStr> {
unsafe { (*(&self as *const _ as *const PyRefExact<PyStr>)).clone() }
}
#[inline]
pub fn to_str(&'static self) -> PyRef<PyStr> {
self.to_owned().into_pyref()
}
#[inline]
pub fn to_object(&'static self) -> PyObjectRef {
self.to_str().into()
}
}
impl Borrow<PyObject> for PyStrInterned {
#[inline(always)]
fn borrow(&self) -> &PyObject {
self.inner.borrow()
}
}
// NOTE: std::hash::Hash of Self and Self::Borrowed *must* be the same
// This is ok only because PyObject doesn't implement Hash
impl std::hash::Hash for PyStrInterned {
#[inline(always)]
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.get_id().hash(state)
}
}
impl Deref for PyStrInterned {
type Target = Py<PyStr>;
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl PartialEq for PyStrInterned {
#[inline(always)]
fn eq(&self, other: &Self) -> bool {
std::ptr::eq(self, other)
}
}
impl Eq for PyStrInterned {}
impl AsRef<str> for PyStrInterned {
#[inline(always)]
fn as_ref(&self) -> &str {
self.as_str()
}
}
impl std::fmt::Debug for PyStrInterned {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(self.as_str(), f)?;
write!(f, "@{:p}", self.as_ptr())
pub fn to_exact(&'static self) -> PyRefExact<PyStr> {
unsafe { PyRefExact::new_unchecked(self.to_owned()) }
}
}
@@ -201,6 +212,13 @@ impl std::fmt::Display for PyStrInterned {
}
}
impl AsRef<str> for PyStrInterned {
#[inline(always)]
fn as_ref(&self) -> &str {
self.as_str()
}
}
mod sealed {
use crate::{
builtins::PyStr,
+2 -2
View File
@@ -132,7 +132,7 @@ mod sys {
} else {
"unknown"
})
.to_str()
.to_owned()
}
#[pyattr]
@@ -513,7 +513,7 @@ mod sys {
#[pyfunction]
fn intern(s: PyRefExact<PyStr>, vm: &VirtualMachine) -> PyRefExact<PyStr> {
vm.ctx.intern_str(s).to_owned()
vm.ctx.intern_str(s).to_exact()
}
#[pyattr]
+2 -3
View File
@@ -80,15 +80,14 @@ impl Context {
let new_str = unsafe { string_pool.intern("__new__", types.str_type.clone()) };
let slot_new_wrapper = create_object(
PyNativeFuncDef::new(PyType::__new__.into_func(), new_str.to_owned().into_pyref())
.into_function(),
PyNativeFuncDef::new(PyType::__new__.into_func(), new_str.to_owned()).into_function(),
&types.builtin_function_or_method_type,
)
.into();
let true_str = unsafe { string_pool.intern("True", types.str_type.clone()) };
let false_str = unsafe { string_pool.intern("False", types.str_type.clone()) };
let empty_str = unsafe { string_pool.intern("", types.str_type.clone()) }.to_str();
let empty_str = unsafe { string_pool.intern("", types.str_type.clone()) }.to_owned();
let context = Context {
true_value,