vm::PyContext

This commit is contained in:
Jeong Yunwon committed 2022-04-23 07:56:20 +09:00
1 parent 1d3ec86ff6
commit 946fc93170
7 files changed
+329 -323

No files matched your search

+2 -3
View File
@@ -84,14 +84,13 @@ mod pyobject {
pub use super::_pyobjectrc::*;
}
// pub use self::Executor;
pub use self::convert::{TryFromBorrowedObject, TryFromObject};
// pyobject items
pub use self::pyobject::{AsObject, PyContext, PyMethod, PyPayload, PyRefExact, PyResult};
pub use self::pyobject::{AsObject, PyMethod, PyPayload, PyRefExact, PyResult};
// pyobjectrc items
pub use self::pyobject::{Py, PyObject, PyObjectRef, PyRef, PyWeakRef};
pub use self::types::PyStructSequence;
pub use self::vm::{InitParameter, Interpreter, PySettings, VirtualMachine};
pub use self::vm::{InitParameter, Interpreter, PyContext, PySettings, VirtualMachine};
pub use rustpython_bytecode as bytecode;
pub use rustpython_common as common;
+2 -1
View File
@@ -2,8 +2,9 @@
use crate::{
builtins::{PyBaseObject, PyBoundMethod, PyType, PyTypeRef},
pyobject::{PyContext, PyObjectPayload, PyObjectRef, PyRef},
pyobject::{PyObjectPayload, PyObjectRef, PyRef},
types::{PyTypeFlags, PyTypeSlots},
vm::PyContext,
};
use rustpython_common::{lock::PyRwLock, static_cell};
+4 -316
View File
@@ -1,27 +1,12 @@
use crate::common::lock::PyRwLockReadGuard;
use crate::{
builtins::{
builtinfunc::{PyBuiltinFunction, PyBuiltinMethod, PyNativeFuncDef},
bytes,
getset::{IntoPyGetterFunc, IntoPySetterFunc, PyGetSet},
object, pystr,
pytype::PyAttributes,
PyBaseException, PyBaseExceptionRef, PyDict, PyDictRef, PyEllipsis, PyFloat, PyFrozenSet,
PyInt, PyIntRef, PyList, PyListRef, PyNone, PyNotImplemented, PyStr, PyTuple, PyTupleRef,
PyType, PyTypeRef,
},
convert::TryFromObject,
convert::{ToPyObject, ToPyResult},
exceptions,
function::{IntoFuncArgs, IntoPyNativeFunc},
intern::{Internable, StringPool},
pyclass::{PyClassImpl, StaticType},
types::{PyTypeFlags, PyTypeSlots, TypeZoo},
builtins::{object, pystr, PyBaseExceptionRef, PyType, PyTypeRef},
convert::{ToPyObject, ToPyResult, TryFromObject},
function::IntoFuncArgs,
types::PyTypeFlags,
VirtualMachine,
_pyobjectrc::{Py, PyObject, PyObjectRef, PyRef},
};
use num_bigint::BigInt;
use num_traits::ToPrimitive;
use std::{any::Any, borrow::Borrow, fmt, ops::Deref};
/* Python objects and references.
@@ -55,303 +40,6 @@ impl fmt::Display for PyObject {
}
}
#[derive(Debug, Clone)]
pub struct PyContext {
pub true_value: PyIntRef,
pub false_value: PyIntRef,
pub none: PyRef<PyNone>,
pub empty_tuple: PyTupleRef,
pub empty_frozenset: PyRef<PyFrozenSet>,
pub ellipsis: PyRef<PyEllipsis>,
pub not_implemented: PyRef<PyNotImplemented>,
pub(crate) true_str: PyRef<PyStr>,
pub(crate) false_str: PyRef<PyStr>,
pub types: TypeZoo,
pub exceptions: exceptions::ExceptionZoo,
pub int_cache_pool: Vec<PyIntRef>,
// there should only be exact objects of str in here, no non-strs and no subclasses
pub(crate) string_pool: StringPool,
pub(super) slot_new_wrapper: PyObjectRef,
}
// Basic objects:
impl PyContext {
pub const INT_CACHE_POOL_MIN: i32 = -5;
pub const INT_CACHE_POOL_MAX: i32 = 256;
fn init() -> Self {
flame_guard!("init PyContext");
let types = TypeZoo::init();
let exceptions = exceptions::ExceptionZoo::init();
#[inline]
fn create_object<T: PyObjectPayload + PyPayload>(payload: T, cls: &PyTypeRef) -> PyRef<T> {
PyRef::new_ref(payload, cls.clone(), None)
}
let none = create_object(PyNone, PyNone::static_type());
let ellipsis = create_object(PyEllipsis, PyEllipsis::static_type());
let not_implemented = create_object(PyNotImplemented, PyNotImplemented::static_type());
let int_cache_pool = (Self::INT_CACHE_POOL_MIN..=Self::INT_CACHE_POOL_MAX)
.map(|v| PyRef::new_ref(PyInt::from(BigInt::from(v)), types.int_type.clone(), None))
.collect();
let true_value = create_object(PyInt::from(1), &types.bool_type);
let false_value = create_object(PyInt::from(0), &types.bool_type);
let empty_tuple = create_object(
PyTuple::new_unchecked(Vec::new().into_boxed_slice()),
&types.tuple_type,
);
let empty_frozenset =
PyRef::new_ref(PyFrozenSet::default(), types.frozenset_type.clone(), None);
let string_pool = StringPool::default();
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.into_pyref()).into_function(),
&types.builtin_function_or_method_type,
)
.into();
let true_str = unsafe { string_pool.intern("True", types.str_type.clone()) }.into_pyref();
let false_str = unsafe { string_pool.intern("False", types.str_type.clone()) }.into_pyref();
let context = PyContext {
true_value,
false_value,
none,
empty_tuple,
empty_frozenset,
ellipsis,
not_implemented,
true_str,
false_str,
types,
exceptions,
int_cache_pool,
string_pool,
slot_new_wrapper,
};
TypeZoo::extend(&context);
exceptions::ExceptionZoo::extend(&context);
context
}
pub fn intern_string<S: Internable>(&self, s: S) -> PyRefExact<PyStr> {
unsafe { self.string_pool.intern(s, self.types.str_type.clone()) }
}
#[inline(always)]
pub fn none(&self) -> PyObjectRef {
self.none.clone().into()
}
#[inline(always)]
pub fn ellipsis(&self) -> PyObjectRef {
self.ellipsis.clone().into()
}
#[inline(always)]
pub fn not_implemented(&self) -> PyObjectRef {
self.not_implemented.clone().into()
}
// shortcuts for common type
#[inline]
pub fn new_int<T: Into<BigInt> + ToPrimitive>(&self, i: T) -> PyIntRef {
if let Some(i) = i.to_i32() {
if i >= Self::INT_CACHE_POOL_MIN && i <= Self::INT_CACHE_POOL_MAX {
let inner_idx = (i - Self::INT_CACHE_POOL_MIN) as usize;
return self.int_cache_pool[inner_idx].clone();
}
}
PyRef::new_ref(PyInt::from(i), self.types.int_type.clone(), None)
}
#[inline]
pub fn new_bigint(&self, i: &BigInt) -> PyIntRef {
if let Some(i) = i.to_i32() {
if i >= Self::INT_CACHE_POOL_MIN && i <= Self::INT_CACHE_POOL_MAX {
let inner_idx = (i - Self::INT_CACHE_POOL_MIN) as usize;
return self.int_cache_pool[inner_idx].clone();
}
}
PyRef::new_ref(PyInt::from(i.clone()), self.types.int_type.clone(), None)
}
#[inline]
pub fn new_float(&self, value: f64) -> PyRef<PyFloat> {
PyRef::new_ref(PyFloat::from(value), self.types.float_type.clone(), None)
}
#[inline]
pub fn new_str(&self, s: impl Into<pystr::PyStr>) -> PyRef<PyStr> {
pystr::PyStr::new_ref(s, self)
}
#[inline]
pub fn new_bytes(&self, data: Vec<u8>) -> PyRef<bytes::PyBytes> {
bytes::PyBytes::new_ref(data, self)
}
#[inline(always)]
pub fn new_bool(&self, b: bool) -> PyIntRef {
let value = if b {
&self.true_value
} else {
&self.false_value
};
value.clone()
}
#[inline(always)]
pub fn new_tuple(&self, elements: Vec<PyObjectRef>) -> PyTupleRef {
PyTuple::new_ref(elements, self)
}
#[inline(always)]
pub fn new_list(&self, elements: Vec<PyObjectRef>) -> PyListRef {
PyList::new_ref(elements, self)
}
#[inline(always)]
pub fn new_dict(&self) -> PyDictRef {
PyDict::new_ref(self)
}
pub fn new_class(
&self,
module: Option<&str>,
name: &str,
base: &PyTypeRef,
slots: PyTypeSlots,
) -> PyTypeRef {
let mut attrs = PyAttributes::default();
if let Some(module) = module {
attrs.insert("__module__".to_string(), self.new_str(module).into());
};
PyType::new_ref(
name,
vec![base.clone()],
attrs,
slots,
self.types.type_type.clone(),
)
.unwrap()
}
pub fn new_exception_type(
&self,
module: &str,
name: &str,
bases: Option<Vec<PyTypeRef>>,
) -> PyTypeRef {
let bases = if let Some(bases) = bases {
bases
} else {
vec![self.exceptions.exception_type.clone()]
};
let mut attrs = PyAttributes::default();
attrs.insert("__module__".to_owned(), self.new_str(module).into());
PyType::new_ref(
name,
bases,
attrs,
PyBaseException::make_slots(),
self.types.type_type.clone(),
)
.unwrap()
}
#[inline]
pub fn make_funcdef<F, FKind>(&self, name: impl Into<PyStr>, f: F) -> PyNativeFuncDef
where
F: IntoPyNativeFunc<FKind>,
{
PyNativeFuncDef::new(f.into_func(), PyStr::new_ref(name, self))
}
// #[deprecated]
pub fn new_function<F, FKind>(&self, name: impl Into<PyStr>, f: F) -> PyRef<PyBuiltinFunction>
where
F: IntoPyNativeFunc<FKind>,
{
self.make_funcdef(name, f).build_function(self)
}
pub fn new_method<F, FKind>(
&self,
name: impl Into<PyStr>,
class: PyTypeRef,
f: F,
) -> PyRef<PyBuiltinMethod>
where
F: IntoPyNativeFunc<FKind>,
{
PyBuiltinMethod::new_ref(name, class, f, self)
}
pub fn new_readonly_getset<F, T>(
&self,
name: impl Into<String>,
class: PyTypeRef,
f: F,
) -> PyRef<PyGetSet>
where
F: IntoPyGetterFunc<T>,
{
PyRef::new_ref(
PyGetSet::new(name.into(), class).with_get(f),
self.types.getset_type.clone(),
None,
)
}
pub fn new_getset<G, S, T, U>(
&self,
name: impl Into<String>,
class: PyTypeRef,
g: G,
s: S,
) -> PyRef<PyGetSet>
where
G: IntoPyGetterFunc<T>,
S: IntoPySetterFunc<U>,
{
PyRef::new_ref(
PyGetSet::new(name.into(), class).with_get(g).with_set(s),
self.types.getset_type.clone(),
None,
)
}
pub fn new_base_object(&self, class: PyTypeRef, dict: Option<PyDictRef>) -> PyObjectRef {
debug_assert_eq!(
class.slots.flags.contains(PyTypeFlags::HAS_DICT),
dict.is_some()
);
PyRef::new_ref(object::PyBaseObject, class, dict).into()
}
}
impl Default for PyContext {
fn default() -> Self {
rustpython_common::static_cell! {
static CONTEXT: PyContext;
}
CONTEXT.get_or_init(Self::init).clone()
}
}
impl<T: fmt::Display> fmt::Display for PyRef<T>
where
T: PyObjectPayload + fmt::Display,
+1 -1
View File
@@ -1,7 +1,7 @@
use crate::{
builtins::{PyTuple, PyTupleRef, PyTypeRef},
pyclass::{PyClassImpl, StaticType},
pyobject::PyContext,
vm::PyContext,
AsObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
};
+1 -1
View File
@@ -9,7 +9,7 @@ use crate::{
zip,
},
pyclass::StaticType,
pyobject::PyContext,
vm::PyContext,
};
/// Holder of references to builtin types.
+316
View File
@@ -0,0 +1,316 @@
use crate::{
builtins::{
builtinfunc::{PyBuiltinFunction, PyBuiltinMethod, PyNativeFuncDef},
bytes,
getset::{IntoPyGetterFunc, IntoPySetterFunc, PyGetSet},
object, pystr,
pytype::PyAttributes,
PyBaseException, PyDict, PyDictRef, PyEllipsis, PyFloat, PyFrozenSet, PyInt, PyIntRef,
PyList, PyListRef, PyNone, PyNotImplemented, PyStr, PyTuple, PyTupleRef, PyType, PyTypeRef,
},
exceptions,
function::IntoPyNativeFunc,
intern::{Internable, StringPool},
pyclass::{PyClassImpl, StaticType},
pyobject::{PyObjectPayload, PyObjectRef, PyPayload, PyRef, PyRefExact},
types::{PyTypeFlags, PyTypeSlots, TypeZoo},
};
use num_bigint::BigInt;
use num_traits::ToPrimitive;
#[derive(Debug, Clone)]
pub struct PyContext {
pub true_value: PyIntRef,
pub false_value: PyIntRef,
pub none: PyRef<PyNone>,
pub empty_tuple: PyTupleRef,
pub empty_frozenset: PyRef<PyFrozenSet>,
pub ellipsis: PyRef<PyEllipsis>,
pub not_implemented: PyRef<PyNotImplemented>,
pub(crate) true_str: PyRef<PyStr>,
pub(crate) false_str: PyRef<PyStr>,
pub types: TypeZoo,
pub exceptions: exceptions::ExceptionZoo,
pub int_cache_pool: Vec<PyIntRef>,
// there should only be exact objects of str in here, no non-strs and no subclasses
pub(crate) string_pool: StringPool,
pub(crate) slot_new_wrapper: PyObjectRef,
}
// Basic objects:
impl PyContext {
pub const INT_CACHE_POOL_MIN: i32 = -5;
pub const INT_CACHE_POOL_MAX: i32 = 256;
fn init() -> Self {
flame_guard!("init PyContext");
let types = TypeZoo::init();
let exceptions = exceptions::ExceptionZoo::init();
#[inline]
fn create_object<T: PyObjectPayload + PyPayload>(payload: T, cls: &PyTypeRef) -> PyRef<T> {
PyRef::new_ref(payload, cls.clone(), None)
}
let none = create_object(PyNone, PyNone::static_type());
let ellipsis = create_object(PyEllipsis, PyEllipsis::static_type());
let not_implemented = create_object(PyNotImplemented, PyNotImplemented::static_type());
let int_cache_pool = (Self::INT_CACHE_POOL_MIN..=Self::INT_CACHE_POOL_MAX)
.map(|v| PyRef::new_ref(PyInt::from(BigInt::from(v)), types.int_type.clone(), None))
.collect();
let true_value = create_object(PyInt::from(1), &types.bool_type);
let false_value = create_object(PyInt::from(0), &types.bool_type);
let empty_tuple = create_object(
PyTuple::new_unchecked(Vec::new().into_boxed_slice()),
&types.tuple_type,
);
let empty_frozenset =
PyRef::new_ref(PyFrozenSet::default(), types.frozenset_type.clone(), None);
let string_pool = StringPool::default();
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.into_pyref()).into_function(),
&types.builtin_function_or_method_type,
)
.into();
let true_str = unsafe { string_pool.intern("True", types.str_type.clone()) }.into_pyref();
let false_str = unsafe { string_pool.intern("False", types.str_type.clone()) }.into_pyref();
let context = PyContext {
true_value,
false_value,
none,
empty_tuple,
empty_frozenset,
ellipsis,
not_implemented,
true_str,
false_str,
types,
exceptions,
int_cache_pool,
string_pool,
slot_new_wrapper,
};
TypeZoo::extend(&context);
exceptions::ExceptionZoo::extend(&context);
context
}
pub fn intern_string<S: Internable>(&self, s: S) -> PyRefExact<PyStr> {
unsafe { self.string_pool.intern(s, self.types.str_type.clone()) }
}
#[inline(always)]
pub fn none(&self) -> PyObjectRef {
self.none.clone().into()
}
#[inline(always)]
pub fn ellipsis(&self) -> PyObjectRef {
self.ellipsis.clone().into()
}
#[inline(always)]
pub fn not_implemented(&self) -> PyObjectRef {
self.not_implemented.clone().into()
}
// shortcuts for common type
#[inline]
pub fn new_int<T: Into<BigInt> + ToPrimitive>(&self, i: T) -> PyIntRef {
if let Some(i) = i.to_i32() {
if i >= Self::INT_CACHE_POOL_MIN && i <= Self::INT_CACHE_POOL_MAX {
let inner_idx = (i - Self::INT_CACHE_POOL_MIN) as usize;
return self.int_cache_pool[inner_idx].clone();
}
}
PyRef::new_ref(PyInt::from(i), self.types.int_type.clone(), None)
}
#[inline]
pub fn new_bigint(&self, i: &BigInt) -> PyIntRef {
if let Some(i) = i.to_i32() {
if i >= Self::INT_CACHE_POOL_MIN && i <= Self::INT_CACHE_POOL_MAX {
let inner_idx = (i - Self::INT_CACHE_POOL_MIN) as usize;
return self.int_cache_pool[inner_idx].clone();
}
}
PyRef::new_ref(PyInt::from(i.clone()), self.types.int_type.clone(), None)
}
#[inline]
pub fn new_float(&self, value: f64) -> PyRef<PyFloat> {
PyRef::new_ref(PyFloat::from(value), self.types.float_type.clone(), None)
}
#[inline]
pub fn new_str(&self, s: impl Into<pystr::PyStr>) -> PyRef<PyStr> {
pystr::PyStr::new_ref(s, self)
}
#[inline]
pub fn new_bytes(&self, data: Vec<u8>) -> PyRef<bytes::PyBytes> {
bytes::PyBytes::new_ref(data, self)
}
#[inline(always)]
pub fn new_bool(&self, b: bool) -> PyIntRef {
let value = if b {
&self.true_value
} else {
&self.false_value
};
value.clone()
}
#[inline(always)]
pub fn new_tuple(&self, elements: Vec<PyObjectRef>) -> PyTupleRef {
PyTuple::new_ref(elements, self)
}
#[inline(always)]
pub fn new_list(&self, elements: Vec<PyObjectRef>) -> PyListRef {
PyList::new_ref(elements, self)
}
#[inline(always)]
pub fn new_dict(&self) -> PyDictRef {
PyDict::new_ref(self)
}
pub fn new_class(
&self,
module: Option<&str>,
name: &str,
base: &PyTypeRef,
slots: PyTypeSlots,
) -> PyTypeRef {
let mut attrs = PyAttributes::default();
if let Some(module) = module {
attrs.insert("__module__".to_string(), self.new_str(module).into());
};
PyType::new_ref(
name,
vec![base.clone()],
attrs,
slots,
self.types.type_type.clone(),
)
.unwrap()
}
pub fn new_exception_type(
&self,
module: &str,
name: &str,
bases: Option<Vec<PyTypeRef>>,
) -> PyTypeRef {
let bases = if let Some(bases) = bases {
bases
} else {
vec![self.exceptions.exception_type.clone()]
};
let mut attrs = PyAttributes::default();
attrs.insert("__module__".to_owned(), self.new_str(module).into());
PyType::new_ref(
name,
bases,
attrs,
PyBaseException::make_slots(),
self.types.type_type.clone(),
)
.unwrap()
}
#[inline]
pub fn make_funcdef<F, FKind>(&self, name: impl Into<PyStr>, f: F) -> PyNativeFuncDef
where
F: IntoPyNativeFunc<FKind>,
{
PyNativeFuncDef::new(f.into_func(), PyStr::new_ref(name, self))
}
// #[deprecated]
pub fn new_function<F, FKind>(&self, name: impl Into<PyStr>, f: F) -> PyRef<PyBuiltinFunction>
where
F: IntoPyNativeFunc<FKind>,
{
self.make_funcdef(name, f).build_function(self)
}
pub fn new_method<F, FKind>(
&self,
name: impl Into<PyStr>,
class: PyTypeRef,
f: F,
) -> PyRef<PyBuiltinMethod>
where
F: IntoPyNativeFunc<FKind>,
{
PyBuiltinMethod::new_ref(name, class, f, self)
}
pub fn new_readonly_getset<F, T>(
&self,
name: impl Into<String>,
class: PyTypeRef,
f: F,
) -> PyRef<PyGetSet>
where
F: IntoPyGetterFunc<T>,
{
PyRef::new_ref(
PyGetSet::new(name.into(), class).with_get(f),
self.types.getset_type.clone(),
None,
)
}
pub fn new_getset<G, S, T, U>(
&self,
name: impl Into<String>,
class: PyTypeRef,
g: G,
s: S,
) -> PyRef<PyGetSet>
where
G: IntoPyGetterFunc<T>,
S: IntoPySetterFunc<U>,
{
PyRef::new_ref(
PyGetSet::new(name.into(), class).with_get(g).with_set(s),
self.types.getset_type.clone(),
None,
)
}
pub fn new_base_object(&self, class: PyTypeRef, dict: Option<PyDictRef>) -> PyObjectRef {
debug_assert_eq!(
class.slots.flags.contains(PyTypeFlags::HAS_DICT),
dict.is_some()
);
PyRef::new_ref(object::PyBaseObject, class, dict).into()
}
}
impl Default for PyContext {
fn default() -> Self {
rustpython_common::static_cell! {
static CONTEXT: PyContext;
}
CONTEXT.get_or_init(Self::init).clone()
}
}
+3 -1
View File
@@ -5,6 +5,7 @@
#[cfg(feature = "rustpython-compiler")]
mod compile;
mod context;
mod interpreter;
mod setting;
pub mod thread;
@@ -30,7 +31,7 @@ use crate::{
import,
protocol::PyIterIter,
scope::Scope,
signal, stdlib, AsObject, PyContext, PyObject, PyObjectRef, PyPayload, PyRef, PyResult,
signal, stdlib, AsObject, PyObject, PyObjectRef, PyPayload, PyRef, PyResult,
};
use crossbeam_utils::atomic::AtomicCell;
use std::{
@@ -39,6 +40,7 @@ use std::{
collections::{HashMap, HashSet},
};
pub use context::PyContext;
pub use interpreter::Interpreter;
pub use setting::PySettings;