Skip to content

Commit 70fb78d

Browse files
authored
Merge pull request RustPython#4721 from youknowone/opt-getattr
type.__name__ & getattr optimization
2 parents 906dfd3 + d41e46b commit 70fb78d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+560
-502
lines changed

Lib/test/test_socket.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1650,8 +1650,6 @@ def test_dealloc_warn(self):
16501650
f = None
16511651
support.gc_collect()
16521652

1653-
# TODO: RUSTPYTHON
1654-
@unittest.expectedFailure
16551653
def test_name_closed_socketio(self):
16561654
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
16571655
fp = sock.makefile("rb")

derive-impl/src/pymodule.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,7 @@ impl ModuleItem for ClassItem {
458458
let set_attr = match py_names.len() {
459459
0 => quote! {
460460
let _ = new_class; // suppress warning
461+
let _ = vm.ctx.intern_str(#class_name);
461462
},
462463
1 => {
463464
let py_name = &py_names[0];

src/shell/helper.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ impl<'vm> ShellHelper<'vm> {
7878
let mut current = self.globals.get_item_opt(first.as_str(), self.vm).ok()??;
7979

8080
for attr in parents {
81-
current = current.get_attr(attr.as_str(), self.vm).ok()?;
81+
let attr = self.vm.ctx.new_str(attr.as_str());
82+
current = current.get_attr(&attr, self.vm).ok()?;
8283
}
8384

8485
let current_iter = str_iter_method(current, identifier!(self.vm, __dir__)).ok()?;

stdlib/src/sqlite.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -766,7 +766,7 @@ mod _sqlite {
766766

767767
pub(super) fn setup_module(module: &PyObject, vm: &VirtualMachine) {
768768
for (name, code) in ERROR_CODES {
769-
let name = vm.ctx.new_str(*name);
769+
let name = vm.ctx.intern_str(*name);
770770
let code = vm.new_pyobj(*code);
771771
module.set_attr(name, code, vm).unwrap();
772772
}

stdlib/src/ssl.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ mod _ssl {
230230
/// SSL/TLS connection terminated abruptly.
231231
#[pyattr(name = "SSLEOFError", once)]
232232
fn ssl_eof_error(vm: &VirtualMachine) -> PyTypeRef {
233-
PyType::new_simple_ref("ssl.SSLEOFError", &ssl_error(vm), &vm.ctx).unwrap()
233+
PyType::new_simple_heap("ssl.SSLEOFError", &ssl_error(vm), &vm.ctx).unwrap()
234234
}
235235

236236
type OpensslVersionInfo = (u8, u8, u8, u8, u8);

vm/src/builtins/builtin_func.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ impl PyBuiltinMethod {
259259
vm: &VirtualMachine,
260260
) -> (Option<PyObjectRef>, (Option<PyObjectRef>, PyStrRef)) {
261261
let builtins_getattr = vm.builtins.get_attr("getattr", vm).ok();
262-
let classname = vm.builtins.get_attr(self.class.name().to_string(), vm).ok();
262+
let classname = vm.builtins.get_attr(&self.class.__name__(vm), vm).ok();
263263
(builtins_getattr, (classname, self.value.name.clone()))
264264
}
265265
}

vm/src/builtins/function.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -501,10 +501,10 @@ impl Comparable for PyBoundMethod {
501501
}
502502

503503
impl GetAttr for PyBoundMethod {
504-
fn getattro(zelf: &Py<Self>, name: PyStrRef, vm: &VirtualMachine) -> PyResult {
504+
fn getattro(zelf: &Py<Self>, name: &Py<PyStr>, vm: &VirtualMachine) -> PyResult {
505505
let class_attr = vm
506506
.ctx
507-
.interned_str(&*name)
507+
.interned_str(name)
508508
.and_then(|attr_name| zelf.get_class_attr(attr_name));
509509
if let Some(obj) = class_attr {
510510
return vm.call_if_get_descriptor(obj, zelf.to_owned().into());

vm/src/builtins/genericalias.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use once_cell::sync::Lazy;
33
use super::type_;
44
use crate::{
55
atomic_func,
6-
builtins::{PyList, PyStr, PyStrRef, PyTuple, PyTupleRef, PyType, PyTypeRef},
6+
builtins::{PyList, PyStr, PyTuple, PyTupleRef, PyType, PyTypeRef},
77
class::PyClassImpl,
88
common::hash,
99
convert::ToPyObject,
@@ -214,9 +214,9 @@ impl PyGenericAlias {
214214
}
215215
}
216216

217-
fn is_typevar(obj: &PyObjectRef, vm: &VirtualMachine) -> bool {
217+
pub(crate) fn is_typevar(obj: &PyObjectRef, vm: &VirtualMachine) -> bool {
218218
let class = obj.class();
219-
class.slot_name() == "TypeVar"
219+
"TypeVar" == &*class.slot_name()
220220
&& class
221221
.get_attr(identifier!(vm, __module__))
222222
.and_then(|o| o.downcast_ref::<PyStr>().map(|s| s.as_str() == "typing"))
@@ -390,7 +390,7 @@ impl Hashable for PyGenericAlias {
390390
}
391391

392392
impl GetAttr for PyGenericAlias {
393-
fn getattro(zelf: &Py<Self>, attr: PyStrRef, vm: &VirtualMachine) -> PyResult {
393+
fn getattro(zelf: &Py<Self>, attr: &Py<PyStr>, vm: &VirtualMachine) -> PyResult {
394394
for exc in ATTR_EXCEPTIONS.iter() {
395395
if *(*exc) == attr.to_string() {
396396
return zelf.as_object().generic_getattr(attr, vm);

vm/src/builtins/module.rs

Lines changed: 36 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
use super::pystr::IntoPyStrRef;
21
use super::{PyDictRef, PyStr, PyStrRef, PyType, PyTypeRef};
32
use crate::{
4-
builtins::PyStrInterned,
3+
builtins::{pystr::AsPyStr, PyStrInterned},
54
class::PyClassImpl,
65
convert::ToPyObject,
76
function::FuncArgs,
@@ -26,60 +25,36 @@ pub struct ModuleInitArgs {
2625
doc: Option<PyStrRef>,
2726
}
2827

29-
#[pyclass(with(GetAttr, Initializer, Representable), flags(BASETYPE, HAS_DICT))]
3028
impl PyModule {
3129
// pub(crate) fn new(d: PyDictRef) -> Self {
3230
// PyModule { dict: d.into() }
3331
// }
32+
}
3433

35-
// #[inline]
36-
// pub fn dict(&self) -> PyDictRef {
37-
// self.dict.get()
38-
// }
39-
40-
#[pyslot]
41-
fn slot_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
42-
PyModule {}.into_ref_with_type(vm, cls).map(Into::into)
43-
}
44-
45-
fn getattr_inner(zelf: &Py<Self>, name: PyStrRef, vm: &VirtualMachine) -> PyResult {
46-
if let Some(attr) = zelf
47-
.as_object()
48-
.generic_getattr_opt(name.clone(), None, vm)?
49-
{
34+
impl Py<PyModule> {
35+
fn getattr_inner(&self, name: &Py<PyStr>, vm: &VirtualMachine) -> PyResult {
36+
if let Some(attr) = self.as_object().generic_getattr_opt(name, None, vm)? {
5037
return Ok(attr);
5138
}
52-
if let Ok(getattr) = zelf.dict().get_item(identifier!(vm, __getattr__), vm) {
53-
return getattr.call((name,), vm);
39+
if let Ok(getattr) = self.dict().get_item(identifier!(vm, __getattr__), vm) {
40+
return getattr.call((name.to_owned(),), vm);
5441
}
55-
let module_name = if let Some(name) = Self::name(zelf.to_owned(), vm) {
42+
let module_name = if let Some(name) = self.name(vm) {
5643
format!(" '{name}'")
5744
} else {
5845
"".to_owned()
5946
};
6047
Err(vm.new_attribute_error(format!("module{module_name} has no attribute '{name}'")))
6148
}
6249

63-
fn name(zelf: PyRef<Self>, vm: &VirtualMachine) -> Option<PyStrRef> {
64-
let name = zelf
50+
fn name(&self, vm: &VirtualMachine) -> Option<PyStrRef> {
51+
let name = self
6552
.as_object()
66-
.generic_getattr_opt(identifier!(vm, __name__).to_owned(), None, vm)
53+
.generic_getattr_opt(identifier!(vm, __name__), None, vm)
6754
.unwrap_or_default()?;
6855
name.downcast::<PyStr>().ok()
6956
}
7057

71-
#[pymethod(magic)]
72-
fn dir(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<Vec<PyObjectRef>> {
73-
let dict = zelf
74-
.as_object()
75-
.dict()
76-
.ok_or_else(|| vm.new_value_error("module has no dict".to_owned()))?;
77-
let attrs = dict.into_iter().map(|(k, _v)| k).collect();
78-
Ok(attrs)
79-
}
80-
}
81-
82-
impl Py<PyModule> {
8358
// TODO: to be replaced by the commented-out dict method above once dictoffsets land
8459
pub fn dict(&self) -> PyDictRef {
8560
self.as_object().dict().unwrap()
@@ -104,19 +79,38 @@ impl Py<PyModule> {
10479
.expect("Failed to set __spec__ on module");
10580
}
10681

107-
pub fn get_attr(&self, attr_name: impl IntoPyStrRef, vm: &VirtualMachine) -> PyResult {
108-
PyModule::getattr_inner(self, attr_name.into_pystr_ref(vm), vm)
82+
pub fn get_attr<'a>(&self, attr_name: impl AsPyStr<'a>, vm: &VirtualMachine) -> PyResult {
83+
self.getattr_inner(attr_name.as_pystr(&vm.ctx), vm)
10984
}
110-
pub fn set_attr(
85+
86+
pub fn set_attr<'a>(
11187
&self,
112-
attr_name: impl IntoPyStrRef,
88+
attr_name: impl AsPyStr<'a>,
11389
attr_value: impl Into<PyObjectRef>,
11490
vm: &VirtualMachine,
11591
) -> PyResult<()> {
11692
self.as_object().set_attr(attr_name, attr_value, vm)
11793
}
11894
}
11995

96+
#[pyclass(with(GetAttr, Initializer, Representable), flags(BASETYPE, HAS_DICT))]
97+
impl PyModule {
98+
#[pyslot]
99+
fn slot_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
100+
PyModule {}.into_ref_with_type(vm, cls).map(Into::into)
101+
}
102+
103+
#[pymethod(magic)]
104+
fn dir(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<Vec<PyObjectRef>> {
105+
let dict = zelf
106+
.as_object()
107+
.dict()
108+
.ok_or_else(|| vm.new_value_error("module has no dict".to_owned()))?;
109+
let attrs = dict.into_iter().map(|(k, _v)| k).collect();
110+
Ok(attrs)
111+
}
112+
}
113+
120114
impl Initializer for PyModule {
121115
type Args = ModuleInitArgs;
122116

@@ -136,8 +130,8 @@ impl Initializer for PyModule {
136130
}
137131

138132
impl GetAttr for PyModule {
139-
fn getattro(zelf: &Py<Self>, name: PyStrRef, vm: &VirtualMachine) -> PyResult {
140-
Self::getattr_inner(zelf, name, vm)
133+
fn getattro(zelf: &Py<Self>, name: &Py<PyStr>, vm: &VirtualMachine) -> PyResult {
134+
zelf.getattr_inner(name, vm)
141135
}
142136
}
143137

vm/src/builtins/namespace.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ impl Initializer for PyNamespace {
5353
return Err(vm.new_type_error("no positional arguments expected".to_owned()));
5454
}
5555
for (name, value) in args.kwargs.into_iter() {
56-
zelf.as_object().set_attr(name, value, vm)?;
56+
let name = vm.ctx.new_str(name);
57+
zelf.as_object().set_attr(&name, value, vm)?;
5758
}
5859
Ok(())
5960
}
@@ -82,7 +83,7 @@ impl Representable for PyNamespace {
8283
let name = if o.class().is(vm.ctx.types.namespace_type) {
8384
"namespace".to_owned()
8485
} else {
85-
o.class().slot_name()
86+
o.class().slot_name().to_owned()
8687
};
8788

8889
let repr = if let Some(_guard) = ReprGuard::enter(vm, zelf.as_object()) {

0 commit comments

Comments
 (0)