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
96febb05
Commit
96febb05
authored
Aug 07, 2015
by
Kevin Modzelewski
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #811 from kmod/exceptions4
more capi exceptions
parents
232e05c4
26dabd18
Changes
27
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
27 changed files
with
732 additions
and
322 deletions
+732
-322
Makefile
Makefile
+6
-0
from_cpython/Include/object.h
from_cpython/Include/object.h
+2
-1
from_cpython/setup.py
from_cpython/setup.py
+6
-0
src/capi/typeobject.cpp
src/capi/typeobject.cpp
+24
-11
src/capi/types.h
src/capi/types.h
+2
-1
src/codegen/ast_interpreter.cpp
src/codegen/ast_interpreter.cpp
+2
-0
src/codegen/compvars.cpp
src/codegen/compvars.cpp
+40
-17
src/codegen/irgen/irgenerator.cpp
src/codegen/irgen/irgenerator.cpp
+29
-14
src/codegen/runtime_hooks.cpp
src/codegen/runtime_hooks.cpp
+49
-18
src/codegen/runtime_hooks.h
src/codegen/runtime_hooks.h
+2
-2
src/codegen/unwinding.cpp
src/codegen/unwinding.cpp
+2
-0
src/core/ast.h
src/core/ast.h
+2
-0
src/runtime/builtin_modules/builtins.cpp
src/runtime/builtin_modules/builtins.cpp
+19
-7
src/runtime/capi.cpp
src/runtime/capi.cpp
+16
-3
src/runtime/descr.cpp
src/runtime/descr.cpp
+30
-5
src/runtime/float.cpp
src/runtime/float.cpp
+58
-19
src/runtime/inline/link_forcer.cpp
src/runtime/inline/link_forcer.cpp
+2
-0
src/runtime/int.cpp
src/runtime/int.cpp
+62
-24
src/runtime/objmodel.cpp
src/runtime/objmodel.cpp
+215
-136
src/runtime/objmodel.h
src/runtime/objmodel.h
+7
-3
src/runtime/tuple.cpp
src/runtime/tuple.cpp
+1
-1
src/runtime/types.cpp
src/runtime/types.cpp
+125
-44
src/runtime/types.h
src/runtime/types.h
+6
-6
src/runtime/util.cpp
src/runtime/util.cpp
+2
-2
src/runtime/util.h
src/runtime/util.h
+2
-2
test/test_extension/setup.py
test/test_extension/setup.py
+20
-5
test/tests/varargs_ics.py
test/tests/varargs_ics.py
+1
-1
No files found.
Makefile
View file @
96febb05
...
...
@@ -1260,6 +1260,12 @@ $(FROM_CPYTHON_SRCS:.c=.prof.o): %.prof.o: %.c $(BUILD_SYSTEM_DEPS)
$(ECHO)
Compiling C file to
$@
$(VERB)
$(CC_PROFILE)
$(EXT_CFLAGS_PROFILE)
-c
$<
-o
$@
-g
-MMD
-MP
-MF
$(
patsubst
%.o,%.d,
$@
)
.PHONY
:
update_section_ordering
update_section_ordering
:
pyston_release
perf record
-o
perf_section_ordering.data
--
./pyston_release
-q
minibenchmarks/combined.py
$(MAKE)
pyston_pgo
python tools/generate_section_ordering_from_pgo_build.py pyston_pgo perf_section_ordering.data
>
section_ordering.txt
rm
perf_section_ordering.data
...
...
from_cpython/Include/object.h
View file @
96febb05
...
...
@@ -460,7 +460,8 @@ struct _typeobject {
bool
_flags
[
7
];
void
*
_tpp_descr_get
;
void
*
_tpp_hasnext
;
void
*
_tpp_call
;
void
*
_tpp_call_capi
;
void
*
_tpp_call_cxx
;
};
/* The *real* layout of a type object when allocated on the heap */
...
...
from_cpython/setup.py
View file @
96febb05
# CPython has a 2kloc version of this file
from
distutils.core
import
setup
,
Extension
import
glob
import
os
import
sysconfig
...
...
@@ -132,5 +133,10 @@ ext_modules = [future_builtins_ext(),
curses_ext
(),
termios_ext
()]
builtin_headers
=
map
(
relpath
,
glob
.
glob
(
"Include/*.h"
))
for
m
in
ext_modules
:
m
.
depends
+=
builtin_headers
setup
(
name
=
"Pyston"
,
version
=
"1.0"
,
description
=
"Pyston shared modules"
,
ext_modules
=
ext_modules
)
src/capi/typeobject.cpp
View file @
96febb05
...
...
@@ -1068,8 +1068,8 @@ Box* slotTpGetattrHookInternal(Box* self, BoxedString* name, GetattrRewriteArgs*
assert
(
PyString_CHECK_INTERNED
(
name
)
==
SSTATE_INTERNED_IMMORTAL
);
crewrite_args
.
arg1
=
rewrite_args
->
rewriter
->
loadConst
((
intptr_t
)
name
,
Location
::
forArg
(
1
));
res
=
callattrInternal
(
self
,
_getattr_str
,
LookupScope
::
CLASS_ONLY
,
&
crewrite_args
,
ArgPassSpec
(
1
),
name
,
NULL
,
NULL
,
NULL
,
NULL
);
res
=
callattrInternal
<
CXX
>
(
self
,
_getattr_str
,
LookupScope
::
CLASS_ONLY
,
&
crewrite_args
,
ArgPassSpec
(
1
),
name
,
NULL
,
NULL
,
NULL
,
NULL
);
assert
(
res
);
if
(
!
crewrite_args
.
out_success
)
...
...
@@ -1082,8 +1082,8 @@ Box* slotTpGetattrHookInternal(Box* self, BoxedString* name, GetattrRewriteArgs*
// the rewrite_args and non-rewrite_args case the same.
// Actually, we might have gotten to the point that doing a runtimeCall on an instancemethod is as
// fast as a callattr, but that hasn't typically been the case.
res
=
callattrInternal
(
self
,
_getattr_str
,
LookupScope
::
CLASS_ONLY
,
NULL
,
ArgPassSpec
(
1
),
name
,
NULL
,
NULL
,
NULL
,
NULL
);
res
=
callattrInternal
<
CXX
>
(
self
,
_getattr_str
,
LookupScope
::
CLASS_ONLY
,
NULL
,
ArgPassSpec
(
1
),
name
,
NULL
,
NULL
,
NULL
,
NULL
);
assert
(
res
);
}
...
...
@@ -3184,8 +3184,10 @@ extern "C" void PyType_Modified(PyTypeObject* type) noexcept {
// We don't cache anything yet that would need to be invalidated:
}
template
<
ExceptionStyle
S
>
static
Box
*
tppProxyToTpCall
(
Box
*
self
,
CallRewriteArgs
*
rewrite_args
,
ArgPassSpec
argspec
,
Box
*
arg1
,
Box
*
arg2
,
Box
*
arg3
,
Box
**
args
,
const
std
::
vector
<
BoxedString
*>*
keyword_names
)
{
Box
*
arg3
,
Box
**
args
,
const
std
::
vector
<
BoxedString
*>*
keyword_names
)
noexcept
(
S
==
CAPI
)
{
ParamReceiveSpec
paramspec
(
0
,
0
,
true
,
true
);
if
(
!
argspec
.
has_kwargs
&&
argspec
.
num_keywords
==
0
)
{
paramspec
.
takes_kwargs
=
false
;
...
...
@@ -3193,8 +3195,16 @@ static Box* tppProxyToTpCall(Box* self, CallRewriteArgs* rewrite_args, ArgPassSp
bool
rewrite_success
=
false
;
Box
*
oarg1
,
*
oarg2
=
NULL
,
*
oarg3
,
**
oargs
=
NULL
;
rearrangeArguments
(
paramspec
,
NULL
,
""
,
NULL
,
rewrite_args
,
rewrite_success
,
argspec
,
arg1
,
arg2
,
arg3
,
args
,
keyword_names
,
oarg1
,
oarg2
,
oarg3
,
oargs
);
try
{
rearrangeArguments
(
paramspec
,
NULL
,
""
,
NULL
,
rewrite_args
,
rewrite_success
,
argspec
,
arg1
,
arg2
,
arg3
,
args
,
keyword_names
,
oarg1
,
oarg2
,
oarg3
,
oargs
);
}
catch
(
ExcInfo
e
)
{
if
(
S
==
CAPI
)
{
setCAPIException
(
e
);
return
NULL
;
}
else
throw
e
;
}
if
(
!
rewrite_success
)
rewrite_args
=
NULL
;
...
...
@@ -3213,12 +3223,13 @@ static Box* tppProxyToTpCall(Box* self, CallRewriteArgs* rewrite_args, ArgPassSp
rewrite_args
->
out_rtn
=
rewrite_args
->
rewriter
->
call
(
true
,
(
void
*
)
self
->
cls
->
tp_call
,
rewrite_args
->
obj
,
rewrite_args
->
arg1
,
rewrite_args
->
arg2
);
rewrite_args
->
rewriter
->
call
(
true
,
(
void
*
)
checkAndThrowCAPIException
);
if
(
S
==
CXX
)
rewrite_args
->
rewriter
->
call
(
true
,
(
void
*
)
checkAndThrowCAPIException
);
rewrite_args
->
out_success
=
true
;
}
Box
*
r
=
self
->
cls
->
tp_call
(
self
,
oarg1
,
oarg2
);
if
(
!
r
)
if
(
!
r
&&
S
==
CXX
)
throwCAPIException
();
return
r
;
}
...
...
@@ -3267,8 +3278,10 @@ extern "C" int PyType_Ready(PyTypeObject* cls) noexcept {
assert
(
cls
->
tp_name
);
if
(
cls
->
tp_call
)
cls
->
tpp_call
=
tppProxyToTpCall
;
if
(
cls
->
tp_call
)
{
cls
->
tpp_call
.
capi_val
=
tppProxyToTpCall
<
CAPI
>
;
cls
->
tpp_call
.
cxx_val
=
tppProxyToTpCall
<
CXX
>
;
}
try
{
add_operators
(
cls
);
...
...
src/capi/types.h
View file @
96febb05
...
...
@@ -43,8 +43,9 @@ public:
}
static
Box
*
__call__
(
BoxedCApiFunction
*
self
,
BoxedTuple
*
varargs
,
BoxedDict
*
kwargs
);
template
<
ExceptionStyle
S
>
static
Box
*
tppCall
(
Box
*
_self
,
CallRewriteArgs
*
rewrite_args
,
ArgPassSpec
argspec
,
Box
*
arg1
,
Box
*
arg2
,
Box
*
arg3
,
Box
**
args
,
const
std
::
vector
<
BoxedString
*>*
keyword_names
);
Box
**
args
,
const
std
::
vector
<
BoxedString
*>*
keyword_names
)
noexcept
(
S
==
CAPI
)
;
static
Box
*
getname
(
Box
*
b
,
void
*
)
{
RELEASE_ASSERT
(
b
->
cls
==
capifunc_cls
,
""
);
...
...
src/codegen/ast_interpreter.cpp
View file @
96febb05
...
...
@@ -332,6 +332,7 @@ Box* ASTInterpreter::execJITedBlock(CFGBlock* b) {
throw
e
;
auto
source
=
getCL
()
->
source
.
get
();
stmt
->
cxx_exception_count
++
;
exceptionCaughtInInterpreter
(
LineInfo
(
stmt
->
lineno
,
stmt
->
col_offset
,
source
->
fn
,
source
->
getName
()),
&
e
);
next_block
=
((
AST_Invoke
*
)
stmt
)
->
exc_dest
;
...
...
@@ -764,6 +765,7 @@ Value ASTInterpreter::visit_invoke(AST_Invoke* node) {
abortJITing
();
auto
source
=
getCL
()
->
source
.
get
();
node
->
cxx_exception_count
++
;
exceptionCaughtInInterpreter
(
LineInfo
(
node
->
lineno
,
node
->
col_offset
,
source
->
fn
,
source
->
getName
()),
&
e
);
next_block
=
node
->
exc_dest
;
...
...
src/codegen/compvars.cpp
View file @
96febb05
...
...
@@ -613,7 +613,8 @@ static ConcreteCompilerVariable* _call(IREmitter& emitter, const OpInfo& info, l
// for (auto a : llvm_args)
// a->dump();
bool
do_patchpoint
=
ENABLE_ICCALLSITES
&&
(
func_addr
==
runtimeCall
||
func_addr
==
pyston
::
callattr
);
bool
do_patchpoint
=
ENABLE_ICCALLSITES
&&
(
func_addr
==
runtimeCall
||
func_addr
==
runtimeCallCapi
||
func_addr
==
pyston
::
callattr
||
func_addr
==
callattrCapi
);
if
(
do_patchpoint
)
{
assert
(
func_addr
);
...
...
@@ -655,26 +656,32 @@ CompilerVariable* UnknownType::call(IREmitter& emitter, const OpInfo& info, Conc
bool
pass_keywords
=
(
argspec
.
num_keywords
!=
0
);
int
npassed_args
=
argspec
.
totalPassed
();
ExceptionStyle
exception_style
=
((
FORCE_LLVM_CAPI
&&
!
info
.
unw_info
.
cxx_exc_dest
)
||
info
.
unw_info
.
capi_exc_dest
)
?
ExceptionStyle
::
CAPI
:
ExceptionStyle
::
CXX
;
llvm
::
Value
*
func
;
if
(
pass_keywords
)
func
=
g
.
funcs
.
runtimeCall
;
func
=
g
.
funcs
.
runtimeCall
.
get
(
exception_style
)
;
else
if
(
npassed_args
==
0
)
func
=
g
.
funcs
.
runtimeCall0
;
func
=
g
.
funcs
.
runtimeCall0
.
get
(
exception_style
)
;
else
if
(
npassed_args
==
1
)
func
=
g
.
funcs
.
runtimeCall1
;
func
=
g
.
funcs
.
runtimeCall1
.
get
(
exception_style
)
;
else
if
(
npassed_args
==
2
)
func
=
g
.
funcs
.
runtimeCall2
;
func
=
g
.
funcs
.
runtimeCall2
.
get
(
exception_style
)
;
else
if
(
npassed_args
==
3
)
func
=
g
.
funcs
.
runtimeCall3
;
func
=
g
.
funcs
.
runtimeCall3
.
get
(
exception_style
)
;
else
func
=
g
.
funcs
.
runtimeCallN
;
func
=
g
.
funcs
.
runtimeCallN
.
get
(
exception_style
);
void
*
func_ptr
=
(
exception_style
==
ExceptionStyle
::
CXX
)
?
(
void
*
)
runtimeCall
:
(
void
*
)
runtimeCallCapi
;
std
::
vector
<
llvm
::
Value
*>
other_args
;
other_args
.
push_back
(
var
->
getValue
());
llvm
::
Value
*
llvm_argspec
=
llvm
::
ConstantInt
::
get
(
g
.
i32
,
argspec
.
asInt
(),
false
);
other_args
.
push_back
(
llvm_argspec
);
return
_call
(
emitter
,
info
,
func
,
CXX
,
(
void
*
)
runtimeCall
,
other_args
,
argspec
,
args
,
keyword_names
,
UNKNOWN
);
return
_call
(
emitter
,
info
,
func
,
exception_style
,
func_ptr
,
other_args
,
argspec
,
args
,
keyword_names
,
UNKNOWN
);
}
CompilerVariable
*
UnknownType
::
callattr
(
IREmitter
&
emitter
,
const
OpInfo
&
info
,
ConcreteCompilerVariable
*
var
,
...
...
@@ -684,25 +691,35 @@ CompilerVariable* UnknownType::callattr(IREmitter& emitter, const OpInfo& info,
bool
pass_keywords
=
(
flags
.
argspec
.
num_keywords
!=
0
);
int
npassed_args
=
flags
.
argspec
.
totalPassed
();
ExceptionStyle
exception_style
=
((
FORCE_LLVM_CAPI
&&
!
info
.
unw_info
.
cxx_exc_dest
&&
!
flags
.
null_on_nonexistent
)
||
info
.
unw_info
.
capi_exc_dest
)
?
ExceptionStyle
::
CAPI
:
ExceptionStyle
::
CXX
;
if
(
exception_style
==
CAPI
)
assert
(
!
flags
.
null_on_nonexistent
);
// Will conflict with CAPI's null-on-exception
llvm
::
Value
*
func
;
if
(
pass_keywords
)
func
=
g
.
funcs
.
callattr
;
func
=
g
.
funcs
.
callattr
.
get
(
exception_style
)
;
else
if
(
npassed_args
==
0
)
func
=
g
.
funcs
.
callattr0
;
func
=
g
.
funcs
.
callattr0
.
get
(
exception_style
)
;
else
if
(
npassed_args
==
1
)
func
=
g
.
funcs
.
callattr1
;
func
=
g
.
funcs
.
callattr1
.
get
(
exception_style
)
;
else
if
(
npassed_args
==
2
)
func
=
g
.
funcs
.
callattr2
;
func
=
g
.
funcs
.
callattr2
.
get
(
exception_style
)
;
else
if
(
npassed_args
==
3
)
func
=
g
.
funcs
.
callattr3
;
func
=
g
.
funcs
.
callattr3
.
get
(
exception_style
)
;
else
func
=
g
.
funcs
.
callattrN
;
func
=
g
.
funcs
.
callattrN
.
get
(
exception_style
);
void
*
func_ptr
=
(
exception_style
==
ExceptionStyle
::
CXX
)
?
(
void
*
)
pyston
::
callattr
:
(
void
*
)
callattrCapi
;
std
::
vector
<
llvm
::
Value
*>
other_args
;
other_args
.
push_back
(
var
->
getValue
());
other_args
.
push_back
(
embedRelocatablePtr
(
attr
,
g
.
llvm_boxedstring_type_ptr
));
other_args
.
push_back
(
getConstantInt
(
flags
.
asInt
(),
g
.
i64
));
return
_call
(
emitter
,
info
,
func
,
CXX
,
(
void
*
)
pyston
::
callat
tr
,
other_args
,
flags
.
argspec
,
args
,
keyword_names
,
return
_call
(
emitter
,
info
,
func
,
exception_style
,
func_p
tr
,
other_args
,
flags
.
argspec
,
args
,
keyword_names
,
UNKNOWN
);
}
...
...
@@ -1700,8 +1717,14 @@ public:
CompilerVariable
*
callattr
(
IREmitter
&
emitter
,
const
OpInfo
&
info
,
ConcreteCompilerVariable
*
var
,
BoxedString
*
attr
,
CallattrFlags
flags
,
const
std
::
vector
<
CompilerVariable
*>&
args
,
const
std
::
vector
<
BoxedString
*>*
keyword_names
)
override
{
ConcreteCompilerVariable
*
called_constant
=
tryCallattrConstant
(
emitter
,
info
,
var
,
attr
,
flags
.
cls_only
,
flags
.
argspec
,
args
,
keyword_names
);
ExceptionStyle
exception_style
=
CXX
;
// Not safe to force-capi here since most of the functions won't have capi variants:
if
(
/*FORCE_LLVM_CAPI ||*/
info
.
unw_info
.
capi_exc_dest
)
exception_style
=
CAPI
;
ConcreteCompilerVariable
*
called_constant
=
tryCallattrConstant
(
emitter
,
info
,
var
,
attr
,
flags
.
cls_only
,
flags
.
argspec
,
args
,
keyword_names
,
NULL
,
exception_style
);
if
(
called_constant
)
return
called_constant
;
...
...
src/codegen/irgen/irgenerator.cpp
View file @
96febb05
...
...
@@ -107,13 +107,23 @@ ExceptionStyle IRGenState::getLandingpadStyle(AST_Invoke* invoke) {
r
=
CXX
;
// default
assert
(
invoke
->
stmt
->
cxx_exception_count
==
0
);
// could be ok but would be unexpected
// First, check if we think it makes sense:
bool
should
=
(
invoke
->
cxx_exception_count
>=
10
||
invoke
->
stmt
->
type
==
AST_TYPE
::
Raise
);
if
(
!
should
)
return
r
;
// Second, check if we are able to do it:
// (not all code paths support capi exceptions yet)
if
(
invoke
->
stmt
->
type
==
AST_TYPE
::
Raise
)
{
AST_Raise
*
raise_stmt
=
ast_cast
<
AST_Raise
>
(
invoke
->
stmt
);
// Currently can't do a re-raise with a capi exception:
if
(
raise_stmt
->
arg0
&&
!
raise_stmt
->
arg2
)
{
if
(
raise_stmt
->
arg0
&&
!
raise_stmt
->
arg2
)
r
=
CAPI
;
return
r
;
}
else
r
=
CXX
;
return
r
;
}
AST_expr
*
expr
=
NULL
;
...
...
@@ -127,21 +137,18 @@ ExceptionStyle IRGenState::getLandingpadStyle(AST_Invoke* invoke) {
if
(
!
expr
)
return
r
;
if
(
0
&&
expr
->
type
==
AST_TYPE
::
Call
)
{
AST_Call
*
call
=
ast_cast
<
AST_Call
>
(
expr
);
if
(
call
->
func
->
type
!=
AST_TYPE
::
Attribute
&&
call
->
func
->
type
!=
AST_TYPE
::
ClsAttribute
)
{
r
=
CAPI
;
// printf("Doing a capi exception to %d\n", invoke->exc_dest->idx);
}
if
(
expr
->
type
==
AST_TYPE
::
Call
)
{
r
=
CAPI
;
return
r
;
}
if
(
expr
->
type
==
AST_TYPE
::
Attribute
||
expr
->
type
==
AST_TYPE
::
Subscript
)
{
r
=
CAPI
;
// printf("Doing a capi exception to %d\n", invoke->exc_dest->idx);
return
r
;
}
// Some expression type we haven't added yet -- might be worth looking into.
r
=
CXX
;
return
r
;
}
...
...
@@ -488,8 +495,7 @@ public:
llvm
::
BasicBlock
*
exc_dest
;
bool
exc_caught
;
if
(
unw_info
.
hasHandler
())
{
assert
(
unw_info
.
capi_exc_dest
);
if
(
unw_info
.
capi_exc_dest
)
{
exc_dest
=
unw_info
.
capi_exc_dest
;
exc_caught
=
true
;
}
else
{
...
...
@@ -508,7 +514,13 @@ public:
embedRelocatablePtr
(
irstate
->
getSourceInfo
(),
g
.
i8_ptr
));
if
(
!
exc_caught
)
{
getBuilder
()
->
CreateCall
(
g
.
funcs
.
reraiseJitCapiExc
);
if
(
unw_info
.
cxx_exc_dest
)
{
// TODO: I'm not sure this gets the tracebacks quite right. this is only for testing though:
assert
(
FORCE_LLVM_CAPI
&&
"this shouldn't happen in non-FORCE mode"
);
createCall
(
unw_info
,
g
.
funcs
.
reraiseJitCapiExc
);
}
else
{
getBuilder
()
->
CreateCall
(
g
.
funcs
.
reraiseJitCapiExc
);
}
getBuilder
()
->
CreateUnreachable
();
}
...
...
@@ -2429,8 +2441,11 @@ private:
if
(
landingpad_style
==
CXX
)
doStmt
(
invoke
->
stmt
,
UnwindInfo
(
node
,
NULL
,
entry_blocks
[
invoke
->
exc_dest
]));
else
else
{
// print_ast(invoke);
// printf(" (%d exceptions)\n", invoke->cxx_exception_count);
doStmt
(
invoke
->
stmt
,
UnwindInfo
(
node
,
entry_blocks
[
invoke
->
exc_dest
],
NULL
));
}
assert
(
state
==
RUNNING
||
state
==
DEAD
);
if
(
state
==
RUNNING
)
{
...
...
src/codegen/runtime_hooks.cpp
View file @
96febb05
...
...
@@ -245,31 +245,62 @@ void initGlobalFuncs(GlobalState& g) {
GET
(
boxedLocalsGet
);
GET
(
boxedLocalsDel
);
g
.
funcs
.
runtimeCall
=
getFunc
((
void
*
)
runtimeCall
,
"runtimeCall"
);
g
.
funcs
.
runtimeCall0
=
addFunc
((
void
*
)
runtimeCall
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
i32
);
g
.
funcs
.
runtimeCall1
g
.
funcs
.
runtimeCall
.
cxx_val
=
getFunc
((
void
*
)
runtimeCall
,
"runtimeCall"
);
g
.
funcs
.
runtimeCall0
.
cxx_val
=
addFunc
((
void
*
)
runtimeCall
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
i32
);
g
.
funcs
.
runtimeCall1
.
cxx_val
=
addFunc
((
void
*
)
runtimeCall
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
i32
,
g
.
llvm_value_type_ptr
);
g
.
funcs
.
runtimeCall2
=
addFunc
((
void
*
)
runtimeCall
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
i32
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
);
g
.
funcs
.
runtimeCall3
=
addFunc
((
void
*
)
runtimeCall
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
i32
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
);
g
.
funcs
.
runtimeCallN
g
.
funcs
.
runtimeCall2
.
cxx_val
=
addFunc
((
void
*
)
runtimeCall
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
i32
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
);
g
.
funcs
.
runtimeCall3
.
cxx_val
=
addFunc
((
void
*
)
runtimeCall
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
i32
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
);
g
.
funcs
.
runtimeCallN
.
cxx_val
=
addFunc
((
void
*
)
runtimeCall
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
i32
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
->
getPointerTo
());
g
.
funcs
.
callattr
=
getFunc
((
void
*
)
callattr
,
"callattr"
);
g
.
funcs
.
callattr0
g
.
funcs
.
runtimeCall
.
capi_val
=
getFunc
((
void
*
)
runtimeCallCapi
,
"runtimeCallCapi"
);
g
.
funcs
.
runtimeCall0
.
capi_val
=
addFunc
((
void
*
)
runtimeCallCapi
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
i32
);
g
.
funcs
.
runtimeCall1
.
capi_val
=
addFunc
((
void
*
)
runtimeCallCapi
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
i32
,
g
.
llvm_value_type_ptr
);
g
.
funcs
.
runtimeCall2
.
capi_val
=
addFunc
((
void
*
)
runtimeCallCapi
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
i32
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
);
g
.
funcs
.
runtimeCall3
.
capi_val
=
addFunc
((
void
*
)
runtimeCallCapi
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
i32
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
);
g
.
funcs
.
runtimeCallN
.
capi_val
=
addFunc
((
void
*
)
runtimeCallCapi
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
i32
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
->
getPointerTo
());
g
.
funcs
.
callattr
.
cxx_val
=
getFunc
((
void
*
)
callattr
,
"callattr"
);
g
.
funcs
.
callattr0
.
cxx_val
=
addFunc
((
void
*
)
callattr
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
llvm_boxedstring_type_ptr
,
g
.
i64
);
g
.
funcs
.
callattr1
=
addFunc
((
void
*
)
callattr
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
llvm_boxedstring_type_ptr
,
g
.
i64
,
g
.
llvm_value_type_ptr
);
g
.
funcs
.
callattr2
=
addFunc
((
void
*
)
callattr
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
llvm_boxedstring_type_ptr
,
g
.
i64
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
);
g
.
funcs
.
callattr3
g
.
funcs
.
callattr1
.
cxx_val
=
addFunc
((
void
*
)
callattr
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
llvm_boxedstring_type_ptr
,
g
.
i64
,
g
.
llvm_value_type_ptr
);
g
.
funcs
.
callattr2
.
cxx_val
=
addFunc
((
void
*
)
callattr
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
llvm_boxedstring_type_ptr
,
g
.
i64
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
);
g
.
funcs
.
callattr3
.
cxx_val
=
addFunc
((
void
*
)
callattr
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
llvm_boxedstring_type_ptr
,
g
.
i64
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
);
g
.
funcs
.
callattrN
.
cxx_val
=
addFunc
(
(
void
*
)
callattr
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
llvm_boxedstring_type_ptr
,
g
.
i64
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
->
getPointerTo
());
g
.
funcs
.
callattr
.
capi_val
=
getFunc
((
void
*
)
callattrCapi
,
"callattrCapi"
);
g
.
funcs
.
callattr0
.
capi_val
=
addFunc
((
void
*
)
callattrCapi
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
llvm_boxedstring_type_ptr
,
g
.
i64
);
g
.
funcs
.
callattr1
.
capi_val
=
addFunc
((
void
*
)
callattrCapi
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
llvm_boxedstring_type_ptr
,
g
.
i64
,
g
.
llvm_value_type_ptr
);
g
.
funcs
.
callattr2
.
capi_val
=
addFunc
((
void
*
)
callattrCapi
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
llvm_boxedstring_type_ptr
,
g
.
i64
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
);
g
.
funcs
.
callattr3
.
capi_val
=
addFunc
((
void
*
)
callattrCapi
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
llvm_boxedstring_type_ptr
,
g
.
i64
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
);
g
.
funcs
.
callattrN
=
addFunc
((
void
*
)
callattr
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
llvm_boxedstring_type_ptr
,
g
.
i64
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
->
getPointerTo
());
g
.
funcs
.
callattrN
.
capi_val
=
addFunc
(
(
void
*
)
callattrCapi
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
llvm_boxedstring_type_ptr
,
g
.
i64
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
,
g
.
llvm_value_type_ptr
->
getPointerTo
());
g
.
funcs
.
reoptCompiledFunc
=
addFunc
((
void
*
)
reoptCompiledFunc
,
g
.
i8_ptr
,
g
.
i8_ptr
);
g
.
funcs
.
compilePartialFunc
=
addFunc
((
void
*
)
compilePartialFunc
,
g
.
i8_ptr
,
g
.
i8_ptr
);
...
...
src/codegen/runtime_hooks.h
View file @
96febb05
...
...
@@ -43,8 +43,8 @@ struct GlobalFuncs {
*
raiseAttributeErrorStrCapi
,
*
raiseNotIterableError
,
*
raiseIndexErrorStr
,
*
raiseIndexErrorStrCapi
,
*
assertNameDefined
,
*
assertFail
,
*
assertFailDerefNameDefined
,
*
printExprHelper
;
llvm
::
Value
*
printFloat
,
*
listAppendInternal
,
*
getSysStdout
;
llvm
::
Value
*
runtimeCall0
,
*
runtimeCall1
,
*
runtimeCall2
,
*
runtimeCall3
,
*
runtimeCall
,
*
runtimeCallN
;
llvm
::
Value
*
callattr0
,
*
callattr1
,
*
callattr2
,
*
callattr3
,
*
callattr
,
*
callattrN
;
ExceptionSwitchable
<
llvm
::
Value
*>
runtimeCall0
,
runtimeCall1
,
runtimeCall2
,
runtimeCall3
,
runtimeCall
,
runtimeCallN
;
ExceptionSwitchable
<
llvm
::
Value
*>
callattr0
,
callattr1
,
callattr2
,
callattr3
,
callattr
,
callattrN
;
llvm
::
Value
*
reoptCompiledFunc
,
*
compilePartialFunc
;
llvm
::
Value
*
exec
;
llvm
::
Value
*
boxedLocalsSet
,
*
boxedLocalsGet
,
*
boxedLocalsDel
;
...
...
src/codegen/unwinding.cpp
View file @
96febb05
...
...
@@ -536,6 +536,8 @@ public:
exc_info
.
reraise
=
false
;
return
;
}
// TODO: shouldn't fetch this multiple times?
frame_iter
.
getCurrentStatement
()
->
cxx_exception_count
++
;
auto
line_info
=
lineInfoForFrame
(
&
frame_iter
);
BoxedTraceback
::
here
(
line_info
,
&
exc_info
.
traceback
);
}
...
...
src/core/ast.h
View file @
96febb05
...
...
@@ -182,6 +182,8 @@ class AST_stmt : public AST {
public:
virtual
void
accept_stmt
(
StmtVisitor
*
v
)
=
0
;
int
cxx_exception_count
=
0
;
AST_stmt
(
AST_TYPE
::
AST_TYPE
type
)
:
AST
(
type
)
{}
};
...
...
src/runtime/builtin_modules/builtins.cpp
View file @
96febb05
...
...
@@ -457,11 +457,23 @@ Box* delattrFunc(Box* obj, Box* _str) {
return
None
;
}
Box
*
getattrFunc
(
Box
*
obj
,
Box
*
_str
,
Box
*
default_value
)
{
_str
=
coerceUnicodeToStr
(
_str
);
template
<
ExceptionStyle
S
>
Box
*
getattrFunc
(
Box
*
obj
,
Box
*
_str
,
Box
*
default_value
)
noexcept
(
S
==
CAPI
)
{
try
{
_str
=
coerceUnicodeToStr
(
_str
);
}
catch
(
ExcInfo
e
)
{
if
(
S
==
CAPI
)
{
setCAPIException
(
e
);
return
NULL
;
}
else
throw
e
;
}
if
(
!
isSubclass
(
_str
->
cls
,
str_cls
))
{
raiseExcHelper
(
TypeError
,
"getattr(): attribute name must be string"
);
if
(
S
==
CAPI
)
{
PyErr_SetString
(
TypeError
,
"getattr(): attribute name must be string"
);
return
NULL
;
}
else
raiseExcHelper
(
TypeError
,
"getattr(): attribute name must be string"
);
}
Box
*
rtn
=
PyObject_GetAttr
(
obj
,
_str
);
...
...
@@ -470,7 +482,7 @@ Box* getattrFunc(Box* obj, Box* _str, Box* default_value) {
return
default_value
;
}
if
(
!
rtn
)
if
(
S
==
CXX
&&
!
rtn
)
throwCAPIException
();
return
rtn
;
}
...
...
@@ -1437,9 +1449,9 @@ void setupBuiltins() {
builtins_module
->
giveAttr
(
"delattr"
,
new
BoxedBuiltinFunctionOrMethod
(
boxRTFunction
((
void
*
)
delattrFunc
,
NONE
,
2
),
"delattr"
));
builtins_module
->
giveAttr
(
"getattr"
,
new
BoxedBuiltinFunctionOrMethod
(
boxRTFunction
((
void
*
)
getattrFunc
,
UNKNOWN
,
3
,
1
,
false
,
false
),
"getattr"
,
{
NULL
}));
auto
getattr_func
=
boxRTFunction
((
void
*
)
getattrFunc
<
CXX
>
,
UNKNOWN
,
3
,
1
,
false
,
false
,
ParamNames
::
empty
(),
CXX
);
addRTFunction
(
getattr_func
,
(
void
*
)
getattrFunc
<
CAPI
>
,
UNKNOWN
,
CAPI
);
builtins_module
->
giveAttr
(
"getattr"
,
new
BoxedBuiltinFunctionOrMethod
(
getattr_func
,
"getattr"
,
{
NULL
}));
builtins_module
->
giveAttr
(
"setattr"
,
...
...
src/runtime/capi.cpp
View file @
96febb05
...
...
@@ -1476,11 +1476,23 @@ Box* BoxedCApiFunction::__call__(BoxedCApiFunction* self, BoxedTuple* varargs, B
// Kind of silly to have asked callFunc to rearrange the arguments for us, just to pass things
// off to tppCall, but this case should be very uncommon (people explicitly asking for __call__)
return
BoxedCApiFunction
::
tppCall
(
self
,
NULL
,
ArgPassSpec
(
0
,
0
,
true
,
true
),
varargs
,
kwargs
,
NULL
,
NULL
,
NULL
);
return
BoxedCApiFunction
::
tppCall
<
CXX
>
(
self
,
NULL
,
ArgPassSpec
(
0
,
0
,
true
,
true
),
varargs
,
kwargs
,
NULL
,
NULL
,
NULL
);
}
template
<
ExceptionStyle
S
>
Box
*
BoxedCApiFunction
::
tppCall
(
Box
*
_self
,
CallRewriteArgs
*
rewrite_args
,
ArgPassSpec
argspec
,
Box
*
arg1
,
Box
*
arg2
,
Box
*
arg3
,
Box
**
args
,
const
std
::
vector
<
BoxedString
*>*
keyword_names
)
{
Box
*
arg3
,
Box
**
args
,
const
std
::
vector
<
BoxedString
*>*
keyword_names
)
noexcept
(
S
==
CAPI
)
{
if
(
S
==
CAPI
)
{
try
{
return
tppCall
<
CXX
>
(
_self
,
NULL
,
argspec
,
arg1
,
arg2
,
arg3
,
args
,
keyword_names
);
}
catch
(
ExcInfo
e
)
{
setCAPIException
(
e
);
return
NULL
;
}
}
STAT_TIMER
(
t0
,
"us_timer_boxedcapifunction__call__"
,
10
);
assert
(
_self
->
cls
==
capifunc_cls
);
...
...
@@ -1634,7 +1646,8 @@ void setupCAPI() {
auto
capi_call
=
new
BoxedFunction
(
boxRTFunction
((
void
*
)
BoxedCApiFunction
::
__call__
,
UNKNOWN
,
1
,
0
,
true
,
true
));
capifunc_cls
->
giveAttr
(
"__call__"
,
capi_call
);
capifunc_cls
->
tpp_call
=
BoxedCApiFunction
::
tppCall
;
capifunc_cls
->
tpp_call
.
capi_val
=
BoxedCApiFunction
::
tppCall
<
CAPI
>
;
capifunc_cls
->
tpp_call
.
cxx_val
=
BoxedCApiFunction
::
tppCall
<
CXX
>
;
capifunc_cls
->
giveAttr
(
"__name__"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
BoxedCApiFunction
::
getname
,
NULL
,
NULL
));
capifunc_cls
->
giveAttr
(
"__doc__"
,
...
...
src/runtime/descr.cpp
View file @
96febb05
...
...
@@ -230,11 +230,23 @@ static Box* classmethodGet(Box* self, Box* obj, Box* type) {
// TODO this should be auto-generated as a slot wrapper:
Box
*
BoxedMethodDescriptor
::
__call__
(
BoxedMethodDescriptor
*
self
,
Box
*
obj
,
BoxedTuple
*
varargs
,
Box
**
_args
)
{
BoxedDict
*
kwargs
=
static_cast
<
BoxedDict
*>
(
_args
[
0
]);
return
BoxedMethodDescriptor
::
tppCall
(
self
,
NULL
,
ArgPassSpec
(
1
,
0
,
true
,
true
),
obj
,
varargs
,
kwargs
,
NULL
,
NULL
);
return
BoxedMethodDescriptor
::
tppCall
<
CXX
>
(
self
,
NULL
,
ArgPassSpec
(
1
,
0
,
true
,
true
),
obj
,
varargs
,
kwargs
,
NULL
,
NULL
);
}
template
<
ExceptionStyle
S
>
Box
*
BoxedMethodDescriptor
::
tppCall
(
Box
*
_self
,
CallRewriteArgs
*
rewrite_args
,
ArgPassSpec
argspec
,
Box
*
arg1
,
Box
*
arg2
,
Box
*
arg3
,
Box
**
args
,
const
std
::
vector
<
BoxedString
*>*
keyword_names
)
{
Box
*
arg2
,
Box
*
arg3
,
Box
**
args
,
const
std
::
vector
<
BoxedString
*>*
keyword_names
)
noexcept
(
S
==
CAPI
)
{
if
(
S
==
CAPI
)
{
try
{
return
tppCall
<
CXX
>
(
_self
,
NULL
,
argspec
,
arg1
,
arg2
,
arg3
,
args
,
keyword_names
);
}
catch
(
ExcInfo
e
)
{
setCAPIException
(
e
);
return
NULL
;
}
}
STAT_TIMER
(
t0
,
"us_timer_boxedmethoddescriptor__call__"
,
10
);
assert
(
_self
->
cls
==
method_cls
);
...
...
@@ -489,8 +501,19 @@ Box* BoxedWrapperObject::__call__(BoxedWrapperObject* self, Box* args, Box* kwds
return
rtn
;
}
template
<
ExceptionStyle
S
>
Box
*
BoxedWrapperObject
::
tppCall
(
Box
*
_self
,
CallRewriteArgs
*
rewrite_args
,
ArgPassSpec
argspec
,
Box
*
arg1
,
Box
*
arg2
,
Box
*
arg3
,
Box
**
args
,
const
std
::
vector
<
BoxedString
*>*
keyword_names
)
{
Box
*
arg3
,
Box
**
args
,
const
std
::
vector
<
BoxedString
*>*
keyword_names
)
noexcept
(
S
==
CAPI
)
{
if
(
S
==
CAPI
)
{
try
{
return
tppCall
<
CXX
>
(
_self
,
NULL
,
argspec
,
arg1
,
arg2
,
arg3
,
args
,
keyword_names
);
}
catch
(
ExcInfo
e
)
{
setCAPIException
(
e
);
return
NULL
;
}
}
STAT_TIMER
(
t0
,
"us_timer_boxedwrapperobject_call"
,
(
_self
->
cls
->
is_user_defined
?
10
:
20
));
assert
(
_self
->
cls
==
wrapperobject_cls
);
...
...
@@ -617,7 +640,8 @@ void setupDescr() {
new
BoxedFunction
(
boxRTFunction
((
void
*
)
BoxedMethodDescriptor
::
__get__
,
UNKNOWN
,
3
)));
CLFunction
*
method_call_cl
=
boxRTFunction
((
void
*
)
BoxedMethodDescriptor
::
__call__
,
UNKNOWN
,
2
,
0
,
true
,
true
);
method_cls
->
giveAttr
(
"__call__"
,
new
BoxedFunction
(
method_call_cl
));
method_cls
->
tpp_call
=
BoxedMethodDescriptor
::
tppCall
;
method_cls
->
tpp_call
.
capi_val
=
BoxedMethodDescriptor
::
tppCall
<
CAPI
>
;
method_cls
->
tpp_call
.
cxx_val
=
BoxedMethodDescriptor
::
tppCall
<
CXX
>
;
method_cls
->
giveAttr
(
"__doc__"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
methodGetDoc
,
NULL
,
NULL
));
method_cls
->
freeze
();
...
...
@@ -632,7 +656,8 @@ void setupDescr() {
wrapperobject_cls
->
giveAttr
(
"__call__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
BoxedWrapperObject
::
__call__
,
UNKNOWN
,
1
,
0
,
true
,
true
)));
wrapperobject_cls
->
tpp_call
=
BoxedWrapperObject
::
tppCall
;
wrapperobject_cls
->
tpp_call
.
capi_val
=
BoxedWrapperObject
::
tppCall
<
CAPI
>
;
wrapperobject_cls
->
tpp_call
.
cxx_val
=
BoxedWrapperObject
::
tppCall
<
CXX
>
;
wrapperobject_cls
->
freeze
();
}
...
...
src/runtime/float.cpp
View file @
96febb05
...
...
@@ -627,9 +627,17 @@ std::string floatFmt(double x, int precision, char code) {
return
std
::
string
(
buf
,
n
);
}
BoxedFloat
*
_floatNew
(
Box
*
a
)
{
template
<
ExceptionStyle
S
>
static
BoxedFloat
*
_floatNew
(
Box
*
a
)
noexcept
(
S
==
CAPI
)
{
// FIXME CPython uses PyUnicode_EncodeDecimal:
a
=
coerceUnicodeToStr
(
a
);
try
{
a
=
coerceUnicodeToStr
(
a
);
}
catch
(
ExcInfo
e
)
{
if
(
S
==
CAPI
)
{
throwCAPIException
();
return
NULL
;
}
throw
e
;
}
if
(
a
->
cls
==
float_cls
)
{
return
static_cast
<
BoxedFloat
*>
(
a
);
...
...
@@ -653,40 +661,70 @@ BoxedFloat* _floatNew(Box* a) {
assert
(
s
.
data
()[
s
.
size
()]
==
'\0'
);
const
char
*
startptr
=
s
.
data
();
double
r
=
strtod
(
startptr
,
&
endptr
);
if
(
endptr
!=
startptr
+
s
.
size
())
raiseExcHelper
(
ValueError
,
"could not convert string to float: %s"
,
s
.
data
());
if
(
endptr
!=
startptr
+
s
.
size
())
{
if
(
S
==
CAPI
)
{
PyErr_Format
(
ValueError
,
"could not convert string to float: %s"
,
s
.
data
());
return
NULL
;
}
else
raiseExcHelper
(
ValueError
,
"could not convert string to float: %s"
,
s
.
data
());
}
return
new
BoxedFloat
(
r
);
}
else
{
static
BoxedString
*
float_str
=
internStringImmortal
(
"__float__"
);
CallattrFlags
callattr_flags
{.
cls_only
=
true
,
.
null_on_nonexistent
=
true
,
.
argspec
=
ArgPassSpec
(
0
)
};
Box
*
r
=
callattr
(
a
,
float_str
,
callattr_flags
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
);
Box
*
r
=
callattrInternal
<
S
>
(
a
,
float_str
,
CLASS_ONLY
,
NULL
,
ArgPassSpec
(
0
),
NULL
,
NULL
,
NULL
,
NULL
,
NULL
);
if
(
!
r
)
{
fprintf
(
stderr
,
"TypeError: float() argument must be a string or a number, not '%s'
\n
"
,
getTypeName
(
a
));
raiseExcHelper
(
TypeError
,
""
);
if
(
S
==
CAPI
)
{
if
(
!
PyErr_Occurred
())
PyErr_Format
(
TypeError
,
"float() argument must be a string or a number, not '%s'
\n
"
,
getTypeName
(
a
));
return
NULL
;
}
else
{
raiseExcHelper
(
TypeError
,
"float() argument must be a string or a number, not '%s'
\n
"
,
getTypeName
(
a
));
}
}
if
(
!
isSubclass
(
r
->
cls
,
float_cls
))
{
raiseExcHelper
(
TypeError
,
"__float__ returned non-float (type %s)"
,
r
->
cls
->
tp_name
);
if
(
S
==
CAPI
)
{
PyErr_Format
(
TypeError
,
"__float__ returned non-float (type %s)"
,
r
->
cls
->
tp_name
);
return
NULL
;
}
else
raiseExcHelper
(
TypeError
,
"__float__ returned non-float (type %s)"
,
r
->
cls
->
tp_name
);
}
return
static_cast
<
BoxedFloat
*>
(
r
);
}
}
Box
*
floatNew
(
BoxedClass
*
_cls
,
Box
*
a
)
{
if
(
!
isSubclass
(
_cls
->
cls
,
type_cls
))
raiseExcHelper
(
TypeError
,
"float.__new__(X): X is not a type object (%s)"
,
getTypeName
(
_cls
));
template
<
ExceptionStyle
S
>
Box
*
floatNew
(
BoxedClass
*
_cls
,
Box
*
a
)
noexcept
(
S
==
CAPI
)
{
if
(
!
isSubclass
(
_cls
->
cls
,
type_cls
))
{
if
(
S
==
CAPI
)
{
PyErr_Format
(
TypeError
,
"float.__new__(X): X is not a type object (%s)"
,
getTypeName
(
_cls
));
return
NULL
;
}
else
raiseExcHelper
(
TypeError
,
"float.__new__(X): X is not a type object (%s)"
,
getTypeName
(
_cls
));
}
BoxedClass
*
cls
=
static_cast
<
BoxedClass
*>
(
_cls
);
if
(
!
isSubclass
(
cls
,
float_cls
))
raiseExcHelper
(
TypeError
,
"float.__new__(%s): %s is not a subtype of float"
,
getNameOfClass
(
cls
),
getNameOfClass
(
cls
));
if
(
!
isSubclass
(
cls
,
float_cls
))
{
if
(
S
==
CAPI
)
{
PyErr_Format
(
TypeError
,
"float.__new__(%s): %s is not a subtype of float"
,
getNameOfClass
(
cls
),
getNameOfClass
(
cls
));
return
NULL
;
}
else
{
raiseExcHelper
(
TypeError
,
"float.__new__(%s): %s is not a subtype of float"
,
getNameOfClass
(
cls
),
getNameOfClass
(
cls
));
}
}
if
(
cls
==
float_cls
)
return
_floatNew
(
a
);
return
_floatNew
<
S
>
(
a
);
BoxedFloat
*
f
=
_floatNew
(
a
);
BoxedFloat
*
f
=
_floatNew
<
S
>
(
a
);
if
(
!
f
)
{
assert
(
S
==
CAPI
);
return
NULL
;
}
return
new
(
cls
)
BoxedFloat
(
f
->
d
);
}
...
...
@@ -1476,8 +1514,9 @@ void setupFloat() {
_addFunc
(
"__sub__"
,
BOXED_FLOAT
,
(
void
*
)
floatSubFloat
,
(
void
*
)
floatSubInt
,
(
void
*
)
floatSub
);
_addFunc
(
"__rsub__"
,
BOXED_FLOAT
,
(
void
*
)
floatRSubFloat
,
(
void
*
)
floatRSubInt
,
(
void
*
)
floatRSub
);
float_cls
->
giveAttr
(
"__new__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
floatNew
,
UNKNOWN
,
2
,
1
,
false
,
false
),
{
boxFloat
(
0.0
)
}));
auto
float_new
=
boxRTFunction
((
void
*
)
floatNew
<
CXX
>
,
UNKNOWN
,
2
,
1
,
false
,
false
,
ParamNames
::
empty
(),
CXX
);
addRTFunction
(
float_new
,
(
void
*
)
floatNew
<
CAPI
>
,
UNKNOWN
,
CAPI
);
float_cls
->
giveAttr
(
"__new__"
,
new
BoxedFunction
(
float_new
,
{
boxFloat
(
0.0
)
}));
float_cls
->
giveAttr
(
"__neg__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
floatNeg
,
BOXED_FLOAT
,
1
)));
float_cls
->
giveAttr
(
"__pos__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
floatPos
,
BOXED_FLOAT
,
1
)));
...
...
src/runtime/inline/link_forcer.cpp
View file @
96febb05
...
...
@@ -120,7 +120,9 @@ void force() {
FORCE
(
getSysStdout
);
FORCE
(
runtimeCall
);
FORCE
(
runtimeCallCapi
);
FORCE
(
callattr
);
FORCE
(
callattrCapi
);
FORCE
(
raise0
);
FORCE
(
raise3
);
...
...
src/runtime/int.cpp
View file @
96febb05
...
...
@@ -884,7 +884,7 @@ extern "C" Box* intIndex(BoxedInt* v) {
return
boxInt
(
v
->
n
);
}
static
Box
*
_intNew
(
Box
*
val
,
Box
*
base
)
{
template
<
ExceptionStyle
S
>
static
Box
*
_intNew
(
Box
*
val
,
Box
*
base
)
noexcept
(
S
==
CAPI
)
{
if
(
val
->
cls
==
int_cls
)
{
RELEASE_ASSERT
(
!
base
,
""
);
BoxedInt
*
n
=
static_cast
<
BoxedInt
*>
(
val
);
...
...
@@ -904,8 +904,12 @@ static Box* _intNew(Box* val, Box* base) {
RELEASE_ASSERT
(
s
->
size
()
==
strlen
(
s
->
data
()),
""
);
Box
*
r
=
PyInt_FromString
(
s
->
data
(),
NULL
,
base_n
);
if
(
!
r
)
throwCAPIException
();
if
(
!
r
)
{
if
(
S
==
CAPI
)
return
NULL
;
else
throwCAPIException
();
}
return
r
;
}
else
if
(
isSubclass
(
val
->
cls
,
unicode_cls
))
{
int
base_n
;
...
...
@@ -917,8 +921,12 @@ static Box* _intNew(Box* val, Box* base) {
}
Box
*
r
=
PyInt_FromUnicode
(
PyUnicode_AS_UNICODE
(
val
),
PyUnicode_GET_SIZE
(
val
),
base_n
);
if
(
!
r
)
throwCAPIException
();
if
(
!
r
)
{
if
(
S
==
CAPI
)
return
NULL
;
else
throwCAPIException
();
}
return
r
;
}
else
if
(
val
->
cls
==
float_cls
)
{
RELEASE_ASSERT
(
!
base
,
""
);
...
...
@@ -952,39 +960,68 @@ static Box* _intNew(Box* val, Box* base) {
}
else
{
RELEASE_ASSERT
(
!
base
,
""
);
static
BoxedString
*
int_str
=
internStringImmortal
(
"__int__"
);
CallattrFlags
callattr_flags
{.
cls_only
=
true
,
.
null_on_nonexistent
=
true
,
.
argspec
=
ArgPassSpec
(
0
)
};
Box
*
r
=
callattr
(
val
,
int_str
,
callattr_flags
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
);
Box
*
r
=
callattrInternal
<
S
>
(
val
,
int_str
,
CLASS_ONLY
,
NULL
,
ArgPassSpec
(
0
),
NULL
,
NULL
,
NULL
,
NULL
,
NULL
);
if
(
!
r
)
{
fprintf
(
stderr
,
"TypeError: int() argument must be a string or a number, not '%s'
\n
"
,
getTypeName
(
val
));
raiseExcHelper
(
TypeError
,
""
);
if
(
S
==
CAPI
)
{
if
(
!
PyErr_Occurred
())
PyErr_Format
(
TypeError
,
"int() argument must be a string or a number, not '%s'
\n
"
,
getTypeName
(
val
));
return
NULL
;
}
else
{
raiseExcHelper
(
TypeError
,
"int() argument must be a string or a number, not '%s'
\n
"
,
getTypeName
(
val
));
}
}
if
(
!
isSubclass
(
r
->
cls
,
int_cls
)
&&
!
isSubclass
(
r
->
cls
,
long_cls
))
{
raiseExcHelper
(
TypeError
,
"__int__ returned non-int (type %s)"
,
r
->
cls
->
tp_name
);
if
(
!
PyInt_Check
(
r
)
&&
!
PyLong_Check
(
r
))
{
if
(
S
==
CAPI
)
{
PyErr_Format
(
TypeError
,
"__int__ returned non-int (type %s)"
,
r
->
cls
->
tp_name
);
return
NULL
;
}
else
raiseExcHelper
(
TypeError
,
"__int__ returned non-int (type %s)"
,
r
->
cls
->
tp_name
);
}
return
r
;
}
}
extern
"C"
Box
*
intNew
(
Box
*
_cls
,
Box
*
val
,
Box
*
base
)
{
if
(
!
isSubclass
(
_cls
->
cls
,
type_cls
))
raiseExcHelper
(
TypeError
,
"int.__new__(X): X is not a type object (%s)"
,
getTypeName
(
_cls
));
template
<
ExceptionStyle
S
>
Box
*
intNew
(
Box
*
_cls
,
Box
*
val
,
Box
*
base
)
noexcept
(
S
==
CAPI
)
{
if
(
!
isSubclass
(
_cls
->
cls
,
type_cls
))
{
if
(
S
==
CAPI
)
{
PyErr_Format
(
TypeError
,
"int.__new__(X): X is not a type object (%s)"
,
getTypeName
(
_cls
));
return
NULL
;
}
else
raiseExcHelper
(
TypeError
,
"int.__new__(X): X is not a type object (%s)"
,
getTypeName
(
_cls
));
}
BoxedClass
*
cls
=
static_cast
<
BoxedClass
*>
(
_cls
);
if
(
!
isSubclass
(
cls
,
int_cls
))
raiseExcHelper
(
TypeError
,
"int.__new__(%s): %s is not a subtype of int"
,
getNameOfClass
(
cls
),
getNameOfClass
(
cls
));
if
(
!
isSubclass
(
cls
,
int_cls
))
{
if
(
S
==
CAPI
)
{
PyErr_Format
(
TypeError
,
"int.__new__(%s): %s is not a subtype of int"
,
getNameOfClass
(
cls
),
getNameOfClass
(
cls
));
return
NULL
;
}
else
raiseExcHelper
(
TypeError
,
"int.__new__(%s): %s is not a subtype of int"
,
getNameOfClass
(
cls
),
getNameOfClass
(
cls
));
}
if
(
cls
==
int_cls
)
return
_intNew
(
val
,
base
);
return
_intNew
<
S
>
(
val
,
base
);
BoxedInt
*
n
=
(
BoxedInt
*
)
_intNew
<
S
>
(
val
,
base
);
if
(
!
n
)
{
assert
(
S
==
CAPI
);
return
NULL
;
}
BoxedInt
*
n
=
(
BoxedInt
*
)
_intNew
(
val
,
base
);
if
(
n
->
cls
==
long_cls
)
{
if
(
cls
==
int_cls
)
return
n
;
raiseExcHelper
(
OverflowError
,
"Python int too large to convert to C long"
,
getNameOfClass
(
cls
),
getNameOfClass
(
cls
));
if
(
S
==
CAPI
)
{
PyErr_Format
(
OverflowError
,
"Python int too large to convert to C long"
);
return
NULL
;
}
else
raiseExcHelper
(
OverflowError
,
"Python int too large to convert to C long"
);
}
return
new
(
cls
)
BoxedInt
(
n
->
n
);
}
...
...
@@ -1138,9 +1175,10 @@ void setupInt() {
int_cls
->
giveAttr
(
"__index__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
intIndex
,
BOXED_INT
,
1
)));
int_cls
->
giveAttr
(
"__int__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
intInt
,
BOXED_INT
,
1
)));
int_cls
->
giveAttr
(
"__new__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
intNew
,
UNKNOWN
,
3
,
2
,
false
,
false
,
ParamNames
({
""
,
"x"
,
"base"
},
""
,
""
)),
{
boxInt
(
0
),
NULL
}));
auto
int_new
=
boxRTFunction
((
void
*
)
intNew
<
CXX
>
,
UNKNOWN
,
3
,
2
,
false
,
false
,
ParamNames
({
""
,
"x"
,
"base"
},
""
,
""
),
CXX
);
addRTFunction
(
int_new
,
(
void
*
)
intNew
<
CAPI
>
,
UNKNOWN
,
CAPI
);
int_cls
->
giveAttr
(
"__new__"
,
new
BoxedFunction
(
int_new
,
{
boxInt
(
0
),
NULL
}));
int_cls
->
giveAttr
(
"bit_length"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
intBitLength
,
BOXED_INT
,
1
)));
...
...
src/runtime/objmodel.cpp
View file @
96febb05
This diff is collapsed.
Click to expand it.
src/runtime/objmodel.h
View file @
96febb05
...
...
@@ -65,7 +65,10 @@ extern "C" void delattrMaybeNonstring(Box* obj, Box* attr);
extern
"C"
void
delattrGeneric
(
Box
*
obj
,
BoxedString
*
attr
,
DelattrRewriteArgs
*
rewrite_args
);
extern
"C"
bool
nonzero
(
Box
*
obj
);
extern
"C"
Box
*
runtimeCall
(
Box
*
,
ArgPassSpec
,
Box
*
,
Box
*
,
Box
*
,
Box
**
,
const
std
::
vector
<
BoxedString
*>*
);
extern
"C"
Box
*
runtimeCallCapi
(
Box
*
,
ArgPassSpec
,
Box
*
,
Box
*
,
Box
*
,
Box
**
,
const
std
::
vector
<
BoxedString
*>*
)
noexcept
;
extern
"C"
Box
*
callattr
(
Box
*
,
BoxedString
*
,
CallattrFlags
,
Box
*
,
Box
*
,
Box
*
,
Box
**
,
const
std
::
vector
<
BoxedString
*>*
);
extern
"C"
Box
*
callattrCapi
(
Box
*
,
BoxedString
*
,
CallattrFlags
,
Box
*
,
Box
*
,
Box
*
,
Box
**
,
const
std
::
vector
<
BoxedString
*>*
)
noexcept
;
extern
"C"
BoxedString
*
str
(
Box
*
obj
);
extern
"C"
BoxedString
*
repr
(
Box
*
obj
);
extern
"C"
BoxedString
*
reprOrNull
(
Box
*
obj
);
// similar to repr, but returns NULL on exception
...
...
@@ -132,9 +135,10 @@ enum LookupScope {
INST_ONLY
=
2
,
CLASS_OR_INST
=
3
,
};
extern
"C"
Box
*
callattrInternal
(
Box
*
obj
,
BoxedString
*
attr
,
LookupScope
,
CallRewriteArgs
*
rewrite_args
,
ArgPassSpec
argspec
,
Box
*
arg1
,
Box
*
arg2
,
Box
*
arg3
,
Box
**
args
,
const
std
::
vector
<
BoxedString
*>*
keyword_names
);
template
<
ExceptionStyle
S
>
Box
*
callattrInternal
(
Box
*
obj
,
BoxedString
*
attr
,
LookupScope
,
CallRewriteArgs
*
rewrite_args
,
ArgPassSpec
argspec
,
Box
*
arg1
,
Box
*
arg2
,
Box
*
arg3
,
Box
**
args
,
const
std
::
vector
<
BoxedString
*>*
keyword_names
)
noexcept
(
S
==
CAPI
);
extern
"C"
void
delattr_internal
(
Box
*
obj
,
BoxedString
*
attr
,
bool
allow_custom
,
DelattrRewriteArgs
*
rewrite_args
);
struct
CompareRewriteArgs
;
Box
*
compareInternal
(
Box
*
lhs
,
Box
*
rhs
,
int
op_type
,
CompareRewriteArgs
*
rewrite_args
);
...
...
src/runtime/tuple.cpp
View file @
96febb05
...
...
@@ -143,7 +143,7 @@ template <ExceptionStyle S> Box* tupleGetitem(BoxedTuple* self, Box* slice) {
}
}
assert
(
self
->
cls
==
tuple_cls
);
assert
(
isSubclass
(
self
->
cls
,
tuple_cls
)
);
if
(
PyIndex_Check
(
slice
))
{
Py_ssize_t
i
=
PyNumber_AsSsize_t
(
slice
,
PyExc_IndexError
);
...
...
src/runtime/types.cpp
View file @
96febb05
This diff is collapsed.
Click to expand it.
src/runtime/types.h
View file @
96febb05
...
...
@@ -242,9 +242,8 @@ public:
pyston_inquiry
tpp_hasnext
;
typedef
Box
*
(
*
pyston_call
)(
Box
*
,
CallRewriteArgs
*
,
ArgPassSpec
,
Box
*
,
Box
*
,
Box
*
,
Box
**
,
const
std
::
vector
<
BoxedString
*>*
);
pyston_call
tpp_call
;
ExceptionSwitchableFunction
<
Box
*
,
Box
*
,
CallRewriteArgs
*
,
ArgPassSpec
,
Box
*
,
Box
*
,
Box
*
,
Box
**
,
const
std
::
vector
<
BoxedString
*>*>
tpp_call
;
bool
hasGenericGetattr
()
{
if
(
tp_getattr
||
tp_getattro
!=
object_cls
->
tp_getattro
)
...
...
@@ -985,8 +984,9 @@ public:
DEFAULT_CLASS
(
wrapperobject_cls
);
static
Box
*
__call__
(
BoxedWrapperObject
*
self
,
Box
*
args
,
Box
*
kwds
);
template
<
ExceptionStyle
S
>
static
Box
*
tppCall
(
Box
*
_self
,
CallRewriteArgs
*
rewrite_args
,
ArgPassSpec
argspec
,
Box
*
arg1
,
Box
*
arg2
,
Box
*
arg3
,
Box
**
args
,
const
std
::
vector
<
BoxedString
*>*
keyword_names
);
Box
**
args
,
const
std
::
vector
<
BoxedString
*>*
keyword_names
)
noexcept
(
S
==
CAPI
)
;
static
void
gcHandler
(
GCVisitor
*
v
,
Box
*
_o
);
};
...
...
@@ -1001,12 +1001,12 @@ public:
static
Box
*
__get__
(
BoxedMethodDescriptor
*
self
,
Box
*
inst
,
Box
*
owner
);
static
Box
*
__call__
(
BoxedMethodDescriptor
*
self
,
Box
*
obj
,
BoxedTuple
*
varargs
,
Box
**
_args
);
template
<
ExceptionStyle
S
>
static
Box
*
tppCall
(
Box
*
_self
,
CallRewriteArgs
*
rewrite_args
,
ArgPassSpec
argspec
,
Box
*
arg1
,
Box
*
arg2
,
Box
*
arg3
,
Box
**
args
,
const
std
::
vector
<
BoxedString
*>*
keyword_names
);
Box
**
args
,
const
std
::
vector
<
BoxedString
*>*
keyword_names
)
noexcept
(
S
==
CAPI
)
;
static
void
gcHandler
(
GCVisitor
*
v
,
Box
*
_o
);
};
Box
*
objectNewNoArgs
(
BoxedClass
*
cls
);
Box
*
objectSetattr
(
Box
*
obj
,
Box
*
attr
,
Box
*
value
);
Box
*
unwrapAttrWrapper
(
Box
*
b
);
...
...
src/runtime/util.cpp
View file @
96febb05
...
...
@@ -41,11 +41,11 @@ void parseSlice(BoxedSlice* slice, int size, i64* out_start, i64* out_stop, i64*
throwCAPIException
();
}
bool
isSliceIndex
(
Box
*
b
)
{
bool
isSliceIndex
(
Box
*
b
)
noexcept
{
return
b
->
cls
==
none_cls
||
b
->
cls
==
int_cls
||
PyIndex_Check
(
b
);
}
void
adjustNegativeIndicesOnObject
(
Box
*
obj
,
i64
*
start_out
,
i64
*
stop_out
)
{
void
adjustNegativeIndicesOnObject
(
Box
*
obj
,
i64
*
start_out
,
i64
*
stop_out
)
noexcept
{
i64
start
=
*
start_out
;
i64
stop
=
*
stop_out
;
PySequenceMethods
*
m
;
...
...
src/runtime/util.h
View file @
96febb05
...
...
@@ -36,9 +36,9 @@ inline void sliceIndex(Box* b, int64_t* out) {
throwCAPIException
();
}
bool
isSliceIndex
(
Box
*
b
);
bool
isSliceIndex
(
Box
*
b
)
noexcept
;
void
adjustNegativeIndicesOnObject
(
Box
*
obj
,
i64
*
start
,
i64
*
stop
);
void
adjustNegativeIndicesOnObject
(
Box
*
obj
,
i64
*
start
,
i64
*
stop
)
noexcept
;
// Adjust the start and stop bounds of the sequence we are slicing to its size.
// Ensure stop >= start and remain within bounds.
...
...
test/test_extension/setup.py
View file @
96febb05
from
distutils.core
import
setup
,
Extension
import
glob
import
os
extensions
=
[
Extension
(
"basic_test"
,
sources
=
[
"basic_test.c"
]),
Extension
(
"descr_test"
,
sources
=
[
"descr_test.c"
]),
Extension
(
"slots_test"
,
sources
=
[
"slots_test.c"
]),
]
def
relpath
(
fn
):
r
=
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
fn
)
return
r
print
glob
.
glob
(
"../from_cpython/Include/*.h"
)
builtin_headers
=
map
(
relpath
,
glob
.
glob
(
"../../from_cpython/Include/*.h"
))
for
m
in
extensions
:
m
.
depends
+=
builtin_headers
setup
(
name
=
"test"
,
version
=
"1.0"
,
description
=
"test"
,
ext_modules
=
[
Extension
(
"basic_test"
,
sources
=
[
"basic_test.c"
]),
Extension
(
"descr_test"
,
sources
=
[
"descr_test.c"
]),
Extension
(
"slots_test"
,
sources
=
[
"slots_test.c"
]),
],
ext_modules
=
extensions
,
)
test/tests/varargs_ics.py
View file @
96febb05
# run_args: -n
# statcheck: 1 <= noninit_count("slowpath_runtimecall") < 20
# statcheck: 1 <= noninit_count("slowpath_runtimecall")
+ noninit_count("slowpath_runtimecall_capi")
< 20
# Make sure we can patch some basic varargs cases
...
...
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