Skip to content

Commit 10f08e0

Browse files
committed
leaked pystr and doc memory usage optimization
1 parent 04b4cce commit 10f08e0

File tree

5 files changed

+36
-23
lines changed

5 files changed

+36
-23
lines changed

vm/src/builtins/str.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1802,6 +1802,30 @@ impl PyStrInterned {
18021802
pub fn to_exact(&'static self) -> PyRefExact<PyStr> {
18031803
unsafe { PyRefExact::new_unchecked(self.to_owned()) }
18041804
}
1805+
1806+
pub(crate) fn new_static_str(s: &'static str, ctx: &Context) -> &'static PyStrInterned {
1807+
if let Some(interned) = ctx.interned_str(s) {
1808+
return interned;
1809+
}
1810+
struct PyStrView {
1811+
_bytes: &'static [u8],
1812+
_kind: PyStrKindData,
1813+
_hash: PyAtomic<hash::PyHash>,
1814+
}
1815+
let kind = PyStrKind::of_str(s);
1816+
let fake_payload = PyStrView {
1817+
_bytes: s.as_bytes(),
1818+
_kind: kind.new_data(),
1819+
_hash: Radium::new(hash::SENTINEL),
1820+
};
1821+
let payload: PyStr = unsafe {
1822+
// Safety:
1823+
// the layout of Box<[u8]> == &<[u8]>
1824+
// and Box::drop will never be called by leaking
1825+
std::mem::transmute(fake_payload)
1826+
};
1827+
ctx.intern_str(payload.into_exact_ref(ctx))
1828+
}
18051829
}
18061830

18071831
impl std::fmt::Display for PyStrInterned {

vm/src/builtins/super.rs

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -257,22 +257,4 @@ fn supercheck(ty: PyTypeRef, obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<
257257
pub fn init(context: &Context) {
258258
let super_type = &context.types.super_type;
259259
PySuper::extend_class(context, super_type);
260-
261-
let super_doc = "super() -> same as super(__class__, <first argument>)\n\
262-
super(type) -> unbound super object\n\
263-
super(type, obj) -> bound super object; requires isinstance(obj, type)\n\
264-
super(type, type2) -> bound super object; requires issubclass(type2, type)\n\
265-
Typical use to call a cooperative superclass method:\n\
266-
class C(B):\n \
267-
def meth(self, arg):\n \
268-
super().meth(arg)\n\
269-
This works for class methods too:\n\
270-
class C(B):\n \
271-
@classmethod\n \
272-
def cmeth(cls, arg):\n \
273-
super().cmeth(arg)\n";
274-
275-
extend_class!(context, super_type, {
276-
"__doc__" => context.new_str(super_doc),
277-
});
278260
}

vm/src/class.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ pub trait PyClassImpl: PyClassDef {
7676
assert!(class.slots.flags.is_created_with_flags());
7777
}
7878

79-
let _ = ctx.intern_str(Self::NAME); // intern type name
79+
let _ = ctx.intern_static_str(Self::NAME); // intern type name
8080

8181
if Self::TP_FLAGS.has_feature(PyTypeFlags::HAS_DICT) {
8282
let __dict__ = identifier!(ctx, __dict__);
@@ -93,12 +93,15 @@ pub trait PyClassImpl: PyClassDef {
9393
}
9494
Self::impl_extend_class(ctx, class);
9595
if let Some(doc) = Self::DOC {
96-
class.set_attr(identifier!(ctx, __doc__), ctx.new_str(doc).into());
96+
class.set_attr(
97+
identifier!(ctx, __doc__),
98+
ctx.intern_static_str(doc).to_owned().into(),
99+
);
97100
}
98101
if let Some(module_name) = Self::MODULE_NAME {
99102
class.set_attr(
100103
identifier!(ctx, __module__),
101-
ctx.new_str(module_name).into(),
104+
ctx.intern_static_str(module_name).to_owned().into(),
102105
);
103106
}
104107

vm/src/stdlib/sys.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::{builtins::PyModule, convert::ToPyObject, Py, PyResult, VirtualMachine};
1+
use crate::{builtins::PyModule, convert::IntoObject, Py, PyResult, VirtualMachine};
22

33
pub(crate) use sys::{UnraisableHookArgs, __module_def, DOC, MAXSIZE, MULTIARCH};
44

@@ -927,7 +927,7 @@ pub(crate) fn init_module(vm: &VirtualMachine, module: &Py<PyModule>, builtins:
927927
.set_item("builtins", builtins.to_owned().into(), vm)
928928
.unwrap();
929929
extend_module!(vm, module, {
930-
"__doc__" => sys::DOC.to_owned().to_pyobject(vm),
930+
"__doc__" => vm.ctx.intern_static_str(sys::DOC.unwrap()).to_owned().into_object(),
931931
"modules" => modules,
932932
});
933933
}

vm/src/vm/context.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,10 @@ impl Context {
323323
unsafe { self.string_pool.intern(s, self.types.str_type.to_owned()) }
324324
}
325325

326+
pub(crate) fn intern_static_str(&self, s: &'static str) -> &'static PyStrInterned {
327+
PyStrInterned::new_static_str(s, self)
328+
}
329+
326330
pub fn interned_str<S: MaybeInternedString + ?Sized>(
327331
&self,
328332
s: &S,

0 commit comments

Comments
 (0)