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
c75e90df
Commit
c75e90df
authored
Jan 20, 2015
by
Kevin Modzelewski
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'excinfo3'
parents
aac0d9e6
90170281
Changes
34
Hide whitespace changes
Inline
Side-by-side
Showing
34 changed files
with
391 additions
and
155 deletions
+391
-155
Makefile
Makefile
+1
-1
microbenchmarks/exceptions_ubench.py
microbenchmarks/exceptions_ubench.py
+11
-0
src/capi/object.cpp
src/capi/object.cpp
+4
-4
src/capi/typeobject.cpp
src/capi/typeobject.cpp
+11
-11
src/codegen/ast_interpreter.cpp
src/codegen/ast_interpreter.cpp
+11
-7
src/codegen/codegen.h
src/codegen/codegen.h
+1
-0
src/codegen/compvars.cpp
src/codegen/compvars.cpp
+28
-0
src/codegen/compvars.h
src/codegen/compvars.h
+19
-0
src/codegen/irgen/irgenerator.cpp
src/codegen/irgen/irgenerator.cpp
+30
-25
src/codegen/runtime_hooks.cpp
src/codegen/runtime_hooks.cpp
+3
-0
src/core/cfg.cpp
src/core/cfg.cpp
+20
-6
src/core/types.h
src/core/types.h
+7
-0
src/gc/collector.h
src/gc/collector.h
+1
-0
src/jit.cpp
src/jit.cpp
+6
-6
src/runtime/builtin_modules/builtins.cpp
src/runtime/builtin_modules/builtins.cpp
+3
-3
src/runtime/builtin_modules/sys.cpp
src/runtime/builtin_modules/sys.cpp
+1
-1
src/runtime/builtin_modules/thread.cpp
src/runtime/builtin_modules/thread.cpp
+2
-2
src/runtime/capi.cpp
src/runtime/capi.cpp
+32
-26
src/runtime/capi.h
src/runtime/capi.h
+2
-0
src/runtime/classobj.cpp
src/runtime/classobj.cpp
+6
-6
src/runtime/dict.cpp
src/runtime/dict.cpp
+10
-9
src/runtime/file.cpp
src/runtime/file.cpp
+4
-3
src/runtime/generator.cpp
src/runtime/generator.cpp
+16
-11
src/runtime/iterobject.cpp
src/runtime/iterobject.cpp
+7
-6
src/runtime/list.cpp
src/runtime/list.cpp
+8
-7
src/runtime/long.cpp
src/runtime/long.cpp
+1
-1
src/runtime/objmodel.cpp
src/runtime/objmodel.cpp
+5
-5
src/runtime/objmodel.h
src/runtime/objmodel.h
+3
-0
src/runtime/stacktrace.cpp
src/runtime/stacktrace.cpp
+11
-6
src/runtime/tuple.cpp
src/runtime/tuple.cpp
+1
-1
src/runtime/types.cpp
src/runtime/types.cpp
+7
-7
src/runtime/types.h
src/runtime/types.h
+1
-1
test/bench_exceptions.cpp
test/bench_exceptions.cpp
+88
-0
test/tests/sys_excinfo.py
test/tests/sys_excinfo.py
+30
-0
No files found.
Makefile
View file @
c75e90df
...
...
@@ -647,7 +647,7 @@ $$(SRCS:.cpp=$1.o.bc): CXXFLAGS:=$2
%$1.h.pch
:
%.h $$(BUILD_SYSTEM_DEPS)
$
$(ECHO)
Compiling
$$
@
$
$(VERB)
rm
-f
$$
@-
*
$
$(VERB)
$
$(CLANGPP_EXE)
$
$(CXXFLAGS)
-MMD
-MP
-MF
$$
<.d
-x
c++-header
$$
<
-o
$$
@
$
$(VERB)
$
$(CLANGPP_EXE)
$
$(CXXFLAGS)
-MMD
-MP
-MF
$
$
(
patsubst
%.pch,%.d,
$$
@
)
-x
c++-header
$$
<
-o
$$
@
$$(CODEGEN_SRCS
:
.cpp=$1.o): CXXFLAGS += -include src/codegen/irgen$1.h
$$(CODEGEN_SRCS
:
.cpp=$1.o): src/codegen/irgen$1.h.pch
...
...
microbenchmarks/exceptions_ubench.py
0 → 100644
View file @
c75e90df
def
f
():
# Try to eliminate as much non-exception stuff as possible:
from
__builtin__
import
Exception
e
=
Exception
()
for
i
in
xrange
(
100000
):
try
:
raise
e
except
Exception
:
pass
f
()
src/capi/object.cpp
View file @
c75e90df
...
...
@@ -39,8 +39,8 @@ extern "C" PyObject* _PyObject_Str(PyObject* v) noexcept {
try
{
return
str
(
v
);
}
catch
(
Box
*
b
)
{
PyErr_SetObject
(
b
->
cls
,
b
);
}
catch
(
ExcInfo
e
)
{
setCAPIException
(
e
);
return
NULL
;
}
}
...
...
@@ -79,8 +79,8 @@ extern "C" PyObject* PyObject_GetAttrString(PyObject* o, const char* attr) noexc
try
{
return
getattr
(
o
,
attr
);
}
catch
(
Box
*
b
)
{
PyErr_SetObject
(
b
->
cls
,
b
);
}
catch
(
ExcInfo
e
)
{
setCAPIException
(
e
);
return
NULL
;
}
}
...
...
src/capi/typeobject.cpp
View file @
c75e90df
...
...
@@ -484,8 +484,8 @@ static PyObject* call_maybe(PyObject* o, const char* name, PyObject** nameobj, c
PyObject
*
slot_tp_repr
(
PyObject
*
self
)
noexcept
{
try
{
return
repr
(
self
);
}
catch
(
Box
*
e
)
{
PyErr_SetObject
(
e
->
cls
,
e
);
}
catch
(
ExcInfo
e
)
{
setCAPIException
(
e
);
return
NULL
;
}
}
...
...
@@ -493,8 +493,8 @@ PyObject* slot_tp_repr(PyObject* self) noexcept {
PyObject
*
slot_tp_str
(
PyObject
*
self
)
noexcept
{
try
{
return
str
(
self
);
}
catch
(
Box
*
e
)
{
PyErr_SetObject
(
e
->
cls
,
e
);
}
catch
(
ExcInfo
e
)
{
setCAPIException
(
e
);
return
NULL
;
}
}
...
...
@@ -542,8 +542,8 @@ PyObject* slot_tp_call(PyObject* self, PyObject* args, PyObject* kwds) noexcept
// TODO: runtime ICs?
return
runtimeCall
(
self
,
ArgPassSpec
(
0
,
0
,
true
,
true
),
args
,
kwds
,
NULL
,
NULL
,
NULL
);
}
catch
(
Box
*
e
)
{
PyErr_SetObject
(
e
->
cls
,
e
);
}
catch
(
ExcInfo
e
)
{
setCAPIException
(
e
);
return
NULL
;
}
}
...
...
@@ -631,8 +631,8 @@ static PyObject* slot_tp_new(PyTypeObject* self, PyObject* args, PyObject* kwds)
new_attr
=
processDescriptor
(
new_attr
,
None
,
self
);
return
runtimeCall
(
new_attr
,
ArgPassSpec
(
1
,
0
,
true
,
true
),
self
,
args
,
kwds
,
NULL
,
NULL
);
}
catch
(
Box
*
e
)
{
PyErr_SetObject
(
e
->
cls
,
e
);
}
catch
(
ExcInfo
e
)
{
setCAPIException
(
e
);
return
NULL
;
}
}
...
...
@@ -660,8 +660,8 @@ static int slot_tp_init(PyObject* self, PyObject* args, PyObject* kwds) noexcept
PyObject
*
slot_sq_item
(
PyObject
*
self
,
Py_ssize_t
i
)
noexcept
{
try
{
return
getitem
(
self
,
boxInt
(
i
));
}
catch
(
Box
*
e
)
{
PyErr_SetObject
(
e
->
cls
,
e
);
}
catch
(
ExcInfo
e
)
{
setCAPIException
(
e
);
return
NULL
;
}
}
...
...
@@ -1781,7 +1781,7 @@ extern "C" int PyType_Ready(PyTypeObject* cls) noexcept {
try
{
add_operators
(
cls
);
}
catch
(
Box
*
b
)
{
}
catch
(
ExcInfo
e
)
{
abort
();
}
...
...
src/codegen/ast_interpreter.cpp
View file @
c75e90df
...
...
@@ -123,7 +123,7 @@ private:
SymMap
sym_table
;
CFGBlock
*
next_block
,
*
current_block
;
AST_stmt
*
current_inst
;
Box
*
last_exception
;
ExcInfo
last_exception
;
BoxedClosure
*
passed_closure
,
*
created_closure
;
BoxedGenerator
*
generator
;
unsigned
edgecount
;
...
...
@@ -224,8 +224,8 @@ void gatherInterpreterRoots(GCVisitor* visitor) {
ASTInterpreter
::
ASTInterpreter
(
CompiledFunction
*
compiled_function
)
:
compiled_func
(
compiled_function
),
source_info
(
compiled_function
->
clfunc
->
source
),
scope_info
(
0
),
next_block
(
0
),
current_block
(
0
),
current_inst
(
0
),
last_exception
(
0
),
passed_closure
(
0
),
created_closure
(
0
),
generator
(
0
),
edgecount
(
0
)
{
current_block
(
0
),
current_inst
(
0
),
last_exception
(
NULL
,
NULL
,
NULL
),
passed_closure
(
0
),
created_closure
(
0
),
generator
(
0
),
edgecount
(
0
)
{
CLFunction
*
f
=
compiled_function
->
clfunc
;
if
(
!
source_info
->
cfg
)
...
...
@@ -506,9 +506,9 @@ Value ASTInterpreter::visit_invoke(AST_Invoke* node) {
try
{
v
=
visit_stmt
(
node
->
stmt
);
next_block
=
node
->
normal_dest
;
}
catch
(
Box
*
b
)
{
}
catch
(
ExcInfo
e
)
{
next_block
=
node
->
exc_dest
;
last_exception
=
b
;
last_exception
=
e
;
}
return
v
;
...
...
@@ -561,8 +561,12 @@ Value ASTInterpreter::visit_langPrimitive(AST_LangPrimitive* node) {
}
else
if
(
node
->
opcode
==
AST_LangPrimitive
::
NONE
)
{
v
=
None
;
}
else
if
(
node
->
opcode
==
AST_LangPrimitive
::
LANDINGPAD
)
{
v
=
last_exception
;
last_exception
=
nullptr
;
assert
(
last_exception
.
type
);
Box
*
type
=
last_exception
.
type
;
Box
*
value
=
last_exception
.
value
?
last_exception
.
value
:
None
;
Box
*
traceback
=
last_exception
.
traceback
?
last_exception
.
traceback
:
None
;
v
=
new
BoxedTuple
({
type
,
value
,
traceback
});
last_exception
=
ExcInfo
(
NULL
,
NULL
,
NULL
);
}
else
if
(
node
->
opcode
==
AST_LangPrimitive
::
ISINSTANCE
)
{
assert
(
node
->
args
.
size
()
==
3
);
Value
obj
=
visit_expr
(
node
->
args
[
0
]);
...
...
src/codegen/codegen.h
View file @
c75e90df
...
...
@@ -72,6 +72,7 @@ struct GlobalState {
llvm
::
Type
*
llvm_str_type_ptr
;
llvm
::
Type
*
llvm_clfunction_type_ptr
,
*
llvm_closure_type_ptr
,
*
llvm_generator_type_ptr
;
llvm
::
Type
*
llvm_module_type_ptr
,
*
llvm_bool_type_ptr
;
llvm
::
Type
*
llvm_excinfo_type
;
llvm
::
Type
*
i1
,
*
i8
,
*
i8_ptr
,
*
i32
,
*
i64
,
*
void_
,
*
double_
;
llvm
::
Type
*
vector_ptr
;
...
...
src/codegen/compvars.cpp
View file @
c75e90df
...
...
@@ -380,6 +380,22 @@ public:
assert
(
vals
.
size
()
==
1
);
return
reinterpret_cast
<
Box
*>
(
vals
[
0
]);
}
std
::
vector
<
CompilerVariable
*>
unpack
(
IREmitter
&
emitter
,
const
OpInfo
&
info
,
VAR
*
var
,
int
num_into
)
override
{
llvm
::
Value
*
unpacked
=
emitter
.
createCall2
(
info
.
unw_info
,
g
.
funcs
.
unpackIntoArray
,
var
->
getValue
(),
getConstantInt
(
num_into
,
g
.
i64
));
assert
(
unpacked
->
getType
()
==
g
.
llvm_value_type_ptr
->
getPointerTo
());
std
::
vector
<
CompilerVariable
*>
rtn
;
for
(
int
i
=
0
;
i
<
num_into
;
i
++
)
{
llvm
::
Value
*
ptr
=
emitter
.
getBuilder
()
->
CreateConstGEP1_32
(
unpacked
,
i
);
llvm
::
Value
*
val
=
emitter
.
getBuilder
()
->
CreateLoad
(
ptr
);
assert
(
val
->
getType
()
==
g
.
llvm_value_type_ptr
);
rtn
.
push_back
(
new
ConcreteCompilerVariable
(
UNKNOWN
,
val
,
true
));
}
return
rtn
;
}
};
ConcreteCompilerType
*
UNKNOWN
=
new
UnknownType
();
...
...
@@ -1986,6 +2002,18 @@ public:
rtn
+=
e
->
numFrameArgs
();
return
rtn
;
}
std
::
vector
<
CompilerVariable
*>
unpack
(
IREmitter
&
emitter
,
const
OpInfo
&
info
,
VAR
*
var
,
int
num_into
)
override
{
if
(
num_into
!=
elt_types
.
size
())
{
return
ValuedCompilerType
::
unpack
(
emitter
,
info
,
var
,
num_into
);
}
// Not sure if this is right:
for
(
auto
e
:
*
var
->
getValue
())
e
->
incvref
();
return
*
var
->
getValue
();
}
};
CompilerType
*
makeTupleType
(
const
std
::
vector
<
CompilerType
*>&
elt_types
)
{
...
...
src/codegen/compvars.h
View file @
c75e90df
...
...
@@ -158,6 +158,8 @@ public:
return
getConcreteType
()
->
guaranteedClass
();
}
virtual
void
serializeToFrame
(
VAR
*
v
,
std
::
vector
<
llvm
::
Value
*>&
stackmap_args
)
=
0
;
virtual
std
::
vector
<
CompilerVariable
*>
unpack
(
IREmitter
&
emitter
,
const
OpInfo
&
info
,
VAR
*
var
,
int
num_into
);
};
template
<
class
V
>
class
ValuedCompilerType
:
public
_ValuedCompilerType
<
V
>
{
public
:
};
...
...
@@ -264,6 +266,8 @@ public:
AST_TYPE
::
AST_TYPE
op_type
,
BinExpType
exp_type
)
=
0
;
virtual
void
serializeToFrame
(
std
::
vector
<
llvm
::
Value
*>&
stackmap_args
)
=
0
;
virtual
std
::
vector
<
CompilerVariable
*>
unpack
(
IREmitter
&
emitter
,
const
OpInfo
&
info
,
int
num_into
)
=
0
;
};
template
<
class
V
>
class
ValuedCompilerVariable
:
public
CompilerVariable
{
...
...
@@ -357,6 +361,10 @@ public:
void
serializeToFrame
(
std
::
vector
<
llvm
::
Value
*>&
stackmap_args
)
override
{
type
->
serializeToFrame
(
this
,
stackmap_args
);
}
std
::
vector
<
CompilerVariable
*>
unpack
(
IREmitter
&
emitter
,
const
OpInfo
&
info
,
int
num_into
)
override
{
return
type
->
unpack
(
emitter
,
info
,
this
,
num_into
);
}
};
// template <>
...
...
@@ -383,6 +391,17 @@ CompilerType* makeFuncType(ConcreteCompilerType* rtn_type, const std::vector<Con
ConcreteCompilerVariable
*
boolFromI1
(
IREmitter
&
,
llvm
::
Value
*
);
llvm
::
Value
*
i1FromBool
(
IREmitter
&
,
ConcreteCompilerVariable
*
);
template
<
typename
V
>
std
::
vector
<
CompilerVariable
*>
_ValuedCompilerType
<
V
>::
unpack
(
IREmitter
&
emitter
,
const
OpInfo
&
info
,
VAR
*
var
,
int
num_into
)
{
assert
((
CompilerType
*
)
this
!=
UNKNOWN
);
ConcreteCompilerVariable
*
converted
=
makeConverted
(
emitter
,
var
,
UNKNOWN
);
auto
r
=
UNKNOWN
->
unpack
(
emitter
,
info
,
converted
,
num_into
);
converted
->
decvref
(
emitter
);
return
r
;
}
}
// namespace pyston
#endif
src/codegen/irgen/irgenerator.cpp
View file @
c75e90df
...
...
@@ -37,6 +37,10 @@
namespace
pyston
{
extern
"C"
void
dumpLLVM
(
llvm
::
Value
*
v
)
{
v
->
dump
();
}
llvm
::
Value
*
IRGenState
::
getScratchSpace
(
int
min_bytes
)
{
llvm
::
BasicBlock
&
entry_block
=
getLLVMFunction
()
->
getEntryBlock
();
...
...
@@ -397,22 +401,36 @@ private:
llvm
::
StructType
::
create
(
std
::
vector
<
llvm
::
Type
*>
{
g
.
i8_ptr
,
g
.
i64
}),
personality_func
,
1
);
landing_pad
->
addClause
(
embedConstantPtr
(
NULL
,
g
.
i8_ptr
));
llvm
::
Value
*
exc_pointer
=
emitter
.
getBuilder
()
->
CreateExtractValue
(
landing_pad
,
{
0
});
llvm
::
Value
*
cxa
exc_pointer
=
emitter
.
getBuilder
()
->
CreateExtractValue
(
landing_pad
,
{
0
});
llvm
::
Value
*
exc_obj
;
if
(
irstate
->
getEffortLevel
()
!=
EffortLevel
::
INTERPRETED
)
{
llvm
::
Value
*
exc_obj_pointer
=
emitter
.
getBuilder
()
->
CreateCall
(
g
.
funcs
.
__cxa_begin_catch
,
exc_pointer
);
llvm
::
Value
*
exc_obj_pointer_casted
=
emitter
.
getBuilder
()
->
CreateBitCast
(
exc_obj_pointer
,
g
.
llvm_value_type_ptr
->
getPointerTo
());
exc_obj
=
emitter
.
getBuilder
()
->
CreateLoad
(
exc_obj_pointer_casted
);
emitter
.
getBuilder
()
->
CreateCall
(
g
.
funcs
.
__cxa_end_catch
);
llvm
::
Value
*
excinfo_pointer
=
emitter
.
getBuilder
()
->
CreateCall
(
g
.
funcs
.
__cxa_begin_catch
,
cxaexc_pointer
);
llvm
::
Value
*
excinfo_pointer_casted
=
emitter
.
getBuilder
()
->
CreateBitCast
(
excinfo_pointer
,
g
.
llvm_excinfo_type
->
getPointerTo
());
auto
*
builder
=
emitter
.
getBuilder
();
llvm
::
Value
*
exc_type
=
builder
->
CreateLoad
(
builder
->
CreateConstInBoundsGEP2_32
(
excinfo_pointer_casted
,
0
,
0
));
llvm
::
Value
*
exc_value
=
builder
->
CreateLoad
(
builder
->
CreateConstInBoundsGEP2_32
(
excinfo_pointer_casted
,
0
,
1
));
llvm
::
Value
*
exc_traceback
=
builder
->
CreateLoad
(
builder
->
CreateConstInBoundsGEP2_32
(
excinfo_pointer_casted
,
0
,
2
));
assert
(
exc_type
->
getType
()
==
g
.
llvm_value_type_ptr
);
assert
(
exc_value
->
getType
()
==
g
.
llvm_value_type_ptr
);
assert
(
exc_traceback
->
getType
()
==
g
.
llvm_value_type_ptr
);
return
makeTuple
({
new
ConcreteCompilerVariable
(
UNKNOWN
,
exc_type
,
true
),
new
ConcreteCompilerVariable
(
UNKNOWN
,
exc_value
,
true
),
new
ConcreteCompilerVariable
(
UNKNOWN
,
exc_traceback
,
true
)
});
}
else
{
// TODO This doesn't get hit, right?
abort
();
// The interpreter can't really support the full C++ exception handling model since it's
// itself written in C++. Let's make it easier for the interpreter and use a simpler interface:
exc_obj
=
emitter
.
getBuilder
()
->
CreateBitCast
(
exc_pointer
,
g
.
llvm_value_type_ptr
);
llvm
::
Value
*
exc_obj
=
emitter
.
getBuilder
()
->
CreateBitCast
(
cxa
exc_pointer
,
g
.
llvm_value_type_ptr
);
}
return
new
ConcreteCompilerVariable
(
UNKNOWN
,
exc_obj
,
true
);
}
case
AST_LangPrimitive
:
:
LOCALS
:
{
assert
(
node
->
args
.
size
()
==
0
);
...
...
@@ -1388,9 +1406,7 @@ private:
assert
(
state
!=
PARTIAL
);
int
ntargets
=
target
->
elts
.
size
();
// TODO can do faster unpacking of non-instantiated tuples; ie for something like
// a, b = 1, 2
// We shouldn't need to do any runtime error checking or allocations
std
::
vector
<
CompilerVariable
*>
unpacked
=
val
->
unpack
(
emitter
,
getOpInfoForNode
(
target
,
unw_info
),
ntargets
);
#ifndef NDEBUG
for
(
auto
e
:
target
->
elts
)
{
...
...
@@ -1399,19 +1415,8 @@ private:
}
#endif
ConcreteCompilerVariable
*
converted_val
=
val
->
makeConverted
(
emitter
,
val
->
getBoxType
());
llvm
::
Value
*
unpacked
=
emitter
.
createCall2
(
unw_info
,
g
.
funcs
.
unpackIntoArray
,
converted_val
->
getValue
(),
getConstantInt
(
ntargets
,
g
.
i64
));
assert
(
unpacked
->
getType
()
==
g
.
llvm_value_type_ptr
->
getPointerTo
());
converted_val
->
decvref
(
emitter
);
for
(
int
i
=
0
;
i
<
ntargets
;
i
++
)
{
llvm
::
Value
*
ptr
=
emitter
.
getBuilder
()
->
CreateConstGEP1_32
(
unpacked
,
i
);
llvm
::
Value
*
val
=
emitter
.
getBuilder
()
->
CreateLoad
(
ptr
);
assert
(
val
->
getType
()
==
g
.
llvm_value_type_ptr
);
CompilerVariable
*
thisval
=
new
ConcreteCompilerVariable
(
UNKNOWN
,
val
,
true
);
CompilerVariable
*
thisval
=
unpacked
[
i
];
_doSet
(
target
->
elts
[
i
],
thisval
,
unw_info
);
thisval
->
decvref
(
emitter
);
}
...
...
src/codegen/runtime_hooks.cpp
View file @
c75e90df
...
...
@@ -143,6 +143,9 @@ void initGlobalFuncs(GlobalState& g) {
g
.
llvm_generator_type_ptr
=
g
.
stdlib_module
->
getTypeByName
(
"class.pyston::BoxedGenerator"
)
->
getPointerTo
();
assert
(
g
.
llvm_generator_type_ptr
);
g
.
llvm_excinfo_type
=
g
.
stdlib_module
->
getTypeByName
(
"struct.pyston::ExcInfo"
);
assert
(
g
.
llvm_excinfo_type
);
#define GET(N) g.funcs.N = getFunc((void*)N, STRINGIFY(N))
g
.
funcs
.
printf
=
addFunc
((
void
*
)
printf
,
g
.
i8_ptr
,
true
);
...
...
src/core/cfg.cpp
View file @
c75e90df
...
...
@@ -78,7 +78,7 @@ private:
struct
ExcBlockInfo
{
CFGBlock
*
exc_dest
;
std
::
string
exc_
obj
_name
;
std
::
string
exc_
type_name
,
exc_value_name
,
exc_traceback
_name
;
};
std
::
vector
<
ExcBlockInfo
>
exc_handlers
;
...
...
@@ -460,6 +460,12 @@ private:
#endif
}
std
::
string
nodeName
(
AST
*
node
,
const
std
::
string
&
suffix
)
{
char
buf
[
50
];
snprintf
(
buf
,
50
,
"#%p_%s"
,
node
,
suffix
.
c_str
());
return
std
::
string
(
buf
);
}
std
::
string
nodeName
(
AST
*
node
,
const
std
::
string
&
suffix
,
int
idx
)
{
char
buf
[
50
];
snprintf
(
buf
,
50
,
"#%p_%s_%d"
,
node
,
suffix
.
c_str
(),
idx
);
...
...
@@ -1102,7 +1108,12 @@ public:
curblock
=
exc_dest
;
AST_Assign
*
exc_asgn
=
new
AST_Assign
();
exc_asgn
->
targets
.
push_back
(
makeName
(
exc_info
.
exc_obj_name
,
AST_TYPE
::
Store
,
node
->
lineno
));
AST_Tuple
*
target
=
new
AST_Tuple
();
target
->
elts
.
push_back
(
makeName
(
exc_info
.
exc_type_name
,
AST_TYPE
::
Store
,
node
->
lineno
));
target
->
elts
.
push_back
(
makeName
(
exc_info
.
exc_value_name
,
AST_TYPE
::
Store
,
node
->
lineno
));
target
->
elts
.
push_back
(
makeName
(
exc_info
.
exc_traceback_name
,
AST_TYPE
::
Store
,
node
->
lineno
));
exc_asgn
->
targets
.
push_back
(
target
);
exc_asgn
->
value
=
new
AST_LangPrimitive
(
AST_LangPrimitive
::
LANDINGPAD
);
curblock
->
push_back
(
exc_asgn
);
...
...
@@ -1811,8 +1822,10 @@ public:
assert
(
node
->
handlers
.
size
()
>
0
);
CFGBlock
*
exc_handler_block
=
cfg
->
addDeferredBlock
();
std
::
string
exc_obj_name
=
nodeName
(
node
);
exc_handlers
.
push_back
({
exc_handler_block
,
exc_obj_name
});
std
::
string
exc_type_name
=
nodeName
(
node
,
"type"
);
std
::
string
exc_value_name
=
nodeName
(
node
,
"value"
);
std
::
string
exc_traceback_name
=
nodeName
(
node
,
"traceback"
);
exc_handlers
.
push_back
({
exc_handler_block
,
exc_type_name
,
exc_value_name
,
exc_traceback_name
});
for
(
AST_stmt
*
subnode
:
node
->
body
)
{
subnode
->
accept
(
this
);
...
...
@@ -1838,7 +1851,8 @@ public:
cfg
->
placeBlock
(
exc_handler_block
);
curblock
=
exc_handler_block
;
AST_expr
*
exc_obj
=
makeName
(
exc_obj_name
,
AST_TYPE
::
Load
,
node
->
lineno
);
// TODO: this should be an EXCEPTION_MATCHES(exc_type_name)
AST_expr
*
exc_obj
=
makeName
(
exc_value_name
,
AST_TYPE
::
Load
,
node
->
lineno
);
bool
caught_all
=
false
;
for
(
AST_ExceptHandler
*
exc_handler
:
node
->
handlers
)
{
...
...
@@ -2231,7 +2245,7 @@ CFG* computeCFG(SourceInfo* source, std::vector<AST_stmt*> body) {
}
}
if
(
VERBOSITY
(
"cfg"
)
>=
2
)
{
if
(
VERBOSITY
(
"cfg"
)
>=
1
)
{
printf
(
"Final cfg:
\n
"
);
rtn
->
print
();
}
...
...
src/core/types.h
View file @
c75e90df
...
...
@@ -469,6 +469,13 @@ public:
LineInfo
(
int
line
,
int
column
,
const
std
::
string
&
file
,
const
std
::
string
&
func
)
:
line
(
line
),
column
(
column
),
file
(
file
),
func
(
func
)
{}
};
struct
ExcInfo
{
Box
*
type
,
*
value
,
*
traceback
;
ExcInfo
(
Box
*
type
,
Box
*
value
,
Box
*
traceback
)
:
type
(
type
),
value
(
value
),
traceback
(
traceback
)
{}
bool
matches
(
BoxedClass
*
cls
)
const
;
};
}
#endif
src/gc/collector.h
View file @
c75e90df
...
...
@@ -42,6 +42,7 @@ public:
void
operator
=
(
Box
*
b
)
{
value
=
b
;
}
operator
Box
*
()
{
return
value
;
}
Box
*
operator
->
()
{
return
value
;
}
};
void
runCollection
();
...
...
src/jit.cpp
View file @
c75e90df
...
...
@@ -150,12 +150,12 @@ int main(int argc, char** argv) {
try
{
main_module
=
createAndRunModule
(
"__main__"
,
fn
);
}
catch
(
Box
*
b
)
{
if
(
isInstance
(
b
,
SystemExit
))
{
}
catch
(
ExcInfo
e
)
{
if
(
e
.
matches
(
SystemExit
))
{
printf
(
"Warning: ignoring SystemExit code
\n
"
);
return
1
;
}
else
{
std
::
string
msg
=
formatException
(
b
);
std
::
string
msg
=
formatException
(
e
.
value
);
printLastTraceback
();
fprintf
(
stderr
,
"%s
\n
"
,
msg
.
c_str
());
return
1
;
...
...
@@ -222,12 +222,12 @@ int main(int argc, char** argv) {
try
{
compileAndRunModule
(
m
,
main_module
);
}
catch
(
Box
*
b
)
{
if
(
isInstance
(
b
,
SystemExit
))
{
}
catch
(
ExcInfo
e
)
{
if
(
e
.
matches
(
SystemExit
))
{
printf
(
"Warning: ignoring SystemExit code
\n
"
);
return
1
;
}
else
{
std
::
string
msg
=
formatException
(
b
);
std
::
string
msg
=
formatException
(
e
.
value
);
printLastTraceback
();
fprintf
(
stderr
,
"%s
\n
"
,
msg
.
c_str
());
}
...
...
src/runtime/builtin_modules/builtins.cpp
View file @
c75e90df
...
...
@@ -446,8 +446,8 @@ Box* hasattr(Box* obj, Box* _str) {
Box
*
attr
;
try
{
attr
=
getattrInternal
(
obj
,
str
->
s
,
NULL
);
}
catch
(
Box
*
e
)
{
if
(
isSubclass
(
e
->
cls
,
Exception
))
}
catch
(
ExcInfo
e
)
{
if
(
e
.
matches
(
Exception
))
return
False
;
throw
;
}
...
...
@@ -623,7 +623,7 @@ extern "C" PyObject* PyErr_NewException(char* name, PyObject* _base, PyObject* d
// TODO Not sure if this should be called here
fixup_slot_dispatchers
(
cls
);
return
cls
;
}
catch
(
Box
*
e
)
{
}
catch
(
ExcInfo
e
)
{
abort
();
}
}
...
...
src/runtime/builtin_modules/sys.cpp
View file @
c75e90df
...
...
@@ -82,7 +82,7 @@ extern "C" int PySys_SetObject(const char* name, PyObject* v) noexcept {
sys_module
->
delattr
(
name
,
NULL
);
}
else
sys_module
->
setattr
(
name
,
v
,
NULL
);
}
catch
(
Box
*
b
)
{
}
catch
(
ExcInfo
e
)
{
abort
();
}
return
0
;
...
...
src/runtime/builtin_modules/thread.cpp
View file @
c75e90df
...
...
@@ -31,8 +31,8 @@ static void* thread_start(Box* target, Box* varargs, Box* kwargs) {
try
{
runtimeCall
(
target
,
ArgPassSpec
(
0
,
0
,
true
,
kwargs
!=
NULL
),
varargs
,
kwargs
,
NULL
,
NULL
,
NULL
);
}
catch
(
Box
*
b
)
{
std
::
string
msg
=
formatException
(
b
);
}
catch
(
ExcInfo
e
)
{
std
::
string
msg
=
formatException
(
e
.
value
);
printLastTraceback
();
fprintf
(
stderr
,
"%s
\n
"
,
msg
.
c_str
());
}
...
...
src/runtime/capi.cpp
View file @
c75e90df
...
...
@@ -158,7 +158,7 @@ extern "C" PyObject* PyObject_CallObject(PyObject* obj, PyObject* args) noexcept
try
{
Box
*
r
=
runtimeCall
(
obj
,
ArgPassSpec
(
0
,
0
,
true
,
false
),
args
,
NULL
,
NULL
,
NULL
,
NULL
);
return
r
;
}
catch
(
Box
*
b
)
{
}
catch
(
ExcInfo
e
)
{
Py_FatalError
(
"unimplemented"
);
}
}
...
...
@@ -174,8 +174,8 @@ extern "C" PyObject* _PyObject_CallMethod_SizeT(PyObject* o, char* name, char* f
extern
"C"
Py_ssize_t
PyObject_Size
(
PyObject
*
o
)
noexcept
{
try
{
return
len
(
o
)
->
n
;
}
catch
(
Box
*
b
)
{
PyErr_SetObject
(
b
->
cls
,
b
);
}
catch
(
ExcInfo
e
)
{
setCAPIException
(
e
);
return
-
1
;
}
}
...
...
@@ -183,8 +183,8 @@ extern "C" Py_ssize_t PyObject_Size(PyObject* o) noexcept {
extern
"C"
PyObject
*
PyObject_GetIter
(
PyObject
*
o
)
noexcept
{
try
{
return
getiter
(
o
);
}
catch
(
Box
*
b
)
{
PyErr_SetObject
(
b
->
cls
,
b
);
}
catch
(
ExcInfo
e
)
{
setCAPIException
(
e
);
return
NULL
;
}
}
...
...
@@ -192,8 +192,8 @@ extern "C" PyObject* PyObject_GetIter(PyObject* o) noexcept {
extern
"C"
PyObject
*
PyObject_Repr
(
PyObject
*
obj
)
noexcept
{
try
{
return
repr
(
obj
);
}
catch
(
Box
*
b
)
{
PyErr_SetObject
(
b
->
cls
,
b
);
}
catch
(
ExcInfo
e
)
{
setCAPIException
(
e
);
return
NULL
;
}
}
...
...
@@ -352,7 +352,7 @@ extern "C" PyObject* PyObject_GetAttr(PyObject* o, PyObject* attr_name) noexcept
try
{
return
getattr
(
o
,
static_cast
<
BoxedString
*>
(
attr_name
)
->
s
.
c_str
());
}
catch
(
Box
*
b
)
{
}
catch
(
ExcInfo
e
)
{
Py_FatalError
(
"unimplemented"
);
}
}
...
...
@@ -364,8 +364,8 @@ extern "C" PyObject* PyObject_GenericGetAttr(PyObject* o, PyObject* name) noexce
extern
"C"
PyObject
*
PyObject_GetItem
(
PyObject
*
o
,
PyObject
*
key
)
noexcept
{
try
{
return
getitem
(
o
,
key
);
}
catch
(
Box
*
b
)
{
PyErr_SetObject
(
b
->
cls
,
b
);
}
catch
(
ExcInfo
e
)
{
setCAPIException
(
e
);
return
NULL
;
}
}
...
...
@@ -389,7 +389,7 @@ int _Py_SwappedOp[] = { Py_GT, Py_GE, Py_EQ, Py_NE, Py_LT, Py_LE };
extern
"C"
long
PyObject_Hash
(
PyObject
*
o
)
noexcept
{
try
{
return
hash
(
o
)
->
n
;
}
catch
(
Box
*
b
)
{
}
catch
(
ExcInfo
e
)
{
Py_FatalError
(
"unimplemented"
);
}
}
...
...
@@ -419,7 +419,7 @@ extern "C" long _Py_HashPointer(void* p) noexcept {
extern
"C"
int
PyObject_IsTrue
(
PyObject
*
o
)
noexcept
{
try
{
return
nonzero
(
o
);
}
catch
(
Box
*
b
)
{
}
catch
(
ExcInfo
e
)
{
Py_FatalError
(
"unimplemented"
);
}
}
...
...
@@ -459,7 +459,7 @@ extern "C" PyObject* PyObject_Call(PyObject* callable_object, PyObject* args, Py
return
runtimeCall
(
callable_object
,
ArgPassSpec
(
0
,
0
,
true
,
true
),
args
,
kw
,
NULL
,
NULL
,
NULL
);
else
return
runtimeCall
(
callable_object
,
ArgPassSpec
(
0
,
0
,
true
,
false
),
args
,
NULL
,
NULL
,
NULL
,
NULL
);
}
catch
(
Box
*
b
)
{
}
catch
(
ExcInfo
e
)
{
Py_FatalError
(
"unimplemented"
);
}
}
...
...
@@ -496,7 +496,7 @@ 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
(
Box
*
b
)
{
}
catch
(
ExcInfo
e
)
{
Py_FatalError
(
"unimplemented"
);
}
}
...
...
@@ -505,7 +505,7 @@ extern "C" PyObject* PySequence_GetSlice(PyObject* o, Py_ssize_t i1, Py_ssize_t
try
{
// Not sure if this is really the same:
return
getitem
(
o
,
new
BoxedSlice
(
boxInt
(
i1
),
boxInt
(
i2
),
None
));
}
catch
(
Box
*
b
)
{
}
catch
(
ExcInfo
e
)
{
Py_FatalError
(
"unimplemented"
);
}
}
...
...
@@ -551,8 +551,8 @@ extern "C" PyObject* PyIter_Next(PyObject* iter) noexcept {
try
{
return
callattr
(
iter
,
&
next_str
,
CallattrFlags
({.
cls_only
=
true
,
.
null_on_nonexistent
=
false
}),
ArgPassSpec
(
0
),
NULL
,
NULL
,
NULL
,
NULL
,
NULL
);
}
catch
(
Box
*
b
)
{
PyErr_SetObject
(
b
->
cls
,
b
);
}
catch
(
ExcInfo
e
)
{
setCAPIException
(
e
);
return
NULL
;
}
}
...
...
@@ -672,6 +672,12 @@ finally:
--
tstate
->
recursion_depth
;
}
void
setCAPIException
(
const
ExcInfo
&
e
)
{
cur_thread_state
.
curexc_type
=
e
.
type
;
cur_thread_state
.
curexc_value
=
e
.
value
;
cur_thread_state
.
curexc_traceback
=
e
.
traceback
;
}
void
checkAndThrowCAPIException
()
{
Box
*
_type
=
cur_thread_state
.
curexc_type
;
if
(
!
_type
)
...
...
@@ -859,7 +865,7 @@ extern "C" PyObject* PyImport_Import(PyObject* module_name) noexcept {
try
{
return
import
(
-
1
,
None
,
&
static_cast
<
BoxedString
*>
(
module_name
)
->
s
);
}
catch
(
Box
*
e
)
{
}
catch
(
ExcInfo
e
)
{
Py_FatalError
(
"unimplemented"
);
}
}
...
...
@@ -895,7 +901,7 @@ extern "C" int PyNumber_Check(PyObject* obj) noexcept {
extern
"C"
PyObject
*
PyNumber_Add
(
PyObject
*
lhs
,
PyObject
*
rhs
)
noexcept
{
try
{
return
binop
(
lhs
,
rhs
,
AST_TYPE
::
Add
);
}
catch
(
Box
*
b
)
{
}
catch
(
ExcInfo
e
)
{
Py_FatalError
(
"unimplemented"
);
}
}
...
...
@@ -903,7 +909,7 @@ extern "C" PyObject* PyNumber_Add(PyObject* lhs, PyObject* rhs) noexcept {
extern
"C"
PyObject
*
PyNumber_Subtract
(
PyObject
*
lhs
,
PyObject
*
rhs
)
noexcept
{
try
{
return
binop
(
lhs
,
rhs
,
AST_TYPE
::
Sub
);
}
catch
(
Box
*
b
)
{
}
catch
(
ExcInfo
e
)
{
Py_FatalError
(
"unimplemented"
);
}
}
...
...
@@ -911,7 +917,7 @@ extern "C" PyObject* PyNumber_Subtract(PyObject* lhs, PyObject* rhs) noexcept {
extern
"C"
PyObject
*
PyNumber_Multiply
(
PyObject
*
lhs
,
PyObject
*
rhs
)
noexcept
{
try
{
return
binop
(
lhs
,
rhs
,
AST_TYPE
::
Mult
);
}
catch
(
Box
*
b
)
{
}
catch
(
ExcInfo
e
)
{
Py_FatalError
(
"unimplemented"
);
}
}
...
...
@@ -919,7 +925,7 @@ extern "C" PyObject* PyNumber_Multiply(PyObject* lhs, PyObject* rhs) noexcept {
extern
"C"
PyObject
*
PyNumber_Divide
(
PyObject
*
lhs
,
PyObject
*
rhs
)
noexcept
{
try
{
return
binop
(
lhs
,
rhs
,
AST_TYPE
::
Div
);
}
catch
(
Box
*
b
)
{
}
catch
(
ExcInfo
e
)
{
Py_FatalError
(
"unimplemented"
);
}
}
...
...
@@ -935,7 +941,7 @@ extern "C" PyObject* PyNumber_TrueDivide(PyObject*, PyObject*) noexcept {
extern
"C"
PyObject
*
PyNumber_Remainder
(
PyObject
*
lhs
,
PyObject
*
rhs
)
noexcept
{
try
{
return
binop
(
lhs
,
rhs
,
AST_TYPE
::
Mod
);
}
catch
(
Box
*
b
)
{
}
catch
(
ExcInfo
e
)
{
Py_FatalError
(
"unimplemented"
);
}
}
...
...
@@ -959,7 +965,7 @@ extern "C" PyObject* PyNumber_Positive(PyObject* o) noexcept {
extern
"C"
PyObject
*
PyNumber_Absolute
(
PyObject
*
o
)
noexcept
{
try
{
return
abs_
(
o
);
}
catch
(
Box
*
b
)
{
}
catch
(
ExcInfo
e
)
{
Py_FatalError
(
"unimplemented"
);
}
}
...
...
@@ -975,7 +981,7 @@ extern "C" PyObject* PyNumber_Lshift(PyObject*, PyObject*) noexcept {
extern
"C"
PyObject
*
PyNumber_Rshift
(
PyObject
*
lhs
,
PyObject
*
rhs
)
noexcept
{
try
{
return
binop
(
lhs
,
rhs
,
AST_TYPE
::
RShift
);
}
catch
(
Box
*
b
)
{
}
catch
(
ExcInfo
e
)
{
Py_FatalError
(
"unimplemented"
);
}
}
...
...
@@ -983,7 +989,7 @@ extern "C" PyObject* PyNumber_Rshift(PyObject* lhs, PyObject* rhs) noexcept {
extern
"C"
PyObject
*
PyNumber_And
(
PyObject
*
lhs
,
PyObject
*
rhs
)
noexcept
{
try
{
return
binop
(
lhs
,
rhs
,
AST_TYPE
::
BitAnd
);
}
catch
(
Box
*
b
)
{
}
catch
(
ExcInfo
e
)
{
Py_FatalError
(
"unimplemented"
);
}
}
...
...
src/runtime/capi.h
View file @
c75e90df
...
...
@@ -23,6 +23,8 @@ class BoxedModule;
BoxedModule
*
importTestExtension
(
const
std
::
string
&
);
void
checkAndThrowCAPIException
();
struct
ExcInfo
;
void
setCAPIException
(
const
ExcInfo
&
e
);
}
#endif
src/runtime/classobj.cpp
View file @
c75e90df
...
...
@@ -224,17 +224,17 @@ Box* instanceNonzero(Box* _inst) {
Box
*
nonzero_func
=
NULL
;
try
{
nonzero_func
=
_instanceGetattribute
(
inst
,
boxStrConstant
(
"__nonzero__"
),
false
);
}
catch
(
Box
*
b
)
{
if
(
!
isInstance
(
b
,
AttributeError
))
throw
;
}
catch
(
ExcInfo
e
)
{
if
(
!
e
.
matches
(
AttributeError
))
throw
e
;
}
if
(
nonzero_func
==
NULL
)
{
try
{
nonzero_func
=
_instanceGetattribute
(
inst
,
boxStrConstant
(
"__len__"
),
false
);
}
catch
(
Box
*
b
)
{
if
(
!
isInstance
(
b
,
AttributeError
))
throw
;
}
catch
(
ExcInfo
e
)
{
if
(
!
e
.
matches
(
AttributeError
))
throw
e
;
}
}
...
...
src/runtime/dict.cpp
View file @
c75e90df
...
...
@@ -14,6 +14,7 @@
#include "runtime/dict.h"
#include "capi/types.h"
#include "core/common.h"
#include "core/stats.h"
#include "core/types.h"
...
...
@@ -136,8 +137,8 @@ extern "C" PyObject* PyDict_Copy(PyObject* o) noexcept {
RELEASE_ASSERT
(
PyDict_Check
(
o
),
""
);
try
{
return
dictCopy
(
static_cast
<
BoxedDict
*>
(
o
));
}
catch
(
Box
*
e
)
{
PyErr_SetObject
(
e
->
cls
,
e
);
}
catch
(
ExcInfo
e
)
{
setCAPIException
(
e
);
return
NULL
;
}
}
...
...
@@ -179,7 +180,7 @@ extern "C" int PyDict_SetItem(PyObject* mp, PyObject* _key, PyObject* _item) noe
try
{
// TODO should demote GIL?
setitem
(
b
,
key
,
item
);
}
catch
(
Box
*
b
)
{
}
catch
(
ExcInfo
e
)
{
abort
();
}
return
0
;
...
...
@@ -189,7 +190,7 @@ extern "C" int PyDict_SetItemString(PyObject* mp, const char* key, PyObject* ite
Box
*
key_s
;
try
{
key_s
=
boxStrConstant
(
key
);
}
catch
(
Box
*
b
)
{
}
catch
(
ExcInfo
e
)
{
abort
();
}
...
...
@@ -200,8 +201,8 @@ extern "C" PyObject* PyDict_GetItem(PyObject* dict, PyObject* key) noexcept {
ASSERT
(
dict
->
cls
==
dict_cls
||
dict
->
cls
==
attrwrapper_cls
,
"%s"
,
getTypeName
(
dict
)
->
c_str
());
try
{
return
getitem
(
dict
,
key
);
}
catch
(
Box
*
b
)
{
if
(
isSubclass
(
b
->
cls
,
KeyError
))
}
catch
(
ExcInfo
e
)
{
if
(
e
.
matches
(
KeyError
))
return
NULL
;
abort
();
}
...
...
@@ -215,7 +216,7 @@ extern "C" PyObject* PyDict_GetItemString(PyObject* dict, const char* key) noexc
Box
*
key_s
;
try
{
key_s
=
boxStrConstant
(
key
);
}
catch
(
Box
*
b
)
{
}
catch
(
ExcInfo
e
)
{
abort
();
}
return
PyDict_GetItem
(
dict
,
key_s
);
...
...
@@ -404,8 +405,8 @@ extern "C" int PyDict_Merge(PyObject* a, PyObject* b, int override_) noexcept {
try
{
dictMerge
(
static_cast
<
BoxedDict
*>
(
a
),
b
);
return
0
;
}
catch
(
Box
*
e
)
{
PyErr_SetObject
(
e
->
cls
,
e
);
}
catch
(
ExcInfo
e
)
{
setCAPIException
(
e
);
return
-
1
;
}
}
...
...
src/runtime/file.cpp
View file @
c75e90df
...
...
@@ -16,6 +16,7 @@
#include <cstring>
#include <sstream>
#include "capi/types.h"
#include "core/common.h"
#include "core/stats.h"
#include "core/types.h"
...
...
@@ -205,8 +206,8 @@ extern "C" int PyFile_WriteObject(PyObject* v, PyObject* f, int flags) noexcept
Box
*
r
=
fileWrite
(
static_cast
<
BoxedFile
*>
(
f
),
v
);
assert
(
r
==
None
);
return
0
;
}
catch
(
Box
*
b
)
{
PyErr_SetObject
(
b
->
cls
,
b
);
}
catch
(
ExcInfo
e
)
{
setCAPIException
(
e
);
return
-
1
;
}
}
...
...
@@ -271,7 +272,7 @@ extern "C" int PyObject_AsFileDescriptor(PyObject* o) noexcept {
extern
"C"
int
PyFile_SoftSpace
(
PyObject
*
f
,
int
newflag
)
noexcept
{
try
{
return
softspace
(
f
,
newflag
);
}
catch
(
Box
*
b
)
{
}
catch
(
ExcInfo
e
)
{
abort
();
}
}
...
...
src/runtime/generator.cpp
View file @
c75e90df
...
...
@@ -53,7 +53,7 @@ static void generatorEntry(BoxedGenerator* g) {
Box
**
args
=
g
->
args
?
&
g
->
args
->
elts
[
0
]
:
nullptr
;
callCLFunc
(
func
->
f
,
nullptr
,
func
->
f
->
numReceivedArgs
(),
func
->
closure
,
g
,
g
->
arg1
,
g
->
arg2
,
g
->
arg3
,
args
);
}
catch
(
Box
*
e
)
{
}
catch
(
ExcInfo
e
)
{
// unhandled exception: propagate the exception to the caller
g
->
exception
=
e
;
}
...
...
@@ -85,8 +85,8 @@ Box* generatorSend(Box* s, Box* v) {
self
->
running
=
false
;
// propagate exception to the caller
if
(
self
->
exception
)
raise
Exc
(
self
->
exception
);
if
(
self
->
exception
.
type
)
raise
Raw
(
self
->
exception
);
// throw StopIteration if the generator exited
if
(
self
->
entryExited
)
...
...
@@ -99,7 +99,8 @@ Box* generatorThrow(Box* s, BoxedClass* e) {
assert
(
s
->
cls
==
generator_cls
);
assert
(
isSubclass
(
e
,
Exception
));
BoxedGenerator
*
self
=
static_cast
<
BoxedGenerator
*>
(
s
);
self
->
exception
=
exceptionNew1
(
e
);
Box
*
ex
=
exceptionNew1
(
e
);
self
->
exception
=
ExcInfo
(
ex
->
cls
,
ex
,
NULL
);
return
generatorSend
(
self
,
None
);
}
...
...
@@ -128,10 +129,10 @@ extern "C" Box* yield(BoxedGenerator* obj, Box* value) {
threading
::
pushGenerator
(
obj
,
obj
->
stack_begin
,
(
void
*
)
obj
->
returnContext
.
uc_mcontext
.
gregs
[
REG_RSP
]);
// if the generator receives a exception from the caller we have to throw it
if
(
self
->
exception
)
{
Box
*
exception
=
self
->
exception
;
self
->
exception
=
nullptr
;
raise
Exc
(
exception
);
if
(
self
->
exception
.
type
)
{
ExcInfo
e
=
self
->
exception
;
self
->
exception
=
ExcInfo
(
NULL
,
NULL
,
NULL
)
;
raise
Raw
(
e
);
}
return
self
->
returnValue
;
}
...
...
@@ -146,7 +147,7 @@ extern "C" BoxedGenerator* createGenerator(BoxedFunction* function, Box* arg1, B
extern
"C"
BoxedGenerator
::
BoxedGenerator
(
BoxedFunction
*
function
,
Box
*
arg1
,
Box
*
arg2
,
Box
*
arg3
,
Box
**
args
)
:
function
(
function
),
arg1
(
arg1
),
arg2
(
arg2
),
arg3
(
arg3
),
args
(
nullptr
),
entryExited
(
false
),
running
(
false
),
returnValue
(
nullptr
),
exception
(
nullptr
)
{
returnValue
(
nullptr
),
exception
(
nullptr
,
nullptr
,
nullptr
)
{
giveAttr
(
"__name__"
,
boxString
(
function
->
f
->
source
->
getName
()));
...
...
@@ -214,8 +215,12 @@ extern "C" void generatorGCHandler(GCVisitor* v, Box* b) {
reinterpret_cast
<
void
*
const
*>
(
&
g
->
args
->
elts
[
num_args
-
3
]));
if
(
g
->
returnValue
)
v
->
visit
(
g
->
returnValue
);
if
(
g
->
exception
)
v
->
visit
(
g
->
exception
);
if
(
g
->
exception
.
type
)
v
->
visit
(
g
->
exception
.
type
);
if
(
g
->
exception
.
value
)
v
->
visit
(
g
->
exception
.
value
);
if
(
g
->
exception
.
traceback
)
v
->
visit
(
g
->
exception
.
traceback
);
if
(
g
->
running
)
{
v
->
visitPotentialRange
((
void
**
)
&
g
->
returnContext
,
...
...
src/runtime/iterobject.cpp
View file @
c75e90df
...
...
@@ -17,6 +17,7 @@
#include <cmath>
#include <sstream>
#include "capi/types.h"
#include "core/common.h"
#include "core/options.h"
#include "core/stats.h"
...
...
@@ -39,7 +40,7 @@ Box* seqiterHasnext(Box* s) {
Box
*
next
;
try
{
next
=
getitem
(
self
->
b
,
boxInt
(
self
->
idx
));
}
catch
(
Box
*
b
)
{
}
catch
(
ExcInfo
e
)
{
return
False
;
}
self
->
idx
++
;
...
...
@@ -75,12 +76,12 @@ Box* iterwrapperHasnext(Box* s) {
try
{
next
=
callattr
(
self
->
iter
,
&
next_str
,
CallattrFlags
({.
cls_only
=
true
,
.
null_on_nonexistent
=
false
}),
ArgPassSpec
(
0
),
NULL
,
NULL
,
NULL
,
NULL
,
NULL
);
}
catch
(
Box
*
b
)
{
if
(
isSubclass
(
b
->
cls
,
StopIteration
))
{
}
catch
(
ExcInfo
e
)
{
if
(
e
.
matches
(
StopIteration
))
{
self
->
next
=
NULL
;
return
False
;
}
throw
;
throw
e
;
}
self
->
next
=
next
;
return
True
;
...
...
@@ -99,8 +100,8 @@ Box* iterwrapperNext(Box* s) {
extern
"C"
PyObject
*
PySeqIter_New
(
PyObject
*
seq
)
noexcept
{
try
{
return
new
BoxedSeqIter
(
seq
);
}
catch
(
Box
*
e
)
{
PyErr_SetObject
(
e
->
cls
,
e
);
}
catch
(
ExcInfo
e
)
{
setCAPIException
(
e
);
return
NULL
;
}
}
...
...
src/runtime/list.cpp
View file @
c75e90df
...
...
@@ -18,6 +18,7 @@
#include <cstring>
#include <sstream>
#include "capi/types.h"
#include "core/ast.h"
#include "core/common.h"
#include "core/stats.h"
...
...
@@ -32,7 +33,7 @@ namespace pyston {
extern
"C"
int
PyList_Append
(
PyObject
*
op
,
PyObject
*
newitem
)
noexcept
{
try
{
listAppend
(
op
,
newitem
);
}
catch
(
Box
*
b
)
{
}
catch
(
ExcInfo
e
)
{
abort
();
}
return
0
;
...
...
@@ -149,7 +150,7 @@ extern "C" PyObject* PyList_GetItem(PyObject* op, Py_ssize_t i) noexcept {
RELEASE_ASSERT
(
i
>=
0
,
""
);
// unlike list.__getitem__, PyList_GetItem doesn't do index wrapping
try
{
return
listGetitemUnboxed
(
static_cast
<
BoxedList
*>
(
op
),
i
);
}
catch
(
Box
*
b
)
{
}
catch
(
ExcInfo
e
)
{
abort
();
}
}
...
...
@@ -539,7 +540,7 @@ extern "C" PyObject* PyList_New(Py_ssize_t size) noexcept {
RELEASE_ASSERT
(
size
==
0
,
""
);
try
{
return
new
BoxedList
();
}
catch
(
Box
*
b
)
{
}
catch
(
ExcInfo
e
)
{
abort
();
}
}
...
...
@@ -622,8 +623,8 @@ extern "C" PyObject* _PyList_Extend(PyListObject* self, PyObject* b) noexcept {
try
{
return
listIAdd
(
l
,
b
);
}
catch
(
Box
*
b
)
{
PyErr_SetObject
(
b
->
cls
,
b
);
}
catch
(
ExcInfo
e
)
{
setCAPIException
(
e
);
return
NULL
;
}
}
...
...
@@ -643,8 +644,8 @@ extern "C" int PyList_SetSlice(PyObject* a, Py_ssize_t ilow, Py_ssize_t ihigh, P
else
listDelitemSlice
(
l
,
new
BoxedSlice
(
boxInt
(
ilow
),
boxInt
(
ihigh
),
None
));
return
0
;
}
catch
(
Box
*
b
)
{
PyErr_SetObject
(
b
->
cls
,
b
);
}
catch
(
ExcInfo
e
)
{
setCAPIException
(
e
);
return
-
1
;
}
}
...
...
src/runtime/long.cpp
View file @
c75e90df
...
...
@@ -94,7 +94,7 @@ extern "C" unsigned long PyLong_AsUnsignedLong(PyObject* vv) noexcept {
try
{
return
asUnsignedLong
(
l
);
}
catch
(
Box
*
e
)
{
}
catch
(
ExcInfo
e
)
{
abort
();
}
}
...
...
src/runtime/objmodel.cpp
View file @
c75e90df
...
...
@@ -1748,7 +1748,7 @@ extern "C" BoxedString* reprOrNull(Box* obj) {
Box
*
r
=
repr
(
obj
);
assert
(
r
->
cls
==
str_cls
);
// this should be checked by repr()
return
static_cast
<
BoxedString
*>
(
r
);
}
catch
(
Box
*
b
)
{
}
catch
(
ExcInfo
e
)
{
return
nullptr
;
}
}
...
...
@@ -1757,7 +1757,7 @@ extern "C" BoxedString* strOrNull(Box* obj) {
try
{
BoxedString
*
r
=
str
(
obj
);
return
static_cast
<
BoxedString
*>
(
r
);
}
catch
(
Box
*
b
)
{
}
catch
(
ExcInfo
e
)
{
return
nullptr
;
}
}
...
...
@@ -3879,10 +3879,10 @@ extern "C" Box* importStar(Box* _from_module, BoxedModule* to_module) {
Box
*
attr_name
;
try
{
attr_name
=
runtimeCallInternal2
(
all_getitem
,
NULL
,
ArgPassSpec
(
2
),
all
,
boxInt
(
idx
));
}
catch
(
Box
*
b
)
{
if
(
b
->
cls
==
IndexError
)
}
catch
(
ExcInfo
e
)
{
if
(
e
.
matches
(
IndexError
)
)
break
;
throw
;
throw
e
;
}
idx
++
;
...
...
src/runtime/objmodel.h
View file @
c75e90df
...
...
@@ -34,6 +34,7 @@ class BoxedGenerator;
extern
"C"
void
raise0
()
__attribute__
((
__noreturn__
));
extern
"C"
void
raise3
(
Box
*
,
Box
*
,
Box
*
)
__attribute__
((
__noreturn__
));
void
raiseExc
(
Box
*
exc_obj
)
__attribute__
((
__noreturn__
));
void
raiseRaw
(
const
ExcInfo
&
e
)
__attribute__
((
__noreturn__
));
// helper function for raising from the runtime:
void
raiseExcHelper
(
BoxedClass
*
,
const
char
*
fmt
,
...)
__attribute__
((
__noreturn__
));
...
...
@@ -138,5 +139,7 @@ static const char* objectNewParameterTypeErrorMsg() {
return
"object.__new__() takes no parameters"
;
}
}
bool
exceptionMatches
(
const
ExcInfo
&
e
,
BoxedClass
*
cls
);
}
#endif
src/runtime/stacktrace.cpp
View file @
c75e90df
...
...
@@ -98,10 +98,10 @@ void unwindExc(Box* exc_obj) {
static
gc
::
GCRootHandle
last_exc
;
static
std
::
vector
<
const
LineInfo
*>
last_tb
;
void
raiseRaw
(
Box
*
exc_obj
)
__attribute__
((
__noreturn__
));
void
raiseRaw
(
Box
*
exc_obj
)
{
void
raiseRaw
(
const
ExcInfo
&
e
)
__attribute__
((
__noreturn__
));
void
raiseRaw
(
const
ExcInfo
&
e
)
{
// Using libgcc:
throw
e
xc_obj
;
throw
e
;
// Using libunwind
// unwindExc(exc_obj);
...
...
@@ -112,7 +112,7 @@ void raiseExc(Box* exc_obj) {
last_tb
=
std
::
move
(
entries
);
last_exc
=
exc_obj
;
raiseRaw
(
exc_obj
);
raiseRaw
(
ExcInfo
(
exc_obj
->
cls
,
exc_obj
,
NULL
)
);
}
// Have a special helper function for syntax errors, since we want to include the location
...
...
@@ -125,7 +125,7 @@ void raiseSyntaxError(const char* msg, int lineno, int col_offset, const std::st
// TODO: leaks this!
last_tb
.
push_back
(
new
LineInfo
(
lineno
,
col_offset
,
file
,
func
));
raiseRaw
(
last_exc
);
raiseRaw
(
ExcInfo
(
SyntaxError
,
last_exc
,
NULL
)
);
}
static
void
_printTraceback
(
const
std
::
vector
<
const
LineInfo
*>&
tb
)
{
...
...
@@ -216,7 +216,12 @@ extern "C" void exit(int code) {
}
void
raise0
()
{
raiseRaw
(
last_exc
);
raiseRaw
(
ExcInfo
(
last_exc
->
cls
,
last_exc
,
NULL
));
}
bool
ExcInfo
::
matches
(
BoxedClass
*
cls
)
const
{
RELEASE_ASSERT
(
isSubclass
(
this
->
type
->
cls
,
type_cls
),
"throwing old-style objects not supported yet"
);
return
isSubclass
(
static_cast
<
BoxedClass
*>
(
this
->
type
),
cls
);
}
void
raise3
(
Box
*
arg0
,
Box
*
arg1
,
Box
*
arg2
)
{
...
...
src/runtime/tuple.cpp
View file @
c75e90df
...
...
@@ -73,7 +73,7 @@ extern "C" PyObject* PyTuple_GetItem(PyObject* op, Py_ssize_t i) noexcept {
RELEASE_ASSERT
(
i
>=
0
,
""
);
// unlike tuple.__getitem__, PyTuple_GetItem doesn't do index wrapping
try
{
return
tupleGetitemUnboxed
(
static_cast
<
BoxedTuple
*>
(
op
),
i
);
}
catch
(
Box
*
b
)
{
}
catch
(
ExcInfo
e
)
{
abort
();
}
}
...
...
src/runtime/types.cpp
View file @
c75e90df
...
...
@@ -240,12 +240,12 @@ BoxIterator& BoxIterator::operator++() {
}
else
{
try
{
value
=
iter
->
nextIC
();
}
catch
(
Box
*
e
)
{
if
(
(
e
==
StopIteration
)
||
isSubclass
(
e
->
cls
,
StopIteration
))
{
}
catch
(
ExcInfo
e
)
{
if
(
e
.
matches
(
StopIteration
))
{
iter
=
nullptr
;
value
=
nullptr
;
}
else
throw
;
throw
e
;
}
}
return
*
this
;
...
...
@@ -531,12 +531,12 @@ extern "C" Box* createUserClass(std::string* name, Box* _bases, Box* _attr_dict)
Box
*
r
=
runtimeCall
(
metaclass
,
ArgPassSpec
(
3
),
boxStringPtr
(
name
),
_bases
,
_attr_dict
,
NULL
,
NULL
);
RELEASE_ASSERT
(
r
,
""
);
return
r
;
}
catch
(
Box
*
b
)
{
}
catch
(
ExcInfo
e
)
{
// TODO [CAPI] bad error handling...
RELEASE_ASSERT
(
isSubclass
(
b
->
cls
,
BaseException
),
""
);
RELEASE_ASSERT
(
e
.
matches
(
BaseException
),
""
);
Box
*
msg
=
b
->
getattr
(
"message"
);
Box
*
msg
=
e
.
value
->
getattr
(
"message"
);
RELEASE_ASSERT
(
msg
,
""
);
RELEASE_ASSERT
(
msg
->
cls
==
str_cls
,
""
);
...
...
@@ -545,7 +545,7 @@ extern "C" Box* createUserClass(std::string* name, Box* _bases, Box* _attr_dict)
" %s"
,
PyString_AS_STRING
(
msg
));
PyErr_Restore
(
b
->
cls
,
newmsg
,
NULL
);
PyErr_Restore
(
e
.
type
,
newmsg
,
NULL
);
checkAndThrowCAPIException
();
// Should not reach here
...
...
src/runtime/types.h
View file @
c75e90df
...
...
@@ -557,7 +557,7 @@ public:
bool
entryExited
;
bool
running
;
Box
*
returnValue
;
Box
*
exception
;
ExcInfo
exception
;
ucontext_t
context
,
returnContext
;
void
*
stack_begin
;
...
...
test/bench_exceptions.cpp
0 → 100644
View file @
c75e90df
#include <vector>
#include <cstdio>
#include "stdint.h"
struct
ExcInfo
{
int64_t
a
,
b
,
c
;
};
void
bench0
()
{
int64_t
t
=
0
;
for
(
int
i
=
0
;
i
<
1000000
;
i
++
)
{
try
{
throw
0
;
}
catch
(
int
x
)
{
}
}
printf
(
"%ld
\n
"
,
t
);
}
void
bench1
()
{
int64_t
t
=
1
;
for
(
int
i
=
0
;
i
<
1000000
;
i
++
)
{
try
{
throw
ExcInfo
({.
a
=
t
,
.
b
=
t
,
.
c
=
t
});
}
catch
(
ExcInfo
e
)
{
t
+=
e
.
a
+
e
.
b
+
e
.
c
;
}
}
printf
(
"b1 %ld
\n
"
,
t
);
}
static
__thread
ExcInfo
curexc
;
struct
ExceptionOccurred
{
};
void
bench2
()
{
int64_t
t
=
1
;
for
(
int
i
=
0
;
i
<
1000000
;
i
++
)
{
try
{
curexc
.
a
=
t
;
curexc
.
b
=
t
;
curexc
.
c
=
t
;
throw
ExceptionOccurred
();
}
catch
(
ExceptionOccurred
)
{
t
+=
curexc
.
a
+
curexc
.
b
+
curexc
.
c
;
}
}
printf
(
"b2 %ld
\n
"
,
t
);
}
void
rbench1
()
{
int64_t
t
=
1
;
for
(
int
i
=
0
;
i
<
1000000
;
i
++
)
{
try
{
try
{
throw
ExcInfo
({.
a
=
t
,
.
b
=
t
,
.
c
=
t
});
}
catch
(
ExcInfo
e
)
{
throw
e
;
}
}
catch
(
ExcInfo
e
)
{
t
+=
e
.
a
+
e
.
b
+
e
.
c
;
}
}
printf
(
"rb1 %ld
\n
"
,
t
);
}
void
rbench2
()
{
int64_t
t
=
1
;
for
(
int
i
=
0
;
i
<
1000000
;
i
++
)
{
try
{
try
{
curexc
.
a
=
t
;
curexc
.
b
=
t
;
curexc
.
c
=
t
;
throw
ExceptionOccurred
();
}
catch
(
ExceptionOccurred
x
)
{
throw
x
;
}
}
catch
(
ExceptionOccurred
)
{
t
+=
curexc
.
a
+
curexc
.
b
+
curexc
.
c
;
}
}
printf
(
"rb2 %ld
\n
"
,
t
);
}
int
main
()
{
bench1
();
}
test/tests/sys_excinfo.py
View file @
c75e90df
...
...
@@ -216,3 +216,33 @@ def f12():
print
"after next:"
,
sys
.
exc_info
()[
0
]
list
(
i
)
f12
()
# If an exception is thrown+caught in course of exception-matching, we need to still operate on the original exception:
def
f13
():
print
print
"f13"
def
inner
():
try
:
raise
KeyError
except
:
pass
print
sys
.
exc_info
()[
0
]
return
ZeroDivisionError
# This applies to what goes into exc_info:
try
:
1
/
0
except
inner
():
print
sys
.
exc_info
()[
0
]
# This also applies to the exception that will propagate:
try
:
try
:
raise
AttributeError
()
except
inner
():
print
"shouldn't get here!"
except
Exception
,
e
:
print
type
(
e
)
print
sys
.
exc_info
()[
0
]
f13
()
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