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
d5ba641b
Commit
d5ba641b
authored
Dec 13, 2014
by
Kevin Modzelewski
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'getitem'
parents
15e86e4f
01a0b1a7
Changes
22
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
883 additions
and
109 deletions
+883
-109
Makefile
Makefile
+1
-0
src/capi/modsupport.cpp
src/capi/modsupport.cpp
+145
-9
src/capi/typeobject.cpp
src/capi/typeobject.cpp
+459
-15
src/capi/types.h
src/capi/types.h
+6
-7
src/runtime/builtin_modules/builtins.cpp
src/runtime/builtin_modules/builtins.cpp
+5
-4
src/runtime/builtin_modules/sys.cpp
src/runtime/builtin_modules/sys.cpp
+1
-1
src/runtime/capi.cpp
src/runtime/capi.cpp
+14
-6
src/runtime/classobj.cpp
src/runtime/classobj.cpp
+4
-4
src/runtime/dict.cpp
src/runtime/dict.cpp
+1
-1
src/runtime/generator.cpp
src/runtime/generator.cpp
+2
-2
src/runtime/inline/xrange.cpp
src/runtime/inline/xrange.cpp
+3
-3
src/runtime/iterobject.cpp
src/runtime/iterobject.cpp
+1
-1
src/runtime/list.cpp
src/runtime/list.cpp
+1
-1
src/runtime/objmodel.cpp
src/runtime/objmodel.cpp
+16
-2
src/runtime/set.cpp
src/runtime/set.cpp
+1
-1
src/runtime/str.cpp
src/runtime/str.cpp
+1
-1
src/runtime/super.cpp
src/runtime/super.cpp
+1
-1
src/runtime/tuple.cpp
src/runtime/tuple.cpp
+2
-1
src/runtime/types.cpp
src/runtime/types.cpp
+32
-29
src/runtime/types.h
src/runtime/types.h
+26
-4
test/test_extension/slots_test.c
test/test_extension/slots_test.c
+142
-12
test/tests/capi_slots.py
test/tests/capi_slots.py
+19
-4
No files found.
Makefile
View file @
d5ba641b
...
...
@@ -142,6 +142,7 @@ COMMON_CXXFLAGS += -fexceptions -fno-rtti
COMMON_CXXFLAGS
+=
-Wno-invalid-offsetof
# allow the use of "offsetof", and we'll just have to make sure to only use it legally.
COMMON_CXXFLAGS
+=
-DENABLE_INTEL_JIT_EVENTS
=
$(ENABLE_INTEL_JIT_EVENTS)
COMMON_CXXFLAGS
+=
-I
$(DEPS_DIR)
/pypa-install/include
COMMON_CXXFLAGS
+=
-Wno-comment
ifeq
($(ENABLE_VALGRIND),0)
COMMON_CXXFLAGS
+=
-DNVALGRIND
...
...
src/capi/modsupport.cpp
View file @
d5ba641b
...
...
@@ -32,24 +32,160 @@ namespace pyston {
#define FLAG_SIZE_T 1
static
PyObject
*
va_build_value
(
const
char
*
fmt
,
va_list
va
,
int
flags
)
{
int
len
=
strlen
(
fmt
);
if
(
len
==
0
)
return
None
;
static
int
countformat
(
const
char
*
format
,
int
endchar
)
{
int
count
=
0
;
int
level
=
0
;
while
(
level
>
0
||
*
format
!=
endchar
)
{
switch
(
*
format
)
{
case
'\0'
:
/* Premature end */
PyErr_SetString
(
PyExc_SystemError
,
"unmatched paren in format"
);
return
-
1
;
case
'('
:
case
'['
:
case
'{'
:
if
(
level
==
0
)
count
++
;
level
++
;
break
;
case
')'
:
case
']'
:
case
'}'
:
level
--
;
break
;
case
'#'
:
case
'&'
:
case
','
:
case
':'
:
case
' '
:
case
'\t'
:
break
;
default:
if
(
level
==
0
)
count
++
;
}
format
++
;
}
return
count
;
}
static
PyObject
*
do_mktuple
(
const
char
**
,
va_list
*
,
int
,
int
,
int
)
noexcept
;
// static PyObject *do_mklist(const char**, va_list *, int, int, int) noexcept;
// static PyObject *do_mkdict(const char**, va_list *, int, int, int) noexcept;
static
PyObject
*
do_mkvalue
(
const
char
**
,
va_list
*
,
int
)
noexcept
;
static
PyObject
*
do_mkvalue
(
const
char
**
p_format
,
va_list
*
p_va
,
int
flags
)
noexcept
{
for
(;;)
{
switch
(
*
(
*
p_format
)
++
)
{
case
'('
:
return
do_mktuple
(
p_format
,
p_va
,
')'
,
countformat
(
*
p_format
,
')'
),
flags
);
#if 0
case '[':
return do_mklist(p_format, p_va, ']', countformat(*p_format, ']'), flags);
case '{':
return do_mkdict(p_format, p_va, '}', countformat(*p_format, '}'), flags);
#endif
if
(
len
==
1
)
{
switch
(
*
fmt
)
{
case
'b'
:
case
'B'
:
case
'h'
:
case
'i'
:
return
PyInt_FromLong
((
long
)
va_arg
(
va
,
int
));
return
PyInt_FromLong
((
long
)
va_arg
(
*
p_va
,
int
));
case
'H'
:
return
PyInt_FromLong
((
long
)
va_arg
(
*
p_va
,
unsigned
int
));
case
'N'
:
case
'S'
:
case
'O'
:
if
(
**
p_format
==
'&'
)
{
typedef
PyObject
*
(
*
converter
)(
void
*
);
converter
func
=
va_arg
(
*
p_va
,
converter
);
void
*
arg
=
va_arg
(
*
p_va
,
void
*
);
++*
p_format
;
return
(
*
func
)(
arg
);
}
else
{
PyObject
*
v
;
v
=
va_arg
(
*
p_va
,
PyObject
*
);
if
(
v
!=
NULL
)
{
if
(
*
(
*
p_format
-
1
)
!=
'N'
)
Py_INCREF
(
v
);
}
else
if
(
!
PyErr_Occurred
())
/* If a NULL was passed
* because a call that should
* have constructed a value
* failed, that's OK, and we
* pass the error on; but if
* no error occurred it's not
* clear that the caller knew
* what she was doing. */
PyErr_SetString
(
PyExc_SystemError
,
"NULL object passed to Py_BuildValue"
);
return
v
;
}
default:
RELEASE_ASSERT
(
0
,
"%c"
,
*
fmt
);
RELEASE_ASSERT
(
0
,
"%c"
,
*
((
*
p_format
)
-
1
));
}
}
abort
();
}
static
PyObject
*
do_mktuple
(
const
char
**
p_format
,
va_list
*
p_va
,
int
endchar
,
int
n
,
int
flags
)
noexcept
{
PyObject
*
v
;
int
i
;
int
itemfailed
=
0
;
if
(
n
<
0
)
return
NULL
;
if
((
v
=
PyTuple_New
(
n
))
==
NULL
)
return
NULL
;
/* Note that we can't bail immediately on error as this will leak
refcounts on any 'N' arguments. */
for
(
i
=
0
;
i
<
n
;
i
++
)
{
PyObject
*
w
=
do_mkvalue
(
p_format
,
p_va
,
flags
);
if
(
w
==
NULL
)
{
itemfailed
=
1
;
Py_INCREF
(
Py_None
);
w
=
Py_None
;
}
PyTuple_SET_ITEM
(
v
,
i
,
w
);
}
if
(
itemfailed
)
{
/* do_mkvalue() should have already set an error */
Py_DECREF
(
v
);
return
NULL
;
}
if
(
**
p_format
!=
endchar
)
{
Py_DECREF
(
v
);
PyErr_SetString
(
PyExc_SystemError
,
"Unmatched paren in format"
);
return
NULL
;
}
if
(
endchar
)
++*
p_format
;
return
v
;
}
static
PyObject
*
va_build_value
(
const
char
*
fmt
,
va_list
va
,
int
flags
)
{
int
n
=
countformat
(
fmt
,
'\0'
);
if
(
n
<
0
)
return
NULL
;
if
(
n
==
0
)
return
None
;
va_list
lva
;
__va_copy
(
lva
,
va
);
if
(
n
==
1
)
return
do_mkvalue
(
&
fmt
,
&
lva
,
flags
);
return
do_mktuple
(
&
fmt
,
&
lva
,
'\0'
,
n
,
flags
);
}
RELEASE_ASSERT
(
0
,
""
);
extern
"C"
PyObject
*
Py_VaBuildValue
(
const
char
*
format
,
va_list
va
)
{
return
va_build_value
(
format
,
va
,
0
);
}
extern
"C"
PyObject
*
_Py_BuildValue_SizeT
(
const
char
*
fmt
,
...)
{
...
...
src/capi/typeobject.cpp
View file @
d5ba641b
This diff is collapsed.
Click to expand it.
src/capi/types.h
View file @
d5ba641b
...
...
@@ -27,7 +27,7 @@ struct wrapper_def {
int
offset
;
void
*
function
;
// "generic" handler that gets put in the tp_* slot which proxies to the python version
wrapperfunc
wrapper
;
// "wrapper" that ends up getting called by the Python-visible WrapperDescr
// exists in CPython: const char* doc
const
char
*
doc
;
int
flags
;
// exists in CPython: PyObject *name_strobj
};
...
...
@@ -83,8 +83,9 @@ class BoxedWrapperDescriptor : public Box {
public:
const
wrapper_def
*
wrapper
;
BoxedClass
*
type
;
BoxedWrapperDescriptor
(
const
wrapper_def
*
wrapper
,
BoxedClass
*
type
)
:
Box
(
wrapperdescr_cls
),
wrapper
(
wrapper
),
type
(
type
)
{}
void
*
wrapped
;
BoxedWrapperDescriptor
(
const
wrapper_def
*
wrapper
,
BoxedClass
*
type
,
void
*
wrapped
)
:
Box
(
wrapperdescr_cls
),
wrapper
(
wrapper
),
type
(
type
),
wrapped
(
wrapped
)
{}
static
Box
*
__get__
(
BoxedWrapperDescriptor
*
self
,
Box
*
inst
,
Box
*
owner
);
};
...
...
@@ -104,14 +105,12 @@ public:
int
flags
=
self
->
descr
->
wrapper
->
flags
;
wrapperfunc
wrapper
=
self
->
descr
->
wrapper
->
wrapper
;
assert
(
self
->
descr
->
wrapper
->
offset
>
0
);
char
*
ptr
=
(
char
*
)
self
->
descr
->
type
+
self
->
descr
->
wrapper
->
offset
;
void
*
wrapped
=
*
reinterpret_cast
<
void
**>
(
ptr
);
if
(
flags
&
PyWrapperFlag_KEYWORDS
)
{
wrapperfunc_kwds
wk
=
(
wrapperfunc_kwds
)
wrapper
;
return
(
*
wk
)(
self
->
obj
,
args
,
wrapped
,
kwds
);
return
(
*
wk
)(
self
->
obj
,
args
,
self
->
descr
->
wrapped
,
kwds
);
}
else
{
return
(
*
wrapper
)(
self
->
obj
,
args
,
wrapped
);
return
(
*
wrapper
)(
self
->
obj
,
args
,
self
->
descr
->
wrapped
);
}
abort
();
}
...
...
src/runtime/builtin_modules/builtins.cpp
View file @
d5ba641b
...
...
@@ -497,7 +497,7 @@ Box* exceptionRepr(Box* b) {
static
BoxedClass
*
makeBuiltinException
(
BoxedClass
*
base
,
const
char
*
name
)
{
BoxedClass
*
cls
=
new
BoxedClass
(
type_cls
,
base
,
NULL
,
offsetof
(
BoxedException
,
attrs
),
sizeof
(
BoxedException
),
false
);
=
new
Boxed
Heap
Class
(
type_cls
,
base
,
NULL
,
offsetof
(
BoxedException
,
attrs
),
sizeof
(
BoxedException
),
false
);
cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
name
));
cls
->
giveAttr
(
"__module__"
,
boxStrConstant
(
"exceptions"
));
...
...
@@ -521,7 +521,7 @@ extern "C" PyObject* PyErr_NewException(char* name, PyObject* _base, PyObject* d
try
{
BoxedClass
*
base
=
Exception
;
BoxedClass
*
cls
=
new
BoxedClass
(
type_cls
,
base
,
NULL
,
offsetof
(
BoxedException
,
attrs
),
sizeof
(
BoxedException
),
true
);
=
new
Boxed
Heap
Class
(
type_cls
,
base
,
NULL
,
offsetof
(
BoxedException
,
attrs
),
sizeof
(
BoxedException
),
true
);
char
*
dot_pos
=
strchr
(
name
,
'.'
);
RELEASE_ASSERT
(
dot_pos
,
""
);
...
...
@@ -702,7 +702,7 @@ void setupBuiltins() {
builtins_module
->
giveAttr
(
"print"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
print
,
NONE
,
0
,
0
,
true
,
true
)));
notimplemented_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
Box
),
false
);
notimplemented_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
Box
),
false
);
notimplemented_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"NotImplementedType"
));
notimplemented_cls
->
giveAttr
(
"__repr__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
notimplementedRepr
,
STR
,
1
)));
notimplemented_cls
->
freeze
();
...
...
@@ -795,7 +795,8 @@ void setupBuiltins() {
builtins_module
->
giveAttr
(
"issubclass"
,
issubclass_obj
);
enumerate_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
BoxedEnumerate
::
gcHandler
,
0
,
sizeof
(
BoxedEnumerate
),
false
);
enumerate_cls
=
new
BoxedHeapClass
(
type_cls
,
object_cls
,
&
BoxedEnumerate
::
gcHandler
,
0
,
sizeof
(
BoxedEnumerate
),
false
);
enumerate_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"enumerate"
));
enumerate_cls
->
giveAttr
(
"__new__"
,
...
...
src/runtime/builtin_modules/sys.cpp
View file @
d5ba641b
...
...
@@ -126,7 +126,7 @@ void setupSys() {
sys_module
->
giveAttr
(
"maxint"
,
boxInt
(
PYSTON_INT_MAX
));
sys_flags_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
BoxedSysFlags
::
gcHandler
,
0
,
sizeof
(
BoxedSysFlags
),
false
);
sys_flags_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
BoxedSysFlags
::
gcHandler
,
0
,
sizeof
(
BoxedSysFlags
),
false
);
sys_flags_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"flags"
));
sys_flags_cls
->
giveAttr
(
"__new__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
BoxedSysFlags
::
__new__
,
UNKNOWN
,
1
,
0
,
true
,
true
)));
...
...
src/runtime/capi.cpp
View file @
d5ba641b
...
...
@@ -322,7 +322,10 @@ extern "C" int PyObject_Not(PyObject* o) {
extern
"C"
PyObject
*
PyObject_Call
(
PyObject
*
callable_object
,
PyObject
*
args
,
PyObject
*
kw
)
{
try
{
if
(
kw
)
return
runtimeCall
(
callable_object
,
ArgPassSpec
(
0
,
0
,
true
,
true
),
args
,
kw
,
NULL
,
NULL
,
NULL
);
else
return
runtimeCall
(
callable_object
,
ArgPassSpec
(
0
,
0
,
true
,
false
),
args
,
NULL
,
NULL
,
NULL
,
NULL
);
}
catch
(
Box
*
b
)
{
Py_FatalError
(
"unimplemented"
);
}
...
...
@@ -699,7 +702,12 @@ extern "C" PyObject* PyNumber_ToBase(PyObject* n, int base) {
}
extern
"C"
Py_ssize_t
PyNumber_AsSsize_t
(
PyObject
*
o
,
PyObject
*
exc
)
{
Py_FatalError
(
"unimplemented"
);
RELEASE_ASSERT
(
o
->
cls
!=
long_cls
,
"unhandled"
);
RELEASE_ASSERT
(
o
->
cls
==
int_cls
,
"??"
);
int64_t
n
=
static_cast
<
BoxedInt
*>
(
o
)
->
n
;
static_assert
(
sizeof
(
n
)
==
sizeof
(
Py_ssize_t
),
""
);
return
n
;
}
extern
"C"
Py_ssize_t
PyUnicode_GET_SIZE
(
PyObject
*
)
{
...
...
@@ -753,7 +761,7 @@ BoxedModule* importTestExtension(const std::string& name) {
}
void
setupCAPI
()
{
capifunc_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedCApiFunction
),
false
);
capifunc_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedCApiFunction
),
false
);
capifunc_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"capifunc"
));
capifunc_cls
->
giveAttr
(
"__repr__"
,
...
...
@@ -765,7 +773,7 @@ void setupCAPI() {
capifunc_cls
->
freeze
();
method_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedMethodDescriptor
),
false
);
method_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedMethodDescriptor
),
false
);
method_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"method"
));
method_cls
->
giveAttr
(
"__get__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
BoxedMethodDescriptor
::
__get__
,
UNKNOWN
,
3
)));
...
...
@@ -773,13 +781,13 @@ void setupCAPI() {
0
,
true
,
true
)));
method_cls
->
freeze
();
wrapperdescr_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedWrapperDescriptor
),
false
);
wrapperdescr_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedWrapperDescriptor
),
false
);
wrapperdescr_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"wrapper_descriptor"
));
wrapperdescr_cls
->
giveAttr
(
"__get__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
BoxedWrapperDescriptor
::
__get__
,
UNKNOWN
,
3
)));
wrapperdescr_cls
->
freeze
();
wrapperobject_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedWrapperObject
),
false
);
wrapperobject_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedWrapperObject
),
false
);
wrapperobject_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"method-wrapper"
));
wrapperobject_cls
->
giveAttr
(
"__call__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
BoxedWrapperObject
::
__call__
,
UNKNOWN
,
1
,
0
,
true
,
true
)));
...
...
src/runtime/classobj.cpp
View file @
d5ba641b
...
...
@@ -241,9 +241,9 @@ Box* instanceSetitem(Box* _inst, Box* key, Box* value) {
}
void
setupClassobj
()
{
classobj_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
BoxedClassobj
::
gcHandler
,
offsetof
(
BoxedClassobj
,
attrs
),
classobj_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
BoxedClassobj
::
gcHandler
,
offsetof
(
BoxedClassobj
,
attrs
),
sizeof
(
BoxedClassobj
),
false
);
instance_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
BoxedInstance
::
gcHandler
,
offsetof
(
BoxedInstance
,
attrs
),
instance_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
BoxedInstance
::
gcHandler
,
offsetof
(
BoxedInstance
,
attrs
),
sizeof
(
BoxedInstance
),
false
);
classobj_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"classobj"
));
...
...
src/runtime/dict.cpp
View file @
d5ba641b
...
...
@@ -378,7 +378,7 @@ extern "C" void dictIteratorGCHandler(GCVisitor* v, Box* b) {
}
void
setupDict
()
{
dict_iterator_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
dictIteratorGCHandler
,
0
,
sizeof
(
BoxedDict
),
false
);
dict_iterator_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
dictIteratorGCHandler
,
0
,
sizeof
(
BoxedDict
),
false
);
dict_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"dict"
));
dict_cls
->
giveAttr
(
"__len__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
dictLen
,
BOXED_INT
,
1
)));
...
...
src/runtime/generator.cpp
View file @
d5ba641b
...
...
@@ -177,7 +177,7 @@ extern "C" void generatorGCHandler(GCVisitor* v, Box* b) {
void
setupGenerator
()
{
generator_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
generatorGCHandler
,
offsetof
(
BoxedGenerator
,
attrs
),
generator_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
generatorGCHandler
,
offsetof
(
BoxedGenerator
,
attrs
),
sizeof
(
BoxedGenerator
),
false
);
generator_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"generator"
));
generator_cls
->
giveAttr
(
"__iter__"
,
...
...
src/runtime/inline/xrange.cpp
View file @
d5ba641b
...
...
@@ -113,9 +113,9 @@ Box* xrangeIter(Box* self) {
}
void
setupXrange
()
{
xrange_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedXrange
),
false
);
xrange_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedXrange
),
false
);
xrange_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"xrange"
));
xrange_iterator_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
BoxedXrangeIterator
::
xrangeIteratorGCHandler
,
0
,
xrange_iterator_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
BoxedXrangeIterator
::
xrangeIteratorGCHandler
,
0
,
sizeof
(
BoxedXrangeIterator
),
false
);
xrange_iterator_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"rangeiterator"
));
...
...
src/runtime/iterobject.cpp
View file @
d5ba641b
...
...
@@ -57,7 +57,7 @@ Box* seqiterNext(Box* s) {
}
void
setupIter
()
{
seqiter_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedSeqIter
),
false
);
seqiter_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedSeqIter
),
false
);
seqiter_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"iterator"
));
seqiter_cls
->
giveAttr
(
"next"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
seqiterNext
,
UNKNOWN
,
1
)));
...
...
src/runtime/list.cpp
View file @
d5ba641b
...
...
@@ -553,7 +553,7 @@ Box* listEq(BoxedList* self, Box* rhs) {
}
void
setupList
()
{
list_iterator_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
listIteratorGCHandler
,
0
,
sizeof
(
BoxedList
),
false
);
list_iterator_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
listIteratorGCHandler
,
0
,
sizeof
(
BoxedList
),
false
);
list_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"list"
));
...
...
src/runtime/objmodel.cpp
View file @
d5ba641b
...
...
@@ -389,6 +389,20 @@ BoxedClass::BoxedClass(BoxedClass* metaclass, BoxedClass* base, gcvisit_func gc_
gc
::
registerPermanentRoot
(
this
);
}
BoxedHeapClass
::
BoxedHeapClass
(
BoxedClass
*
metaclass
,
BoxedClass
*
base
,
gcvisit_func
gc_visit
,
int
attrs_offset
,
int
instance_size
,
bool
is_user_defined
)
:
BoxedClass
(
metaclass
,
base
,
gc_visit
,
attrs_offset
,
instance_size
,
is_user_defined
),
ht_name
(
NULL
),
ht_slots
(
NULL
)
{
tp_as_number
=
&
as_number
;
tp_as_mapping
=
&
as_mapping
;
tp_as_sequence
=
&
as_sequence
;
tp_as_buffer
=
&
as_buffer
;
// just make sure these get zero-initialized:
assert
(
as_sequence
.
sq_item
==
NULL
);
}
std
::
string
getFullNameOfClass
(
BoxedClass
*
cls
)
{
Box
*
b
=
cls
->
getattr
(
"__name__"
);
assert
(
b
);
...
...
@@ -3272,10 +3286,10 @@ Box* typeNew(Box* _cls, Box* arg1, Box* arg2, Box** _args) {
BoxedClass
*
made
;
if
(
base
->
instancesHaveAttrs
())
{
made
=
new
BoxedClass
(
cls
,
base
,
NULL
,
base
->
attrs_offset
,
base
->
tp_basicsize
,
true
);
made
=
new
Boxed
Heap
Class
(
cls
,
base
,
NULL
,
base
->
attrs_offset
,
base
->
tp_basicsize
,
true
);
}
else
{
assert
(
base
->
tp_basicsize
%
sizeof
(
void
*
)
==
0
);
made
=
new
BoxedClass
(
cls
,
base
,
NULL
,
base
->
tp_basicsize
,
base
->
tp_basicsize
+
sizeof
(
HCAttrs
),
true
);
made
=
new
Boxed
Heap
Class
(
cls
,
base
,
NULL
,
base
->
tp_basicsize
,
base
->
tp_basicsize
+
sizeof
(
HCAttrs
),
true
);
}
made
->
giveAttr
(
"__module__"
,
boxString
(
getCurrentModule
()
->
name
()));
...
...
src/runtime/set.cpp
View file @
d5ba641b
...
...
@@ -216,7 +216,7 @@ void setupSet() {
set_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"set"
));
frozenset_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"frozenset"
));
set_iterator_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
setIteratorGCHandler
,
0
,
sizeof
(
BoxedSet
),
false
);
set_iterator_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
setIteratorGCHandler
,
0
,
sizeof
(
BoxedSet
),
false
);
set_iterator_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"setiterator"
));
set_iterator_cls
->
giveAttr
(
"__hasnext__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
setiteratorHasnext
,
BOXED_BOOL
,
1
)));
...
...
src/runtime/str.cpp
View file @
d5ba641b
...
...
@@ -1037,7 +1037,7 @@ static PyBufferProcs string_as_buffer = {
};
void
setupStr
()
{
str_iterator_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
strIteratorGCHandler
,
0
,
sizeof
(
BoxedString
),
false
);
str_iterator_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
strIteratorGCHandler
,
0
,
sizeof
(
BoxedString
),
false
);
str_iterator_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"striterator"
));
str_iterator_cls
->
giveAttr
(
"__hasnext__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
BoxedStringIterator
::
hasnext
,
BOXED_BOOL
,
1
)));
...
...
src/runtime/super.cpp
View file @
d5ba641b
...
...
@@ -125,7 +125,7 @@ Box* superNew(Box* _cls, Box* _type, Box* obj) {
}
void
setupSuper
()
{
super_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
BoxedSuper
::
gcHandler
,
0
,
sizeof
(
BoxedSuper
),
false
);
super_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
BoxedSuper
::
gcHandler
,
0
,
sizeof
(
BoxedSuper
),
false
);
super_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"super"
));
...
...
src/runtime/tuple.cpp
View file @
d5ba641b
...
...
@@ -382,7 +382,8 @@ extern "C" void tupleIteratorGCHandler(GCVisitor* v, Box* b) {
void
setupTuple
()
{
tuple_iterator_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
tupleIteratorGCHandler
,
0
,
sizeof
(
BoxedTuple
),
false
);
tuple_iterator_cls
=
new
BoxedHeapClass
(
type_cls
,
object_cls
,
&
tupleIteratorGCHandler
,
0
,
sizeof
(
BoxedTuple
),
false
);
tuple_cls
->
giveAttr
(
"__name__"
,
boxStrConstant
(
"tuple"
));
...
...
src/runtime/types.cpp
View file @
d5ba641b
...
...
@@ -780,21 +780,22 @@ void setupRuntime() {
root_hcls
=
HiddenClass
::
makeRoot
();
gc
::
registerPermanentRoot
(
root_hcls
);
object_cls
=
new
BoxedClass
(
NULL
,
NULL
,
&
boxGCHandler
,
0
,
sizeof
(
Box
),
false
);
type_cls
=
new
BoxedClass
(
NULL
,
object_cls
,
&
typeGCHandler
,
offsetof
(
BoxedClass
,
attrs
),
sizeof
(
BoxedClass
),
false
);
object_cls
=
new
BoxedHeapClass
(
NULL
,
NULL
,
&
boxGCHandler
,
0
,
sizeof
(
Box
),
false
);
type_cls
=
new
BoxedHeapClass
(
NULL
,
object_cls
,
&
typeGCHandler
,
offsetof
(
BoxedClass
,
attrs
),
sizeof
(
BoxedClass
),
false
);
type_cls
->
cls
=
type_cls
;
object_cls
->
cls
=
type_cls
;
none_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
Box
),
false
);
none_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
Box
),
false
);
None
=
new
Box
(
none_cls
);
gc
::
registerPermanentRoot
(
None
);
// You can't actually have an instance of basestring
basestring_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
Box
),
false
);
basestring_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
Box
),
false
);
// TODO we leak all the string data!
str_cls
=
new
BoxedClass
(
type_cls
,
basestring_cls
,
NULL
,
0
,
sizeof
(
BoxedString
),
false
);
unicode_cls
=
new
BoxedClass
(
type_cls
,
basestring_cls
,
NULL
,
0
,
sizeof
(
BoxedUnicode
),
false
);
str_cls
=
new
Boxed
Heap
Class
(
type_cls
,
basestring_cls
,
NULL
,
0
,
sizeof
(
BoxedString
),
false
);
unicode_cls
=
new
Boxed
Heap
Class
(
type_cls
,
basestring_cls
,
NULL
,
0
,
sizeof
(
BoxedUnicode
),
false
);
// It wasn't safe to add __base__ attributes until object+type+str are set up, so do that now:
type_cls
->
giveAttr
(
"__base__"
,
object_cls
);
...
...
@@ -804,40 +805,42 @@ void setupRuntime() {
object_cls
->
giveAttr
(
"__base__"
,
None
);
tuple_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
tupleGCHandler
,
0
,
sizeof
(
BoxedTuple
),
false
);
tuple_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
tupleGCHandler
,
0
,
sizeof
(
BoxedTuple
),
false
);
EmptyTuple
=
new
BoxedTuple
({});
gc
::
registerPermanentRoot
(
EmptyTuple
);
module_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
NULL
,
offsetof
(
BoxedModule
,
attrs
),
sizeof
(
BoxedModule
),
false
);
module_cls
=
new
BoxedHeapClass
(
type_cls
,
object_cls
,
NULL
,
offsetof
(
BoxedModule
,
attrs
),
sizeof
(
BoxedModule
),
false
);
// TODO it'd be nice to be able to do these in the respective setupType methods,
// but those setup methods probably want access to these objects.
// We could have a multi-stage setup process, but that seems overkill for now.
bool_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedBool
),
false
);
int_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedInt
),
false
);
complex_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedComplex
),
false
);
bool_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedBool
),
false
);
int_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedInt
),
false
);
complex_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedComplex
),
false
);
// TODO we're leaking long memory!
long_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedLong
),
false
);
float_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedFloat
),
false
);
function_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
functionGCHandler
,
offsetof
(
BoxedFunction
,
attrs
),
long_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedLong
),
false
);
float_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedFloat
),
false
);
function_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
functionGCHandler
,
offsetof
(
BoxedFunction
,
attrs
),
sizeof
(
BoxedFunction
),
false
);
instancemethod_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
instancemethodGCHandler
,
0
,
sizeof
(
BoxedInstanceMethod
),
false
);
list_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
listGCHandler
,
0
,
sizeof
(
BoxedList
),
false
);
slice_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
sliceGCHandler
,
0
,
sizeof
(
BoxedSlice
),
false
);
dict_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
dictGCHandler
,
0
,
sizeof
(
BoxedDict
),
false
);
file_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedFile
),
false
);
set_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
setGCHandler
,
0
,
sizeof
(
BoxedSet
),
false
);
frozenset_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
setGCHandler
,
0
,
sizeof
(
BoxedSet
),
false
);
member_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedMemberDescriptor
),
false
);
closure_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
closureGCHandler
,
offsetof
(
BoxedClosure
,
attrs
),
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
instancemethodGCHandler
,
0
,
sizeof
(
BoxedInstanceMethod
),
false
);
list_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
listGCHandler
,
0
,
sizeof
(
BoxedList
),
false
);
slice_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
sliceGCHandler
,
0
,
sizeof
(
BoxedSlice
),
false
);
dict_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
dictGCHandler
,
0
,
sizeof
(
BoxedDict
),
false
);
file_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedFile
),
false
);
set_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
setGCHandler
,
0
,
sizeof
(
BoxedSet
),
false
);
frozenset_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
setGCHandler
,
0
,
sizeof
(
BoxedSet
),
false
);
member_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
NULL
,
0
,
sizeof
(
BoxedMemberDescriptor
),
false
);
closure_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
closureGCHandler
,
offsetof
(
BoxedClosure
,
attrs
),
sizeof
(
BoxedClosure
),
false
);
property_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
propertyGCHandler
,
0
,
sizeof
(
BoxedProperty
),
false
);
property_cls
=
new
Boxed
Heap
Class
(
type_cls
,
object_cls
,
&
propertyGCHandler
,
0
,
sizeof
(
BoxedProperty
),
false
);
staticmethod_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
staticmethodGCHandler
,
0
,
sizeof
(
BoxedStaticmethod
),
false
);
classmethod_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
classmethodGCHandler
,
0
,
sizeof
(
BoxedClassmethod
),
false
);
attrwrapper_cls
=
new
BoxedClass
(
type_cls
,
object_cls
,
&
AttrWrapper
::
gcHandler
,
0
,
sizeof
(
AttrWrapper
),
false
);
=
new
BoxedHeapClass
(
type_cls
,
object_cls
,
&
staticmethodGCHandler
,
0
,
sizeof
(
BoxedStaticmethod
),
false
);
classmethod_cls
=
new
BoxedHeapClass
(
type_cls
,
object_cls
,
&
classmethodGCHandler
,
0
,
sizeof
(
BoxedClassmethod
),
false
);
attrwrapper_cls
=
new
BoxedHeapClass
(
type_cls
,
object_cls
,
&
AttrWrapper
::
gcHandler
,
0
,
sizeof
(
AttrWrapper
),
false
);
STR
=
typeFromClass
(
str_cls
);
BOXED_INT
=
typeFromClass
(
int_cls
);
...
...
src/runtime/types.h
View file @
d5ba641b
...
...
@@ -172,6 +172,13 @@ class conservative_unordered_map
:
public
std
::
unordered_map
<
K
,
V
,
Hash
,
KeyEqual
,
StlCompatAllocator
<
std
::
pair
<
const
K
,
V
>
>
>
{};
class
BoxedClass
:
public
BoxVar
{
public:
typedef
void
(
*
gcvisit_func
)(
GCVisitor
*
,
Box
*
);
protected:
BoxedClass
(
BoxedClass
*
metaclass
,
BoxedClass
*
base
,
gcvisit_func
gc_visit
,
int
attrs_offset
,
int
instance_size
,
bool
is_user_defined
);
public:
PyTypeObject_BODY
;
...
...
@@ -195,7 +202,6 @@ public:
// Is NULL iff this is object_cls
BoxedClass
*
base
;
typedef
void
(
*
gcvisit_func
)(
GCVisitor
*
,
Box
*
);
gcvisit_func
gc_visit
;
// Offset of the HCAttrs object or 0 if there are no hcattrs.
...
...
@@ -217,12 +223,21 @@ public:
// will need to update this once we support tp_getattr-style overriding:
bool
hasGenericGetattr
()
{
return
true
;
}
BoxedClass
(
BoxedClass
*
metaclass
,
BoxedClass
*
base
,
gcvisit_func
gc_visit
,
int
attrs_offset
,
int
instance_size
,
bool
is_user_defined
);
void
freeze
();
};
class
BoxedHeapClass
:
public
BoxedClass
{
public:
PyNumberMethods
as_number
;
PyMappingMethods
as_mapping
;
PySequenceMethods
as_sequence
;
PyBufferProcs
as_buffer
;
PyObject
*
ht_name
,
*
ht_slots
;
BoxedHeapClass
(
BoxedClass
*
metaclass
,
BoxedClass
*
base
,
gcvisit_func
gc_visit
,
int
attrs_offset
,
int
instance_size
,
bool
is_user_defined
);
};
static_assert
(
sizeof
(
pyston
::
Box
)
==
sizeof
(
struct
_object
),
""
);
static_assert
(
offsetof
(
pyston
::
Box
,
cls
)
==
offsetof
(
struct
_object
,
ob_type
),
""
);
...
...
@@ -234,6 +249,13 @@ static_assert(offsetof(pyston::BoxedClass, base) == offsetof(struct _typeobject,
static_assert
(
offsetof
(
pyston
::
BoxedClass
,
gc_visit
)
==
offsetof
(
struct
_typeobject
,
_gcvisit_func
),
""
);
static_assert
(
sizeof
(
pyston
::
BoxedClass
)
==
sizeof
(
struct
_typeobject
),
""
);
static_assert
(
offsetof
(
pyston
::
BoxedHeapClass
,
base
)
==
offsetof
(
PyHeapTypeObject
,
ht_type
.
_base
),
""
);
static_assert
(
offsetof
(
pyston
::
BoxedHeapClass
,
as_number
)
==
offsetof
(
PyHeapTypeObject
,
as_number
),
""
);
static_assert
(
offsetof
(
pyston
::
BoxedHeapClass
,
as_mapping
)
==
offsetof
(
PyHeapTypeObject
,
as_mapping
),
""
);
static_assert
(
offsetof
(
pyston
::
BoxedHeapClass
,
as_sequence
)
==
offsetof
(
PyHeapTypeObject
,
as_sequence
),
""
);
static_assert
(
offsetof
(
pyston
::
BoxedHeapClass
,
as_buffer
)
==
offsetof
(
PyHeapTypeObject
,
as_buffer
),
""
);
static_assert
(
sizeof
(
pyston
::
BoxedHeapClass
)
==
sizeof
(
PyHeapTypeObject
),
""
);
class
HiddenClass
:
public
ConservativeGCObject
{
private:
...
...
test/test_extension/slots_test.c
View file @
d5ba641b
...
...
@@ -29,7 +29,7 @@ slots_tester_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
}
static
PyObject
*
slots_tester_repr
(
slots_tester_object
*
obj
)
slots_tester_
seq_
repr
(
slots_tester_object
*
obj
)
{
char
buf
[
80
];
snprintf
(
buf
,
sizeof
(
buf
),
"<my custom repr: %d>"
,
obj
->
n
);
...
...
@@ -37,7 +37,7 @@ slots_tester_repr(slots_tester_object *obj)
}
static
PyObject
*
slots_tester_call
(
slots_tester_object
*
obj
,
PyObject
*
args
,
PyObject
*
kw
)
slots_tester_
seq_
call
(
slots_tester_object
*
obj
,
PyObject
*
args
,
PyObject
*
kw
)
{
if
(
!
PyArg_ParseTuple
(
args
,
""
))
return
NULL
;
...
...
@@ -45,11 +45,33 @@ slots_tester_call(slots_tester_object *obj, PyObject *args, PyObject *kw)
return
PyInt_FromLong
(
obj
->
n
);
}
PyDoc_STRVAR
(
slots_tester_doc
,
"slots_tester doc"
);
static
PyObject
*
slots_tester_seq_item
(
slots_tester_object
*
obj
,
Py_ssize_t
i
)
{
if
(
i
<
0
||
i
>=
5
)
{
PyErr_SetString
(
PyExc_IndexError
,
"tuple index out of range"
);
return
NULL
;
}
return
PyInt_FromLong
(
i
+
obj
->
n
);
}
PyDoc_STRVAR
(
slots_tester_seq_doc
,
"slots_tester_seq doc"
);
static
PyTypeObject
slots_tester
=
{
static
PySequenceMethods
slots_tester_seq_as_sequence
=
{
(
lenfunc
)
0
,
(
binaryfunc
)
0
,
/* sq_concat */
(
ssizeargfunc
)
0
,
/* sq_repeat */
(
ssizeargfunc
)
slots_tester_seq_item
,
/* sq_item */
(
ssizessizeargfunc
)
0
,
/* sq_slice */
0
,
/* sq_ass_item */
0
,
/* sq_ass_slice */
(
objobjproc
)
0
,
/* sq_contains */
};
static
PyTypeObject
slots_tester_seq
=
{
PyVarObject_HEAD_INIT
(
NULL
,
0
)
"slots_test.slots_tester"
,
/* tp_name */
"slots_test.slots_tester
_seq
"
,
/* tp_name */
sizeof
(
slots_tester_object
),
/* tp_basicsize */
0
,
/* tp_itemsize */
/* methods */
...
...
@@ -58,18 +80,83 @@ static PyTypeObject slots_tester = {
0
,
/* tp_getattr */
0
,
/* tp_setattr */
0
,
/* tp_compare */
(
reprfunc
)
slots_tester_repr
,
/* tp_repr */
(
reprfunc
)
slots_tester_
seq_
repr
,
/* tp_repr */
0
,
/* tp_as_number */
0
,
/* tp_as_sequence */
&
slots_tester_seq_as_sequence
,
/* tp_as_sequence */
0
,
/* tp_as_mapping */
0
,
/* tp_hash */
(
ternaryfunc
)
slots_tester_call
,
/* tp_call */
(
ternaryfunc
)
slots_tester_
seq_
call
,
/* tp_call */
0
,
/* tp_str */
0
,
/* tp_getattro */
0
,
/* tp_setattro */
0
,
/* tp_as_buffer */
Py_TPFLAGS_DEFAULT
,
/* tp_flags */
slots_tester_doc
,
/* tp_doc */
slots_tester_seq_doc
,
/* tp_doc */
0
,
/* tp_traverse */
0
,
/* tp_clear */
0
,
/* tp_richcompare */
0
,
/* tp_weaklistoffset */
0
,
/* tp_iter */
0
,
/* tp_iternext */
0
,
/* tp_methods */
0
,
/* tp_members */
0
,
/* tp_getset */
0
,
/* tp_base */
0
,
/* tp_dict */
0
,
/* tp_descr_get */
0
,
/* tp_descr_set */
0
,
/* tp_dictoffset */
0
,
/* tp_init */
0
,
/* tp_alloc */
slots_tester_new
,
/* tp_new */
0
,
/* tp_free */
};
static
Py_ssize_t
slots_tester_map_length
(
slots_tester_object
*
obj
)
{
return
obj
->
n
;
}
static
PyObject
*
slots_tester_map_subscript
(
slots_tester_object
*
obj
,
PyObject
*
key
)
{
int
n2
=
PyInt_AsLong
(
key
);
return
PyInt_FromLong
(
n2
+
obj
->
n
);
}
static
int
slots_tester_map_ass_sub
(
slots_tester_object
*
obj
,
PyObject
*
key
,
PyObject
*
value
)
{
int
n2
=
PyInt_AsLong
(
key
);
printf
(
"Assigning to subscript for object with n=%d, key=%d, set/delete=%d
\n
"
,
obj
->
n
,
n2
,
!!
value
);
return
0
;
}
static
PyMappingMethods
slots_tester_map_asmapping
=
{
(
lenfunc
)
slots_tester_map_length
,
/*mp_length*/
(
binaryfunc
)
slots_tester_map_subscript
,
/*mp_subscript*/
(
objobjargproc
)
slots_tester_map_ass_sub
,
/*mp_ass_subscript*/
};
static
PyTypeObject
slots_tester_map
=
{
PyVarObject_HEAD_INIT
(
NULL
,
0
)
"slots_test.slots_tester_map"
,
/* tp_name */
sizeof
(
slots_tester_object
),
/* tp_basicsize */
0
,
/* tp_itemsize */
/* methods */
0
,
/* tp_dealloc */
0
,
/* tp_print */
0
,
/* tp_getattr */
0
,
/* tp_setattr */
0
,
/* tp_compare */
0
,
/* tp_repr */
0
,
/* tp_as_number */
0
,
/* tp_as_sequence */
&
slots_tester_map_asmapping
,
/* tp_as_mapping */
0
,
/* tp_hash */
0
,
/* tp_call */
0
,
/* tp_str */
0
,
/* tp_getattro */
0
,
/* tp_setattro */
0
,
/* tp_as_buffer */
Py_TPFLAGS_DEFAULT
,
/* tp_flags */
0
,
/* tp_doc */
0
,
/* tp_traverse */
0
,
/* tp_clear */
0
,
/* tp_richcompare */
...
...
@@ -120,6 +207,44 @@ call_funcs(PyObject* _module, PyObject* args) {
printf
(
"tp_call doesnt exist
\n
"
);
}
if
(
cls
->
tp_as_mapping
)
{
printf
(
"tp_as_mapping exists
\n
"
);
PyMappingMethods
*
map
=
cls
->
tp_as_mapping
;
if
(
map
->
mp_subscript
)
{
PyObject
*
rtn
=
map
->
mp_subscript
(
obj
,
PyInt_FromLong
(
1
));
printf
(
"mp_subscript exists and returned
\n
"
);
Py_DECREF
(
rtn
);
}
else
{
printf
(
"mp_subscript does not exist
\n
"
);
}
if
(
map
->
mp_length
)
{
Py_ssize_t
rtn
=
map
->
mp_length
(
obj
);
printf
(
"mp_length exists and returned %ld
\n
"
,
rtn
);
}
}
else
{
printf
(
"tp_as_mapping doesnt exist
\n
"
);
}
if
(
cls
->
tp_as_sequence
)
{
printf
(
"tp_as_sequence exists
\n
"
);
PySequenceMethods
*
seq
=
cls
->
tp_as_sequence
;
if
(
seq
->
sq_length
)
{
Py_ssize_t
rtn
=
seq
->
sq_length
(
obj
);
printf
(
"sq_length exists and returned %ld
\n
"
,
rtn
);
}
if
(
seq
->
sq_item
)
{
PyObject
*
rtn
=
cls
->
tp_as_sequence
->
sq_item
(
obj
,
1
);
printf
(
"sq_item exists and returned
\n
"
);
Py_DECREF
(
rtn
);
}
}
else
{
printf
(
"tp_as_sequence doesnt exist
\n
"
);
}
Py_DECREF
(
obj
);
Py_RETURN_NONE
;
...
...
@@ -139,12 +264,17 @@ initslots_test(void)
if
(
m
==
NULL
)
return
;
int
res
=
PyType_Ready
(
&
slots_tester
);
int
res
=
PyType_Ready
(
&
slots_tester_seq
);
if
(
res
<
0
)
return
;
res
=
PyType_Ready
(
&
slots_tester_map
);
if
(
res
<
0
)
return
;
// Not sure if the result of PyInt_FromLong needs to be decref'd
PyDict_SetItemString
(
slots_tester
.
tp_dict
,
"set_through_tpdict"
,
PyInt_FromLong
(
123
));
PyDict_SetItemString
(
slots_tester
_seq
.
tp_dict
,
"set_through_tpdict"
,
PyInt_FromLong
(
123
));
PyModule_AddObject
(
m
,
"SlotsTester"
,
(
PyObject
*
)
&
slots_tester
);
PyModule_AddObject
(
m
,
"SlotsTesterSeq"
,
(
PyObject
*
)
&
slots_tester_seq
);
PyModule_AddObject
(
m
,
"SlotsTesterMap"
,
(
PyObject
*
)
&
slots_tester_map
);
}
test/tests/capi_slots.py
View file @
d5ba641b
import
slots_test
for
i
in
xrange
(
3
):
t
=
slots_test
.
SlotsTester
(
i
+
5
)
print
t
,
repr
(
t
),
t
()
t
=
slots_test
.
SlotsTester
Seq
(
i
+
5
)
print
t
,
repr
(
t
),
t
()
,
t
[
2
]
print
slots_test
.
SlotsTester
.
set_through_tpdict
,
slots_test
.
SlotsTester
(
5
).
set_through_tpdict
# print slots_test.SlotsTesterSeq.__doc__
print
slots_test
.
SlotsTesterSeq
.
set_through_tpdict
,
slots_test
.
SlotsTesterSeq
(
5
).
set_through_tpdict
for
i
in
xrange
(
3
):
t
=
slots_test
.
SlotsTesterMap
(
i
+
5
)
print
len
(
t
),
t
[
2
]
t
[
1
]
=
5
del
t
[
2
]
class
C
(
object
):
def
__repr__
(
self
):
print
"__repr__()"
return
"<C object>"
def
__getitem__
(
self
,
idx
):
print
"__getitem__"
,
idx
return
idx
-
5
def
__len__
(
self
):
print
"__len__"
return
3
slots_test
.
call_funcs
(
C
())
# Test to make sure that updating an existing class also updates the tp_* slots:
def
repr2
(
self
):
return
"repr2()"
C
.
repr2
=
repr2
C
.
__repr__
=
repr2
slots_test
.
call_funcs
(
C
())
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