Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
Pyston
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Boxiang Sun
Pyston
Commits
b5f06903
Commit
b5f06903
authored
May 08, 2015
by
Kevin Modzelewski
Browse files
Options
Browse Files
Download
Plain Diff
Merge commit 'pr/466'
Conflicts: src/runtime/objmodel.cpp Closes #466
parents
87b8302d
b332f703
Changes
9
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
586 additions
and
181 deletions
+586
-181
src/analysis/scoping_analysis.cpp
src/analysis/scoping_analysis.cpp
+25
-0
src/analysis/scoping_analysis.h
src/analysis/scoping_analysis.h
+3
-0
src/core/types.h
src/core/types.h
+71
-1
src/runtime/builtin_modules/sys.cpp
src/runtime/builtin_modules/sys.cpp
+2
-2
src/runtime/objmodel.cpp
src/runtime/objmodel.cpp
+252
-53
src/runtime/types.cpp
src/runtime/types.cpp
+87
-46
src/runtime/types.h
src/runtime/types.h
+35
-79
test/tests/python_slots_test.py
test/tests/python_slots_test.py
+106
-0
test/tests/str_subclassing_gc.py
test/tests/str_subclassing_gc.py
+5
-0
No files found.
src/analysis/scoping_analysis.cpp
View file @
b5f06903
...
@@ -20,6 +20,7 @@
...
@@ -20,6 +20,7 @@
#include "core/common.h"
#include "core/common.h"
#include "core/types.h"
#include "core/types.h"
#include "core/util.h"
#include "core/util.h"
#include "runtime/types.h"
namespace
pyston
{
namespace
pyston
{
...
@@ -52,6 +53,30 @@ bool containsYield(AST* ast) {
...
@@ -52,6 +53,30 @@ bool containsYield(AST* ast) {
return
visitor
.
containsYield
;
return
visitor
.
containsYield
;
}
}
// TODO
// Combine this with the below? Basically the same logic with different string types...
// Also should this go in this file?
BoxedString
*
mangleNameBoxedString
(
BoxedString
*
id
,
BoxedString
*
private_name
)
{
assert
(
id
);
assert
(
private_name
);
int
len
=
id
->
s
.
size
();
if
(
len
<
2
||
id
->
s
[
0
]
!=
'_'
||
id
->
s
[
1
]
!=
'_'
)
return
id
;
if
((
id
->
s
[
len
-
2
]
==
'_'
&&
id
->
s
[
len
-
1
]
==
'_'
)
||
id
->
s
.
find
(
'.'
)
!=
llvm
::
StringRef
::
npos
)
return
id
;
const
char
*
p
=
private_name
->
s
.
data
();
while
(
*
p
==
'_'
)
{
p
++
;
len
--
;
}
if
(
*
p
==
'\0'
)
return
id
;
return
static_cast
<
BoxedString
*>
(
boxStringTwine
(
"_"
+
(
p
+
id
->
s
)));
}
static
void
mangleNameInPlace
(
InternedString
&
id
,
const
std
::
string
*
private_name
,
static
void
mangleNameInPlace
(
InternedString
&
id
,
const
std
::
string
*
private_name
,
InternedStringPool
&
interned_strings
)
{
InternedStringPool
&
interned_strings
)
{
if
(
!
private_name
)
if
(
!
private_name
)
...
...
src/analysis/scoping_analysis.h
View file @
b5f06903
...
@@ -178,6 +178,9 @@ public:
...
@@ -178,6 +178,9 @@ public:
};
};
bool
containsYield
(
AST
*
ast
);
bool
containsYield
(
AST
*
ast
);
class
BoxedString
;
BoxedString
*
mangleNameBoxedString
(
BoxedString
*
id
,
BoxedString
*
private_name
);
}
}
#endif
#endif
src/core/types.h
View file @
b5f06903
...
@@ -443,10 +443,12 @@ public:
...
@@ -443,10 +443,12 @@ public:
llvm
::
iterator_range
<
BoxIterator
>
pyElements
();
llvm
::
iterator_range
<
BoxIterator
>
pyElements
();
size_t
getHCAttrsOffset
();
HCAttrs
*
getHCAttrsPtr
();
HCAttrs
*
getHCAttrsPtr
();
void
setDict
(
BoxedDict
*
d
);
void
setDict
(
BoxedDict
*
d
);
BoxedDict
*
getDict
();
BoxedDict
*
getDict
();
void
setattr
(
const
std
::
string
&
attr
,
Box
*
val
,
SetattrRewriteArgs
*
rewrite_args
);
void
setattr
(
const
std
::
string
&
attr
,
Box
*
val
,
SetattrRewriteArgs
*
rewrite_args
);
void
giveAttr
(
const
std
::
string
&
attr
,
Box
*
val
)
{
void
giveAttr
(
const
std
::
string
&
attr
,
Box
*
val
)
{
assert
(
!
this
->
hasattr
(
attr
));
assert
(
!
this
->
hasattr
(
attr
));
...
@@ -476,9 +478,11 @@ extern "C" PyObject* PystonType_GenericAlloc(BoxedClass* cls, Py_ssize_t nitems)
...
@@ -476,9 +478,11 @@ extern "C" PyObject* PystonType_GenericAlloc(BoxedClass* cls, Py_ssize_t nitems)
#define DEFAULT_CLASS(default_cls) \
#define DEFAULT_CLASS(default_cls) \
void* operator new(size_t size, BoxedClass * cls) __attribute__((visibility("default"))) { \
void* operator new(size_t size, BoxedClass * cls) __attribute__((visibility("default"))) { \
assert(cls->tp_itemsize == 0); \
return Box::operator new(size, cls); \
return Box::operator new(size, cls); \
} \
} \
void* operator new(size_t size) __attribute__((visibility("default"))) { \
void* operator new(size_t size) __attribute__((visibility("default"))) { \
assert(default_cls->tp_itemsize == 0); \
return Box::operator new(size, default_cls); \
return Box::operator new(size, default_cls); \
}
}
...
@@ -488,8 +492,27 @@ extern "C" PyObject* PystonType_GenericAlloc(BoxedClass* cls, Py_ssize_t nitems)
...
@@ -488,8 +492,27 @@ extern "C" PyObject* PystonType_GenericAlloc(BoxedClass* cls, Py_ssize_t nitems)
std::string per_name_allocsize_name = "allocsize." + std::string(cls->tp_name); \
std::string per_name_allocsize_name = "allocsize." + std::string(cls->tp_name); \
Stats::log(Stats::getStatId(per_name_alloc_name)); \
Stats::log(Stats::getStatId(per_name_alloc_name)); \
Stats::log(Stats::getStatId(per_name_allocsize_name), size);
Stats::log(Stats::getStatId(per_name_allocsize_name), size);
#define ALLOC_STATS_VAR(cls) \
if (cls->tp_name) { \
std::string per_name_alloc_name = "alloc." + std::string(cls->tp_name); \
std::string per_name_alloc_name0 = "alloc." + std::string(cls->tp_name) + "(0)"; \
std::string per_name_allocsize_name = "allocsize." + std::string(cls->tp_name); \
std::string per_name_allocsize_name0 = "allocsize." + std::string(cls->tp_name) + "(0)"; \
static StatCounter alloc_name(per_name_alloc_name); \
static StatCounter alloc_name0(per_name_alloc_name0); \
static StatCounter allocsize_name(per_name_allocsize_name); \
static StatCounter allocsize_name0(per_name_allocsize_name0); \
if (nitems == 0) { \
alloc_name0.log(); \
allocsize_name0.log(_PyObject_VAR_SIZE(cls, nitems)); \
} else { \
alloc_name.log(); \
allocsize_name.log(_PyObject_VAR_SIZE(cls, nitems)); \
} \
}
#else
#else
#define ALLOC_STATS(cls)
#define ALLOC_STATS(cls)
#define ALLOC_STATS_VAR(cls)
#endif
#endif
...
@@ -525,12 +548,59 @@ extern "C" PyObject* PystonType_GenericAlloc(BoxedClass* cls, Py_ssize_t nitems)
...
@@ -525,12 +548,59 @@ extern "C" PyObject* PystonType_GenericAlloc(BoxedClass* cls, Py_ssize_t nitems)
/* TODO: there should be a way to not have to do this nested inlining by hand */
\
/* TODO: there should be a way to not have to do this nested inlining by hand */
\
}
}
#define DEFAULT_CLASS_VAR(default_cls, itemsize) \
static_assert(itemsize > 0, ""); \
/* asserts that the class in question is a subclass of BoxVar */
\
inline void _base_check() { \
static_assert(std::is_base_of<BoxVar, std::remove_pointer<decltype(this)>::type>::value, ""); \
} \
\
void* operator new(size_t size, BoxedClass * cls, size_t nitems) __attribute__((visibility("default"))) { \
assert(cls->tp_itemsize == itemsize); \
return BoxVar::operator new(size, cls, nitems); \
} \
void* operator new(size_t size, size_t nitems) __attribute__((visibility("default"))) { \
assert(default_cls->tp_itemsize == itemsize); \
return BoxVar::operator new(size, default_cls, nitems); \
}
#define DEFAULT_CLASS_VAR_SIMPLE(default_cls, itemsize) \
static_assert(itemsize > 0, ""); \
inline void _base_check() { \
static_assert(std::is_base_of<BoxVar, std::remove_pointer<decltype(this)>::type>::value, ""); \
} \
\
void* operator new(size_t size, BoxedClass * cls, size_t nitems) __attribute__((visibility("default"))) { \
ALLOC_STATS_VAR(default_cls) \
assert(cls->tp_itemsize == itemsize); \
return BoxVar::operator new(size, cls, nitems); \
} \
void* operator new(size_t size, size_t nitems) __attribute__((visibility("default"))) { \
ALLOC_STATS_VAR(default_cls) \
assert(default_cls->tp_alloc == PystonType_GenericAlloc); \
assert(default_cls->tp_itemsize == itemsize); \
assert(default_cls->tp_basicsize == size); \
assert(default_cls->is_pyston_class); \
assert(default_cls->attrs_offset == 0); \
\
void* mem = gc_alloc(size + nitems * itemsize, gc::GCKind::PYTHON); \
assert(mem); \
\
BoxVar* rtn = static_cast<BoxVar*>(mem); \
rtn->cls = default_cls; \
rtn->ob_size = nitems; \
return rtn; \
}
// CPython C API compatibility class:
// CPython C API compatibility class:
class
BoxVar
:
public
Box
{
class
BoxVar
:
public
Box
{
public:
public:
// This field gets initialized in operator new.
Py_ssize_t
ob_size
;
Py_ssize_t
ob_size
;
BoxVar
(
Py_ssize_t
ob_size
)
:
ob_size
(
ob_size
)
{}
BoxVar
()
{}
void
*
operator
new
(
size_t
size
,
BoxedClass
*
cls
,
size_t
nitems
)
__attribute__
((
visibility
(
"default"
)));
};
};
static_assert
(
offsetof
(
BoxVar
,
ob_size
)
==
offsetof
(
struct
_varobject
,
ob_size
),
""
);
static_assert
(
offsetof
(
BoxVar
,
ob_size
)
==
offsetof
(
struct
_varobject
,
ob_size
),
""
);
...
...
src/runtime/builtin_modules/sys.cpp
View file @
b5f06903
...
@@ -461,7 +461,7 @@ void setupSys() {
...
@@ -461,7 +461,7 @@ void setupSys() {
sys_module
->
giveAttr
(
"maxint"
,
boxInt
(
PYSTON_INT_MAX
));
sys_module
->
giveAttr
(
"maxint"
,
boxInt
(
PYSTON_INT_MAX
));
sys_module
->
giveAttr
(
"maxsize"
,
boxInt
(
PY_SSIZE_T_MAX
));
sys_module
->
giveAttr
(
"maxsize"
,
boxInt
(
PY_SSIZE_T_MAX
));
sys_flags_cls
=
new
BoxedHeapClass
(
object_cls
,
BoxedSysFlags
::
gcHandler
,
0
,
0
,
sizeof
(
BoxedSysFlags
),
false
,
sys_flags_cls
=
new
(
0
)
BoxedHeapClass
(
object_cls
,
BoxedSysFlags
::
gcHandler
,
0
,
0
,
sizeof
(
BoxedSysFlags
),
false
,
static_cast
<
BoxedString
*>
(
boxString
(
"flags"
)));
static_cast
<
BoxedString
*>
(
boxString
(
"flags"
)));
sys_flags_cls
->
giveAttr
(
"__new__"
,
sys_flags_cls
->
giveAttr
(
"__new__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
BoxedSysFlags
::
__new__
,
UNKNOWN
,
1
,
0
,
true
,
true
)));
new
BoxedFunction
(
boxRTFunction
((
void
*
)
BoxedSysFlags
::
__new__
,
UNKNOWN
,
1
,
0
,
true
,
true
)));
...
...
src/runtime/objmodel.cpp
View file @
b5f06903
...
@@ -318,8 +318,8 @@ void BoxedClass::freeze() {
...
@@ -318,8 +318,8 @@ void BoxedClass::freeze() {
BoxedClass
::
BoxedClass
(
BoxedClass
*
base
,
gcvisit_func
gc_visit
,
int
attrs_offset
,
int
weaklist_offset
,
BoxedClass
::
BoxedClass
(
BoxedClass
*
base
,
gcvisit_func
gc_visit
,
int
attrs_offset
,
int
weaklist_offset
,
int
instance_size
,
bool
is_user_defined
)
int
instance_size
,
bool
is_user_defined
)
:
BoxVar
(
0
),
attrs
(
HiddenClass
::
makeSingleton
()),
gc_visit
(
gc_visit
),
simple_destructor
(
NULL
),
:
attrs
(
HiddenClass
::
makeSingleton
()),
gc_visit
(
gc_visit
),
simple_destructor
(
NULL
),
attrs_offset
(
attrs_offset
),
attrs_offset
(
attrs_offset
),
is_constant
(
false
),
is_user_defined
(
is_user_defined
),
is_pyston_class
(
true
)
{
is_constant
(
false
),
is_user_defined
(
is_user_defined
),
is_pyston_class
(
true
)
{
// Zero out the CPython tp_* slots:
// Zero out the CPython tp_* slots:
memset
(
&
tp_name
,
0
,
(
char
*
)(
&
tp_version_tag
+
1
)
-
(
char
*
)(
&
tp_name
));
memset
(
&
tp_name
,
0
,
(
char
*
)(
&
tp_version_tag
+
1
)
-
(
char
*
)(
&
tp_name
));
...
@@ -375,16 +375,6 @@ BoxedClass::BoxedClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset
...
@@ -375,16 +375,6 @@ BoxedClass::BoxedClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset
if
(
base
&&
cls
&&
str_cls
)
if
(
base
&&
cls
&&
str_cls
)
giveAttr
(
"__base__"
,
base
);
giveAttr
(
"__base__"
,
base
);
// this isn't strictly correct, as it permits subclasses from
// e.g. Tuples/Longs to have weakrefs, which cpython disallows.
if
(
tp_weaklistoffset
==
0
&&
base
)
tp_weaklistoffset
=
base
->
tp_weaklistoffset
;
if
(
is_user_defined
&&
tp_weaklistoffset
==
0
)
{
tp_weaklistoffset
=
tp_basicsize
;
tp_basicsize
+=
sizeof
(
Box
**
);
}
assert
(
tp_basicsize
%
sizeof
(
void
*
)
==
0
);
// Not critical I suppose, but probably signals a bug
if
(
attrs_offset
)
{
if
(
attrs_offset
)
{
assert
(
tp_basicsize
>=
attrs_offset
+
sizeof
(
HCAttrs
));
assert
(
tp_basicsize
>=
attrs_offset
+
sizeof
(
HCAttrs
));
assert
(
attrs_offset
%
sizeof
(
void
*
)
==
0
);
// Not critical I suppose, but probably signals a bug
assert
(
attrs_offset
%
sizeof
(
void
*
)
==
0
);
// Not critical I suppose, but probably signals a bug
...
@@ -433,13 +423,13 @@ BoxedHeapClass* BoxedHeapClass::create(BoxedClass* metaclass, BoxedClass* base,
...
@@ -433,13 +423,13 @@ BoxedHeapClass* BoxedHeapClass::create(BoxedClass* metaclass, BoxedClass* base,
int
weaklist_offset
,
int
instance_size
,
bool
is_user_defined
,
int
weaklist_offset
,
int
instance_size
,
bool
is_user_defined
,
const
std
::
string
&
name
)
{
const
std
::
string
&
name
)
{
return
create
(
metaclass
,
base
,
gc_visit
,
attrs_offset
,
weaklist_offset
,
instance_size
,
is_user_defined
,
return
create
(
metaclass
,
base
,
gc_visit
,
attrs_offset
,
weaklist_offset
,
instance_size
,
is_user_defined
,
static_cast
<
BoxedString
*>
(
boxString
(
name
)),
NULL
);
static_cast
<
BoxedString
*>
(
boxString
(
name
)),
NULL
,
0
);
}
}
BoxedHeapClass
*
BoxedHeapClass
::
create
(
BoxedClass
*
metaclass
,
BoxedClass
*
base
,
gcvisit_func
gc_visit
,
int
attrs_offset
,
BoxedHeapClass
*
BoxedHeapClass
::
create
(
BoxedClass
*
metaclass
,
BoxedClass
*
base
,
gcvisit_func
gc_visit
,
int
attrs_offset
,
int
weaklist_offset
,
int
instance_size
,
bool
is_user_defined
,
BoxedString
*
name
,
int
weaklist_offset
,
int
instance_size
,
bool
is_user_defined
,
BoxedString
*
name
,
BoxedTuple
*
bases
)
{
BoxedTuple
*
bases
,
size_t
nslots
)
{
BoxedHeapClass
*
made
=
new
(
metaclass
)
BoxedHeapClass
*
made
=
new
(
metaclass
,
nslots
)
BoxedHeapClass
(
base
,
gc_visit
,
attrs_offset
,
weaklist_offset
,
instance_size
,
is_user_defined
,
name
);
BoxedHeapClass
(
base
,
gc_visit
,
attrs_offset
,
weaklist_offset
,
instance_size
,
is_user_defined
,
name
);
assert
((
name
||
str_cls
==
NULL
)
&&
"name can only be NULL before str_cls has been initialized."
);
assert
((
name
||
str_cls
==
NULL
)
&&
"name can only be NULL before str_cls has been initialized."
);
...
@@ -584,16 +574,33 @@ HiddenClass* HiddenClass::delAttrToMakeHC(const std::string& attr) {
...
@@ -584,16 +574,33 @@ HiddenClass* HiddenClass::delAttrToMakeHC(const std::string& attr) {
return
cur
;
return
cur
;
}
}
HCAttrs
*
Box
::
getHCAttrsPtr
()
{
size_t
Box
::
getHCAttrsOffset
()
{
assert
(
cls
->
instancesHaveHCAttrs
());
assert
(
cls
->
instancesHaveHCAttrs
());
if
(
unlikely
(
cls
->
attrs_offset
<
0
))
{
// negative indicates an offset from the end of an object
if
(
cls
->
tp_itemsize
!=
0
)
{
size_t
ob_size
=
static_cast
<
BoxVar
*>
(
this
)
->
ob_size
;
return
cls
->
tp_basicsize
+
ob_size
*
cls
->
tp_itemsize
+
cls
->
attrs_offset
;
}
else
{
// This case is unlikely: why would we use a negative attrs_offset
// if it wasn't a var-sized object? But I guess it's technically allowed.
return
cls
->
attrs_offset
;
}
}
else
{
return
cls
->
attrs_offset
;
}
}
HCAttrs
*
Box
::
getHCAttrsPtr
()
{
char
*
p
=
reinterpret_cast
<
char
*>
(
this
);
char
*
p
=
reinterpret_cast
<
char
*>
(
this
);
p
+=
cls
->
attrs_offset
;
p
+=
this
->
getHCAttrsOffset
()
;
return
reinterpret_cast
<
HCAttrs
*>
(
p
);
return
reinterpret_cast
<
HCAttrs
*>
(
p
);
}
}
BoxedDict
**
Box
::
getDictPtr
()
{
BoxedDict
**
Box
::
getDictPtr
()
{
assert
(
cls
->
instancesHaveDictAttrs
());
assert
(
cls
->
instancesHaveDictAttrs
());
RELEASE_ASSERT
(
cls
->
tp_dictoffset
>
0
,
"not implemented: handle < 0 case like in getHCAttrsPtr"
);
char
*
p
=
reinterpret_cast
<
char
*>
(
this
);
char
*
p
=
reinterpret_cast
<
char
*>
(
this
);
p
+=
cls
->
tp_dictoffset
;
p
+=
cls
->
tp_dictoffset
;
...
@@ -670,23 +677,39 @@ Box* Box::getattr(const std::string& attr, GetattrRewriteArgs* rewrite_args) {
...
@@ -670,23 +677,39 @@ Box* Box::getattr(const std::string& attr, GetattrRewriteArgs* rewrite_args) {
if
(
rewrite_args
)
{
if
(
rewrite_args
)
{
if
(
!
rewrite_args
->
obj_hcls_guarded
)
{
if
(
!
rewrite_args
->
obj_hcls_guarded
)
{
if
(
cls
->
attrs_offset
<
0
)
{
REWRITE_ABORTED
(
""
);
rewrite_args
=
NULL
;
}
else
{
rewrite_args
->
obj
->
addAttrGuard
(
cls
->
attrs_offset
+
HCATTRS_HCLS_OFFSET
,
(
intptr_t
)
hcls
);
rewrite_args
->
obj
->
addAttrGuard
(
cls
->
attrs_offset
+
HCATTRS_HCLS_OFFSET
,
(
intptr_t
)
hcls
);
if
(
hcls
->
type
==
HiddenClass
::
SINGLETON
)
if
(
hcls
->
type
==
HiddenClass
::
SINGLETON
)
hcls
->
addDependence
(
rewrite_args
->
rewriter
);
hcls
->
addDependence
(
rewrite_args
->
rewriter
);
}
}
}
rewrite_args
->
out_success
=
true
;
}
}
int
offset
=
hcls
->
getOffset
(
attr
);
int
offset
=
hcls
->
getOffset
(
attr
);
if
(
offset
==
-
1
)
{
if
(
offset
==
-
1
)
{
if
(
rewrite_args
)
{
rewrite_args
->
out_success
=
true
;
}
return
NULL
;
return
NULL
;
}
}
if
(
rewrite_args
)
{
if
(
rewrite_args
)
{
if
(
cls
->
attrs_offset
<
0
)
{
REWRITE_ABORTED
(
""
);
rewrite_args
=
NULL
;
}
else
{
RewriterVar
*
r_attrs
RewriterVar
*
r_attrs
=
rewrite_args
->
obj
->
getAttr
(
cls
->
attrs_offset
+
HCATTRS_ATTRS_OFFSET
,
Location
::
any
());
=
rewrite_args
->
obj
->
getAttr
(
cls
->
attrs_offset
+
HCATTRS_ATTRS_OFFSET
,
Location
::
any
());
rewrite_args
->
out_rtn
=
r_attrs
->
getAttr
(
offset
*
sizeof
(
Box
*
)
+
ATTRLIST_ATTRS_OFFSET
,
Location
::
any
());
rewrite_args
->
out_rtn
=
r_attrs
->
getAttr
(
offset
*
sizeof
(
Box
*
)
+
ATTRLIST_ATTRS_OFFSET
,
Location
::
any
());
}
}
if
(
rewrite_args
)
{
rewrite_args
->
out_success
=
true
;
}
}
Box
*
rtn
=
attrs
->
attr_list
->
attrs
[
offset
];
Box
*
rtn
=
attrs
->
attr_list
->
attrs
[
offset
];
...
@@ -707,8 +730,9 @@ Box* Box::getattr(const std::string& attr, GetattrRewriteArgs* rewrite_args) {
...
@@ -707,8 +730,9 @@ Box* Box::getattr(const std::string& attr, GetattrRewriteArgs* rewrite_args) {
return
it
->
second
;
return
it
->
second
;
}
}
if
(
rewrite_args
)
if
(
rewrite_args
)
{
rewrite_args
->
out_success
=
true
;
rewrite_args
->
out_success
=
true
;
}
return
NULL
;
return
NULL
;
}
}
...
@@ -734,12 +758,17 @@ void Box::appendNewHCAttr(Box* new_attr, SetattrRewriteArgs* rewrite_args) {
...
@@ -734,12 +758,17 @@ void Box::appendNewHCAttr(Box* new_attr, SetattrRewriteArgs* rewrite_args) {
}
else
{
}
else
{
attrs
->
attr_list
=
(
HCAttrs
::
AttrList
*
)
gc
::
gc_realloc
(
attrs
->
attr_list
,
new_size
);
attrs
->
attr_list
=
(
HCAttrs
::
AttrList
*
)
gc
::
gc_realloc
(
attrs
->
attr_list
,
new_size
);
if
(
rewrite_args
)
{
if
(
rewrite_args
)
{
if
(
cls
->
attrs_offset
<
0
)
{
REWRITE_ABORTED
(
""
);
rewrite_args
=
NULL
;
}
else
{
RewriterVar
*
r_oldarray
RewriterVar
*
r_oldarray
=
rewrite_args
->
obj
->
getAttr
(
cls
->
attrs_offset
+
HCATTRS_ATTRS_OFFSET
,
Location
::
forArg
(
0
));
=
rewrite_args
->
obj
->
getAttr
(
cls
->
attrs_offset
+
HCATTRS_ATTRS_OFFSET
,
Location
::
forArg
(
0
));
RewriterVar
*
r_newsize
=
rewrite_args
->
rewriter
->
loadConst
(
new_size
,
Location
::
forArg
(
1
));
RewriterVar
*
r_newsize
=
rewrite_args
->
rewriter
->
loadConst
(
new_size
,
Location
::
forArg
(
1
));
r_new_array2
=
rewrite_args
->
rewriter
->
call
(
true
,
(
void
*
)
gc
::
gc_realloc
,
r_oldarray
,
r_newsize
);
r_new_array2
=
rewrite_args
->
rewriter
->
call
(
true
,
(
void
*
)
gc
::
gc_realloc
,
r_oldarray
,
r_newsize
);
}
}
}
}
}
if
(
rewrite_args
)
{
if
(
rewrite_args
)
{
r_new_array2
->
setAttr
(
numattrs
*
sizeof
(
Box
*
)
+
ATTRLIST_ATTRS_OFFSET
,
rewrite_args
->
attrval
);
r_new_array2
->
setAttr
(
numattrs
*
sizeof
(
Box
*
)
+
ATTRLIST_ATTRS_OFFSET
,
rewrite_args
->
attrval
);
...
@@ -787,10 +816,15 @@ void Box::setattr(const std::string& attr, Box* val, SetattrRewriteArgs* rewrite
...
@@ -787,10 +816,15 @@ void Box::setattr(const std::string& attr, Box* val, SetattrRewriteArgs* rewrite
int
offset
=
hcls
->
getOffset
(
attr
);
int
offset
=
hcls
->
getOffset
(
attr
);
if
(
rewrite_args
)
{
if
(
rewrite_args
)
{
if
(
cls
->
attrs_offset
<
0
)
{
REWRITE_ABORTED
(
""
);
rewrite_args
=
NULL
;
}
else
{
rewrite_args
->
obj
->
addAttrGuard
(
cls
->
attrs_offset
+
HCATTRS_HCLS_OFFSET
,
(
intptr_t
)
hcls
);
rewrite_args
->
obj
->
addAttrGuard
(
cls
->
attrs_offset
+
HCATTRS_HCLS_OFFSET
,
(
intptr_t
)
hcls
);
if
(
hcls
->
type
==
HiddenClass
::
SINGLETON
)
if
(
hcls
->
type
==
HiddenClass
::
SINGLETON
)
hcls
->
addDependence
(
rewrite_args
->
rewriter
);
hcls
->
addDependence
(
rewrite_args
->
rewriter
);
}
}
}
if
(
offset
>=
0
)
{
if
(
offset
>=
0
)
{
assert
(
offset
<
hcls
->
attributeArraySize
());
assert
(
offset
<
hcls
->
attributeArraySize
());
...
@@ -799,6 +833,10 @@ void Box::setattr(const std::string& attr, Box* val, SetattrRewriteArgs* rewrite
...
@@ -799,6 +833,10 @@ void Box::setattr(const std::string& attr, Box* val, SetattrRewriteArgs* rewrite
if
(
rewrite_args
)
{
if
(
rewrite_args
)
{
if
(
cls
->
attrs_offset
<
0
)
{
REWRITE_ABORTED
(
""
);
rewrite_args
=
NULL
;
}
else
{
RewriterVar
*
r_hattrs
RewriterVar
*
r_hattrs
=
rewrite_args
->
obj
->
getAttr
(
cls
->
attrs_offset
+
HCATTRS_ATTRS_OFFSET
,
Location
::
any
());
=
rewrite_args
->
obj
->
getAttr
(
cls
->
attrs_offset
+
HCATTRS_ATTRS_OFFSET
,
Location
::
any
());
...
@@ -806,6 +844,7 @@ void Box::setattr(const std::string& attr, Box* val, SetattrRewriteArgs* rewrite
...
@@ -806,6 +844,7 @@ void Box::setattr(const std::string& attr, Box* val, SetattrRewriteArgs* rewrite
rewrite_args
->
out_success
=
true
;
rewrite_args
->
out_success
=
true
;
}
}
}
return
;
return
;
}
}
...
@@ -4066,6 +4105,28 @@ static void assertInitNone(Box* obj) {
...
@@ -4066,6 +4105,28 @@ static void assertInitNone(Box* obj) {
}
}
}
}
void
assertValidSlotIdentifier
(
Box
*
s
)
{
// Ported from `valid_identifier` in cpython
unsigned
char
*
p
;
size_t
i
,
n
;
if
(
!
PyString_Check
(
s
))
{
raiseExcHelper
(
TypeError
,
"__slots__ items must be strings, not '%.200s'"
,
Py_TYPE
(
s
)
->
tp_name
);
}
p
=
(
unsigned
char
*
)
PyString_AS_STRING
(
s
);
n
=
PyString_GET_SIZE
(
s
);
/* We must reject an empty name. As a hack, we bump the
length to 1 so that the loop will balk on the trailing \0. */
if
(
n
==
0
)
n
=
1
;
for
(
i
=
0
;
i
<
n
;
i
++
,
p
++
)
{
if
(
!
(
i
==
0
?
isalpha
(
*
p
)
:
isalnum
(
*
p
))
&&
*
p
!=
'_'
)
{
raiseExcHelper
(
TypeError
,
"__slots__ must be identifiers"
);
}
}
}
Box
*
typeNew
(
Box
*
_cls
,
Box
*
arg1
,
Box
*
arg2
,
Box
**
_args
)
{
Box
*
typeNew
(
Box
*
_cls
,
Box
*
arg1
,
Box
*
arg2
,
Box
**
_args
)
{
STAT_TIMER
(
t0
,
"us_timer_typeNew"
);
STAT_TIMER
(
t0
,
"us_timer_typeNew"
);
...
@@ -4134,28 +4195,166 @@ Box* typeNew(Box* _cls, Box* arg1, Box* arg2, Box** _args) {
...
@@ -4134,28 +4195,166 @@ Box* typeNew(Box* _cls, Box* arg1, Box* arg2, Box** _args) {
raiseExcHelper
(
TypeError
,
"type '%.100s' is not an acceptable base type"
,
base
->
tp_name
);
raiseExcHelper
(
TypeError
,
"type '%.100s' is not an acceptable base type"
,
base
->
tp_name
);
assert
(
isSubclass
(
base
->
cls
,
type_cls
));
assert
(
isSubclass
(
base
->
cls
,
type_cls
));
// Handle slots
Box
*
boxedSlots
=
PyDict_GetItemString
(
attr_dict
,
"__slots__"
);
int
add_dict
=
0
;
int
add_weak
=
0
;
bool
may_add_dict
=
base
->
tp_dictoffset
==
0
&&
base
->
attrs_offset
==
0
;
bool
may_add_weak
=
base
->
tp_weaklistoffset
==
0
&&
base
->
tp_itemsize
==
0
;
std
::
vector
<
Box
*>
final_slot_names
;
if
(
boxedSlots
==
NULL
)
{
if
(
may_add_dict
)
{
add_dict
++
;
}
if
(
may_add_weak
)
{
add_weak
++
;
}
}
else
{
// Get a pointer to an array of slots.
std
::
vector
<
Box
*>
slots
;
if
(
PyString_Check
(
boxedSlots
)
||
PyUnicode_Check
(
boxedSlots
))
{
slots
=
{
boxedSlots
};
}
else
{
BoxedTuple
*
tuple
=
static_cast
<
BoxedTuple
*>
(
PySequence_Tuple
(
boxedSlots
));
checkAndThrowCAPIException
();
slots
=
std
::
vector
<
Box
*>
(
tuple
->
size
());
for
(
size_t
i
=
0
;
i
<
tuple
->
size
();
i
++
)
{
slots
[
i
]
=
(
*
tuple
)[
i
];
}
}
// Check that slots are allowed
if
(
slots
.
size
()
>
0
&&
base
->
tp_itemsize
!=
0
)
{
raiseExcHelper
(
TypeError
,
"nonempty __slots__ not supported for subtype of '%s'"
,
base
->
tp_name
);
}
// Convert unicode -> string
for
(
size_t
i
=
0
;
i
<
slots
.
size
();
i
++
)
{
Box
*
slot_name
=
slots
[
i
];
if
(
PyUnicode_Check
(
slot_name
))
{
slots
[
i
]
=
_PyUnicode_AsDefaultEncodedString
(
slot_name
,
NULL
);
checkAndThrowCAPIException
();
}
}
// TODO I don't think we have to implement the __slots__ memory savings behavior
// Check for valid slot names and two special cases
// (we get almost all of that automatically with hidden classes), but adding a __slots__
// Mangle and sort names
// adds other restrictions (ex for multiple inheritance) that we won't end up enforcing.
for
(
size_t
i
=
0
;
i
<
slots
.
size
();
i
++
)
{
// I guess it should be ok if we're more permissive?
Box
*
tmp
=
slots
[
i
];
// auto slots = PyDict_GetItemString(attr_dict, "__slots__");
assertValidSlotIdentifier
(
tmp
);
// RELEASE_ASSERT(!slots, "__slots__ unsupported");
assert
(
PyString_Check
(
tmp
));
if
(
static_cast
<
BoxedString
*>
(
tmp
)
->
s
==
"__dict__"
)
{
if
(
!
may_add_dict
||
add_dict
)
{
raiseExcHelper
(
TypeError
,
"__dict__ slot disallowed: "
"we already got one"
);
}
add_dict
++
;
continue
;
}
else
if
(
static_cast
<
BoxedString
*>
(
tmp
)
->
s
==
"__weakref__"
)
{
if
(
!
may_add_weak
||
add_weak
)
{
raiseExcHelper
(
TypeError
,
"__weakref__ slot disallowed: "
"either we already got one, "
"or __itemsize__ != 0"
);
}
add_weak
++
;
continue
;
}
assert
(
tmp
->
cls
==
str_cls
);
final_slot_names
.
push_back
(
mangleNameBoxedString
(
static_cast
<
BoxedString
*>
(
tmp
),
name
));
}
BoxedClass
*
made
;
std
::
sort
(
final_slot_names
.
begin
(),
final_slot_names
.
end
(),
PyLt
())
;
if
(
base
->
instancesHaveDictAttrs
()
||
base
->
instancesHaveHCAttrs
())
{
if
(
nbases
>
1
&&
((
may_add_dict
&&
!
add_dict
)
||
(
may_add_weak
&&
!
add_weak
)))
{
made
=
BoxedHeapClass
::
create
(
metatype
,
base
,
NULL
,
base
->
attrs_offset
,
base
->
tp_weaklistoffset
,
for
(
size_t
i
=
0
;
i
<
nbases
;
i
++
)
{
base
->
tp_basicsize
,
true
,
name
,
bases
);
Box
*
tmp
=
PyTuple_GET_ITEM
(
bases
,
i
);
}
else
{
if
(
tmp
==
(
PyObject
*
)
base
)
assert
(
base
->
tp_basicsize
%
sizeof
(
void
*
)
==
0
);
continue
;
/* Skip primary base */
made
=
BoxedHeapClass
::
create
(
metatype
,
base
,
NULL
,
base
->
tp_basicsize
,
base
->
tp_weaklistoffset
,
if
(
PyClass_Check
(
tmp
))
{
base
->
tp_basicsize
+
sizeof
(
HCAttrs
),
true
,
name
,
bases
);
/* Classic base class provides both */
if
(
may_add_dict
&&
!
add_dict
)
add_dict
++
;
if
(
may_add_weak
&&
!
add_weak
)
add_weak
++
;
break
;
}
assert
(
PyType_Check
(
tmp
));
BoxedClass
*
tmptype
=
static_cast
<
BoxedClass
*>
(
tmp
);
if
(
may_add_dict
&&
!
add_dict
&&
(
tmptype
->
tp_dictoffset
!=
0
||
tmptype
->
attrs_offset
!=
0
))
add_dict
++
;
if
(
may_add_weak
&&
!
add_weak
&&
tmptype
->
tp_weaklistoffset
!=
0
)
add_weak
++
;
if
(
may_add_dict
&&
!
add_dict
)
continue
;
if
(
may_add_weak
&&
!
add_weak
)
continue
;
/* Nothing more to check */
break
;
}
}
}
}
int
attrs_offset
=
base
->
attrs_offset
;
int
dict_offset
=
base
->
tp_dictoffset
;
int
weaklist_offset
=
0
;
int
basic_size
=
0
;
// TODO: how much of these should be in BoxedClass::finishInitialization()?
int
cur_offset
=
base
->
tp_basicsize
+
sizeof
(
Box
*
)
*
final_slot_names
.
size
();
made
->
tp_dictoffset
=
base
->
tp_dictoffset
;
if
(
add_dict
)
{
// CPython would set tp_dictoffset here, but we want to use attrs instead.
if
(
base
->
tp_itemsize
)
{
// A negative value indicates an offset from the end of the object
attrs_offset
=
-
(
long
)
sizeof
(
HCAttrs
);
}
else
{
attrs_offset
=
cur_offset
;
}
cur_offset
+=
sizeof
(
HCAttrs
);
}
if
(
add_weak
)
{
assert
(
!
base
->
tp_itemsize
);
weaklist_offset
=
cur_offset
;
cur_offset
+=
sizeof
(
Box
*
);
}
basic_size
=
cur_offset
;
size_t
total_slots
=
final_slot_names
.
size
()
+
(
base
->
tp_flags
&
Py_TPFLAGS_HEAPTYPE
?
static_cast
<
BoxedHeapClass
*>
(
base
)
->
nslots
()
:
0
);
BoxedHeapClass
*
made
=
BoxedHeapClass
::
create
(
metatype
,
base
,
NULL
,
attrs_offset
,
weaklist_offset
,
basic_size
,
true
,
name
,
bases
,
total_slots
);
made
->
tp_dictoffset
=
dict_offset
;
if
(
boxedSlots
)
{
// Set ht_slots
BoxedTuple
*
slotsTuple
=
BoxedTuple
::
create
(
final_slot_names
.
size
());
for
(
size_t
i
=
0
;
i
<
final_slot_names
.
size
();
i
++
)
(
*
slotsTuple
)[
i
]
=
final_slot_names
[
i
];
assert
(
made
->
tp_flags
&
Py_TPFLAGS_HEAPTYPE
);
static_cast
<
BoxedHeapClass
*>
(
made
)
->
ht_slots
=
slotsTuple
;
BoxedHeapClass
::
SlotOffset
*
slot_offsets
=
made
->
slotOffsets
();
size_t
slot_offset_offset
=
made
->
tp_basicsize
;
// Add the member descriptors
size_t
offset
=
base
->
tp_basicsize
;
for
(
size_t
i
=
0
;
i
<
final_slot_names
.
size
();
i
++
)
{
made
->
giveAttr
(
static_cast
<
BoxedString
*>
(
slotsTuple
->
elts
[
i
])
->
s
.
data
(),
new
BoxedMemberDescriptor
(
BoxedMemberDescriptor
::
OBJECT_EX
,
offset
,
false
/* read only */
));
slot_offsets
[
i
]
=
offset
;
offset
+=
sizeof
(
Box
*
);
}
}
// Add slot offsets for slots of the base
// NOTE: CPython does this, but I don't want to have to traverse the class hierarchy to
// traverse all the slots, so I'm putting them all here.
if
(
base
->
tp_flags
&
Py_TPFLAGS_HEAPTYPE
)
{
BoxedHeapClass
::
SlotOffset
*
slot_offsets
=
made
->
slotOffsets
();
BoxedHeapClass
*
base_heap_cls
=
static_cast
<
BoxedHeapClass
*>
(
base
);
BoxedHeapClass
::
SlotOffset
*
base_slot_offsets
=
base_heap_cls
->
slotOffsets
();
memcpy
(
&
slot_offsets
[
final_slot_names
.
size
()],
base_slot_offsets
,
base_heap_cls
->
nslots
()
*
sizeof
(
BoxedHeapClass
::
SlotOffset
));
}
if
(
!
made
->
getattr
(
"__dict__"
)
&&
(
made
->
instancesHaveHCAttrs
()
||
made
->
instancesHaveDictAttrs
()))
if
(
!
made
->
getattr
(
"__dict__"
)
&&
(
made
->
instancesHaveHCAttrs
()
||
made
->
instancesHaveDictAttrs
()))
made
->
giveAttr
(
"__dict__"
,
dict_descr
);
made
->
giveAttr
(
"__dict__"
,
dict_descr
);
...
...
src/runtime/types.cpp
View file @
b5f06903
...
@@ -94,7 +94,7 @@ bool IN_SHUTDOWN = false;
...
@@ -94,7 +94,7 @@ bool IN_SHUTDOWN = false;
extern
"C"
PyObject
*
PystonType_GenericAlloc
(
BoxedClass
*
cls
,
Py_ssize_t
nitems
)
noexcept
{
extern
"C"
PyObject
*
PystonType_GenericAlloc
(
BoxedClass
*
cls
,
Py_ssize_t
nitems
)
noexcept
{
assert
(
cls
);
assert
(
cls
);
const
size_t
size
=
_PyObject_VAR_SIZE
(
cls
,
nitems
+
1
);
const
size_t
size
=
_PyObject_VAR_SIZE
(
cls
,
nitems
);
#ifndef NDEBUG
#ifndef NDEBUG
#if 0
#if 0
...
@@ -132,7 +132,10 @@ extern "C" PyObject* PystonType_GenericAlloc(BoxedClass* cls, Py_ssize_t nitems)
...
@@ -132,7 +132,10 @@ extern "C" PyObject* PystonType_GenericAlloc(BoxedClass* cls, Py_ssize_t nitems)
Box
*
rtn
=
static_cast
<
Box
*>
(
mem
);
Box
*
rtn
=
static_cast
<
Box
*>
(
mem
);
PyObject_Init
(
rtn
,
cls
);
if
(
cls
->
tp_itemsize
!=
0
)
static_cast
<
BoxVar
*>
(
rtn
)
->
ob_size
=
nitems
;
PyObject_INIT
(
rtn
,
cls
);
assert
(
rtn
->
cls
);
assert
(
rtn
->
cls
);
return
rtn
;
return
rtn
;
...
@@ -140,7 +143,7 @@ extern "C" PyObject* PystonType_GenericAlloc(BoxedClass* cls, Py_ssize_t nitems)
...
@@ -140,7 +143,7 @@ extern "C" PyObject* PystonType_GenericAlloc(BoxedClass* cls, Py_ssize_t nitems)
extern
"C"
PyObject
*
PyType_GenericAlloc
(
PyTypeObject
*
type
,
Py_ssize_t
nitems
)
noexcept
{
extern
"C"
PyObject
*
PyType_GenericAlloc
(
PyTypeObject
*
type
,
Py_ssize_t
nitems
)
noexcept
{
PyObject
*
obj
;
PyObject
*
obj
;
const
size_t
size
=
_PyObject_VAR_SIZE
(
type
,
nitems
+
1
);
const
size_t
size
=
_PyObject_VAR_SIZE
(
type
,
nitems
);
/* note that we need to add one, for the sentinel */
/* note that we need to add one, for the sentinel */
if
(
PyType_IS_GC
(
type
))
if
(
PyType_IS_GC
(
type
))
...
@@ -175,9 +178,21 @@ extern "C" PyObject* _PyObject_New(PyTypeObject* tp) noexcept {
...
@@ -175,9 +178,21 @@ extern "C" PyObject* _PyObject_New(PyTypeObject* tp) noexcept {
}
}
// Analogue of PyType_GenericNew
// Analogue of PyType_GenericNew
void
*
BoxVar
::
operator
new
(
size_t
size
,
BoxedClass
*
cls
,
size_t
nitems
)
{
assert
(
cls
);
ASSERT
(
cls
->
tp_basicsize
>=
size
,
"%s"
,
cls
->
tp_name
);
assert
(
cls
->
tp_itemsize
>
0
);
assert
(
cls
->
tp_alloc
);
void
*
mem
=
cls
->
tp_alloc
(
cls
,
nitems
);
RELEASE_ASSERT
(
mem
,
""
);
return
mem
;
}
void
*
Box
::
operator
new
(
size_t
size
,
BoxedClass
*
cls
)
{
void
*
Box
::
operator
new
(
size_t
size
,
BoxedClass
*
cls
)
{
assert
(
cls
);
assert
(
cls
);
ASSERT
(
cls
->
tp_basicsize
>=
size
,
"%s"
,
cls
->
tp_name
);
ASSERT
(
cls
->
tp_basicsize
>=
size
,
"%s"
,
cls
->
tp_name
);
assert
(
cls
->
tp_itemsize
==
0
);
assert
(
cls
->
tp_alloc
);
assert
(
cls
->
tp_alloc
);
void
*
mem
=
cls
->
tp_alloc
(
cls
,
0
);
void
*
mem
=
cls
->
tp_alloc
(
cls
,
0
);
...
@@ -449,6 +464,14 @@ extern "C" void boxGCHandler(GCVisitor* v, Box* b) {
...
@@ -449,6 +464,14 @@ extern "C" void boxGCHandler(GCVisitor* v, Box* b) {
if
(
b
->
cls
->
instancesHaveDictAttrs
())
{
if
(
b
->
cls
->
instancesHaveDictAttrs
())
{
RELEASE_ASSERT
(
0
,
"Shouldn't all of these objects be conservatively scanned?"
);
RELEASE_ASSERT
(
0
,
"Shouldn't all of these objects be conservatively scanned?"
);
}
}
if
(
b
->
cls
->
tp_flags
&
Py_TPFLAGS_HEAPTYPE
)
{
BoxedHeapClass
*
heap_cls
=
static_cast
<
BoxedHeapClass
*>
(
b
->
cls
);
BoxedHeapClass
::
SlotOffset
*
slotOffsets
=
heap_cls
->
slotOffsets
();
for
(
int
i
=
0
;
i
<
heap_cls
->
nslots
();
i
++
)
{
v
->
visit
(
*
((
Box
**
)((
char
*
)
b
+
slotOffsets
[
i
])));
}
}
}
else
{
}
else
{
assert
(
type_cls
==
NULL
||
b
==
type_cls
);
assert
(
type_cls
==
NULL
||
b
==
type_cls
);
}
}
...
@@ -2047,6 +2070,20 @@ extern "C" PyObject* PyObject_Init(PyObject* op, PyTypeObject* tp) noexcept {
...
@@ -2047,6 +2070,20 @@ extern "C" PyObject* PyObject_Init(PyObject* op, PyTypeObject* tp) noexcept {
// initUserAttrs themselves, though.
// initUserAttrs themselves, though.
initUserAttrs
(
op
,
tp
);
initUserAttrs
(
op
,
tp
);
#ifndef NDEBUG
if
(
tp
->
tp_flags
&
Py_TPFLAGS_HEAPTYPE
)
{
BoxedHeapClass
*
heap_cls
=
static_cast
<
BoxedHeapClass
*>
(
tp
);
if
(
heap_cls
->
nslots
()
>
0
)
{
BoxedHeapClass
::
SlotOffset
*
slotOffsets
=
heap_cls
->
slotOffsets
();
for
(
int
i
=
0
;
i
<
heap_cls
->
nslots
();
i
++
)
{
// This should be set to 0 on allocation:
// (If it wasn't, we would need to initialize it to 0 here.)
assert
(
*
(
Box
**
)((
char
*
)
op
+
slotOffsets
[
i
])
==
NULL
);
}
}
}
#endif
return
op
;
return
op
;
}
}
...
@@ -2076,18 +2113,20 @@ void setupRuntime() {
...
@@ -2076,18 +2113,20 @@ void setupRuntime() {
type_cls
=
::
new
(
mem
)
BoxedHeapClass
(
object_cls
,
&
typeGCHandler
,
offsetof
(
BoxedClass
,
attrs
),
type_cls
=
::
new
(
mem
)
BoxedHeapClass
(
object_cls
,
&
typeGCHandler
,
offsetof
(
BoxedClass
,
attrs
),
offsetof
(
BoxedClass
,
tp_weaklist
),
sizeof
(
BoxedHeapClass
),
false
,
NULL
);
offsetof
(
BoxedClass
,
tp_weaklist
),
sizeof
(
BoxedHeapClass
),
false
,
NULL
);
type_cls
->
tp_flags
|=
Py_TPFLAGS_TYPE_SUBCLASS
;
type_cls
->
tp_flags
|=
Py_TPFLAGS_TYPE_SUBCLASS
;
type_cls
->
tp_itemsize
=
sizeof
(
BoxedHeapClass
::
SlotOffset
);
PyObject_Init
(
object_cls
,
type_cls
);
PyObject_Init
(
object_cls
,
type_cls
);
PyObject_Init
(
type_cls
,
type_cls
);
PyObject_Init
(
type_cls
,
type_cls
);
none_cls
=
new
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
0
,
sizeof
(
Box
),
false
,
NULL
);
none_cls
=
new
(
0
)
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
0
,
sizeof
(
Box
),
false
,
NULL
);
None
=
new
(
none_cls
)
Box
();
None
=
new
(
none_cls
)
Box
();
assert
(
None
->
cls
);
assert
(
None
->
cls
);
gc
::
registerPermanentRoot
(
None
);
gc
::
registerPermanentRoot
(
None
);
// You can't actually have an instance of basestring
// You can't actually have an instance of basestring
basestring_cls
=
new
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
0
,
sizeof
(
Box
),
false
,
NULL
);
basestring_cls
=
new
(
0
)
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
0
,
sizeof
(
Box
),
false
,
NULL
);
str_cls
=
new
BoxedHeapClass
(
basestring_cls
,
NULL
,
0
,
0
,
sizeof
(
BoxedString
),
false
,
NULL
);
// We add 1 to the tp_basicsize of the BoxedString in order to hold the null byte at the end.
str_cls
=
new
(
0
)
BoxedHeapClass
(
basestring_cls
,
NULL
,
0
,
0
,
sizeof
(
BoxedString
)
+
1
,
false
,
NULL
);
str_cls
->
tp_flags
|=
Py_TPFLAGS_STRING_SUBCLASS
;
str_cls
->
tp_flags
|=
Py_TPFLAGS_STRING_SUBCLASS
;
str_cls
->
tp_itemsize
=
sizeof
(
char
);
str_cls
->
tp_itemsize
=
sizeof
(
char
);
...
@@ -2116,57 +2155,59 @@ void setupRuntime() {
...
@@ -2116,57 +2155,59 @@ void setupRuntime() {
object_cls
->
giveAttr
(
"__base__"
,
None
);
object_cls
->
giveAttr
(
"__base__"
,
None
);
tuple_cls
tuple_cls
=
new
(
0
)
=
new
BoxedHeapClass
(
object_cls
,
&
tupleGCHandler
,
0
,
0
,
sizeof
(
BoxedTuple
),
false
,
boxStrConstant
(
"tuple"
));
BoxedHeapClass
(
object_cls
,
&
tupleGCHandler
,
0
,
0
,
sizeof
(
BoxedTuple
),
false
,
boxStrConstant
(
"tuple"
));
tuple_cls
->
tp_flags
|=
Py_TPFLAGS_TUPLE_SUBCLASS
;
tuple_cls
->
tp_flags
|=
Py_TPFLAGS_TUPLE_SUBCLASS
;
tuple_cls
->
tp_itemsize
=
sizeof
(
Box
*
);
tuple_cls
->
tp_itemsize
=
sizeof
(
Box
*
);
tuple_cls
->
tp_mro
=
BoxedTuple
::
create
({
tuple_cls
,
object_cls
});
tuple_cls
->
tp_mro
=
BoxedTuple
::
create
({
tuple_cls
,
object_cls
});
EmptyTuple
=
BoxedTuple
::
create
({});
EmptyTuple
=
BoxedTuple
::
create
({});
gc
::
registerPermanentRoot
(
EmptyTuple
);
gc
::
registerPermanentRoot
(
EmptyTuple
);
list_cls
=
new
BoxedHeapClass
(
object_cls
,
&
listGCHandler
,
0
,
0
,
sizeof
(
BoxedList
),
false
,
boxStrConstant
(
"list"
));
list_cls
=
new
(
0
)
BoxedHeapClass
(
object_cls
,
&
listGCHandler
,
0
,
0
,
sizeof
(
BoxedList
),
false
,
boxStrConstant
(
"list"
));
list_cls
->
tp_flags
|=
Py_TPFLAGS_LIST_SUBCLASS
;
list_cls
->
tp_flags
|=
Py_TPFLAGS_LIST_SUBCLASS
;
pyston_getset_cls
pyston_getset_cls
=
new
(
0
)
=
new
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
0
,
sizeof
(
BoxedGetsetDescriptor
),
false
,
boxStrConstant
(
"getset"
));
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
0
,
sizeof
(
BoxedGetsetDescriptor
),
false
,
boxStrConstant
(
"getset"
));
attrwrapper_cls
=
new
BoxedHeapClass
(
object_cls
,
&
AttrWrapper
::
gcHandler
,
0
,
0
,
sizeof
(
AttrWrapper
),
false
,
attrwrapper_cls
=
new
(
0
)
BoxedHeapClass
(
object_cls
,
&
AttrWrapper
::
gcHandler
,
0
,
0
,
sizeof
(
AttrWrapper
),
false
,
static_cast
<
BoxedString
*>
(
boxStrConstant
(
"attrwrapper"
)));
static_cast
<
BoxedString
*>
(
boxStrConstant
(
"attrwrapper"
)));
dict_cls
=
new
BoxedHeapClass
(
object_cls
,
&
dictGCHandler
,
0
,
0
,
sizeof
(
BoxedDict
),
false
,
dict_cls
=
new
(
0
)
BoxedHeapClass
(
object_cls
,
&
dictGCHandler
,
0
,
0
,
sizeof
(
BoxedDict
),
false
,
static_cast
<
BoxedString
*>
(
boxStrConstant
(
"dict"
)));
static_cast
<
BoxedString
*>
(
boxStrConstant
(
"dict"
)));
dict_cls
->
tp_flags
|=
Py_TPFLAGS_DICT_SUBCLASS
;
dict_cls
->
tp_flags
|=
Py_TPFLAGS_DICT_SUBCLASS
;
file_cls
=
new
BoxedHeapClass
(
object_cls
,
&
BoxedFile
::
gcHandler
,
0
,
offsetof
(
BoxedFile
,
weakreflist
),
file_cls
=
new
(
0
)
BoxedHeapClass
(
object_cls
,
&
BoxedFile
::
gcHandler
,
0
,
offsetof
(
BoxedFile
,
weakreflist
),
sizeof
(
BoxedFile
),
false
,
static_cast
<
BoxedString
*>
(
boxStrConstant
(
"file"
)));
sizeof
(
BoxedFile
),
false
,
static_cast
<
BoxedString
*>
(
boxStrConstant
(
"file"
)));
int_cls
=
new
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
0
,
sizeof
(
BoxedInt
),
false
,
int_cls
=
new
(
0
)
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
0
,
sizeof
(
BoxedInt
),
false
,
static_cast
<
BoxedString
*>
(
boxStrConstant
(
"int"
)));
static_cast
<
BoxedString
*>
(
boxStrConstant
(
"int"
)));
int_cls
->
tp_flags
|=
Py_TPFLAGS_INT_SUBCLASS
;
int_cls
->
tp_flags
|=
Py_TPFLAGS_INT_SUBCLASS
;
bool_cls
=
new
BoxedHeapClass
(
int_cls
,
NULL
,
0
,
0
,
sizeof
(
BoxedBool
),
false
,
bool_cls
=
new
(
0
)
BoxedHeapClass
(
int_cls
,
NULL
,
0
,
0
,
sizeof
(
BoxedBool
),
false
,
static_cast
<
BoxedString
*>
(
boxStrConstant
(
"bool"
)));
static_cast
<
BoxedString
*>
(
boxStrConstant
(
"bool"
)));
complex_cls
=
new
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
0
,
sizeof
(
BoxedComplex
),
false
,
complex_cls
=
new
(
0
)
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
0
,
sizeof
(
BoxedComplex
),
false
,
static_cast
<
BoxedString
*>
(
boxStrConstant
(
"complex"
)));
static_cast
<
BoxedString
*>
(
boxStrConstant
(
"complex"
)));
long_cls
=
new
BoxedHeapClass
(
object_cls
,
&
BoxedLong
::
gchandler
,
0
,
0
,
sizeof
(
BoxedLong
),
false
,
long_cls
=
new
(
0
)
BoxedHeapClass
(
object_cls
,
&
BoxedLong
::
gchandler
,
0
,
0
,
sizeof
(
BoxedLong
),
false
,
static_cast
<
BoxedString
*>
(
boxStrConstant
(
"long"
)));
static_cast
<
BoxedString
*>
(
boxStrConstant
(
"long"
)));
long_cls
->
tp_flags
|=
Py_TPFLAGS_LONG_SUBCLASS
;
long_cls
->
tp_flags
|=
Py_TPFLAGS_LONG_SUBCLASS
;
float_cls
=
new
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
0
,
sizeof
(
BoxedFloat
),
false
,
float_cls
=
new
(
0
)
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
0
,
sizeof
(
BoxedFloat
),
false
,
static_cast
<
BoxedString
*>
(
boxStrConstant
(
"float"
)));
static_cast
<
BoxedString
*>
(
boxStrConstant
(
"float"
)));
function_cls
=
new
BoxedHeapClass
(
object_cls
,
&
functionGCHandler
,
offsetof
(
BoxedFunction
,
attrs
),
function_cls
=
new
(
0
)
BoxedHeapClass
(
object_cls
,
&
functionGCHandler
,
offsetof
(
BoxedFunction
,
attrs
),
offsetof
(
BoxedFunction
,
in_weakreflist
),
sizeof
(
BoxedFunction
),
false
,
offsetof
(
BoxedFunction
,
in_weakreflist
),
sizeof
(
BoxedFunction
),
false
,
static_cast
<
BoxedString
*>
(
boxStrConstant
(
"function"
)));
static_cast
<
BoxedString
*>
(
boxStrConstant
(
"function"
)));
builtin_function_or_method_cls
builtin_function_or_method_cls
=
new
(
0
)
=
new
BoxedHeapClass
(
object_cls
,
&
functionGCHandler
,
0
,
offsetof
(
BoxedBuiltinFunctionOrMethod
,
in_weakreflist
),
BoxedHeapClass
(
object_cls
,
&
functionGCHandler
,
0
,
offsetof
(
BoxedBuiltinFunctionOrMethod
,
in_weakreflist
),
sizeof
(
BoxedBuiltinFunctionOrMethod
),
false
,
sizeof
(
BoxedBuiltinFunctionOrMethod
),
false
,
static_cast
<
BoxedString
*>
(
boxStrConstant
(
"builtin_function_or_method"
)));
static_cast
<
BoxedString
*>
(
boxStrConstant
(
"builtin_function_or_method"
)));
function_cls
->
simple_destructor
=
builtin_function_or_method_cls
->
simple_destructor
=
functionDtor
;
function_cls
->
simple_destructor
=
builtin_function_or_method_cls
->
simple_destructor
=
functionDtor
;
module_cls
=
new
BoxedHeapClass
(
object_cls
,
&
moduleGCHandler
,
offsetof
(
BoxedModule
,
attrs
),
0
,
sizeof
(
BoxedModule
),
module_cls
=
new
(
0
)
false
,
static_cast
<
BoxedString
*>
(
boxStrConstant
(
"module"
)));
BoxedHeapClass
(
object_cls
,
&
moduleGCHandler
,
offsetof
(
BoxedModule
,
attrs
),
0
,
sizeof
(
BoxedModule
),
false
,
member_descriptor_cls
=
new
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
0
,
sizeof
(
BoxedMemberDescriptor
),
false
,
static_cast
<
BoxedString
*>
(
boxStrConstant
(
"module"
)));
member_descriptor_cls
=
new
(
0
)
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
0
,
sizeof
(
BoxedMemberDescriptor
),
false
,
static_cast
<
BoxedString
*>
(
boxStrConstant
(
"member_descriptor"
)));
static_cast
<
BoxedString
*>
(
boxStrConstant
(
"member_descriptor"
)));
capifunc_cls
=
new
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
0
,
sizeof
(
BoxedCApiFunction
),
false
,
capifunc_cls
=
new
(
0
)
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
0
,
sizeof
(
BoxedCApiFunction
),
false
,
static_cast
<
BoxedString
*>
(
boxStrConstant
(
"capifunc"
)));
static_cast
<
BoxedString
*>
(
boxStrConstant
(
"capifunc"
)));
method_cls
=
new
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
0
,
sizeof
(
BoxedMethodDescriptor
),
false
,
method_cls
=
new
(
0
)
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
0
,
sizeof
(
BoxedMethodDescriptor
),
false
,
static_cast
<
BoxedString
*>
(
boxStrConstant
(
"method"
)));
static_cast
<
BoxedString
*>
(
boxStrConstant
(
"method"
)));
wrapperobject_cls
=
new
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
0
,
sizeof
(
BoxedWrapperObject
),
false
,
wrapperobject_cls
=
new
(
0
)
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
0
,
sizeof
(
BoxedWrapperObject
),
false
,
static_cast
<
BoxedString
*>
(
boxStrConstant
(
"method-wrapper"
)));
static_cast
<
BoxedString
*>
(
boxStrConstant
(
"method-wrapper"
)));
wrapperdescr_cls
=
new
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
0
,
sizeof
(
BoxedWrapperDescriptor
),
false
,
wrapperdescr_cls
=
new
(
0
)
BoxedHeapClass
(
object_cls
,
NULL
,
0
,
0
,
sizeof
(
BoxedWrapperDescriptor
),
false
,
static_cast
<
BoxedString
*>
(
boxStrConstant
(
"wrapper_descriptor"
)));
static_cast
<
BoxedString
*>
(
boxStrConstant
(
"wrapper_descriptor"
)));
EmptyString
=
boxStrConstant
(
""
);
EmptyString
=
boxStrConstant
(
""
);
...
...
src/runtime/types.h
View file @
b5f06903
...
@@ -177,7 +177,10 @@ public:
...
@@ -177,7 +177,10 @@ public:
void
(
*
simple_destructor
)(
Box
*
);
void
(
*
simple_destructor
)(
Box
*
);
// Offset of the HCAttrs object or 0 if there are no hcattrs.
// Offset of the HCAttrs object or 0 if there are no hcattrs.
// Negative offset is from the end of the class (useful for variable-size objects with the attrs at the end)
// Analogous to tp_dictoffset
// Analogous to tp_dictoffset
// A class should have at most of one attrs_offset and tp_dictoffset be nonzero.
// (But having nonzero attrs_offset here would map to having nonzero tp_dictoffset in CPython)
const
int
attrs_offset
;
const
int
attrs_offset
;
bool
instancesHaveHCAttrs
()
{
return
attrs_offset
!=
0
;
}
bool
instancesHaveHCAttrs
()
{
return
attrs_offset
!=
0
;
}
...
@@ -231,12 +234,16 @@ public:
...
@@ -231,12 +234,16 @@ public:
PyBufferProcs
as_buffer
;
PyBufferProcs
as_buffer
;
BoxedString
*
ht_name
;
BoxedString
*
ht_name
;
PyObject
**
ht_slots
;
PyObject
*
ht_slots
;
typedef
size_t
SlotOffset
;
SlotOffset
*
slotOffsets
()
{
return
(
BoxedHeapClass
::
SlotOffset
*
)((
char
*
)
this
+
this
->
cls
->
tp_basicsize
);
}
size_t
nslots
()
{
return
this
->
ob_size
;
}
// These functions are the preferred way to construct new types:
// These functions are the preferred way to construct new types:
static
BoxedHeapClass
*
create
(
BoxedClass
*
metatype
,
BoxedClass
*
base
,
gcvisit_func
gc_visit
,
int
attrs_offset
,
static
BoxedHeapClass
*
create
(
BoxedClass
*
metatype
,
BoxedClass
*
base
,
gcvisit_func
gc_visit
,
int
attrs_offset
,
int
weaklist_offset
,
int
instance_size
,
bool
is_user_defined
,
BoxedString
*
name
,
int
weaklist_offset
,
int
instance_size
,
bool
is_user_defined
,
BoxedString
*
name
,
BoxedTuple
*
bases
);
BoxedTuple
*
bases
,
size_t
nslots
);
static
BoxedHeapClass
*
create
(
BoxedClass
*
metatype
,
BoxedClass
*
base
,
gcvisit_func
gc_visit
,
int
attrs_offset
,
static
BoxedHeapClass
*
create
(
BoxedClass
*
metatype
,
BoxedClass
*
base
,
gcvisit_func
gc_visit
,
int
attrs_offset
,
int
weaklist_offset
,
int
instance_size
,
bool
is_user_defined
,
int
weaklist_offset
,
int
instance_size
,
bool
is_user_defined
,
const
std
::
string
&
name
);
const
std
::
string
&
name
);
...
@@ -251,7 +258,7 @@ private:
...
@@ -251,7 +258,7 @@ private:
friend
void
setupRuntime
();
friend
void
setupRuntime
();
friend
void
setupSys
();
friend
void
setupSys
();
DEFAULT_CLASS
(
type_cls
);
DEFAULT_CLASS
_VAR
(
type_cls
,
sizeof
(
SlotOffset
)
);
};
};
static_assert
(
sizeof
(
pyston
::
Box
)
==
sizeof
(
struct
_object
),
""
);
static_assert
(
sizeof
(
pyston
::
Box
)
==
sizeof
(
struct
_object
),
""
);
...
@@ -417,7 +424,7 @@ public:
...
@@ -417,7 +424,7 @@ public:
DEFAULT_CLASS_SIMPLE
(
bool_cls
);
DEFAULT_CLASS_SIMPLE
(
bool_cls
);
};
};
class
BoxedString
:
public
Box
{
class
BoxedString
:
public
Box
Var
{
public:
public:
llvm
::
StringRef
s
;
llvm
::
StringRef
s
;
char
interned_state
;
char
interned_state
;
...
@@ -425,40 +432,28 @@ public:
...
@@ -425,40 +432,28 @@ public:
char
*
data
()
{
return
const_cast
<
char
*>
(
s
.
data
());
}
char
*
data
()
{
return
const_cast
<
char
*>
(
s
.
data
());
}
size_t
size
()
{
return
s
.
size
();
}
size_t
size
()
{
return
s
.
size
();
}
void
*
operator
new
(
size_t
size
,
size_t
ssize
)
__attribute__
((
visibility
(
"default"
)))
{
// DEFAULT_CLASS_VAR_SIMPLE doesn't work because of the +1 for the null byte
#if STAT_ALLOCATIONS
void
*
operator
new
(
size_t
size
,
BoxedClass
*
cls
,
size_t
nitems
)
__attribute__
((
visibility
(
"default"
)))
{
static
StatCounter
alloc_str
(
"alloc.str"
);
ALLOC_STATS_VAR
(
str_cls
)
static
StatCounter
alloc_str1
(
"alloc.str(1)"
);
static
StatCounter
allocsize_str
(
"allocsize.str"
);
if
(
ssize
==
1
)
alloc_str1
.
log
();
else
alloc_str
.
log
();
allocsize_str
.
log
(
str_cls
->
tp_basicsize
+
ssize
+
1
);
assert
(
cls
->
tp_itemsize
==
sizeof
(
char
));
#endif
return
BoxVar
::
operator
new
(
size
,
cls
,
nitems
);
Box
*
rtn
=
static_cast
<
Box
*>
(
gc_alloc
(
str_cls
->
tp_basicsize
+
ssize
+
1
,
gc
::
GCKind
::
PYTHON
));
rtn
->
cls
=
str_cls
;
return
rtn
;
}
}
void
*
operator
new
(
size_t
size
,
size_t
nitems
)
__attribute__
((
visibility
(
"default"
)))
{
ALLOC_STATS_VAR
(
str_cls
)
void
*
operator
new
(
size_t
size
,
BoxedClass
*
cls
,
size_t
ssize
)
__attribute__
((
visibility
(
"default"
)))
{
assert
(
str_cls
->
tp_alloc
==
PystonType_GenericAlloc
);
#if STAT_ALLOCATIONS
assert
(
str_cls
->
tp_itemsize
==
1
);
static
StatCounter
alloc_str
(
"alloc.str"
);
assert
(
str_cls
->
tp_basicsize
==
sizeof
(
BoxedString
)
+
1
);
static
StatCounter
alloc_str1
(
"alloc.str(1)"
);
assert
(
str_cls
->
is_pyston_class
);
assert
(
str_cls
->
attrs_offset
==
0
);
static
StatCounter
allocsize_str
(
"allocsize.str"
);
if
(
ssize
==
1
)
void
*
mem
=
gc_alloc
(
sizeof
(
BoxedString
)
+
1
+
nitems
,
gc
::
GCKind
::
PYTHON
);
alloc_str1
.
log
();
assert
(
mem
);
else
alloc_str
.
log
();
allocsize_str
.
log
(
cls
->
tp_basicsize
+
ssize
+
1
);
BoxVar
*
rtn
=
static_cast
<
BoxVar
*>
(
mem
);
#endif
rtn
->
cls
=
str_cls
;
Box
*
rtn
=
static_cast
<
Box
*>
(
cls
->
tp_alloc
(
cls
,
ssize
+
1
));
rtn
->
ob_size
=
nitems
;
rtn
->
cls
=
cls
;
return
rtn
;
return
rtn
;
}
}
...
@@ -470,7 +465,8 @@ public:
...
@@ -470,7 +465,8 @@ public:
private:
private:
// used only in ctors to give our llvm::StringRef the proper pointer
// used only in ctors to give our llvm::StringRef the proper pointer
char
*
storage
()
{
return
(
char
*
)
this
+
cls
->
tp_basicsize
;
}
// Note: sizeof(BoxedString) = str_cls->tp_basicsize - 1
char
*
storage
()
{
return
(
char
*
)
this
+
sizeof
(
BoxedString
);
}
void
*
operator
new
(
size_t
size
)
=
delete
;
void
*
operator
new
(
size_t
size
)
=
delete
;
};
};
...
@@ -551,54 +547,13 @@ public:
...
@@ -551,54 +547,13 @@ public:
DEFAULT_CLASS_SIMPLE
(
list_cls
);
DEFAULT_CLASS_SIMPLE
(
list_cls
);
};
};
class
BoxedTuple
:
public
Box
{
class
BoxedTuple
:
public
Box
Var
{
public:
public:
typedef
std
::
vector
<
Box
*
,
StlCompatAllocator
<
Box
*>>
GCVector
;
typedef
std
::
vector
<
Box
*
,
StlCompatAllocator
<
Box
*>>
GCVector
;
Box
**
elts
;
Box
**
elts
;
void
*
operator
new
(
size_t
size
,
size_t
nelts
)
__attribute__
((
visibility
(
"default"
)))
{
DEFAULT_CLASS_VAR_SIMPLE
(
tuple_cls
,
sizeof
(
Box
*
));
#if STAT_ALLOCATIONS
static
StatCounter
alloc_tuple
(
"alloc.tuple"
);
static
StatCounter
alloc_tuple0
(
"alloc.tuple(0)"
);
static
StatCounter
allocsize_tuple
(
"allocsize.tuple"
);
static
StatCounter
allocsize_tuple0
(
"allocsize.tuple(0)"
);
if
(
nelts
==
0
)
{
alloc_tuple0
.
log
();
allocsize_tuple0
.
log
(
_PyObject_VAR_SIZE
(
tuple_cls
,
nelts
+
1
));
}
else
{
alloc_tuple
.
log
();
allocsize_tuple
.
log
(
_PyObject_VAR_SIZE
(
tuple_cls
,
nelts
+
1
));
}
#endif
Box
*
rtn
=
static_cast
<
Box
*>
(
gc_alloc
(
_PyObject_VAR_SIZE
(
tuple_cls
,
nelts
+
1
),
gc
::
GCKind
::
PYTHON
));
rtn
->
cls
=
tuple_cls
;
return
rtn
;
}
void
*
operator
new
(
size_t
size
,
BoxedClass
*
cls
,
size_t
nelts
)
__attribute__
((
visibility
(
"default"
)))
{
#if STAT_ALLOCATIONS
static
StatCounter
alloc_tuple
(
"alloc.tuple"
);
static
StatCounter
alloc_tuple0
(
"alloc.tuple(0)"
);
static
StatCounter
allocsize_tuple
(
"allocsize.tuple"
);
static
StatCounter
allocsize_tuple0
(
"allocsize.tuple(0)"
);
if
(
nelts
==
0
)
{
alloc_tuple0
.
log
();
allocsize_tuple0
.
log
(
_PyObject_VAR_SIZE
(
cls
,
nelts
+
1
));
}
else
{
alloc_tuple
.
log
();
allocsize_tuple
.
log
(
_PyObject_VAR_SIZE
(
cls
,
nelts
+
1
));
}
#endif
Box
*
rtn
=
static_cast
<
Box
*>
(
cls
->
tp_alloc
(
cls
,
nelts
));
rtn
->
cls
=
cls
;
return
rtn
;
}
static
BoxedTuple
*
create
(
int64_t
size
)
{
return
new
(
size
)
BoxedTuple
(
size
);
}
static
BoxedTuple
*
create
(
int64_t
size
)
{
return
new
(
size
)
BoxedTuple
(
size
);
}
static
BoxedTuple
*
create
(
int64_t
nelts
,
Box
**
elts
)
{
static
BoxedTuple
*
create
(
int64_t
nelts
,
Box
**
elts
)
{
...
@@ -640,18 +595,19 @@ public:
...
@@ -640,18 +595,19 @@ public:
Box
**
begin
()
const
{
return
&
elts
[
0
];
}
Box
**
begin
()
const
{
return
&
elts
[
0
];
}
Box
**
end
()
const
{
return
&
elts
[
nelts
];
}
Box
**
end
()
const
{
return
&
elts
[
nelts
];
}
Box
*&
operator
[](
size_t
index
)
{
return
elts
[
index
];
}
size_t
size
()
const
{
return
nelts
;
}
size_t
size
()
const
{
return
nelts
;
}
private:
private:
size_t
nelts
;
size_t
nelts
;
BoxedTuple
(
size_t
size
)
:
elts
(
reinterpret_cast
<
Box
**>
((
char
*
)
this
+
t
his
->
cls
->
tp_basicsize
)),
nelts
(
size
)
{
BoxedTuple
(
size_t
size
)
:
elts
(
reinterpret_cast
<
Box
**>
((
char
*
)
this
+
t
uple_
cls
->
tp_basicsize
)),
nelts
(
size
)
{
memset
(
elts
,
0
,
sizeof
(
Box
*
)
*
size
);
memset
(
elts
,
0
,
sizeof
(
Box
*
)
*
size
);
}
}
BoxedTuple
(
std
::
initializer_list
<
Box
*>&
members
)
BoxedTuple
(
std
::
initializer_list
<
Box
*>&
members
)
:
elts
(
reinterpret_cast
<
Box
**>
((
char
*
)
this
+
t
his
->
cls
->
tp_basicsize
)),
nelts
(
members
.
size
())
{
:
elts
(
reinterpret_cast
<
Box
**>
((
char
*
)
this
+
t
uple_
cls
->
tp_basicsize
)),
nelts
(
members
.
size
())
{
// by the time we make it here elts[] is big enough to contain members
// by the time we make it here elts[] is big enough to contain members
Box
**
p
=
&
elts
[
0
];
Box
**
p
=
&
elts
[
0
];
for
(
auto
b
:
members
)
{
for
(
auto
b
:
members
)
{
...
...
test/tests/python_slots_test.py
0 → 100644
View file @
b5f06903
print
'basic test'
class
C
(
object
):
__slots__
=
[
'a'
,
'b'
,
'__private_var'
]
c
=
C
()
try
:
print
c
.
a
except
AttributeError
as
e
:
print
e
.
message
c
.
a
=
5
print
c
.
a
print
c
.
__slots__
c
.
_C__private_var
=
6
print
c
.
_C__private_var
try
:
c
.
x
=
12
except
AttributeError
as
e
:
print
e
.
message
print
'testing __dict__'
class
C
(
object
):
__slots__
=
[
'd'
,
'e'
,
'__dict__'
]
c
=
C
()
c
.
d
=
5
print
c
.
d
c
.
r
=
6
print
c
.
r
print
c
.
__dict__
.
items
()
# dict should contain only r (not d)
print
'testing inheritance'
class
C
(
object
):
__slots__
=
[
'a'
,
'b'
]
class
D
(
object
):
__slots__
=
[
'c'
,
'd'
]
class
E
(
object
):
pass
class
G
(
C
):
__slots__
=
[
'k'
,
'l'
]
g
=
G
()
g
.
a
=
5
print
g
.
a
g
.
k
=
12
print
g
.
k
class
G
(
C
,
E
):
__slots__
=
[
'k'
,
'l'
]
g
=
G
()
g
.
a
=
5
print
g
.
a
g
.
k
=
12
print
g
.
k
class
G
(
E
,
C
):
__slots__
=
[
'k'
,
'l'
]
g
=
G
()
g
.
a
=
5
print
g
.
a
g
.
k
=
12
print
g
.
k
try
:
class
G
(
C
,
D
):
pass
except
TypeError
as
e
:
print
e
.
message
print
'testing a lot of slots'
class
C
(
object
):
__slots__
=
[
'a'
+
str
(
i
)
for
i
in
xrange
(
1000
)]
c
=
C
()
c
.
a0
=
-
8
print
c
.
a0
for
i
in
xrange
(
1000
):
setattr
(
c
,
'a'
+
str
(
i
),
i
)
for
i
in
xrange
(
1000
):
print
getattr
(
c
,
'a'
+
str
(
i
))
print
'slots on a subclass of str'
try
:
class
C
(
str
):
__slots__
=
[
'a'
]
except
TypeError
as
e
:
print
e
.
message
print
'slots on a class with a metaclass'
class
M
(
type
):
def
__new__
(
*
args
):
print
"M.__new__"
,
args
[:
3
]
return
type
.
__new__
(
*
args
)
def
__call__
(
*
args
):
print
"M.__call__"
,
args
[:
3
]
return
type
.
__call__
(
*
args
)
class
C
(
object
):
__metaclass__
=
M
__slots__
=
[
'a'
,
'b'
]
c
=
C
()
c
.
a
=
5
print
c
.
a
c
.
b
=
6
print
c
.
b
test/tests/str_subclassing_gc.py
View file @
b5f06903
...
@@ -8,3 +8,8 @@ def f():
...
@@ -8,3 +8,8 @@ def f():
for
i
in
xrange
(
100
):
for
i
in
xrange
(
100
):
s
=
S
(
base
)
s
=
S
(
base
)
f
()
f
()
# make sure it has attrs
s
=
S
(
"blah"
)
s
.
blah
=
2
print
s
.
blah
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment