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
2d2406d5
Commit
2d2406d5
authored
Jun 23, 2015
by
Kevin Modzelewski
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #633 from kmod/cleanup
Some capi/descr code cleanup
parents
df9ec460
15928944
Changes
26
Hide whitespace changes
Inline
Side-by-side
Showing
26 changed files
with
481 additions
and
544 deletions
+481
-544
src/CMakeLists.txt
src/CMakeLists.txt
+0
-1
src/capi/abstract.cpp
src/capi/abstract.cpp
+71
-0
src/capi/descrobject.cpp
src/capi/descrobject.cpp
+0
-147
src/capi/errors.cpp
src/capi/errors.cpp
+0
-1
src/capi/types.h
src/capi/types.h
+0
-121
src/codegen/ast_interpreter.cpp
src/codegen/ast_interpreter.cpp
+0
-1
src/codegen/irgen/hooks.cpp
src/codegen/irgen/hooks.cpp
+0
-1
src/codegen/pypa-parser.cpp
src/codegen/pypa-parser.cpp
+0
-1
src/runtime/builtin_modules/builtins.cpp
src/runtime/builtin_modules/builtins.cpp
+0
-1
src/runtime/builtin_modules/thread.cpp
src/runtime/builtin_modules/thread.cpp
+0
-1
src/runtime/capi.cpp
src/runtime/capi.cpp
+0
-203
src/runtime/capi.h
src/runtime/capi.h
+0
-40
src/runtime/descr.cpp
src/runtime/descr.cpp
+281
-0
src/runtime/import.cpp
src/runtime/import.cpp
+51
-1
src/runtime/import.h
src/runtime/import.h
+1
-0
src/runtime/inline/xrange.cpp
src/runtime/inline/xrange.cpp
+0
-1
src/runtime/int.cpp
src/runtime/int.cpp
+0
-1
src/runtime/long.cpp
src/runtime/long.cpp
+0
-1
src/runtime/objmodel.cpp
src/runtime/objmodel.cpp
+0
-1
src/runtime/set.cpp
src/runtime/set.cpp
+0
-1
src/runtime/str.cpp
src/runtime/str.cpp
+0
-1
src/runtime/tuple.cpp
src/runtime/tuple.cpp
+0
-1
src/runtime/types.cpp
src/runtime/types.cpp
+0
-1
src/runtime/types.h
src/runtime/types.h
+71
-1
src/runtime/util.cpp
src/runtime/util.cpp
+0
-1
test/tests/weakref1.py
test/tests/weakref1.py
+6
-15
No files found.
src/CMakeLists.txt
View file @
2d2406d5
...
...
@@ -28,7 +28,6 @@ add_library(PYSTON_OBJECTS OBJECT ${OPTIONAL_SRCS}
asm_writing/rewriter.cpp
capi/abstract.cpp
capi/codecs.cpp
capi/descrobject.cpp
capi/errors.cpp
capi/modsupport.cpp
capi/object.cpp
...
...
src/capi/abstract.cpp
View file @
2d2406d5
...
...
@@ -1416,6 +1416,77 @@ Fail:
return
NULL
;
}
extern
"C"
PyObject
*
PySequence_Repeat
(
PyObject
*
o
,
Py_ssize_t
count
)
noexcept
{
fatalOrError
(
PyExc_NotImplementedError
,
"unimplemented"
);
return
nullptr
;
}
extern
"C"
PyObject
*
PySequence_InPlaceConcat
(
PyObject
*
o1
,
PyObject
*
o2
)
noexcept
{
fatalOrError
(
PyExc_NotImplementedError
,
"unimplemented"
);
return
nullptr
;
}
extern
"C"
PyObject
*
PySequence_InPlaceRepeat
(
PyObject
*
o
,
Py_ssize_t
count
)
noexcept
{
fatalOrError
(
PyExc_NotImplementedError
,
"unimplemented"
);
return
nullptr
;
}
extern
"C"
PyObject
*
PySequence_GetItem
(
PyObject
*
o
,
Py_ssize_t
i
)
noexcept
{
try
{
// Not sure if this is really the same:
return
getitem
(
o
,
boxInt
(
i
));
}
catch
(
ExcInfo
e
)
{
setCAPIException
(
e
);
return
NULL
;
}
}
extern
"C"
PyObject
*
PySequence_GetSlice
(
PyObject
*
o
,
Py_ssize_t
i1
,
Py_ssize_t
i2
)
noexcept
{
try
{
// Not sure if this is really the same:
return
getitem
(
o
,
createSlice
(
boxInt
(
i1
),
boxInt
(
i2
),
None
));
}
catch
(
ExcInfo
e
)
{
fatalOrError
(
PyExc_NotImplementedError
,
"unimplemented"
);
return
nullptr
;
}
}
extern
"C"
int
PySequence_SetItem
(
PyObject
*
o
,
Py_ssize_t
i
,
PyObject
*
v
)
noexcept
{
fatalOrError
(
PyExc_NotImplementedError
,
"unimplemented"
);
return
-
1
;
}
extern
"C"
int
PySequence_DelItem
(
PyObject
*
o
,
Py_ssize_t
i
)
noexcept
{
try
{
// Not sure if this is really the same:
delitem
(
o
,
boxInt
(
i
));
return
0
;
}
catch
(
ExcInfo
e
)
{
setCAPIException
(
e
);
return
-
1
;
}
}
extern
"C"
int
PySequence_SetSlice
(
PyObject
*
o
,
Py_ssize_t
i1
,
Py_ssize_t
i2
,
PyObject
*
v
)
noexcept
{
fatalOrError
(
PyExc_NotImplementedError
,
"unimplemented"
);
return
-
1
;
}
extern
"C"
int
PySequence_DelSlice
(
PyObject
*
o
,
Py_ssize_t
i1
,
Py_ssize_t
i2
)
noexcept
{
fatalOrError
(
PyExc_NotImplementedError
,
"unimplemented"
);
return
-
1
;
}
extern
"C"
Py_ssize_t
PySequence_Count
(
PyObject
*
o
,
PyObject
*
value
)
noexcept
{
fatalOrError
(
PyExc_NotImplementedError
,
"unimplemented"
);
return
-
1
;
}
extern
"C"
Py_ssize_t
PySequence_Index
(
PyObject
*
o
,
PyObject
*
value
)
noexcept
{
fatalOrError
(
PyExc_NotImplementedError
,
"unimplemented"
);
return
-
1
;
}
extern
"C"
PyObject
*
PyObject_CallFunction
(
PyObject
*
callable
,
const
char
*
format
,
...)
noexcept
{
va_list
va
;
PyObject
*
args
;
...
...
src/capi/descrobject.cpp
deleted
100644 → 0
View file @
df9ec460
// Copyright (c) 2014-2015 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "capi/types.h"
#include "runtime/objmodel.h"
#include "runtime/rewrite_args.h"
namespace
pyston
{
Box
*
BoxedMethodDescriptor
::
__call__
(
BoxedMethodDescriptor
*
self
,
Box
*
obj
,
BoxedTuple
*
varargs
,
Box
**
_args
)
{
STAT_TIMER
(
t0
,
"us_timer_boxedmethoddescriptor__call__"
,
10
);
BoxedDict
*
kwargs
=
static_cast
<
BoxedDict
*>
(
_args
[
0
]);
assert
(
self
->
cls
==
method_cls
);
assert
(
varargs
->
cls
==
tuple_cls
);
assert
(
kwargs
->
cls
==
dict_cls
);
int
ml_flags
=
self
->
method
->
ml_flags
;
int
call_flags
;
if
(
ml_flags
&
METH_CLASS
)
{
if
(
!
isSubclass
(
obj
->
cls
,
type_cls
))
raiseExcHelper
(
TypeError
,
"descriptor '%s' requires a type but received a '%s'"
,
self
->
method
->
ml_name
,
getFullTypeName
(
obj
).
c_str
());
call_flags
=
ml_flags
&
(
~
METH_CLASS
);
}
else
{
if
(
!
isSubclass
(
obj
->
cls
,
self
->
type
))
raiseExcHelper
(
TypeError
,
"descriptor '%s' requires a '%s' object but received a '%s'"
,
self
->
method
->
ml_name
,
getFullNameOfClass
(
self
->
type
).
c_str
(),
getFullTypeName
(
obj
).
c_str
());
call_flags
=
ml_flags
;
}
threading
::
GLPromoteRegion
_gil_lock
;
Box
*
rtn
;
if
(
call_flags
==
METH_NOARGS
)
{
RELEASE_ASSERT
(
varargs
->
size
()
==
0
,
""
);
RELEASE_ASSERT
(
kwargs
->
d
.
size
()
==
0
,
""
);
rtn
=
(
Box
*
)
self
->
method
->
ml_meth
(
obj
,
NULL
);
}
else
if
(
call_flags
==
METH_VARARGS
)
{
RELEASE_ASSERT
(
kwargs
->
d
.
size
()
==
0
,
""
);
rtn
=
(
Box
*
)
self
->
method
->
ml_meth
(
obj
,
varargs
);
}
else
if
(
call_flags
==
(
METH_VARARGS
|
METH_KEYWORDS
))
{
rtn
=
(
Box
*
)((
PyCFunctionWithKeywords
)
self
->
method
->
ml_meth
)(
obj
,
varargs
,
kwargs
);
}
else
if
(
call_flags
==
METH_O
)
{
RELEASE_ASSERT
(
kwargs
->
d
.
size
()
==
0
,
""
);
RELEASE_ASSERT
(
varargs
->
size
()
==
1
,
""
);
rtn
=
(
Box
*
)
self
->
method
->
ml_meth
(
obj
,
varargs
->
elts
[
0
]);
}
else
{
RELEASE_ASSERT
(
0
,
"0x%x"
,
call_flags
);
}
checkAndThrowCAPIException
();
assert
(
rtn
&&
"should have set + thrown an exception!"
);
return
rtn
;
}
Box
*
BoxedMethodDescriptor
::
callInternal
(
BoxedFunctionBase
*
f
,
CallRewriteArgs
*
rewrite_args
,
ArgPassSpec
argspec
,
Box
*
arg1
,
Box
*
arg2
,
Box
*
arg3
,
Box
**
args
,
const
std
::
vector
<
BoxedString
*>*
keyword_names
)
{
// TODO: could also handle cases where we have starargs but no positional args,
// and similarly for kwargs but no keywords
if
(
!
rewrite_args
||
argspec
.
has_kwargs
||
argspec
.
has_starargs
||
argspec
.
num_keywords
>
0
||
argspec
.
num_args
>
4
)
return
callFunc
(
f
,
rewrite_args
,
argspec
,
arg1
,
arg2
,
arg3
,
args
,
keyword_names
);
assert
(
argspec
.
num_args
>=
2
);
int
passed_varargs
=
argspec
.
num_args
-
2
;
assert
(
arg1
->
cls
==
method_cls
);
BoxedMethodDescriptor
*
self
=
static_cast
<
BoxedMethodDescriptor
*>
(
arg1
);
Box
*
obj
=
arg2
;
RewriterVar
*
r_obj
=
rewrite_args
->
arg2
;
// We could also guard on the fields of the method object, but lets just guard on the object itself
// for now.
// TODO: what if it gets GC'd?
rewrite_args
->
arg1
->
addGuard
((
intptr_t
)
self
);
int
ml_flags
=
self
->
method
->
ml_flags
;
RELEASE_ASSERT
((
ml_flags
&
METH_CLASS
)
==
0
,
"unimplemented"
);
if
(
!
isSubclass
(
obj
->
cls
,
self
->
type
))
raiseExcHelper
(
TypeError
,
"descriptor '%s' requires a '%s' object but received a '%s'"
,
self
->
method
->
ml_name
,
getFullNameOfClass
(
self
->
type
).
c_str
(),
getFullTypeName
(
obj
).
c_str
());
r_obj
->
addAttrGuard
(
offsetof
(
Box
,
cls
),
(
intptr_t
)
obj
->
cls
);
int
call_flags
=
ml_flags
;
Box
*
rtn
;
RewriterVar
*
r_rtn
;
if
(
call_flags
==
METH_NOARGS
)
{
RELEASE_ASSERT
(
passed_varargs
==
0
,
""
);
rtn
=
(
Box
*
)(
self
->
method
->
ml_meth
)(
obj
,
NULL
);
r_rtn
=
rewrite_args
->
rewriter
->
call
(
true
,
(
void
*
)
self
->
method
->
ml_meth
,
r_obj
,
rewrite_args
->
rewriter
->
loadConst
(
0
,
Location
::
forArg
(
1
)));
}
else
if
(
call_flags
&
METH_VARARGS
)
{
RELEASE_ASSERT
(
call_flags
==
METH_VARARGS
||
call_flags
==
(
METH_VARARGS
|
METH_KEYWORDS
),
""
);
Box
*
varargs
;
RewriterVar
*
r_varargs
;
if
(
passed_varargs
==
0
)
{
varargs
=
EmptyTuple
;
r_varargs
=
rewrite_args
->
rewriter
->
loadConst
((
intptr_t
)
EmptyTuple
,
Location
::
forArg
(
1
));
}
else
if
(
passed_varargs
==
1
)
{
varargs
=
BoxedTuple
::
create1
(
arg3
);
r_varargs
=
rewrite_args
->
rewriter
->
call
(
false
,
(
void
*
)
BoxedTuple
::
create1
,
rewrite_args
->
arg3
);
}
else
if
(
passed_varargs
==
2
)
{
varargs
=
BoxedTuple
::
create2
(
arg3
,
args
[
0
]);
r_varargs
=
rewrite_args
->
rewriter
->
call
(
false
,
(
void
*
)
BoxedTuple
::
create2
,
rewrite_args
->
arg3
,
rewrite_args
->
args
->
getAttr
(
0
,
Location
::
forArg
(
1
)));
}
else
{
RELEASE_ASSERT
(
0
,
""
);
}
if
(
call_flags
&
METH_KEYWORDS
)
{
Box
*
kwargs
=
NULL
;
RewriterVar
*
r_kwargs
=
rewrite_args
->
rewriter
->
loadConst
(
0
);
rtn
=
(
Box
*
)((
PyCFunctionWithKeywords
)
self
->
method
->
ml_meth
)(
obj
,
varargs
,
kwargs
);
r_rtn
=
rewrite_args
->
rewriter
->
call
(
true
,
(
void
*
)
self
->
method
->
ml_meth
,
r_obj
,
r_varargs
,
r_kwargs
);
}
else
{
rtn
=
(
Box
*
)(
self
->
method
->
ml_meth
)(
obj
,
varargs
);
r_rtn
=
rewrite_args
->
rewriter
->
call
(
true
,
(
void
*
)
self
->
method
->
ml_meth
,
r_obj
,
r_varargs
);
}
}
else
if
(
call_flags
==
METH_O
)
{
RELEASE_ASSERT
(
passed_varargs
==
1
,
""
);
rtn
=
(
Box
*
)(
self
->
method
->
ml_meth
)(
obj
,
arg3
);
r_rtn
=
rewrite_args
->
rewriter
->
call
(
true
,
(
void
*
)
self
->
method
->
ml_meth
,
r_obj
,
rewrite_args
->
arg3
);
}
else
{
RELEASE_ASSERT
(
0
,
"0x%x"
,
call_flags
);
}
rewrite_args
->
rewriter
->
call
(
true
,
(
void
*
)
checkAndThrowCAPIException
);
rewrite_args
->
out_rtn
=
r_rtn
;
rewrite_args
->
out_success
=
true
;
return
rtn
;
}
}
src/capi/errors.cpp
View file @
2d2406d5
...
...
@@ -21,7 +21,6 @@
#include "core/types.h"
#include "core/util.h"
#include "gc/collector.h"
#include "runtime/capi.h"
#include "runtime/dict.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
...
...
src/capi/types.h
View file @
2d2406d5
...
...
@@ -15,7 +15,6 @@
#ifndef PYSTON_CAPI_TYPES_H
#define PYSTON_CAPI_TYPES_H
#include "runtime/capi.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
...
...
@@ -24,18 +23,6 @@ namespace pyston {
typedef
PyObject
*
(
*
wrapperfunc
)(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
);
typedef
PyObject
*
(
*
wrapperfunc_kwds
)(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
,
PyObject
*
kwds
);
struct
wrapper_def
{
const
llvm
::
StringRef
name
;
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
const
llvm
::
StringRef
doc
;
int
flags
;
// exists in CPython: PyObject *name_strobj
};
extern
"C"
BoxedClass
*
capifunc_cls
,
*
wrapperdescr_cls
,
*
wrapperobject_cls
;
class
BoxedCApiFunction
:
public
Box
{
public:
PyMethodDef
*
method_def
;
...
...
@@ -132,114 +119,6 @@ static_assert(offsetof(BoxedCApiFunction, method_def) == offsetof(PyCFunctionObj
static_assert
(
offsetof
(
BoxedCApiFunction
,
passthrough
)
==
offsetof
(
PyCFunctionObject
,
m_self
),
""
);
static_assert
(
offsetof
(
BoxedCApiFunction
,
module
)
==
offsetof
(
PyCFunctionObject
,
m_module
),
""
);
class
BoxedWrapperDescriptor
:
public
Box
{
public:
const
wrapper_def
*
wrapper
;
BoxedClass
*
type
;
void
*
wrapped
;
BoxedWrapperDescriptor
(
const
wrapper_def
*
wrapper
,
BoxedClass
*
type
,
void
*
wrapped
)
:
wrapper
(
wrapper
),
type
(
type
),
wrapped
(
wrapped
)
{}
DEFAULT_CLASS
(
wrapperdescr_cls
);
static
Box
*
__get__
(
BoxedWrapperDescriptor
*
self
,
Box
*
inst
,
Box
*
owner
);
static
Box
*
descr_get
(
Box
*
self
,
Box
*
inst
,
Box
*
owner
)
noexcept
;
static
Box
*
__call__
(
BoxedWrapperDescriptor
*
descr
,
PyObject
*
self
,
BoxedTuple
*
args
,
Box
**
_args
);
static
void
gcHandler
(
GCVisitor
*
v
,
Box
*
_o
)
{
assert
(
_o
->
cls
==
wrapperdescr_cls
);
BoxedWrapperDescriptor
*
o
=
static_cast
<
BoxedWrapperDescriptor
*>
(
_o
);
boxGCHandler
(
v
,
o
);
v
->
visit
(
o
->
type
);
}
};
class
BoxedWrapperObject
:
public
Box
{
public:
BoxedWrapperDescriptor
*
descr
;
Box
*
obj
;
BoxedWrapperObject
(
BoxedWrapperDescriptor
*
descr
,
Box
*
obj
)
:
descr
(
descr
),
obj
(
obj
)
{}
DEFAULT_CLASS
(
wrapperobject_cls
);
static
Box
*
__call__
(
BoxedWrapperObject
*
self
,
Box
*
args
,
Box
*
kwds
)
{
STAT_TIMER
(
t0
,
"us_timer_boxedwrapperobject__call__"
,
(
self
->
cls
->
is_user_defined
?
1
:
2
));
assert
(
self
->
cls
==
wrapperobject_cls
);
assert
(
args
->
cls
==
tuple_cls
);
assert
(
kwds
->
cls
==
dict_cls
);
int
flags
=
self
->
descr
->
wrapper
->
flags
;
wrapperfunc
wrapper
=
self
->
descr
->
wrapper
->
wrapper
;
assert
(
self
->
descr
->
wrapper
->
offset
>
0
);
Box
*
rtn
;
if
(
flags
==
PyWrapperFlag_KEYWORDS
)
{
wrapperfunc_kwds
wk
=
(
wrapperfunc_kwds
)
wrapper
;
rtn
=
(
*
wk
)(
self
->
obj
,
args
,
self
->
descr
->
wrapped
,
kwds
);
}
else
if
(
flags
==
PyWrapperFlag_PYSTON
||
flags
==
0
)
{
rtn
=
(
*
wrapper
)(
self
->
obj
,
args
,
self
->
descr
->
wrapped
);
}
else
{
RELEASE_ASSERT
(
0
,
"%d"
,
flags
);
}
checkAndThrowCAPIException
();
assert
(
rtn
&&
"should have set + thrown an exception!"
);
return
rtn
;
}
static
void
gcHandler
(
GCVisitor
*
v
,
Box
*
_o
)
{
assert
(
_o
->
cls
==
wrapperobject_cls
);
BoxedWrapperObject
*
o
=
static_cast
<
BoxedWrapperObject
*>
(
_o
);
boxGCHandler
(
v
,
o
);
v
->
visit
(
o
->
obj
);
}
};
class
BoxedMethodDescriptor
:
public
Box
{
public:
PyMethodDef
*
method
;
BoxedClass
*
type
;
BoxedMethodDescriptor
(
PyMethodDef
*
method
,
BoxedClass
*
type
)
:
method
(
method
),
type
(
type
)
{}
DEFAULT_CLASS
(
method_cls
);
static
Box
*
__get__
(
BoxedMethodDescriptor
*
self
,
Box
*
inst
,
Box
*
owner
)
{
RELEASE_ASSERT
(
self
->
cls
==
method_cls
,
""
);
// 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
,
self
->
type
);
if
(
self
->
method
->
ml_flags
&
METH_STATIC
)
Py_FatalError
(
"unimplemented"
);
if
(
self
->
method
->
ml_flags
&
METH_COEXIST
)
Py_FatalError
(
"unimplemented"
);
if
(
inst
==
None
)
return
self
;
else
return
boxInstanceMethod
(
inst
,
self
,
self
->
type
);
}
static
Box
*
__call__
(
BoxedMethodDescriptor
*
self
,
Box
*
obj
,
BoxedTuple
*
varargs
,
Box
**
_args
);
static
Box
*
callInternal
(
BoxedFunctionBase
*
f
,
CallRewriteArgs
*
rewrite_args
,
ArgPassSpec
argspec
,
Box
*
arg1
,
Box
*
arg2
,
Box
*
arg3
,
Box
**
args
,
const
std
::
vector
<
BoxedString
*>*
keyword_names
);
static
void
gcHandler
(
GCVisitor
*
v
,
Box
*
_o
)
{
assert
(
_o
->
cls
==
method_cls
);
BoxedMethodDescriptor
*
o
=
static_cast
<
BoxedMethodDescriptor
*>
(
_o
);
boxGCHandler
(
v
,
o
);
v
->
visit
(
o
->
type
);
}
};
PyObject
*
convert_3way_to_object
(
int
op
,
int
c
)
noexcept
;
int
default_3way_compare
(
PyObject
*
v
,
PyObject
*
w
);
...
...
src/codegen/ast_interpreter.cpp
View file @
2d2406d5
...
...
@@ -34,7 +34,6 @@
#include "core/stats.h"
#include "core/thread_utils.h"
#include "core/util.h"
#include "runtime/capi.h"
#include "runtime/generator.h"
#include "runtime/import.h"
#include "runtime/inline/boxing.h"
...
...
src/codegen/irgen/hooks.cpp
View file @
2d2406d5
...
...
@@ -38,7 +38,6 @@
#include "core/stats.h"
#include "core/types.h"
#include "core/util.h"
#include "runtime/capi.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
...
...
src/codegen/pypa-parser.cpp
View file @
2d2406d5
...
...
@@ -33,7 +33,6 @@
#include "core/types.h"
#include "core/util.h"
#include "gc/collector.h"
#include "runtime/capi.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
...
...
src/runtime/builtin_modules/builtins.cpp
View file @
2d2406d5
...
...
@@ -27,7 +27,6 @@
#include "core/ast.h"
#include "core/types.h"
#include "gc/collector.h"
#include "runtime/capi.h"
#include "runtime/classobj.h"
#include "runtime/file.h"
#include "runtime/ics.h"
...
...
src/runtime/builtin_modules/thread.cpp
View file @
2d2406d5
...
...
@@ -21,7 +21,6 @@
#include "capi/typeobject.h"
#include "core/threading.h"
#include "core/types.h"
#include "runtime/capi.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
...
...
src/runtime/capi.cpp
View file @
2d2406d5
...
...
@@ -12,7 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include <dlfcn.h>
#include <fcntl.h>
#include <stdarg.h>
#include <string.h>
...
...
@@ -53,47 +52,6 @@ extern "C" {
int
Py_Py3kWarningFlag
;
BoxedClass
*
capifunc_cls
;
BoxedClass
*
wrapperdescr_cls
,
*
wrapperobject_cls
;
}
Box
*
BoxedWrapperDescriptor
::
__get__
(
BoxedWrapperDescriptor
*
self
,
Box
*
inst
,
Box
*
owner
)
{
RELEASE_ASSERT
(
self
->
cls
==
wrapperdescr_cls
,
""
);
if
(
inst
==
None
)
return
self
;
if
(
!
isSubclass
(
inst
->
cls
,
self
->
type
))
raiseExcHelper
(
TypeError
,
"Descriptor '' for '%s' objects doesn't apply to '%s' object"
,
getFullNameOfClass
(
self
->
type
).
c_str
(),
getFullTypeName
(
inst
).
c_str
());
return
new
BoxedWrapperObject
(
self
,
inst
);
}
Box
*
BoxedWrapperDescriptor
::
descr_get
(
Box
*
_self
,
Box
*
inst
,
Box
*
owner
)
noexcept
{
RELEASE_ASSERT
(
_self
->
cls
==
wrapperdescr_cls
,
""
);
BoxedWrapperDescriptor
*
self
=
static_cast
<
BoxedWrapperDescriptor
*>
(
_self
);
if
(
inst
==
None
)
return
self
;
if
(
!
isSubclass
(
inst
->
cls
,
self
->
type
))
PyErr_Format
(
TypeError
,
"Descriptor '' for '%s' objects doesn't apply to '%s' object"
,
getFullNameOfClass
(
self
->
type
).
c_str
(),
getFullTypeName
(
inst
).
c_str
());
return
new
BoxedWrapperObject
(
self
,
inst
);
}
Box
*
BoxedWrapperDescriptor
::
__call__
(
BoxedWrapperDescriptor
*
descr
,
PyObject
*
self
,
BoxedTuple
*
args
,
Box
**
_args
)
{
RELEASE_ASSERT
(
descr
->
cls
==
wrapperdescr_cls
,
""
);
BoxedDict
*
kw
=
static_cast
<
BoxedDict
*>
(
_args
[
0
]);
if
(
!
isSubclass
(
self
->
cls
,
descr
->
type
))
raiseExcHelper
(
TypeError
,
"descriptor '' requires a '%s' object but received a '%s'"
,
getFullNameOfClass
(
descr
->
type
).
c_str
(),
getFullTypeName
(
self
).
c_str
());
auto
wrapper
=
new
BoxedWrapperObject
(
descr
,
self
);
return
BoxedWrapperObject
::
__call__
(
wrapper
,
args
,
kw
);
}
extern
"C"
void
_PyErr_BadInternalCall
(
const
char
*
filename
,
int
lineno
)
noexcept
{
...
...
@@ -675,77 +633,6 @@ extern "C" int PyObject_Print(PyObject* obj, FILE* fp, int flags) noexcept {
return
internal_print
(
obj
,
fp
,
flags
,
0
);
};
extern
"C"
PyObject
*
PySequence_Repeat
(
PyObject
*
o
,
Py_ssize_t
count
)
noexcept
{
fatalOrError
(
PyExc_NotImplementedError
,
"unimplemented"
);
return
nullptr
;
}
extern
"C"
PyObject
*
PySequence_InPlaceConcat
(
PyObject
*
o1
,
PyObject
*
o2
)
noexcept
{
fatalOrError
(
PyExc_NotImplementedError
,
"unimplemented"
);
return
nullptr
;
}
extern
"C"
PyObject
*
PySequence_InPlaceRepeat
(
PyObject
*
o
,
Py_ssize_t
count
)
noexcept
{
fatalOrError
(
PyExc_NotImplementedError
,
"unimplemented"
);
return
nullptr
;
}
extern
"C"
PyObject
*
PySequence_GetItem
(
PyObject
*
o
,
Py_ssize_t
i
)
noexcept
{
try
{
// Not sure if this is really the same:
return
getitem
(
o
,
boxInt
(
i
));
}
catch
(
ExcInfo
e
)
{
setCAPIException
(
e
);
return
NULL
;
}
}
extern
"C"
PyObject
*
PySequence_GetSlice
(
PyObject
*
o
,
Py_ssize_t
i1
,
Py_ssize_t
i2
)
noexcept
{
try
{
// Not sure if this is really the same:
return
getitem
(
o
,
createSlice
(
boxInt
(
i1
),
boxInt
(
i2
),
None
));
}
catch
(
ExcInfo
e
)
{
fatalOrError
(
PyExc_NotImplementedError
,
"unimplemented"
);
return
nullptr
;
}
}
extern
"C"
int
PySequence_SetItem
(
PyObject
*
o
,
Py_ssize_t
i
,
PyObject
*
v
)
noexcept
{
fatalOrError
(
PyExc_NotImplementedError
,
"unimplemented"
);
return
-
1
;
}
extern
"C"
int
PySequence_DelItem
(
PyObject
*
o
,
Py_ssize_t
i
)
noexcept
{
try
{
// Not sure if this is really the same:
delitem
(
o
,
boxInt
(
i
));
return
0
;
}
catch
(
ExcInfo
e
)
{
setCAPIException
(
e
);
return
-
1
;
}
}
extern
"C"
int
PySequence_SetSlice
(
PyObject
*
o
,
Py_ssize_t
i1
,
Py_ssize_t
i2
,
PyObject
*
v
)
noexcept
{
fatalOrError
(
PyExc_NotImplementedError
,
"unimplemented"
);
return
-
1
;
}
extern
"C"
int
PySequence_DelSlice
(
PyObject
*
o
,
Py_ssize_t
i1
,
Py_ssize_t
i2
)
noexcept
{
fatalOrError
(
PyExc_NotImplementedError
,
"unimplemented"
);
return
-
1
;
}
extern
"C"
Py_ssize_t
PySequence_Count
(
PyObject
*
o
,
PyObject
*
value
)
noexcept
{
fatalOrError
(
PyExc_NotImplementedError
,
"unimplemented"
);
return
-
1
;
}
extern
"C"
Py_ssize_t
PySequence_Index
(
PyObject
*
o
,
PyObject
*
value
)
noexcept
{
fatalOrError
(
PyExc_NotImplementedError
,
"unimplemented"
);
return
-
1
;
}
extern
"C"
PyObject
*
PyIter_Next
(
PyObject
*
iter
)
noexcept
{
try
{
Box
*
hasnext
=
iter
->
hasnextOrNullIC
();
...
...
@@ -1570,56 +1457,6 @@ extern "C" char* PyModule_GetFilename(PyObject* m) noexcept {
return
PyString_AsString
(
fileobj
);
}
BoxedModule
*
importCExtension
(
const
std
::
string
&
full_name
,
const
std
::
string
&
last_name
,
const
std
::
string
&
path
)
{
void
*
handle
=
dlopen
(
path
.
c_str
(),
RTLD_NOW
);
if
(
!
handle
)
{
// raiseExcHelper(ImportError, "%s", dlerror());
fprintf
(
stderr
,
"%s
\n
"
,
dlerror
());
exit
(
1
);
}
assert
(
handle
);
std
::
string
initname
=
"init"
+
last_name
;
void
(
*
init
)()
=
(
void
(
*
)())
dlsym
(
handle
,
initname
.
c_str
());
char
*
error
;
if
((
error
=
dlerror
())
!=
NULL
)
{
// raiseExcHelper(ImportError, "%s", error);
fprintf
(
stderr
,
"%s
\n
"
,
error
);
exit
(
1
);
}
assert
(
init
);
// Let the GC know about the static variables.
uintptr_t
bss_start
=
(
uintptr_t
)
dlsym
(
handle
,
"__bss_start"
);
uintptr_t
bss_end
=
(
uintptr_t
)
dlsym
(
handle
,
"_end"
);
RELEASE_ASSERT
(
bss_end
-
bss_start
<
100000
,
"Large BSS section detected - there maybe something wrong"
);
// only track void* aligned memory
bss_start
=
(
bss_start
+
(
sizeof
(
void
*
)
-
1
))
&
~
(
sizeof
(
void
*
)
-
1
);
bss_end
-=
bss_end
%
sizeof
(
void
*
);
gc
::
registerPotentialRootRange
((
void
*
)
bss_start
,
(
void
*
)
bss_end
);
char
*
packagecontext
=
strdup
(
full_name
.
c_str
());
char
*
oldcontext
=
_Py_PackageContext
;
_Py_PackageContext
=
packagecontext
;
(
*
init
)();
_Py_PackageContext
=
oldcontext
;
free
(
packagecontext
);
checkAndThrowCAPIException
();
BoxedDict
*
sys_modules
=
getSysModulesDict
();
Box
*
s
=
boxString
(
full_name
);
Box
*
_m
=
sys_modules
->
d
[
s
];
RELEASE_ASSERT
(
_m
,
"dynamic module not initialized properly"
);
assert
(
_m
->
cls
==
module_cls
);
BoxedModule
*
m
=
static_cast
<
BoxedModule
*>
(
_m
);
m
->
setattr
(
"__file__"
,
boxString
(
path
),
NULL
);
return
m
;
}
Box
*
BoxedCApiFunction
::
callInternal
(
BoxedFunctionBase
*
func
,
CallRewriteArgs
*
rewrite_args
,
ArgPassSpec
argspec
,
Box
*
arg1
,
Box
*
arg2
,
Box
*
arg3
,
Box
**
args
,
const
std
::
vector
<
BoxedString
*>*
keyword_names
)
{
...
...
@@ -1645,21 +1482,6 @@ Box* BoxedCApiFunction::callInternal(BoxedFunctionBase* func, CallRewriteArgs* r
return
r
;
}
static
Box
*
methodGetDoc
(
Box
*
b
,
void
*
)
{
assert
(
b
->
cls
==
method_cls
);
const
char
*
s
=
static_cast
<
BoxedMethodDescriptor
*>
(
b
)
->
method
->
ml_doc
;
if
(
s
)
return
boxString
(
s
);
return
None
;
}
static
Box
*
wrapperdescrGetDoc
(
Box
*
b
,
void
*
)
{
assert
(
b
->
cls
==
wrapperdescr_cls
);
auto
s
=
static_cast
<
BoxedWrapperDescriptor
*>
(
b
)
->
wrapper
->
doc
;
assert
(
s
.
size
());
return
boxString
(
s
);
}
/* extension modules might be compiled with GC support so these
functions must always be available */
...
...
@@ -1719,10 +1541,6 @@ extern "C" void _Py_FatalError(const char* fmt, const char* function, const char
abort
();
}
extern
"C"
PyObject
*
PyClassMethod_New
(
PyObject
*
callable
)
noexcept
{
return
new
BoxedClassmethod
(
callable
);
}
void
setupCAPI
()
{
capifunc_cls
->
giveAttr
(
"__repr__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
BoxedCApiFunction
::
__repr__
,
UNKNOWN
,
1
)));
...
...
@@ -1736,27 +1554,6 @@ void setupCAPI() {
"__module__"
,
new
BoxedMemberDescriptor
(
BoxedMemberDescriptor
::
OBJECT
,
offsetof
(
BoxedCApiFunction
,
module
)));
capifunc_cls
->
freeze
();
method_cls
->
giveAttr
(
"__get__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
BoxedMethodDescriptor
::
__get__
,
UNKNOWN
,
3
)));
CLFunction
*
method_call_cl
=
boxRTFunction
((
void
*
)
BoxedMethodDescriptor
::
__call__
,
UNKNOWN
,
2
,
0
,
true
,
true
);
method_call_cl
->
internal_callable
=
BoxedMethodDescriptor
::
callInternal
;
method_cls
->
giveAttr
(
"__call__"
,
new
BoxedFunction
(
method_call_cl
));
method_cls
->
giveAttr
(
"__doc__"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
methodGetDoc
,
NULL
,
NULL
));
method_cls
->
freeze
();
wrapperdescr_cls
->
giveAttr
(
"__get__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
BoxedWrapperDescriptor
::
__get__
,
UNKNOWN
,
3
)));
wrapperdescr_cls
->
giveAttr
(
"__call__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
BoxedWrapperDescriptor
::
__call__
,
UNKNOWN
,
2
,
0
,
true
,
true
)));
wrapperdescr_cls
->
giveAttr
(
"__doc__"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
wrapperdescrGetDoc
,
NULL
,
NULL
));
wrapperdescr_cls
->
freeze
();
wrapperdescr_cls
->
tp_descr_get
=
BoxedWrapperDescriptor
::
descr_get
;
wrapperobject_cls
->
giveAttr
(
"__call__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
BoxedWrapperObject
::
__call__
,
UNKNOWN
,
1
,
0
,
true
,
true
)));
wrapperobject_cls
->
freeze
();
}
void
teardownCAPI
()
{
...
...
src/runtime/capi.h
deleted
100644 → 0
View file @
df9ec460
// Copyright (c) 2014-2015 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PYSTON_RUNTIME_CAPI_H
#define PYSTON_RUNTIME_CAPI_H
#include <string>
namespace
pyston
{
class
Box
;
class
BoxedModule
;
BoxedModule
*
importCExtension
(
const
std
::
string
&
full_name
,
const
std
::
string
&
last_name
,
const
std
::
string
&
path
);
void
checkAndThrowCAPIException
();
void
throwCAPIException
()
__attribute__
((
noreturn
));
struct
ExcInfo
;
void
setCAPIException
(
const
ExcInfo
&
e
);
#define fatalOrError(exception, message) \
do { \
if (CONTINUE_AFTER_FATAL) \
PyErr_SetString((exception), (message)); \
else \
Py_FatalError((message)); \
} while (0)
}
#endif
src/runtime/descr.cpp
View file @
2d2406d5
...
...
@@ -14,10 +14,15 @@
#include "codegen/compvars.h"
#include "runtime/objmodel.h"
#include "runtime/rewrite_args.h"
#include "runtime/types.h"
namespace
pyston
{
extern
"C"
{
BoxedClass
*
wrapperdescr_cls
,
*
wrapperobject_cls
;
}
static
Box
*
memberGet
(
BoxedMemberDescriptor
*
self
,
Box
*
inst
,
Box
*
owner
)
{
RELEASE_ASSERT
(
self
->
cls
==
member_descriptor_cls
,
""
);
...
...
@@ -193,6 +198,10 @@ static Box* staticmethodGet(Box* self, Box* obj, Box* type) {
return
sm
->
sm_callable
;
}
extern
"C"
PyObject
*
PyClassMethod_New
(
PyObject
*
callable
)
noexcept
{
return
new
BoxedClassmethod
(
callable
);
}
static
Box
*
classmethodInit
(
Box
*
_self
,
Box
*
f
)
{
RELEASE_ASSERT
(
_self
->
cls
==
classmethod_cls
,
""
);
BoxedClassmethod
*
self
=
static_cast
<
BoxedClassmethod
*>
(
_self
);
...
...
@@ -217,6 +226,257 @@ static Box* classmethodGet(Box* self, Box* obj, Box* type) {
return
new
BoxedInstanceMethod
(
type
,
cm
->
cm_callable
,
type
);
}
Box
*
BoxedMethodDescriptor
::
__call__
(
BoxedMethodDescriptor
*
self
,
Box
*
obj
,
BoxedTuple
*
varargs
,
Box
**
_args
)
{
STAT_TIMER
(
t0
,
"us_timer_boxedmethoddescriptor__call__"
,
10
);
BoxedDict
*
kwargs
=
static_cast
<
BoxedDict
*>
(
_args
[
0
]);
assert
(
self
->
cls
==
method_cls
);
assert
(
varargs
->
cls
==
tuple_cls
);
assert
(
kwargs
->
cls
==
dict_cls
);
int
ml_flags
=
self
->
method
->
ml_flags
;
int
call_flags
;
if
(
ml_flags
&
METH_CLASS
)
{
if
(
!
isSubclass
(
obj
->
cls
,
type_cls
))
raiseExcHelper
(
TypeError
,
"descriptor '%s' requires a type but received a '%s'"
,
self
->
method
->
ml_name
,
getFullTypeName
(
obj
).
c_str
());
call_flags
=
ml_flags
&
(
~
METH_CLASS
);
}
else
{
if
(
!
isSubclass
(
obj
->
cls
,
self
->
type
))
raiseExcHelper
(
TypeError
,
"descriptor '%s' requires a '%s' object but received a '%s'"
,
self
->
method
->
ml_name
,
getFullNameOfClass
(
self
->
type
).
c_str
(),
getFullTypeName
(
obj
).
c_str
());
call_flags
=
ml_flags
;
}
threading
::
GLPromoteRegion
_gil_lock
;
Box
*
rtn
;
if
(
call_flags
==
METH_NOARGS
)
{
RELEASE_ASSERT
(
varargs
->
size
()
==
0
,
""
);
RELEASE_ASSERT
(
kwargs
->
d
.
size
()
==
0
,
""
);
rtn
=
(
Box
*
)
self
->
method
->
ml_meth
(
obj
,
NULL
);
}
else
if
(
call_flags
==
METH_VARARGS
)
{
RELEASE_ASSERT
(
kwargs
->
d
.
size
()
==
0
,
""
);
rtn
=
(
Box
*
)
self
->
method
->
ml_meth
(
obj
,
varargs
);
}
else
if
(
call_flags
==
(
METH_VARARGS
|
METH_KEYWORDS
))
{
rtn
=
(
Box
*
)((
PyCFunctionWithKeywords
)
self
->
method
->
ml_meth
)(
obj
,
varargs
,
kwargs
);
}
else
if
(
call_flags
==
METH_O
)
{
RELEASE_ASSERT
(
kwargs
->
d
.
size
()
==
0
,
""
);
RELEASE_ASSERT
(
varargs
->
size
()
==
1
,
""
);
rtn
=
(
Box
*
)
self
->
method
->
ml_meth
(
obj
,
varargs
->
elts
[
0
]);
}
else
{
RELEASE_ASSERT
(
0
,
"0x%x"
,
call_flags
);
}
checkAndThrowCAPIException
();
assert
(
rtn
&&
"should have set + thrown an exception!"
);
return
rtn
;
}
Box
*
BoxedMethodDescriptor
::
callInternal
(
BoxedFunctionBase
*
f
,
CallRewriteArgs
*
rewrite_args
,
ArgPassSpec
argspec
,
Box
*
arg1
,
Box
*
arg2
,
Box
*
arg3
,
Box
**
args
,
const
std
::
vector
<
BoxedString
*>*
keyword_names
)
{
// TODO: could also handle cases where we have starargs but no positional args,
// and similarly for kwargs but no keywords
if
(
!
rewrite_args
||
argspec
.
has_kwargs
||
argspec
.
has_starargs
||
argspec
.
num_keywords
>
0
||
argspec
.
num_args
>
4
)
return
callFunc
(
f
,
rewrite_args
,
argspec
,
arg1
,
arg2
,
arg3
,
args
,
keyword_names
);
assert
(
argspec
.
num_args
>=
2
);
int
passed_varargs
=
argspec
.
num_args
-
2
;
assert
(
arg1
->
cls
==
method_cls
);
BoxedMethodDescriptor
*
self
=
static_cast
<
BoxedMethodDescriptor
*>
(
arg1
);
Box
*
obj
=
arg2
;
RewriterVar
*
r_obj
=
rewrite_args
->
arg2
;
// We could also guard on the fields of the method object, but lets just guard on the object itself
// for now.
// TODO: what if it gets GC'd?
rewrite_args
->
arg1
->
addGuard
((
intptr_t
)
self
);
int
ml_flags
=
self
->
method
->
ml_flags
;
RELEASE_ASSERT
((
ml_flags
&
METH_CLASS
)
==
0
,
"unimplemented"
);
if
(
!
isSubclass
(
obj
->
cls
,
self
->
type
))
raiseExcHelper
(
TypeError
,
"descriptor '%s' requires a '%s' object but received a '%s'"
,
self
->
method
->
ml_name
,
getFullNameOfClass
(
self
->
type
).
c_str
(),
getFullTypeName
(
obj
).
c_str
());
r_obj
->
addAttrGuard
(
offsetof
(
Box
,
cls
),
(
intptr_t
)
obj
->
cls
);
int
call_flags
=
ml_flags
;
Box
*
rtn
;
RewriterVar
*
r_rtn
;
if
(
call_flags
==
METH_NOARGS
)
{
RELEASE_ASSERT
(
passed_varargs
==
0
,
""
);
rtn
=
(
Box
*
)(
self
->
method
->
ml_meth
)(
obj
,
NULL
);
r_rtn
=
rewrite_args
->
rewriter
->
call
(
true
,
(
void
*
)
self
->
method
->
ml_meth
,
r_obj
,
rewrite_args
->
rewriter
->
loadConst
(
0
,
Location
::
forArg
(
1
)));
}
else
if
(
call_flags
&
METH_VARARGS
)
{
RELEASE_ASSERT
(
call_flags
==
METH_VARARGS
||
call_flags
==
(
METH_VARARGS
|
METH_KEYWORDS
),
""
);
Box
*
varargs
;
RewriterVar
*
r_varargs
;
if
(
passed_varargs
==
0
)
{
varargs
=
EmptyTuple
;
r_varargs
=
rewrite_args
->
rewriter
->
loadConst
((
intptr_t
)
EmptyTuple
,
Location
::
forArg
(
1
));
}
else
if
(
passed_varargs
==
1
)
{
varargs
=
BoxedTuple
::
create1
(
arg3
);
r_varargs
=
rewrite_args
->
rewriter
->
call
(
false
,
(
void
*
)
BoxedTuple
::
create1
,
rewrite_args
->
arg3
);
}
else
if
(
passed_varargs
==
2
)
{
varargs
=
BoxedTuple
::
create2
(
arg3
,
args
[
0
]);
r_varargs
=
rewrite_args
->
rewriter
->
call
(
false
,
(
void
*
)
BoxedTuple
::
create2
,
rewrite_args
->
arg3
,
rewrite_args
->
args
->
getAttr
(
0
,
Location
::
forArg
(
1
)));
}
else
{
RELEASE_ASSERT
(
0
,
""
);
}
if
(
call_flags
&
METH_KEYWORDS
)
{
Box
*
kwargs
=
NULL
;
RewriterVar
*
r_kwargs
=
rewrite_args
->
rewriter
->
loadConst
(
0
);
rtn
=
(
Box
*
)((
PyCFunctionWithKeywords
)
self
->
method
->
ml_meth
)(
obj
,
varargs
,
kwargs
);
r_rtn
=
rewrite_args
->
rewriter
->
call
(
true
,
(
void
*
)
self
->
method
->
ml_meth
,
r_obj
,
r_varargs
,
r_kwargs
);
}
else
{
rtn
=
(
Box
*
)(
self
->
method
->
ml_meth
)(
obj
,
varargs
);
r_rtn
=
rewrite_args
->
rewriter
->
call
(
true
,
(
void
*
)
self
->
method
->
ml_meth
,
r_obj
,
r_varargs
);
}
}
else
if
(
call_flags
==
METH_O
)
{
RELEASE_ASSERT
(
passed_varargs
==
1
,
""
);
rtn
=
(
Box
*
)(
self
->
method
->
ml_meth
)(
obj
,
arg3
);
r_rtn
=
rewrite_args
->
rewriter
->
call
(
true
,
(
void
*
)
self
->
method
->
ml_meth
,
r_obj
,
rewrite_args
->
arg3
);
}
else
{
RELEASE_ASSERT
(
0
,
"0x%x"
,
call_flags
);
}
rewrite_args
->
rewriter
->
call
(
true
,
(
void
*
)
checkAndThrowCAPIException
);
rewrite_args
->
out_rtn
=
r_rtn
;
rewrite_args
->
out_success
=
true
;
return
rtn
;
}
static
Box
*
methodGetDoc
(
Box
*
b
,
void
*
)
{
assert
(
b
->
cls
==
method_cls
);
const
char
*
s
=
static_cast
<
BoxedMethodDescriptor
*>
(
b
)
->
method
->
ml_doc
;
if
(
s
)
return
boxString
(
s
);
return
None
;
}
Box
*
BoxedMethodDescriptor
::
__get__
(
BoxedMethodDescriptor
*
self
,
Box
*
inst
,
Box
*
owner
)
{
RELEASE_ASSERT
(
self
->
cls
==
method_cls
,
""
);
// 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
,
self
->
type
);
if
(
self
->
method
->
ml_flags
&
METH_STATIC
)
Py_FatalError
(
"unimplemented"
);
if
(
self
->
method
->
ml_flags
&
METH_COEXIST
)
Py_FatalError
(
"unimplemented"
);
if
(
inst
==
None
)
return
self
;
else
return
boxInstanceMethod
(
inst
,
self
,
self
->
type
);
}
void
BoxedMethodDescriptor
::
gcHandler
(
GCVisitor
*
v
,
Box
*
_o
)
{
assert
(
_o
->
cls
==
method_cls
);
BoxedMethodDescriptor
*
o
=
static_cast
<
BoxedMethodDescriptor
*>
(
_o
);
boxGCHandler
(
v
,
o
);
v
->
visit
(
o
->
type
);
}
Box
*
BoxedWrapperDescriptor
::
__get__
(
BoxedWrapperDescriptor
*
self
,
Box
*
inst
,
Box
*
owner
)
{
RELEASE_ASSERT
(
self
->
cls
==
wrapperdescr_cls
,
""
);
if
(
inst
==
None
)
return
self
;
if
(
!
isSubclass
(
inst
->
cls
,
self
->
type
))
raiseExcHelper
(
TypeError
,
"Descriptor '' for '%s' objects doesn't apply to '%s' object"
,
getFullNameOfClass
(
self
->
type
).
c_str
(),
getFullTypeName
(
inst
).
c_str
());
return
new
BoxedWrapperObject
(
self
,
inst
);
}
Box
*
BoxedWrapperDescriptor
::
descr_get
(
Box
*
_self
,
Box
*
inst
,
Box
*
owner
)
noexcept
{
RELEASE_ASSERT
(
_self
->
cls
==
wrapperdescr_cls
,
""
);
BoxedWrapperDescriptor
*
self
=
static_cast
<
BoxedWrapperDescriptor
*>
(
_self
);
if
(
inst
==
None
)
return
self
;
if
(
!
isSubclass
(
inst
->
cls
,
self
->
type
))
PyErr_Format
(
TypeError
,
"Descriptor '' for '%s' objects doesn't apply to '%s' object"
,
getFullNameOfClass
(
self
->
type
).
c_str
(),
getFullTypeName
(
inst
).
c_str
());
return
new
BoxedWrapperObject
(
self
,
inst
);
}
Box
*
BoxedWrapperDescriptor
::
__call__
(
BoxedWrapperDescriptor
*
descr
,
PyObject
*
self
,
BoxedTuple
*
args
,
Box
**
_args
)
{
RELEASE_ASSERT
(
descr
->
cls
==
wrapperdescr_cls
,
""
);
BoxedDict
*
kw
=
static_cast
<
BoxedDict
*>
(
_args
[
0
]);
if
(
!
isSubclass
(
self
->
cls
,
descr
->
type
))
raiseExcHelper
(
TypeError
,
"descriptor '' requires a '%s' object but received a '%s'"
,
getFullNameOfClass
(
descr
->
type
).
c_str
(),
getFullTypeName
(
self
).
c_str
());
auto
wrapper
=
new
BoxedWrapperObject
(
descr
,
self
);
return
BoxedWrapperObject
::
__call__
(
wrapper
,
args
,
kw
);
}
void
BoxedWrapperDescriptor
::
gcHandler
(
GCVisitor
*
v
,
Box
*
_o
)
{
assert
(
_o
->
cls
==
wrapperdescr_cls
);
BoxedWrapperDescriptor
*
o
=
static_cast
<
BoxedWrapperDescriptor
*>
(
_o
);
boxGCHandler
(
v
,
o
);
v
->
visit
(
o
->
type
);
}
static
Box
*
wrapperdescrGetDoc
(
Box
*
b
,
void
*
)
{
assert
(
b
->
cls
==
wrapperdescr_cls
);
auto
s
=
static_cast
<
BoxedWrapperDescriptor
*>
(
b
)
->
wrapper
->
doc
;
assert
(
s
.
size
());
return
boxString
(
s
);
}
Box
*
BoxedWrapperObject
::
__call__
(
BoxedWrapperObject
*
self
,
Box
*
args
,
Box
*
kwds
)
{
STAT_TIMER
(
t0
,
"us_timer_boxedwrapperobject__call__"
,
(
self
->
cls
->
is_user_defined
?
1
:
2
));
assert
(
self
->
cls
==
wrapperobject_cls
);
assert
(
args
->
cls
==
tuple_cls
);
assert
(
kwds
->
cls
==
dict_cls
);
int
flags
=
self
->
descr
->
wrapper
->
flags
;
wrapperfunc
wrapper
=
self
->
descr
->
wrapper
->
wrapper
;
assert
(
self
->
descr
->
wrapper
->
offset
>
0
);
Box
*
rtn
;
if
(
flags
==
PyWrapperFlag_KEYWORDS
)
{
wrapperfunc_kwds
wk
=
(
wrapperfunc_kwds
)
wrapper
;
rtn
=
(
*
wk
)(
self
->
obj
,
args
,
self
->
descr
->
wrapped
,
kwds
);
}
else
if
(
flags
==
PyWrapperFlag_PYSTON
||
flags
==
0
)
{
rtn
=
(
*
wrapper
)(
self
->
obj
,
args
,
self
->
descr
->
wrapped
);
}
else
{
RELEASE_ASSERT
(
0
,
"%d"
,
flags
);
}
checkAndThrowCAPIException
();
assert
(
rtn
&&
"should have set + thrown an exception!"
);
return
rtn
;
}
void
BoxedWrapperObject
::
gcHandler
(
GCVisitor
*
v
,
Box
*
_o
)
{
assert
(
_o
->
cls
==
wrapperobject_cls
);
BoxedWrapperObject
*
o
=
static_cast
<
BoxedWrapperObject
*>
(
_o
);
boxGCHandler
(
v
,
o
);
v
->
visit
(
o
->
obj
);
}
void
setupDescr
()
{
member_descriptor_cls
->
giveAttr
(
"__get__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
memberGet
,
UNKNOWN
,
3
)));
member_descriptor_cls
->
freeze
();
...
...
@@ -255,6 +515,27 @@ void setupDescr() {
classmethod_cls
->
giveAttr
(
"__get__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
classmethodGet
,
UNKNOWN
,
3
,
1
,
false
,
false
),
{
None
}));
classmethod_cls
->
freeze
();
method_cls
->
giveAttr
(
"__get__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
BoxedMethodDescriptor
::
__get__
,
UNKNOWN
,
3
)));
CLFunction
*
method_call_cl
=
boxRTFunction
((
void
*
)
BoxedMethodDescriptor
::
__call__
,
UNKNOWN
,
2
,
0
,
true
,
true
);
method_call_cl
->
internal_callable
=
BoxedMethodDescriptor
::
callInternal
;
method_cls
->
giveAttr
(
"__call__"
,
new
BoxedFunction
(
method_call_cl
));
method_cls
->
giveAttr
(
"__doc__"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
methodGetDoc
,
NULL
,
NULL
));
method_cls
->
freeze
();
wrapperdescr_cls
->
giveAttr
(
"__get__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
BoxedWrapperDescriptor
::
__get__
,
UNKNOWN
,
3
)));
wrapperdescr_cls
->
giveAttr
(
"__call__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
BoxedWrapperDescriptor
::
__call__
,
UNKNOWN
,
2
,
0
,
true
,
true
)));
wrapperdescr_cls
->
giveAttr
(
"__doc__"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
wrapperdescrGetDoc
,
NULL
,
NULL
));
wrapperdescr_cls
->
freeze
();
wrapperdescr_cls
->
tp_descr_get
=
BoxedWrapperDescriptor
::
descr_get
;
wrapperobject_cls
->
giveAttr
(
"__call__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
BoxedWrapperObject
::
__call__
,
UNKNOWN
,
1
,
0
,
true
,
true
)));
wrapperobject_cls
->
freeze
();
}
void
teardownDescr
()
{
...
...
src/runtime/import.cpp
View file @
2d2406d5
...
...
@@ -14,6 +14,7 @@
#include "runtime/import.h"
#include <dlfcn.h>
#include <limits.h>
#include "llvm/Support/FileSystem.h"
...
...
@@ -23,7 +24,6 @@
#include "codegen/parser.h"
#include "codegen/unwinding.h"
#include "core/ast.h"
#include "runtime/capi.h"
#include "runtime/objmodel.h"
namespace
pyston
{
...
...
@@ -777,6 +777,56 @@ Box* impLoadDynamic(Box* _name, Box* _pathname, Box* _file) {
return
importCExtension
(
name
->
s
(),
shortname
,
pathname
->
s
());
}
BoxedModule
*
importCExtension
(
const
std
::
string
&
full_name
,
const
std
::
string
&
last_name
,
const
std
::
string
&
path
)
{
void
*
handle
=
dlopen
(
path
.
c_str
(),
RTLD_NOW
);
if
(
!
handle
)
{
// raiseExcHelper(ImportError, "%s", dlerror());
fprintf
(
stderr
,
"%s
\n
"
,
dlerror
());
exit
(
1
);
}
assert
(
handle
);
std
::
string
initname
=
"init"
+
last_name
;
void
(
*
init
)()
=
(
void
(
*
)())
dlsym
(
handle
,
initname
.
c_str
());
char
*
error
;
if
((
error
=
dlerror
())
!=
NULL
)
{
// raiseExcHelper(ImportError, "%s", error);
fprintf
(
stderr
,
"%s
\n
"
,
error
);
exit
(
1
);
}
assert
(
init
);
// Let the GC know about the static variables.
uintptr_t
bss_start
=
(
uintptr_t
)
dlsym
(
handle
,
"__bss_start"
);
uintptr_t
bss_end
=
(
uintptr_t
)
dlsym
(
handle
,
"_end"
);
RELEASE_ASSERT
(
bss_end
-
bss_start
<
100000
,
"Large BSS section detected - there maybe something wrong"
);
// only track void* aligned memory
bss_start
=
(
bss_start
+
(
sizeof
(
void
*
)
-
1
))
&
~
(
sizeof
(
void
*
)
-
1
);
bss_end
-=
bss_end
%
sizeof
(
void
*
);
gc
::
registerPotentialRootRange
((
void
*
)
bss_start
,
(
void
*
)
bss_end
);
char
*
packagecontext
=
strdup
(
full_name
.
c_str
());
char
*
oldcontext
=
_Py_PackageContext
;
_Py_PackageContext
=
packagecontext
;
(
*
init
)();
_Py_PackageContext
=
oldcontext
;
free
(
packagecontext
);
checkAndThrowCAPIException
();
BoxedDict
*
sys_modules
=
getSysModulesDict
();
Box
*
s
=
boxString
(
full_name
);
Box
*
_m
=
sys_modules
->
d
[
s
];
RELEASE_ASSERT
(
_m
,
"dynamic module not initialized properly"
);
assert
(
_m
->
cls
==
module_cls
);
BoxedModule
*
m
=
static_cast
<
BoxedModule
*>
(
_m
);
m
->
setattr
(
"__file__"
,
boxString
(
path
),
NULL
);
return
m
;
}
Box
*
impGetSuffixes
()
{
BoxedList
*
list
=
new
BoxedList
;
// For now only add *.py
...
...
src/runtime/import.h
View file @
2d2406d5
...
...
@@ -21,6 +21,7 @@ namespace pyston {
extern
"C"
Box
*
import
(
int
level
,
Box
*
from_imports
,
llvm
::
StringRef
module_name
);
extern
Box
*
importModuleLevel
(
llvm
::
StringRef
module_name
,
Box
*
globals
,
Box
*
from_imports
,
int
level
);
BoxedModule
*
importCExtension
(
const
std
::
string
&
full_name
,
const
std
::
string
&
last_name
,
const
std
::
string
&
path
);
}
#endif
src/runtime/inline/xrange.cpp
View file @
2d2406d5
...
...
@@ -13,7 +13,6 @@
// limitations under the License.
#include "core/types.h"
#include "runtime/capi.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
...
...
src/runtime/int.cpp
View file @
2d2406d5
...
...
@@ -24,7 +24,6 @@
#include "core/stats.h"
#include "core/types.h"
#include "gc/collector.h"
#include "runtime/capi.h"
#include "runtime/float.h"
#include "runtime/inline/boxing.h"
#include "runtime/long.h"
...
...
src/runtime/long.cpp
View file @
2d2406d5
...
...
@@ -27,7 +27,6 @@
#include "core/stats.h"
#include "core/types.h"
#include "gc/collector.h"
#include "runtime/capi.h"
#include "runtime/inline/boxing.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
...
...
src/runtime/objmodel.cpp
View file @
2d2406d5
...
...
@@ -39,7 +39,6 @@
#include "core/types.h"
#include "gc/collector.h"
#include "gc/heap.h"
#include "runtime/capi.h"
#include "runtime/classobj.h"
#include "runtime/dict.h"
#include "runtime/file.h"
...
...
src/runtime/set.cpp
View file @
2d2406d5
...
...
@@ -17,7 +17,6 @@
#include <llvm/Support/raw_ostream.h>
#include "gc/collector.h"
#include "runtime/capi.h"
#include "runtime/objmodel.h"
namespace
pyston
{
...
...
src/runtime/str.cpp
View file @
2d2406d5
...
...
@@ -29,7 +29,6 @@
#include "core/types.h"
#include "core/util.h"
#include "gc/collector.h"
#include "runtime/capi.h"
#include "runtime/dict.h"
#include "runtime/long.h"
#include "runtime/objmodel.h"
...
...
src/runtime/tuple.cpp
View file @
2d2406d5
...
...
@@ -24,7 +24,6 @@
#include "core/stats.h"
#include "core/types.h"
#include "gc/collector.h"
#include "runtime/capi.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
#include "runtime/util.h"
...
...
src/runtime/types.cpp
View file @
2d2406d5
...
...
@@ -32,7 +32,6 @@
#include "core/stats.h"
#include "core/types.h"
#include "gc/collector.h"
#include "runtime/capi.h"
#include "runtime/classobj.h"
#include "runtime/complex.h"
#include "runtime/dict.h"
...
...
src/runtime/types.h
View file @
2d2406d5
...
...
@@ -88,7 +88,8 @@ extern BoxedClass* object_cls, *type_cls, *bool_cls, *int_cls, *long_cls, *float
*
none_cls
,
*
instancemethod_cls
,
*
list_cls
,
*
slice_cls
,
*
module_cls
,
*
dict_cls
,
*
tuple_cls
,
*
file_cls
,
*
enumerate_cls
,
*
xrange_cls
,
*
member_descriptor_cls
,
*
method_cls
,
*
closure_cls
,
*
generator_cls
,
*
complex_cls
,
*
basestring_cls
,
*
property_cls
,
*
staticmethod_cls
,
*
classmethod_cls
,
*
attrwrapper_cls
,
*
pyston_getset_cls
,
*
capi_getset_cls
,
*
builtin_function_or_method_cls
,
*
set_cls
,
*
frozenset_cls
,
*
code_cls
,
*
frame_cls
;
*
capi_getset_cls
,
*
builtin_function_or_method_cls
,
*
set_cls
,
*
frozenset_cls
,
*
code_cls
,
*
frame_cls
,
*
capifunc_cls
,
*
wrapperdescr_cls
,
*
wrapperobject_cls
;
}
#define unicode_cls (&PyUnicode_Type)
#define memoryview_cls (&PyMemoryView_Type)
...
...
@@ -869,6 +870,62 @@ public:
DEFAULT_CLASS
(
generator_cls
);
};
struct
wrapper_def
{
const
llvm
::
StringRef
name
;
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
const
llvm
::
StringRef
doc
;
int
flags
;
// exists in CPython: PyObject *name_strobj
};
class
BoxedWrapperDescriptor
:
public
Box
{
public:
const
wrapper_def
*
wrapper
;
BoxedClass
*
type
;
void
*
wrapped
;
BoxedWrapperDescriptor
(
const
wrapper_def
*
wrapper
,
BoxedClass
*
type
,
void
*
wrapped
)
:
wrapper
(
wrapper
),
type
(
type
),
wrapped
(
wrapped
)
{}
DEFAULT_CLASS
(
wrapperdescr_cls
);
static
Box
*
__get__
(
BoxedWrapperDescriptor
*
self
,
Box
*
inst
,
Box
*
owner
);
static
Box
*
descr_get
(
Box
*
self
,
Box
*
inst
,
Box
*
owner
)
noexcept
;
static
Box
*
__call__
(
BoxedWrapperDescriptor
*
descr
,
PyObject
*
self
,
BoxedTuple
*
args
,
Box
**
_args
);
static
void
gcHandler
(
GCVisitor
*
v
,
Box
*
_o
);
};
class
BoxedWrapperObject
:
public
Box
{
public:
BoxedWrapperDescriptor
*
descr
;
Box
*
obj
;
BoxedWrapperObject
(
BoxedWrapperDescriptor
*
descr
,
Box
*
obj
)
:
descr
(
descr
),
obj
(
obj
)
{}
DEFAULT_CLASS
(
wrapperobject_cls
);
static
Box
*
__call__
(
BoxedWrapperObject
*
self
,
Box
*
args
,
Box
*
kwds
);
static
void
gcHandler
(
GCVisitor
*
v
,
Box
*
_o
);
};
class
BoxedMethodDescriptor
:
public
Box
{
public:
PyMethodDef
*
method
;
BoxedClass
*
type
;
BoxedMethodDescriptor
(
PyMethodDef
*
method
,
BoxedClass
*
type
)
:
method
(
method
),
type
(
type
)
{}
DEFAULT_CLASS
(
method_cls
);
static
Box
*
__get__
(
BoxedMethodDescriptor
*
self
,
Box
*
inst
,
Box
*
owner
);
static
Box
*
__call__
(
BoxedMethodDescriptor
*
self
,
Box
*
obj
,
BoxedTuple
*
varargs
,
Box
**
_args
);
static
Box
*
callInternal
(
BoxedFunctionBase
*
f
,
CallRewriteArgs
*
rewrite_args
,
ArgPassSpec
argspec
,
Box
*
arg1
,
Box
*
arg2
,
Box
*
arg3
,
Box
**
args
,
const
std
::
vector
<
BoxedString
*>*
keyword_names
);
static
void
gcHandler
(
GCVisitor
*
v
,
Box
*
_o
);
};
extern
"C"
void
boxGCHandler
(
GCVisitor
*
v
,
Box
*
b
);
Box
*
objectNewNoArgs
(
BoxedClass
*
cls
);
...
...
@@ -905,6 +962,19 @@ AST* unboxAst(Box* b);
// Our default for tp_alloc:
extern
"C"
PyObject
*
PystonType_GenericAlloc
(
BoxedClass
*
cls
,
Py_ssize_t
nitems
)
noexcept
;
void
checkAndThrowCAPIException
();
void
throwCAPIException
()
__attribute__
((
noreturn
));
struct
ExcInfo
;
void
setCAPIException
(
const
ExcInfo
&
e
);
#define fatalOrError(exception, message) \
do { \
if (CONTINUE_AFTER_FATAL) \
PyErr_SetString((exception), (message)); \
else \
Py_FatalError((message)); \
} while (0)
// A descriptor that you can add to your class to provide instances with a __dict__ accessor.
// Classes created in Python get this automatically, but builtin types (including extension types)
// are supposed to add one themselves. type_cls and function_cls do this, for example.
...
...
src/runtime/util.cpp
View file @
2d2406d5
...
...
@@ -15,7 +15,6 @@
#include "runtime/util.h"
#include "core/options.h"
#include "runtime/capi.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
...
...
test/tests/weakref1.py
View file @
2d2406d5
import
weakref
import
gc
num_destroyed
=
0
def
cb
(
wr
):
print
"object was destroyed"
,
wr
()
global
num_destroyed
num_destroyed
+=
1
def
doStuff
():
def
meth
():
...
...
@@ -11,18 +13,7 @@ def doStuff():
wr
=
weakref
.
ref
(
meth
,
cb
)
return
wr
def
fact
(
n
):
if
n
<=
1
:
return
n
return
n
*
fact
(
n
-
1
)
w
=
doStuff
()
fact
(
10
)
# try to clear some memory
def
recurse
(
f
,
n
):
if
n
:
return
recurse
(
f
,
n
-
1
)
return
f
()
recurse
(
gc
.
collect
,
50
)
l
=
[
doStuff
()
for
i
in
xrange
(
5
)]
gc
.
collect
()
assert
num_destroyed
>=
1
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