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
dd12bff0
Commit
dd12bff0
authored
Jan 08, 2015
by
Kevin Modzelewski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add support for tp_as_number->nb_nonzero
parent
f87c03be
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
115 additions
and
24 deletions
+115
-24
Makefile
Makefile
+4
-0
from_cpython/Include/intobject.h
from_cpython/Include/intobject.h
+1
-1
src/capi/typeobject.cpp
src/capi/typeobject.cpp
+75
-1
src/runtime/objmodel.cpp
src/runtime/objmodel.cpp
+20
-20
test/test_extension/slots_test.c
test/test_extension/slots_test.c
+6
-1
test/tests/capi_slots.py
test/tests/capi_slots.py
+6
-0
tools/tester.py
tools/tester.py
+3
-1
No files found.
Makefile
View file @
dd12bff0
...
...
@@ -865,6 +865,10 @@ $(call make_target,_grwl)
$(call
make_target,_grwl_dbg)
$(call
make_target,_nosync)
runpy_%
:
%.py ext_python
PYTHONPATH
=
test
/test_extension/build/lib.linux-x86_64-2.7 python
$<
$(call
make_search,runpy_%)
# "kill valgrind":
kv
:
ps aux |
awk
'/[v]algrind/ {print $$2}'
| xargs
kill
-9
;
true
...
...
from_cpython/Include/intobject.h
View file @
dd12bff0
...
...
@@ -42,7 +42,7 @@ PyAPI_FUNC(bool) PyInt_Check(PyObject*);
#define PyInt_Check(op) \
PyType_FastSubclass((op)->ob_type, Py_TPFLAGS_INT_SUBCLASS)
#endif
#define PyInt_CheckExact(op) (
(op)->ob_type
== &PyInt_Type)
#define PyInt_CheckExact(op) (
Py_TYPE(op)
== &PyInt_Type)
PyAPI_FUNC
(
PyObject
*
)
PyInt_FromString
(
char
*
,
char
**
,
int
);
#ifdef Py_USING_UNICODE
...
...
src/capi/typeobject.cpp
View file @
dd12bff0
...
...
@@ -87,6 +87,18 @@ static PyObject* wrap_unaryfunc(PyObject* self, PyObject* args, void* wrapped) n
return
(
*
func
)(
self
);
}
static
PyObject
*
wrap_inquirypred
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
noexcept
{
inquiry
func
=
(
inquiry
)
wrapped
;
int
res
;
if
(
!
check_num_args
(
args
,
0
))
return
NULL
;
res
=
(
*
func
)(
self
);
if
(
res
==
-
1
&&
PyErr_Occurred
())
return
NULL
;
return
PyBool_FromLong
((
long
)
res
);
}
static
PyObject
*
wrap_binaryfunc
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
noexcept
{
binaryfunc
func
=
(
binaryfunc
)
wrapped
;
PyObject
*
other
;
...
...
@@ -400,6 +412,41 @@ PyObject* slot_tp_call(PyObject* self, PyObject* args, PyObject* kwds) noexcept
}
}
static
int
slot_nb_nonzero
(
PyObject
*
self
)
noexcept
{
PyObject
*
func
,
*
args
;
static
PyObject
*
nonzero_str
,
*
len_str
;
int
result
=
-
1
;
int
using_len
=
0
;
func
=
lookup_maybe
(
self
,
"__nonzero__"
,
&
nonzero_str
);
if
(
func
==
NULL
)
{
if
(
PyErr_Occurred
())
return
-
1
;
func
=
lookup_maybe
(
self
,
"__len__"
,
&
len_str
);
if
(
func
==
NULL
)
return
PyErr_Occurred
()
?
-
1
:
1
;
using_len
=
1
;
}
args
=
PyTuple_New
(
0
);
if
(
args
!=
NULL
)
{
PyObject
*
temp
=
PyObject_Call
(
func
,
args
,
NULL
);
Py_DECREF
(
args
);
if
(
temp
!=
NULL
)
{
if
(
PyInt_CheckExact
(
temp
)
||
PyBool_Check
(
temp
))
result
=
PyObject_IsTrue
(
temp
);
else
{
PyErr_Format
(
PyExc_TypeError
,
"%s should return "
"bool or int, returned %s"
,
(
using_len
?
"__len__"
:
"__nonzero__"
),
temp
->
cls
->
tp_name
);
result
=
-
1
;
}
Py_DECREF
(
temp
);
}
}
Py_DECREF
(
func
);
return
result
;
}
static
const
char
*
name_op
[]
=
{
"__lt__"
,
"__le__"
,
"__eq__"
,
"__ne__"
,
"__gt__"
,
"__ge__"
,
};
...
...
@@ -699,6 +746,8 @@ static slotdef slotdefs[] = {
PyWrapperFlag_KEYWORDS
),
TPSLOT
(
"__new__"
,
tp_new
,
slot_tp_new
,
NULL
,
""
),
UNSLOT
(
"__nonzero__"
,
nb_nonzero
,
slot_nb_nonzero
,
wrap_inquirypred
,
"x != 0"
),
MPSLOT
(
"__len__"
,
mp_length
,
slot_mp_length
,
wrap_lenfunc
,
"x.__len__() <==> len(x)"
),
MPSLOT
(
"__getitem__"
,
mp_subscript
,
slot_mp_subscript
,
wrap_binaryfunc
,
"x.__getitem__(y) <==> x[y]"
),
MPSLOT
(
"__setitem__"
,
mp_ass_subscript
,
slot_mp_ass_subscript
,
wrap_objobjargproc
,
...
...
@@ -739,6 +788,17 @@ static void init_slotdefs() {
for
(
int
i
=
0
;
i
<
sizeof
(
slotdefs
)
/
sizeof
(
slotdefs
[
0
]);
i
++
)
{
if
(
i
>
0
)
{
#ifndef NDEBUG
if
(
slotdefs
[
i
-
1
].
offset
>
slotdefs
[
i
].
offset
)
{
printf
(
"slotdef for %s in the wrong place
\n
"
,
slotdefs
[
i
-
1
].
name
);
for
(
int
j
=
i
;
j
<
sizeof
(
slotdefs
)
/
sizeof
(
slotdefs
[
0
]);
j
++
)
{
if
(
slotdefs
[
i
-
1
].
offset
<=
slotdefs
[
j
].
offset
)
{
printf
(
"Should go before %s
\n
"
,
slotdefs
[
j
].
name
);
break
;
}
}
}
#endif
ASSERT
(
slotdefs
[
i
].
offset
>=
slotdefs
[
i
-
1
].
offset
,
"%d %s"
,
i
,
slotdefs
[
i
-
1
].
name
);
// CPython interns the name here
}
...
...
@@ -839,7 +899,21 @@ extern "C" int PyType_Ready(PyTypeObject* cls) {
RELEASE_ASSERT
(
cls
->
tp_getattr
==
NULL
,
""
);
RELEASE_ASSERT
(
cls
->
tp_setattr
==
NULL
,
""
);
RELEASE_ASSERT
(
cls
->
tp_compare
==
NULL
,
""
);
RELEASE_ASSERT
(
cls
->
tp_as_number
==
NULL
,
""
);
// Hacky way to assert that only tp_as_number slots we support are getting set:
// zero out the ones we know about, then assert that the entire struct
// is zero, then restore the ones we know about.
if
(
cls
->
tp_as_number
)
{
auto
nb_nonzero
=
cls
->
tp_as_number
->
nb_nonzero
;
cls
->
tp_as_number
->
nb_nonzero
=
NULL
;
for
(
void
**
p
=
(
void
**
)
cls
->
tp_as_number
;
p
<
(
void
**
)
cls
->
tp_as_number
+
1
;
p
++
)
{
RELEASE_ASSERT
(
*
p
==
NULL
,
""
);
}
cls
->
tp_as_number
->
nb_nonzero
=
nb_nonzero
;
}
RELEASE_ASSERT
(
cls
->
tp_str
==
NULL
,
""
);
RELEASE_ASSERT
(
cls
->
tp_getattro
==
NULL
||
cls
->
tp_getattro
==
PyObject_GenericGetAttr
,
""
);
RELEASE_ASSERT
(
cls
->
tp_setattro
==
NULL
||
cls
->
tp_setattro
==
PyObject_GenericSetAttr
,
""
);
...
...
src/runtime/objmodel.cpp
View file @
dd12bff0
...
...
@@ -1456,26 +1456,6 @@ void setattrInternal(Box* obj, const std::string& attr, Box* val, SetattrRewrite
descr
=
typeLookup
(
obj
->
cls
,
attr
,
NULL
);
}
if
(
isSubclass
(
obj
->
cls
,
type_cls
))
{
BoxedClass
*
self
=
static_cast
<
BoxedClass
*>
(
obj
);
if
(
attr
==
_getattr_str
||
attr
==
_getattribute_str
)
{
// Will have to embed the clear in the IC, so just disable the patching for now:
rewrite_args
=
NULL
;
// TODO should put this clearing behavior somewhere else, since there are probably more
// cases in which we want to do it.
self
->
dependent_icgetattrs
.
invalidateAll
();
}
if
(
attr
==
"__base__"
&&
self
->
getattr
(
"__base__"
))
raiseExcHelper
(
TypeError
,
"readonly attribute"
);
bool
touched_slot
=
update_slot
(
self
,
attr
);
if
(
touched_slot
)
rewrite_args
=
NULL
;
}
Box
*
_set_
=
NULL
;
RewriterVar
*
r_set
=
NULL
;
if
(
descr
)
{
...
...
@@ -1511,6 +1491,26 @@ void setattrInternal(Box* obj, const std::string& attr, Box* val, SetattrRewrite
}
else
{
obj
->
setattr
(
attr
,
val
,
rewrite_args
);
}
if
(
isSubclass
(
obj
->
cls
,
type_cls
))
{
BoxedClass
*
self
=
static_cast
<
BoxedClass
*>
(
obj
);
if
(
attr
==
_getattr_str
||
attr
==
_getattribute_str
)
{
// Will have to embed the clear in the IC, so just disable the patching for now:
rewrite_args
=
NULL
;
// TODO should put this clearing behavior somewhere else, since there are probably more
// cases in which we want to do it.
self
->
dependent_icgetattrs
.
invalidateAll
();
}
if
(
attr
==
"__base__"
&&
self
->
getattr
(
"__base__"
))
raiseExcHelper
(
TypeError
,
"readonly attribute"
);
bool
touched_slot
=
update_slot
(
self
,
attr
);
if
(
touched_slot
)
rewrite_args
=
NULL
;
}
}
extern
"C"
void
setattr
(
Box
*
obj
,
const
char
*
attr
,
Box
*
attr_val
)
{
...
...
test/test_extension/slots_test.c
View file @
dd12bff0
...
...
@@ -373,7 +373,12 @@ call_funcs(PyObject* _module, PyObject* args) {
if
(
cls
->
tp_as_number
)
{
printf
(
"tp_as_number exists
\n
"
);
PyNumberMethods
*
seq
=
cls
->
tp_as_number
;
PyNumberMethods
*
num
=
cls
->
tp_as_number
;
if
(
num
->
nb_nonzero
)
{
int
n
=
num
->
nb_nonzero
(
obj
);
printf
(
"nb_nonzero exists and returned %d
\n
"
,
n
);
}
}
else
{
printf
(
"tp_as_number doesnt exist
\n
"
);
}
...
...
test/tests/capi_slots.py
View file @
dd12bff0
...
...
@@ -37,4 +37,10 @@ slots_test.call_funcs(C())
def
repr2
(
self
):
return
"repr2()"
C
.
__repr__
=
repr2
def
nonzero
(
self
):
print
"nonzero"
return
True
C
.
__nonzero__
=
nonzero
slots_test
.
call_funcs
(
C
())
tools/tester.py
View file @
dd12bff0
...
...
@@ -350,7 +350,7 @@ if __name__ == "__main__":
run_memcheck = False
start = 1
opts, patterns = getopt.gnu_getopt(sys.argv[1:], "j:a:t:mR:k")
opts, patterns = getopt.gnu_getopt(sys.argv[1:], "j:a:t:mR:k
K
")
for (t, v) in opts:
if t == '-m':
run_memcheck = True
...
...
@@ -361,6 +361,8 @@ if __name__ == "__main__":
IMAGE = v
elif t == '-k':
KEEP_GOING = True
elif t == '-K':
KEEP_GOING = False
elif t == '-a':
EXTRA_JIT_ARGS.append(v)
elif t == '-t':
...
...
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