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
4210ed9b
Commit
4210ed9b
authored
Apr 13, 2015
by
Travis Hance
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add im_class field to BoxedInstanceMethod, implement instancemethodRepr
parent
3d9ead49
Changes
10
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
145 additions
and
41 deletions
+145
-41
src/capi/types.h
src/capi/types.h
+2
-2
src/codegen/compvars.cpp
src/codegen/compvars.cpp
+14
-8
src/core/common.h
src/core/common.h
+8
-0
src/runtime/descr.cpp
src/runtime/descr.cpp
+1
-1
src/runtime/dict.cpp
src/runtime/dict.cpp
+1
-1
src/runtime/objmodel.cpp
src/runtime/objmodel.cpp
+14
-7
src/runtime/types.cpp
src/runtime/types.cpp
+58
-17
src/runtime/types.h
src/runtime/types.h
+5
-5
test/tests/function_instancemethod.py
test/tests/function_instancemethod.py
+10
-0
test/tests/instance_methods.py
test/tests/instance_methods.py
+32
-0
No files found.
src/capi/types.h
View file @
4210ed9b
...
...
@@ -150,7 +150,7 @@ public:
// CPython handles this differently: they create the equivalent of different BoxedMethodDescriptor
// objects but with different class objects, which define different __get__ and __call__ methods.
if
(
self
->
method
->
ml_flags
&
METH_CLASS
)
return
boxInstanceMethod
(
owner
,
self
);
return
boxInstanceMethod
(
owner
,
self
,
self
->
type
);
if
(
self
->
method
->
ml_flags
&
METH_STATIC
)
Py_FatalError
(
"unimplemented"
);
...
...
@@ -160,7 +160,7 @@ public:
if
(
inst
==
None
)
return
self
;
else
return
boxInstanceMethod
(
inst
,
self
);
return
boxInstanceMethod
(
inst
,
self
,
self
->
type
);
}
static
Box
*
__call__
(
BoxedMethodDescriptor
*
self
,
Box
*
obj
,
BoxedTuple
*
varargs
,
Box
**
_args
);
...
...
src/codegen/compvars.cpp
View file @
4210ed9b
...
...
@@ -75,9 +75,10 @@ std::string ValuedCompilerType<llvm::Value*>::debugName() {
}
struct
RawInstanceMethod
{
CompilerVariable
*
obj
,
*
func
;
CompilerVariable
*
obj
,
*
func
,
*
im_class
;
RawInstanceMethod
(
CompilerVariable
*
obj
,
CompilerVariable
*
func
)
:
obj
(
obj
),
func
(
func
)
{}
RawInstanceMethod
(
CompilerVariable
*
obj
,
CompilerVariable
*
func
,
CompilerVariable
*
im_class
)
:
obj
(
obj
),
func
(
func
),
im_class
(
im_class
)
{}
};
class
InstanceMethodType
:
public
ValuedCompilerType
<
RawInstanceMethod
*>
{
...
...
@@ -108,9 +109,9 @@ public:
return
rtn
;
}
static
CompilerVariable
*
makeIM
(
CompilerVariable
*
obj
,
CompilerVariable
*
func
)
{
static
CompilerVariable
*
makeIM
(
CompilerVariable
*
obj
,
CompilerVariable
*
func
,
CompilerVariable
*
im_class
)
{
CompilerVariable
*
rtn
=
new
ValuedCompilerVariable
<
RawInstanceMethod
*>
(
InstanceMethodType
::
get
(
obj
->
getType
(),
func
->
getType
()),
new
RawInstanceMethod
(
obj
,
func
),
true
);
InstanceMethodType
::
get
(
obj
->
getType
(),
func
->
getType
()),
new
RawInstanceMethod
(
obj
,
func
,
im_class
),
true
);
obj
->
incvref
();
func
->
incvref
();
return
rtn
;
...
...
@@ -160,9 +161,10 @@ public:
assert
(
im
->
func
);
ConcreteCompilerVariable
*
obj
=
im
->
obj
->
makeConverted
(
emitter
,
UNKNOWN
);
ConcreteCompilerVariable
*
func
=
im
->
func
->
makeConverted
(
emitter
,
UNKNOWN
);
ConcreteCompilerVariable
*
im_class
=
im
->
im_class
->
makeConverted
(
emitter
,
UNKNOWN
);
llvm
::
Value
*
boxed
=
emitter
.
getBuilder
()
->
CreateCall2
(
g
.
funcs
.
boxInstanceMethod
,
obj
->
getValue
(),
func
->
getValue
());
llvm
::
Value
*
boxed
=
emitter
.
getBuilder
()
->
CreateCall3
(
g
.
funcs
.
boxInstanceMethod
,
obj
->
getValue
(),
func
->
getValue
(),
im_class
->
getValue
());
obj
->
decvref
(
emitter
);
func
->
decvref
(
emitter
);
...
...
@@ -175,7 +177,8 @@ public:
CompilerVariable
*
rtn
=
cache
[
var
];
if
(
rtn
==
NULL
)
{
RawInstanceMethod
*
im
=
var
->
getValue
();
RawInstanceMethod
*
new_im
=
new
RawInstanceMethod
(
im
->
obj
->
dup
(
cache
),
im
->
func
->
dup
(
cache
));
RawInstanceMethod
*
new_im
=
new
RawInstanceMethod
(
im
->
obj
->
dup
(
cache
),
im
->
func
->
dup
(
cache
),
im
->
im_class
->
dup
(
cache
));
rtn
=
new
VAR
(
this
,
new_im
,
var
->
isGrabbed
());
while
(
rtn
->
getVrefs
()
<
var
->
getVrefs
())
rtn
->
incvref
();
...
...
@@ -1476,7 +1479,10 @@ public:
if
(
rtattr
->
cls
==
function_cls
)
{
CompilerVariable
*
clattr
=
new
ConcreteCompilerVariable
(
typeFromClass
(
function_cls
),
embedRelocatablePtr
(
rtattr
,
g
.
llvm_value_type_ptr
),
false
);
return
InstanceMethodType
::
makeIM
(
var
,
clattr
);
return
InstanceMethodType
::
makeIM
(
var
,
clattr
,
new
ConcreteCompilerVariable
(
UNKNOWN
,
embedRelocatablePtr
(
cls
,
g
.
llvm_value_type_ptr
),
false
));
}
}
...
...
src/core/common.h
View file @
4210ed9b
...
...
@@ -87,4 +87,12 @@ template <typename T1, typename T2> struct hash<pair<T1, T2>> {
};
}
namespace
std
{
template
<
typename
T1
,
typename
T2
,
typename
T3
>
struct
hash
<
tuple
<
T1
,
T2
,
T3
>>
{
size_t
operator
()(
const
tuple
<
T1
,
T2
,
T3
>
p
)
const
{
return
hash
<
T1
>
()(
std
::
get
<
0
>
(
p
))
^
(
hash
<
T2
>
()(
std
::
get
<
1
>
(
p
))
<<
1
)
^
(
hash
<
T3
>
()(
std
::
get
<
2
>
(
p
))
<<
2
);
}
};
}
#endif
src/runtime/descr.cpp
View file @
4210ed9b
...
...
@@ -165,7 +165,7 @@ static Box* classmethodGet(Box* self, Box* obj, Box* type) {
type
=
obj
->
cls
;
}
return
new
BoxedInstanceMethod
(
type
,
cm
->
cm_callable
);
return
new
BoxedInstanceMethod
(
type
,
cm
->
cm_callable
,
type
);
}
void
setupDescr
()
{
...
...
src/runtime/dict.cpp
View file @
4210ed9b
...
...
@@ -667,7 +667,7 @@ void setupDict() {
dict_cls
->
giveAttr
(
"popitem"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
dictPopitem
,
BOXED_TUPLE
,
1
)));
auto
*
fromkeys_func
=
new
BoxedFunction
(
boxRTFunction
((
void
*
)
dictFromkeys
,
DICT
,
3
,
1
,
false
,
false
),
{
None
});
dict_cls
->
giveAttr
(
"fromkeys"
,
boxInstanceMethod
(
dict_cls
,
fromkeys_func
));
dict_cls
->
giveAttr
(
"fromkeys"
,
boxInstanceMethod
(
dict_cls
,
fromkeys_func
,
dict_cls
));
dict_cls
->
giveAttr
(
"viewkeys"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
dictViewKeys
,
UNKNOWN
,
1
)));
dict_cls
->
giveAttr
(
"viewvalues"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
dictViewValues
,
UNKNOWN
,
1
)));
...
...
src/runtime/objmodel.cpp
View file @
4210ed9b
...
...
@@ -860,8 +860,13 @@ Box* nondataDescriptorInstanceSpecialCases(GetattrRewriteArgs* rewrite_args, Box
if
(
descr
->
cls
==
function_cls
||
descr
->
cls
==
instancemethod_cls
||
descr
->
cls
==
classmethod_cls
||
(
descr
->
cls
==
method_cls
&&
(
static_cast
<
BoxedMethodDescriptor
*>
(
descr
)
->
method
->
ml_flags
&
(
METH_CLASS
|
METH_STATIC
))
==
0
))
{
Box
*
im_self
=
NULL
,
*
im_func
=
NULL
;
RewriterVar
*
r_im_self
=
NULL
,
*
r_im_func
=
NULL
;
Box
*
im_self
=
NULL
,
*
im_func
=
NULL
,
*
im_class
=
obj
->
cls
;
RewriterVar
*
r_im_self
=
NULL
,
*
r_im_func
=
NULL
,
*
r_im_class
=
NULL
;
if
(
rewrite_args
)
{
r_im_class
=
rewrite_args
->
obj
->
getAttr
(
BOX_CLS_OFFSET
);
}
if
(
descr
->
cls
==
function_cls
)
{
im_self
=
obj
;
im_func
=
descr
;
...
...
@@ -888,7 +893,7 @@ Box* nondataDescriptorInstanceSpecialCases(GetattrRewriteArgs* rewrite_args, Box
im_func
=
cm
->
cm_callable
;
if
(
rewrite_args
)
{
r_im_self
=
r
ewrite_args
->
obj
->
getAttr
(
BOX_CLS_OFFSET
)
;
r_im_self
=
r
_im_class
;
r_im_func
=
r_descr
->
getAttr
(
offsetof
(
BoxedClassmethod
,
cm_callable
));
r_im_func
->
addGuardNotEq
(
0
);
}
...
...
@@ -919,10 +924,10 @@ Box* nondataDescriptorInstanceSpecialCases(GetattrRewriteArgs* rewrite_args, Box
if
(
!
for_call
)
{
if
(
rewrite_args
)
{
rewrite_args
->
out_rtn
=
rewrite_args
->
rewriter
->
call
(
true
,
(
void
*
)
boxInstanceMethod
,
r_im_self
,
r_im_func
);
=
rewrite_args
->
rewriter
->
call
(
true
,
(
void
*
)
boxInstanceMethod
,
r_im_self
,
r_im_func
,
r_im_class
);
rewrite_args
->
out_success
=
true
;
}
return
boxInstanceMethod
(
im_self
,
im_func
);
return
boxInstanceMethod
(
im_self
,
im_func
,
im_class
);
}
else
{
*
bind_obj_out
=
im_self
;
if
(
rewrite_args
)
{
...
...
@@ -966,10 +971,12 @@ Box* descriptorClsSpecialCases(GetattrRewriteArgs* rewrite_args, BoxedClass* cls
if
(
!
for_call
&&
descr
->
cls
==
function_cls
)
{
if
(
rewrite_args
)
{
// return an unbound instancemethod
rewrite_args
->
out_rtn
=
rewrite_args
->
rewriter
->
call
(
true
,
(
void
*
)
boxUnboundInstanceMethod
,
r_descr
);
RewriterVar
*
r_cls
=
rewrite_args
->
obj
;
rewrite_args
->
out_rtn
=
rewrite_args
->
rewriter
->
call
(
true
,
(
void
*
)
boxUnboundInstanceMethod
,
r_descr
,
r_cls
);
rewrite_args
->
out_success
=
true
;
}
return
boxUnboundInstanceMethod
(
descr
);
return
boxUnboundInstanceMethod
(
descr
,
cls
);
}
if
(
rewrite_args
)
{
...
...
src/runtime/types.cpp
View file @
4210ed9b
...
...
@@ -715,15 +715,15 @@ extern "C" Box* createUserClass(const std::string* name, Box* _bases, Box* _attr
}
}
extern
"C"
Box
*
boxInstanceMethod
(
Box
*
obj
,
Box
*
func
)
{
extern
"C"
Box
*
boxInstanceMethod
(
Box
*
obj
,
Box
*
func
,
Box
*
type
)
{
static
StatCounter
num_ims
(
"num_instancemethods"
);
num_ims
.
log
();
return
new
BoxedInstanceMethod
(
obj
,
func
);
return
new
BoxedInstanceMethod
(
obj
,
func
,
type
);
}
extern
"C"
Box
*
boxUnboundInstanceMethod
(
Box
*
func
)
{
return
new
BoxedInstanceMethod
(
NULL
,
func
);
extern
"C"
Box
*
boxUnboundInstanceMethod
(
Box
*
func
,
Box
*
type
)
{
return
new
BoxedInstanceMethod
(
NULL
,
func
,
type
);
}
extern
"C"
BoxedString
*
noneRepr
(
Box
*
v
)
{
...
...
@@ -773,8 +773,8 @@ static Box* functionGet(BoxedFunction* self, Box* inst, Box* owner) {
RELEASE_ASSERT
(
self
->
cls
==
function_cls
,
""
);
if
(
inst
==
None
)
return
boxUnboundInstanceMethod
(
self
)
;
return
boxInstanceMethod
(
inst
,
self
);
inst
=
NULL
;
return
new
BoxedInstanceMethod
(
inst
,
self
,
owner
);
}
static
Box
*
functionCall
(
BoxedFunction
*
self
,
Box
*
args
,
Box
*
kwargs
)
{
...
...
@@ -919,9 +919,11 @@ Box* instancemethodGet(BoxedInstanceMethod* self, Box* obj, Box* type) {
return
self
;
}
// TODO subclass test
if
(
!
PyObject_IsSubclass
(
type
,
self
->
im_class
))
{
return
self
;
}
return
new
BoxedInstanceMethod
(
obj
,
self
->
func
);
return
new
BoxedInstanceMethod
(
obj
,
self
->
func
,
self
->
im_class
);
}
Box
*
instancemethodNew
(
BoxedClass
*
cls
,
Box
*
func
,
Box
*
self
,
Box
**
args
)
{
...
...
@@ -938,14 +940,49 @@ Box* instancemethodNew(BoxedClass* cls, Box* func, Box* self, Box** args) {
return
NULL
;
}
return
new
BoxedInstanceMethod
(
self
,
func
);
return
new
BoxedInstanceMethod
(
self
,
func
,
classObj
);
}
Box
*
instancemethodRepr
(
BoxedInstanceMethod
*
self
)
{
if
(
self
->
obj
)
return
boxStrConstant
(
"<bound instancemethod object>"
);
else
return
boxStrConstant
(
"<unbound instancemethod object>"
);
// Modified from cpython, Objects/object.c, instancemethod_repr
static
Box
*
instancemethodRepr
(
Box
*
b
)
{
assert
(
isSubclass
(
b
->
cls
,
instancemethod_cls
));
BoxedInstanceMethod
*
a
=
static_cast
<
BoxedInstanceMethod
*>
(
b
);
Box
*
self
=
a
->
obj
;
Box
*
func
=
a
->
func
;
Box
*
klass
=
a
->
im_class
;
Box
*
funcname
=
NULL
,
*
klassname
=
NULL
,
*
result
=
NULL
;
const
char
*
sfuncname
=
"?"
,
*
sklassname
=
"?"
;
funcname
=
getattrInternal
(
func
,
"__name__"
,
NULL
);
if
(
funcname
!=
NULL
)
{
if
(
!
PyString_Check
(
funcname
))
{
funcname
=
NULL
;
}
else
sfuncname
=
PyString_AS_STRING
(
funcname
);
}
if
(
klass
==
NULL
)
{
klassname
=
NULL
;
}
else
{
klassname
=
getattrInternal
(
klass
,
"__name__"
,
NULL
);
if
(
klassname
!=
NULL
)
{
if
(
!
PyString_Check
(
klassname
))
{
klassname
=
NULL
;
}
else
{
sklassname
=
PyString_AS_STRING
(
klassname
);
}
}
}
if
(
self
==
NULL
)
result
=
PyString_FromFormat
(
"<unbound method %s.%s>"
,
sklassname
,
sfuncname
);
else
{
// This was a CPython comment: /* XXX Shouldn't use repr() here! */
Box
*
selfrepr
=
repr
(
self
);
assert
(
PyString_Check
(
selfrepr
));
result
=
PyString_FromFormat
(
"<bound method %s.%s of %s>"
,
sklassname
,
sfuncname
,
PyString_AS_STRING
(
selfrepr
));
}
return
result
;
}
Box
*
instancemethodEq
(
BoxedInstanceMethod
*
self
,
Box
*
rhs
)
{
...
...
@@ -2203,9 +2240,10 @@ void setupRuntime() {
object_cls
->
giveAttr
(
"__init__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
objectInit
,
UNKNOWN
,
1
,
0
,
true
,
false
)));
object_cls
->
giveAttr
(
"__repr__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
objectRepr
,
UNKNOWN
,
1
,
0
,
false
,
false
)));
object_cls
->
giveAttr
(
"__str__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
objectStr
,
UNKNOWN
,
1
,
0
,
false
,
false
)));
object_cls
->
giveAttr
(
"__subclasshook__"
,
boxInstanceMethod
(
object_cls
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
objectSubclasshook
,
UNKNOWN
,
2
))));
object_cls
->
giveAttr
(
"__subclasshook__"
,
boxInstanceMethod
(
object_cls
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
objectSubclasshook
,
UNKNOWN
,
2
)),
object_cls
));
// __setattr__ was already set to a WrapperDescriptor; it'd be nice to set this to a faster BoxedFunction
// object_cls->setattr("__setattr__", new BoxedFunction(boxRTFunction((void*)objectSetattr, UNKNOWN, 3)), NULL);
// but unfortunately that will set tp_setattro to slot_tp_setattro on object_cls and all already-made subclasses!
...
...
@@ -2317,6 +2355,9 @@ void setupRuntime() {
instancemethod_cls
->
giveAttr
(
"__self__"
,
instancemethod_cls
->
getattr
(
"im_self"
));
instancemethod_cls
->
freeze
();
instancemethod_cls
->
giveAttr
(
"im_class"
,
new
BoxedMemberDescriptor
(
BoxedMemberDescriptor
::
OBJECT
,
offsetof
(
BoxedInstanceMethod
,
im_class
),
true
));
slice_cls
->
giveAttr
(
"__new__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
sliceNew
,
UNKNOWN
,
4
,
2
,
false
,
false
),
{
NULL
,
None
}));
slice_cls
->
giveAttr
(
"__repr__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
sliceRepr
,
STR
,
1
)));
...
...
src/runtime/types.h
View file @
4210ed9b
...
...
@@ -107,8 +107,8 @@ extern "C" Box* boxBool(bool);
extern
"C"
Box
*
boxInt
(
i64
);
extern
"C"
i64
unboxInt
(
Box
*
);
extern
"C"
Box
*
boxFloat
(
double
d
);
extern
"C"
Box
*
boxInstanceMethod
(
Box
*
obj
,
Box
*
func
);
extern
"C"
Box
*
boxUnboundInstanceMethod
(
Box
*
func
);
extern
"C"
Box
*
boxInstanceMethod
(
Box
*
obj
,
Box
*
func
,
Box
*
type
);
extern
"C"
Box
*
boxUnboundInstanceMethod
(
Box
*
func
,
Box
*
type
);
extern
"C"
Box
*
boxStringPtr
(
const
std
::
string
*
s
);
Box
*
boxString
(
const
std
::
string
&
s
);
...
...
@@ -470,10 +470,10 @@ public:
Box
**
in_weakreflist
;
// obj is NULL for unbound instancemethod
Box
*
obj
,
*
func
;
Box
*
obj
,
*
func
,
*
im_class
;
BoxedInstanceMethod
(
Box
*
obj
,
Box
*
func
)
__attribute__
((
visibility
(
"default"
)))
:
in_weakreflist
(
NULL
),
obj
(
obj
),
func
(
func
)
{}
BoxedInstanceMethod
(
Box
*
obj
,
Box
*
func
,
Box
*
im_class
)
__attribute__
((
visibility
(
"default"
)))
:
in_weakreflist
(
NULL
),
obj
(
obj
),
func
(
func
)
,
im_class
(
im_class
)
{}
DEFAULT_CLASS_SIMPLE
(
instancemethod_cls
);
};
...
...
test/tests/function_instancemethod.py
View file @
4210ed9b
...
...
@@ -117,3 +117,13 @@ print type(bound_instancemethod)
unbound_instancemethod
=
C
.
l
unbound_instancemethod
(
c2
)
print
type
(
unbound_instancemethod
)
### Test instancemethod repr
print
'test instancemethod repr'
class
C
(
object
):
def
f
(
self
):
pass
def
__repr__
(
self
):
return
'(alpacas are cool)'
print
repr
(
C
.
f
)
print
repr
(
C
().
f
)
test/tests/instance_methods.py
View file @
4210ed9b
...
...
@@ -2,6 +2,38 @@ class C(object):
def
foo
(
self
):
pass
def
__repr__
(
self
):
return
'some C obj'
print
type
(
C
.
foo
)
print
type
(
C
.
foo
.
im_func
),
type
(
C
.
foo
.
__func__
)
print
type
(
C
.
foo
.
im_self
),
type
(
C
.
foo
.
__self__
)
print
type
(
C
.
foo
.
im_class
)
print
repr
(
C
.
foo
)
print
type
(
C
().
foo
)
print
type
(
C
().
foo
.
im_func
),
type
(
C
().
foo
.
__func__
)
print
type
(
C
().
foo
.
im_self
),
type
(
C
().
foo
.
__self__
)
print
type
(
C
().
foo
.
im_class
)
print
repr
(
C
().
foo
)
# old-style classes
class
C
:
def
foo
(
self
):
pass
def
__repr__
(
self
):
return
'some old-style C obj'
print
type
(
C
.
foo
)
print
type
(
C
.
foo
.
im_func
),
type
(
C
.
foo
.
__func__
)
print
type
(
C
.
foo
.
im_self
),
type
(
C
.
foo
.
__self__
)
print
type
(
C
.
foo
.
im_class
)
print
repr
(
C
.
foo
)
print
type
(
C
().
foo
)
print
type
(
C
().
foo
.
im_func
),
type
(
C
().
foo
.
__func__
)
print
type
(
C
().
foo
.
im_self
),
type
(
C
().
foo
.
__self__
)
print
type
(
C
().
foo
.
im_class
)
print
repr
(
C
().
foo
)
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