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
39dbe4fd
Commit
39dbe4fd
authored
Jan 08, 2015
by
Kevin Modzelewski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Import some more TypeReady handling from CPython
parent
fa2942ae
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
211 additions
and
104 deletions
+211
-104
src/capi/typeobject.cpp
src/capi/typeobject.cpp
+206
-104
src/runtime/capi.cpp
src/runtime/capi.cpp
+5
-0
No files found.
src/capi/typeobject.cpp
View file @
39dbe4fd
...
@@ -896,27 +896,6 @@ static void** slotptr(BoxedClass* type, int offset) {
...
@@ -896,27 +896,6 @@ static void** slotptr(BoxedClass* type, int offset) {
return
(
void
**
)
ptr
;
return
(
void
**
)
ptr
;
}
}
static
void
update_one_slot
(
BoxedClass
*
self
,
const
slotdef
&
p
)
{
// TODO: CPython version is significantly more sophisticated
void
**
ptr
=
slotptr
(
self
,
p
.
offset
);
Box
*
attr
=
typeLookup
(
self
,
p
.
name
,
NULL
);
if
(
!
ptr
)
{
assert
(
!
attr
&&
"I don't think this case should happen? CPython handles it though"
);
return
;
}
if
(
attr
)
{
if
(
attr
==
None
&&
ptr
==
(
void
**
)
&
self
->
tp_hash
)
{
*
ptr
=
(
void
*
)
&
PyObject_HashNotImplemented
;
}
else
{
*
ptr
=
p
.
function
;
}
}
else
{
*
ptr
=
NULL
;
}
}
// Copied from CPython:
// Copied from CPython:
#define TPSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \
#define TPSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \
{ NAME, offsetof(PyTypeObject, SLOT), (void*)(FUNCTION), WRAPPER, PyDoc_STR(DOC), 0 }
{ NAME, offsetof(PyTypeObject, SLOT), (void*)(FUNCTION), WRAPPER, PyDoc_STR(DOC), 0 }
...
@@ -940,8 +919,8 @@ static void update_one_slot(BoxedClass* self, const slotdef& p) {
...
@@ -940,8 +919,8 @@ static void update_one_slot(BoxedClass* self, const slotdef& p) {
#define RBINSLOTNOTINFIX(NAME, SLOT, FUNCTION, DOC) \
#define RBINSLOTNOTINFIX(NAME, SLOT, FUNCTION, DOC) \
ETSLOT(NAME, as_number.SLOT, FUNCTION, wrap_binaryfunc_r, "x." NAME "(y) <==> " DOC)
ETSLOT(NAME, as_number.SLOT, FUNCTION, wrap_binaryfunc_r, "x." NAME "(y) <==> " DOC)
static
slotdef
slotdefs
[]
=
{
static
slotdef
slotdefs
[]
TPSLOT
(
"__repr__"
,
tp_repr
,
slot_tp_repr
,
wrap_unaryfunc
,
"x.__repr__() <==> repr(x)"
),
=
{
TPSLOT
(
"__repr__"
,
tp_repr
,
slot_tp_repr
,
wrap_unaryfunc
,
"x.__repr__() <==> repr(x)"
),
TPSLOT
(
"__hash__"
,
tp_hash
,
slot_tp_hash
,
wrap_hashfunc
,
"x.__hash__() <==> hash(x)"
),
TPSLOT
(
"__hash__"
,
tp_hash
,
slot_tp_hash
,
wrap_hashfunc
,
"x.__hash__() <==> hash(x)"
),
FLSLOT
(
"__call__"
,
tp_call
,
slot_tp_call
,
(
wrapperfunc
)
wrap_call
,
"x.__call__(...) <==> x(...)"
,
FLSLOT
(
"__call__"
,
tp_call
,
slot_tp_call
,
(
wrapperfunc
)
wrap_call
,
"x.__call__(...) <==> x(...)"
,
PyWrapperFlag_KEYWORDS
),
PyWrapperFlag_KEYWORDS
),
...
@@ -1024,7 +1003,7 @@ static slotdef slotdefs[] = {
...
@@ -1024,7 +1003,7 @@ static slotdef slotdefs[] = {
SQSLOT
(
"__contains__"
,
sq_contains
,
slot_sq_contains
,
wrap_objobjproc
,
"x.__contains__(y) <==> y in x"
),
SQSLOT
(
"__contains__"
,
sq_contains
,
slot_sq_contains
,
wrap_objobjproc
,
"x.__contains__(y) <==> y in x"
),
SQSLOT
(
"__iadd__"
,
sq_inplace_concat
,
NULL
,
wrap_binaryfunc
,
"x.__iadd__(y) <==> x+=y"
),
SQSLOT
(
"__iadd__"
,
sq_inplace_concat
,
NULL
,
wrap_binaryfunc
,
"x.__iadd__(y) <==> x+=y"
),
SQSLOT
(
"__imul__"
,
sq_inplace_repeat
,
NULL
,
wrap_indexargfunc
,
"x.__imul__(y) <==> x*=y"
),
SQSLOT
(
"__imul__"
,
sq_inplace_repeat
,
NULL
,
wrap_indexargfunc
,
"x.__imul__(y) <==> x*=y"
),
};
{
NULL
,
0
,
NULL
,
NULL
,
NULL
,
0
}
};
static
void
init_slotdefs
()
{
static
void
init_slotdefs
()
{
static
bool
initialized
=
false
;
static
bool
initialized
=
false
;
...
@@ -1033,6 +1012,9 @@ static void init_slotdefs() {
...
@@ -1033,6 +1012,9 @@ static void init_slotdefs() {
for
(
int
i
=
0
;
i
<
sizeof
(
slotdefs
)
/
sizeof
(
slotdefs
[
0
]);
i
++
)
{
for
(
int
i
=
0
;
i
<
sizeof
(
slotdefs
)
/
sizeof
(
slotdefs
[
0
]);
i
++
)
{
if
(
i
>
0
)
{
if
(
i
>
0
)
{
if
(
!
slotdefs
[
i
].
name
)
continue
;
#ifndef NDEBUG
#ifndef NDEBUG
if
(
slotdefs
[
i
-
1
].
offset
>
slotdefs
[
i
].
offset
)
{
if
(
slotdefs
[
i
-
1
].
offset
>
slotdefs
[
i
].
offset
)
{
printf
(
"slotdef for %s in the wrong place
\n
"
,
slotdefs
[
i
-
1
].
name
);
printf
(
"slotdef for %s in the wrong place
\n
"
,
slotdefs
[
i
-
1
].
name
);
...
@@ -1052,12 +1034,132 @@ static void init_slotdefs() {
...
@@ -1052,12 +1034,132 @@ static void init_slotdefs() {
initialized
=
true
;
initialized
=
true
;
}
}
/* Length of array of slotdef pointers used to store slots with the
same __name__. There should be at most MAX_EQUIV-1 slotdef entries with
the same __name__, for any __name__. Since that's a static property, it is
appropriate to declare fixed-size arrays for this. */
#define MAX_EQUIV 10
/* Return a slot pointer for a given name, but ONLY if the attribute has
exactly one slot function. The name must be an interned string. */
static
void
**
resolve_slotdups
(
PyTypeObject
*
type
,
const
std
::
string
&
name
)
{
/* XXX Maybe this could be optimized more -- but is it worth it? */
/* pname and ptrs act as a little cache */
static
std
::
string
pname
;
static
slotdef
*
ptrs
[
MAX_EQUIV
];
slotdef
*
p
,
**
pp
;
void
**
res
,
**
ptr
;
if
(
pname
!=
name
)
{
/* Collect all slotdefs that match name into ptrs. */
pname
=
name
;
pp
=
ptrs
;
for
(
p
=
slotdefs
;
p
->
name
;
p
++
)
{
if
(
p
->
name
==
name
)
*
pp
++
=
p
;
}
*
pp
=
NULL
;
}
/* Look in all matching slots of the type; if exactly one of these has
a filled-in slot, return its value. Otherwise return NULL. */
res
=
NULL
;
for
(
pp
=
ptrs
;
*
pp
;
pp
++
)
{
ptr
=
slotptr
(
type
,
(
*
pp
)
->
offset
);
if
(
ptr
==
NULL
||
*
ptr
==
NULL
)
continue
;
if
(
res
!=
NULL
)
return
NULL
;
res
=
ptr
;
}
return
res
;
}
static
const
slotdef
*
update_one_slot
(
BoxedClass
*
type
,
const
slotdef
*
p
)
{
assert
(
p
->
name
);
PyObject
*
descr
;
BoxedWrapperDescriptor
*
d
;
void
*
generic
=
NULL
,
*
specific
=
NULL
;
int
use_generic
=
0
;
int
offset
=
p
->
offset
;
void
**
ptr
=
slotptr
(
type
,
offset
);
if
(
ptr
==
NULL
)
{
do
{
++
p
;
}
while
(
p
->
offset
==
offset
);
return
p
;
}
do
{
descr
=
typeLookup
(
type
,
p
->
name
,
NULL
);
if
(
descr
==
NULL
)
{
if
(
ptr
==
(
void
**
)
&
type
->
tp_iternext
)
{
specific
=
(
void
*
)
_PyObject_NextNotImplemented
;
}
continue
;
}
if
(
Py_TYPE
(
descr
)
==
wrapperdescr_cls
&&
((
BoxedWrapperDescriptor
*
)
descr
)
->
wrapper
->
name
==
std
::
string
(
p
->
name
))
{
void
**
tptr
=
resolve_slotdups
(
type
,
p
->
name
);
if
(
tptr
==
NULL
||
tptr
==
ptr
)
generic
=
p
->
function
;
d
=
(
BoxedWrapperDescriptor
*
)
descr
;
if
(
d
->
wrapper
->
wrapper
==
p
->
wrapper
&&
PyType_IsSubtype
(
type
,
d
->
type
))
{
if
(
specific
==
NULL
||
specific
==
d
->
wrapped
)
specific
=
d
->
wrapped
;
else
use_generic
=
1
;
}
// TODO Pyston doesn't support PyCFunction_Type yet I think?
#if 0
} else if (Py_TYPE(descr) == &PyCFunction_Type && PyCFunction_GET_FUNCTION(descr) == (PyCFunction)tp_new_wrapper
&& ptr == (void**)&type->tp_new) {
/* The __new__ wrapper is not a wrapper descriptor,
so must be special-cased differently.
If we don't do this, creating an instance will
always use slot_tp_new which will look up
__new__ in the MRO which will call tp_new_wrapper
which will look through the base classes looking
for a static base and call its tp_new (usually
PyType_GenericNew), after performing various
sanity checks and constructing a new argument
list. Cut all that nonsense short -- this speeds
up instance creation tremendously. */
specific = (void*)type->tp_new;
/* XXX I'm not 100% sure that there isn't a hole
in this reasoning that requires additional
sanity checks. I'll buy the first person to
point out a bug in this reasoning a beer. */
#endif
}
else
if
(
descr
==
Py_None
&&
ptr
==
(
void
**
)
&
type
->
tp_hash
)
{
/* We specifically allow __hash__ to be set to None
to prevent inheritance of the default
implementation from object.__hash__ */
specific
=
(
void
*
)
PyObject_HashNotImplemented
;
}
else
{
use_generic
=
1
;
generic
=
p
->
function
;
}
}
while
((
++
p
)
->
offset
==
offset
);
if
(
specific
&&
!
use_generic
)
*
ptr
=
specific
;
else
*
ptr
=
generic
;
return
p
;
}
bool
update_slot
(
BoxedClass
*
self
,
const
std
::
string
&
attr
)
{
bool
update_slot
(
BoxedClass
*
self
,
const
std
::
string
&
attr
)
{
bool
updated
=
false
;
bool
updated
=
false
;
for
(
const
slotdef
&
p
:
slotdefs
)
{
for
(
const
slotdef
&
p
:
slotdefs
)
{
if
(
!
p
.
name
)
continue
;
if
(
p
.
name
==
attr
)
{
if
(
p
.
name
==
attr
)
{
// TODO update subclasses;
// TODO update subclasses;
update_one_slot
(
self
,
p
);
update_one_slot
(
self
,
&
p
);
updated
=
true
;
updated
=
true
;
}
}
}
}
...
@@ -1067,9 +1169,9 @@ bool update_slot(BoxedClass* self, const std::string& attr) {
...
@@ -1067,9 +1169,9 @@ bool update_slot(BoxedClass* self, const std::string& attr) {
void
fixup_slot_dispatchers
(
BoxedClass
*
self
)
{
void
fixup_slot_dispatchers
(
BoxedClass
*
self
)
{
init_slotdefs
();
init_slotdefs
();
for
(
const
slotdef
&
p
:
slotdefs
)
{
const
slotdef
*
p
=
slotdefs
;
update_one_slot
(
self
,
p
);
while
(
p
->
name
)
}
p
=
update_one_slot
(
self
,
p
);
// TODO: CPython handles this by having the __name__ attribute wrap (via a getset object)
// TODO: CPython handles this by having the __name__ attribute wrap (via a getset object)
// the tp_name field, whereas we're (needlessly?) doing the opposite.
// the tp_name field, whereas we're (needlessly?) doing the opposite.
...
...
src/runtime/capi.cpp
View file @
39dbe4fd
...
@@ -456,6 +456,11 @@ extern "C" long PyObject_HashNotImplemented(PyObject* self) {
...
@@ -456,6 +456,11 @@ extern "C" long PyObject_HashNotImplemented(PyObject* self) {
return
-
1
;
return
-
1
;
}
}
extern
"C"
PyObject
*
_PyObject_NextNotImplemented
(
PyObject
*
self
)
{
PyErr_Format
(
PyExc_TypeError
,
"'%.200s' object is not iterable"
,
Py_TYPE
(
self
)
->
tp_name
);
return
NULL
;
}
extern
"C"
long
_Py_HashPointer
(
void
*
p
)
{
extern
"C"
long
_Py_HashPointer
(
void
*
p
)
{
long
x
;
long
x
;
size_t
y
=
(
size_t
)
p
;
size_t
y
=
(
size_t
)
p
;
...
...
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