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
6be5e446
Commit
6be5e446
authored
Feb 26, 2016
by
Kevin Modzelewski
Browse files
Options
Browse Files
Download
Plain Diff
Merge commit '30d451' into refcounting
some merge conflicts, about to get to
parents
b8f207ee
30d4519f
Changes
22
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
354 additions
and
370 deletions
+354
-370
from_cpython/Include/pystate.h
from_cpython/Include/pystate.h
+2
-0
from_cpython/Lib/logging/__init__.py
from_cpython/Lib/logging/__init__.py
+12
-12
from_cpython/Lib/traceback.py
from_cpython/Lib/traceback.py
+0
-46
src/codegen/ast_interpreter.cpp
src/codegen/ast_interpreter.cpp
+30
-36
src/codegen/ast_interpreter.h
src/codegen/ast_interpreter.h
+0
-4
src/codegen/irgen/irgenerator.cpp
src/codegen/irgen/irgenerator.cpp
+21
-24
src/codegen/irgen/irgenerator.h
src/codegen/irgen/irgenerator.h
+1
-2
src/codegen/runtime_hooks.cpp
src/codegen/runtime_hooks.cpp
+2
-0
src/codegen/runtime_hooks.h
src/codegen/runtime_hooks.h
+1
-1
src/codegen/unwinding.cpp
src/codegen/unwinding.cpp
+87
-121
src/codegen/unwinding.h
src/codegen/unwinding.h
+1
-14
src/core/threading.cpp
src/core/threading.cpp
+1
-1
src/core/types.h
src/core/types.h
+7
-5
src/runtime/exceptions.cpp
src/runtime/exceptions.cpp
+2
-2
src/runtime/frame.cpp
src/runtime/frame.cpp
+86
-54
src/runtime/generator.cpp
src/runtime/generator.cpp
+30
-2
src/runtime/inline/link_forcer.cpp
src/runtime/inline/link_forcer.cpp
+2
-0
src/runtime/traceback.cpp
src/runtime/traceback.cpp
+12
-38
src/runtime/traceback.h
src/runtime/traceback.h
+11
-5
src/runtime/types.h
src/runtime/types.h
+5
-0
test/tests/generator_threads2.py
test/tests/generator_threads2.py
+31
-0
test/tests/sys_getframe_exited.py
test/tests/sys_getframe_exited.py
+10
-3
No files found.
from_cpython/Include/pystate.h
View file @
6be5e446
...
@@ -111,6 +111,8 @@ typedef struct _ts {
...
@@ -111,6 +111,8 @@ typedef struct _ts {
} PyThreadState;
} PyThreadState;
#endif
#endif
typedef
struct
_ts
{
typedef
struct
_ts
{
void
*
frame_info
;
// This points to top python FrameInfo object
int
recursion_depth
;
int
recursion_depth
;
int
gilstate_counter
;
int
gilstate_counter
;
...
...
from_cpython/Lib/logging/__init__.py
View file @
6be5e446
...
@@ -71,9 +71,15 @@ else:
...
@@ -71,9 +71,15 @@ else:
_srcfile
=
__file__
_srcfile
=
__file__
_srcfile
=
os
.
path
.
normcase
(
_srcfile
)
_srcfile
=
os
.
path
.
normcase
(
_srcfile
)
# pyston changes: we don't support tb_frame or f_back, so always use sys._getframe
# next bit filched from 1.5.2's inspect.py
currentframe
=
lambda
:
sys
.
_getframe
(
4
)
def
currentframe
():
start_getframe
=
4
"""Return the frame object for the caller's stack frame."""
try
:
raise
Exception
except
:
return
sys
.
exc_info
()[
2
].
tb_frame
.
f_back
if
hasattr
(
sys
,
'_getframe'
):
currentframe
=
lambda
:
sys
.
_getframe
(
3
)
# done filching
# done filching
# _srcfile is only used in conjunction with sys._getframe().
# _srcfile is only used in conjunction with sys._getframe().
...
@@ -1222,23 +1228,17 @@ class Logger(Filterer):
...
@@ -1222,23 +1228,17 @@ class Logger(Filterer):
Find the stack frame of the caller so that we can note the source
Find the stack frame of the caller so that we can note the source
file name, line number and function name.
file name, line number and function name.
"""
"""
f
=
currentframe
()
f
=
currentframe
()
# pyston change: we can't use f_back to walk back up the stack, so increment a counter of
# frames to skip and repeatedly call sys._getframe
fn
=
start_getframe
#On some versions of IronPython, currentframe() returns None if
#On some versions of IronPython, currentframe() returns None if
#IronPython isn't run with -X:Frames.
#IronPython isn't run with -X:Frames.
#
if f is not None:
if
f
is
not
None
:
#
f = f.f_back
f
=
f
.
f_back
rv
=
"(unknown file)"
,
0
,
"(unknown function)"
rv
=
"(unknown file)"
,
0
,
"(unknown function)"
while
hasattr
(
f
,
"f_code"
):
while
hasattr
(
f
,
"f_code"
):
co
=
f
.
f_code
co
=
f
.
f_code
filename
=
os
.
path
.
normcase
(
co
.
co_filename
)
filename
=
os
.
path
.
normcase
(
co
.
co_filename
)
if
filename
==
_srcfile
:
if
filename
==
_srcfile
:
fn
+=
1
f
=
f
.
f_back
f
=
sys
.
_getframe
(
fn
);
#f = f.f_back
continue
continue
rv
=
(
co
.
co_filename
,
f
.
f_lineno
,
co
.
co_name
)
rv
=
(
co
.
co_filename
,
f
.
f_lineno
,
co
.
co_name
)
break
break
...
...
from_cpython/Lib/traceback.py
View file @
6be5e446
"""Extract, format and print information about Python stack traces."""
"""Extract, format and print information about Python stack traces."""
# This module has been heavily modified for Pyston, since we don't provide the
# same traceback objects as CPython.
import
linecache
import
linecache
import
sys
import
sys
import
types
import
types
...
@@ -59,20 +56,7 @@ def print_tb(tb, limit=None, file=None):
...
@@ -59,20 +56,7 @@ def print_tb(tb, limit=None, file=None):
if
limit
is
None
:
if
limit
is
None
:
if
hasattr
(
sys
,
'tracebacklimit'
):
if
hasattr
(
sys
,
'tracebacklimit'
):
limit
=
sys
.
tracebacklimit
limit
=
sys
.
tracebacklimit
n
=
0
n
=
0
# Pyston change:
for
(
filename
,
name
,
lineno
)
in
tb
.
getLines
():
if
limit
and
n
>=
limit
:
break
_print
(
file
,
' File "%s", line %d, in %s'
%
(
filename
,
lineno
,
name
))
linecache
.
checkcache
(
filename
)
line
=
linecache
.
getline
(
filename
,
lineno
,
None
)
if
line
:
_print
(
file
,
' '
+
line
.
strip
())
n
=
n
+
1
"""
while
tb
is
not
None
and
(
limit
is
None
or
n
<
limit
):
while
tb
is
not
None
and
(
limit
is
None
or
n
<
limit
):
f
=
tb
.
tb_frame
f
=
tb
.
tb_frame
lineno
=
tb
.
tb_lineno
lineno
=
tb
.
tb_lineno
...
@@ -86,7 +70,6 @@ def print_tb(tb, limit=None, file=None):
...
@@ -86,7 +70,6 @@ def print_tb(tb, limit=None, file=None):
if
line
:
_print
(
file
,
' '
+
line
.
strip
())
if
line
:
_print
(
file
,
' '
+
line
.
strip
())
tb
=
tb
.
tb_next
tb
=
tb
.
tb_next
n
=
n
+
1
n
=
n
+
1
"""
def
format_tb
(
tb
,
limit
=
None
):
def
format_tb
(
tb
,
limit
=
None
):
"""A shorthand for 'format_list(extract_tb(tb, limit))'."""
"""A shorthand for 'format_list(extract_tb(tb, limit))'."""
...
@@ -108,18 +91,6 @@ def extract_tb(tb, limit = None):
...
@@ -108,18 +91,6 @@ def extract_tb(tb, limit = None):
limit
=
sys
.
tracebacklimit
limit
=
sys
.
tracebacklimit
list
=
[]
list
=
[]
n
=
0
n
=
0
# Pyston change:
for
(
filename
,
name
,
lineno
)
in
tb
.
getLines
():
if
limit
and
n
>=
limit
:
break
linecache
.
checkcache
(
filename
)
line
=
linecache
.
getline
(
filename
,
lineno
,
None
)
if
line
:
line
=
line
.
strip
()
else
:
line
=
None
list
.
append
((
filename
,
lineno
,
name
,
line
))
n
=
n
+
1
"""
while
tb
is
not
None
and
(
limit
is
None
or
n
<
limit
):
while
tb
is
not
None
and
(
limit
is
None
or
n
<
limit
):
f
=
tb
.
tb_frame
f
=
tb
.
tb_frame
lineno
=
tb
.
tb_lineno
lineno
=
tb
.
tb_lineno
...
@@ -133,7 +104,6 @@ def extract_tb(tb, limit = None):
...
@@ -133,7 +104,6 @@ def extract_tb(tb, limit = None):
list
.
append
((
filename
,
lineno
,
name
,
line
))
list
.
append
((
filename
,
lineno
,
name
,
line
))
tb
=
tb
.
tb_next
tb
=
tb
.
tb_next
n
=
n
+
1
n
=
n
+
1
"""
return
list
return
list
...
@@ -293,28 +263,19 @@ def print_stack(f=None, limit=None, file=None):
...
@@ -293,28 +263,19 @@ def print_stack(f=None, limit=None, file=None):
arguments have the same meaning as for print_exception().
arguments have the same meaning as for print_exception().
"""
"""
if
f
is
None
:
if
f
is
None
:
# Pyston change:
"""
try
:
try
:
raise
ZeroDivisionError
raise
ZeroDivisionError
except
ZeroDivisionError
:
except
ZeroDivisionError
:
f
=
sys
.
exc_info
()[
2
].
tb_frame
.
f_back
f
=
sys
.
exc_info
()[
2
].
tb_frame
.
f_back
"""
f
=
sys
.
_getframe
(
1
)
print_list
(
extract_stack
(
f
,
limit
),
file
)
print_list
(
extract_stack
(
f
,
limit
),
file
)
def
format_stack
(
f
=
None
,
limit
=
None
):
def
format_stack
(
f
=
None
,
limit
=
None
):
"""Shorthand for 'format_list(extract_stack(f, limit))'."""
"""Shorthand for 'format_list(extract_stack(f, limit))'."""
if
f
is
None
:
if
f
is
None
:
# Pyston change:
"""
try
:
try
:
raise
ZeroDivisionError
raise
ZeroDivisionError
except
ZeroDivisionError
:
except
ZeroDivisionError
:
f
=
sys
.
exc_info
()[
2
].
tb_frame
.
f_back
f
=
sys
.
exc_info
()[
2
].
tb_frame
.
f_back
"""
f
=
sys
.
_getframe
(
1
)
return
format_list
(
extract_stack
(
f
,
limit
))
return
format_list
(
extract_stack
(
f
,
limit
))
def
extract_stack
(
f
=
None
,
limit
=
None
):
def
extract_stack
(
f
=
None
,
limit
=
None
):
...
@@ -326,16 +287,11 @@ def extract_stack(f=None, limit = None):
...
@@ -326,16 +287,11 @@ def extract_stack(f=None, limit = None):
line number, function name, text), and the entries are in order
line number, function name, text), and the entries are in order
from oldest to newest stack frame.
from oldest to newest stack frame.
"""
"""
if
f
is
None
:
if
f
is
None
:
# Pyston change:
"""
try
:
try
:
raise
ZeroDivisionError
raise
ZeroDivisionError
except
ZeroDivisionError
:
except
ZeroDivisionError
:
f
=
sys
.
exc_info
()[
2
].
tb_frame
.
f_back
f
=
sys
.
exc_info
()[
2
].
tb_frame
.
f_back
"""
f
=
sys
.
_getframe
(
1
)
if
limit
is
None
:
if
limit
is
None
:
if
hasattr
(
sys
,
'tracebacklimit'
):
if
hasattr
(
sys
,
'tracebacklimit'
):
limit
=
sys
.
tracebacklimit
limit
=
sys
.
tracebacklimit
...
@@ -361,6 +317,4 @@ def tb_lineno(tb):
...
@@ -361,6 +317,4 @@ def tb_lineno(tb):
Obsolete in 2.3.
Obsolete in 2.3.
"""
"""
raise
NotImplementedError
(
"This function is currently not implemented in Pyston"
)
return
tb
.
tb_lineno
return
tb
.
tb_lineno
src/codegen/ast_interpreter.cpp
View file @
6be5e446
...
@@ -138,7 +138,6 @@ private:
...
@@ -138,7 +138,6 @@ private:
CFGBlock
*
next_block
,
*
current_block
;
CFGBlock
*
next_block
,
*
current_block
;
FrameInfo
frame_info
;
FrameInfo
frame_info
;
FunctionMetadata
*
md
;
SourceInfo
*
source_info
;
SourceInfo
*
source_info
;
ScopeInfo
*
scope_info
;
ScopeInfo
*
scope_info
;
PhiAnalysis
*
phis
;
PhiAnalysis
*
phis
;
...
@@ -156,7 +155,7 @@ public:
...
@@ -156,7 +155,7 @@ public:
~
ASTInterpreter
()
{
~
ASTInterpreter
()
{
Py_XDECREF
(
frame_info
.
boxedLocals
);
Py_XDECREF
(
frame_info
.
boxedLocals
);
int
nvregs
=
md
->
calculateNumVRegs
();
int
nvregs
=
getMD
()
->
calculateNumVRegs
();
for
(
int
i
=
0
;
i
<
nvregs
;
i
++
)
{
for
(
int
i
=
0
;
i
<
nvregs
;
i
++
)
{
Py_XDECREF
(
vregs
[
i
]);
Py_XDECREF
(
vregs
[
i
]);
...
@@ -184,7 +183,7 @@ public:
...
@@ -184,7 +183,7 @@ public:
return
incref
(
frame_info
.
globals
);
return
incref
(
frame_info
.
globals
);
}
}
FunctionMetadata
*
getMD
()
{
return
md
;
}
FunctionMetadata
*
getMD
()
{
return
frame_info
.
md
;
}
FrameInfo
*
getFrameInfo
()
{
return
&
frame_info
;
}
FrameInfo
*
getFrameInfo
()
{
return
&
frame_info
;
}
BoxedClosure
*
getPassedClosure
()
{
return
frame_info
.
passed_closure
;
}
BoxedClosure
*
getPassedClosure
()
{
return
frame_info
.
passed_closure
;
}
Box
**
getVRegs
()
{
return
vregs
;
}
Box
**
getVRegs
()
{
return
vregs
;
}
...
@@ -231,7 +230,9 @@ void ASTInterpreter::setBoxedLocals(Box* boxedLocals) {
...
@@ -231,7 +230,9 @@ void ASTInterpreter::setBoxedLocals(Box* boxedLocals) {
}
}
void
ASTInterpreter
::
setFrameInfo
(
const
FrameInfo
*
frame_info
)
{
void
ASTInterpreter
::
setFrameInfo
(
const
FrameInfo
*
frame_info
)
{
Box
**
vregs
=
this
->
frame_info
.
vregs
;
this
->
frame_info
=
*
frame_info
;
this
->
frame_info
=
*
frame_info
;
this
->
frame_info
.
vregs
=
vregs
;
}
}
void
ASTInterpreter
::
setGlobals
(
Box
*
globals
)
{
void
ASTInterpreter
::
setGlobals
(
Box
*
globals
)
{
...
@@ -243,7 +244,6 @@ void ASTInterpreter::setGlobals(Box* globals) {
...
@@ -243,7 +244,6 @@ void ASTInterpreter::setGlobals(Box* globals) {
ASTInterpreter
::
ASTInterpreter
(
FunctionMetadata
*
md
,
Box
**
vregs
)
ASTInterpreter
::
ASTInterpreter
(
FunctionMetadata
*
md
,
Box
**
vregs
)
:
current_block
(
0
),
:
current_block
(
0
),
frame_info
(
ExcInfo
(
NULL
,
NULL
,
NULL
)),
frame_info
(
ExcInfo
(
NULL
,
NULL
,
NULL
)),
md
(
md
),
source_info
(
md
->
source
.
get
()),
source_info
(
md
->
source
.
get
()),
scope_info
(
0
),
scope_info
(
0
),
phis
(
NULL
),
phis
(
NULL
),
...
@@ -257,6 +257,7 @@ ASTInterpreter::ASTInterpreter(FunctionMetadata* md, Box** vregs)
...
@@ -257,6 +257,7 @@ ASTInterpreter::ASTInterpreter(FunctionMetadata* md, Box** vregs)
scope_info
=
source_info
->
getScopeInfo
();
scope_info
=
source_info
->
getScopeInfo
();
frame_info
.
vregs
=
vregs
;
frame_info
.
vregs
=
vregs
;
frame_info
.
md
=
md
;
assert
(
scope_info
);
assert
(
scope_info
);
}
}
...
@@ -269,7 +270,7 @@ void ASTInterpreter::initArguments(BoxedClosure* _closure, BoxedGenerator* _gene
...
@@ -269,7 +270,7 @@ void ASTInterpreter::initArguments(BoxedClosure* _closure, BoxedGenerator* _gene
if
(
scope_info
->
createsClosure
())
if
(
scope_info
->
createsClosure
())
created_closure
=
createClosure
(
_closure
,
scope_info
->
getClosureSize
());
created_closure
=
createClosure
(
_closure
,
scope_info
->
getClosureSize
());
const
ParamNames
&
param_names
=
md
->
param_names
;
const
ParamNames
&
param_names
=
getMD
()
->
param_names
;
// make sure the AST_Name nodes are set
// make sure the AST_Name nodes are set
assert
(
param_names
.
args
.
size
()
==
param_names
.
arg_names
.
size
());
assert
(
param_names
.
args
.
size
()
==
param_names
.
arg_names
.
size
());
...
@@ -299,7 +300,7 @@ void ASTInterpreter::startJITing(CFGBlock* block, int exit_offset) {
...
@@ -299,7 +300,7 @@ void ASTInterpreter::startJITing(CFGBlock* block, int exit_offset) {
assert
(
ENABLE_BASELINEJIT
);
assert
(
ENABLE_BASELINEJIT
);
assert
(
!
jit
);
assert
(
!
jit
);
auto
&
code_blocks
=
md
->
code_blocks
;
auto
&
code_blocks
=
getMD
()
->
code_blocks
;
JitCodeBlock
*
code_block
=
NULL
;
JitCodeBlock
*
code_block
=
NULL
;
if
(
!
code_blocks
.
empty
())
if
(
!
code_blocks
.
empty
())
code_block
=
code_blocks
[
code_blocks
.
size
()
-
1
].
get
();
code_block
=
code_blocks
[
code_blocks
.
size
()
-
1
].
get
();
...
@@ -343,6 +344,8 @@ Box* ASTInterpreter::execJITedBlock(CFGBlock* b) {
...
@@ -343,6 +344,8 @@ Box* ASTInterpreter::execJITedBlock(CFGBlock* b) {
if
(
stmt
->
type
!=
AST_TYPE
::
Invoke
)
if
(
stmt
->
type
!=
AST_TYPE
::
Invoke
)
throw
e
;
throw
e
;
assert
(
getPythonFrameInfo
(
0
)
==
getFrameInfo
());
auto
source
=
getMD
()
->
source
.
get
();
auto
source
=
getMD
()
->
source
.
get
();
stmt
->
cxx_exception_count
++
;
stmt
->
cxx_exception_count
++
;
caughtCxxException
(
LineInfo
(
stmt
->
lineno
,
stmt
->
col_offset
,
source
->
getFn
(),
source
->
getName
()),
&
e
);
caughtCxxException
(
LineInfo
(
stmt
->
lineno
,
stmt
->
col_offset
,
source
->
getFn
(),
source
->
getName
()),
&
e
);
...
@@ -387,7 +390,7 @@ Box* ASTInterpreter::executeInner(ASTInterpreter& interpreter, CFGBlock* start_b
...
@@ -387,7 +390,7 @@ Box* ASTInterpreter::executeInner(ASTInterpreter& interpreter, CFGBlock* start_b
interpreter
.
next_block
=
start_block
;
interpreter
.
next_block
=
start_block
;
}
}
if
(
ENABLE_BASELINEJIT
&&
interpreter
.
md
->
times_interpreted
>=
REOPT_THRESHOLD_INTERPRETER
)
if
(
ENABLE_BASELINEJIT
&&
interpreter
.
getMD
()
->
times_interpreted
>=
REOPT_THRESHOLD_INTERPRETER
)
interpreter
.
should_jit
=
true
;
interpreter
.
should_jit
=
true
;
while
(
interpreter
.
next_block
)
{
while
(
interpreter
.
next_block
)
{
...
@@ -662,7 +665,8 @@ Value ASTInterpreter::visit_jump(AST_Jump* node) {
...
@@ -662,7 +665,8 @@ Value ASTInterpreter::visit_jump(AST_Jump* node) {
// we may have started JITing because the OSR thresholds got triggered in this case we don't want to jit
// we may have started JITing because the OSR thresholds got triggered in this case we don't want to jit
// additional blocks ouside of the loop if the function is cold.
// additional blocks ouside of the loop if the function is cold.
//if (md->times_interpreted < REOPT_THRESHOLD_INTERPRETER)
// XXX reenable this
//if (getMD()->times_interpreted < REOPT_THRESHOLD_INTERPRETER)
//should_jit = false;
//should_jit = false;
}
}
...
@@ -693,7 +697,8 @@ Box* ASTInterpreter::doOSR(AST_Jump* node) {
...
@@ -693,7 +697,8 @@ Box* ASTInterpreter::doOSR(AST_Jump* node) {
ast_osrs
.
log
();
ast_osrs
.
log
();
LivenessAnalysis
*
liveness
=
source_info
->
getLiveness
();
LivenessAnalysis
*
liveness
=
source_info
->
getLiveness
();
std
::
unique_ptr
<
PhiAnalysis
>
phis
=
computeRequiredPhis
(
md
->
param_names
,
source_info
->
cfg
,
liveness
,
scope_info
);
std
::
unique_ptr
<
PhiAnalysis
>
phis
=
computeRequiredPhis
(
getMD
()
->
param_names
,
source_info
->
cfg
,
liveness
,
scope_info
);
llvm
::
DenseMap
<
int
,
InternedString
>
offset_name_map
;
llvm
::
DenseMap
<
int
,
InternedString
>
offset_name_map
;
for
(
auto
&&
v
:
getSymVRegMap
())
{
for
(
auto
&&
v
:
getSymVRegMap
())
{
...
@@ -715,7 +720,7 @@ Box* ASTInterpreter::doOSR(AST_Jump* node) {
...
@@ -715,7 +720,7 @@ Box* ASTInterpreter::doOSR(AST_Jump* node) {
}
}
const
OSREntryDescriptor
*
found_entry
=
nullptr
;
const
OSREntryDescriptor
*
found_entry
=
nullptr
;
for
(
auto
&
p
:
md
->
osr_versions
)
{
for
(
auto
&
p
:
getMD
()
->
osr_versions
)
{
if
(
p
.
first
->
backedge
!=
node
)
if
(
p
.
first
->
backedge
!=
node
)
continue
;
continue
;
...
@@ -767,7 +772,7 @@ Box* ASTInterpreter::doOSR(AST_Jump* node) {
...
@@ -767,7 +772,7 @@ Box* ASTInterpreter::doOSR(AST_Jump* node) {
sorted_symbol_table
[
source_info
->
getInternedStrings
().
get
(
FRAME_INFO_PTR_NAME
)]
=
(
Box
*
)
&
frame_info
;
sorted_symbol_table
[
source_info
->
getInternedStrings
().
get
(
FRAME_INFO_PTR_NAME
)]
=
(
Box
*
)
&
frame_info
;
if
(
found_entry
==
nullptr
)
{
if
(
found_entry
==
nullptr
)
{
OSREntryDescriptor
*
entry
=
OSREntryDescriptor
::
create
(
md
,
node
,
CXX
);
OSREntryDescriptor
*
entry
=
OSREntryDescriptor
::
create
(
getMD
()
,
node
,
CXX
);
for
(
auto
&
it
:
sorted_symbol_table
)
{
for
(
auto
&
it
:
sorted_symbol_table
)
{
if
(
isIsDefinedName
(
it
.
first
))
if
(
isIsDefinedName
(
it
.
first
))
...
@@ -824,6 +829,8 @@ Value ASTInterpreter::visit_invoke(AST_Invoke* node) {
...
@@ -824,6 +829,8 @@ Value ASTInterpreter::visit_invoke(AST_Invoke* node) {
}
catch
(
ExcInfo
e
)
{
}
catch
(
ExcInfo
e
)
{
abortJITing
();
abortJITing
();
assert
(
getPythonFrameInfo
(
0
)
==
getFrameInfo
());
auto
source
=
getMD
()
->
source
.
get
();
auto
source
=
getMD
()
->
source
.
get
();
node
->
cxx_exception_count
++
;
node
->
cxx_exception_count
++
;
caughtCxxException
(
LineInfo
(
node
->
lineno
,
node
->
col_offset
,
source
->
getFn
(),
source
->
getName
()),
&
e
);
caughtCxxException
(
LineInfo
(
node
->
lineno
,
node
->
col_offset
,
source
->
getFn
(),
source
->
getName
()),
&
e
);
...
@@ -1773,7 +1780,10 @@ const void* interpreter_instr_addr = (void*)&executeInnerAndSetupFrame;
...
@@ -1773,7 +1780,10 @@ const void* interpreter_instr_addr = (void*)&executeInnerAndSetupFrame;
// small wrapper around executeInner because we can not directly call the member function from asm.
// small wrapper around executeInner because we can not directly call the member function from asm.
extern
"C"
Box
*
executeInnerFromASM
(
ASTInterpreter
&
interpreter
,
CFGBlock
*
start_block
,
AST_stmt
*
start_at
)
{
extern
"C"
Box
*
executeInnerFromASM
(
ASTInterpreter
&
interpreter
,
CFGBlock
*
start_block
,
AST_stmt
*
start_at
)
{
return
ASTInterpreter
::
executeInner
(
interpreter
,
start_block
,
start_at
);
initFrame
(
interpreter
.
getFrameInfo
());
Box
*
rtn
=
ASTInterpreter
::
executeInner
(
interpreter
,
start_block
,
start_at
);
deinitFrame
(
interpreter
.
getFrameInfo
());
return
rtn
;
}
}
Box
*
astInterpretFunction
(
FunctionMetadata
*
md
,
Box
*
closure
,
Box
*
generator
,
Box
*
globals
,
Box
*
arg1
,
Box
*
arg2
,
Box
*
astInterpretFunction
(
FunctionMetadata
*
md
,
Box
*
closure
,
Box
*
generator
,
Box
*
globals
,
Box
*
arg1
,
Box
*
arg2
,
...
@@ -1924,6 +1934,9 @@ static Box* astInterpretDeoptInner(FunctionMetadata* md, AST_expr* after_expr, A
...
@@ -1924,6 +1934,9 @@ static Box* astInterpretDeoptInner(FunctionMetadata* md, AST_expr* after_expr, A
SourceInfo
*
source_info
=
md
->
source
.
get
();
SourceInfo
*
source_info
=
md
->
source
.
get
();
// We can't reuse the existing vregs from the LLVM tier because they only contain the user visible ones this means
// there wouldn't be enough space for the compiler generated ones which the interpreter (+bjit) stores inside the
// vreg array.
Box
**
vregs
=
NULL
;
Box
**
vregs
=
NULL
;
int
num_vregs
=
md
->
calculateNumVRegs
();
int
num_vregs
=
md
->
calculateNumVRegs
();
if
(
num_vregs
>
0
)
{
if
(
num_vregs
>
0
)
{
...
@@ -2001,6 +2014,11 @@ static Box* astInterpretDeoptInner(FunctionMetadata* md, AST_expr* after_expr, A
...
@@ -2001,6 +2014,11 @@ static Box* astInterpretDeoptInner(FunctionMetadata* md, AST_expr* after_expr, A
assert
(
starting_statement
);
assert
(
starting_statement
);
}
}
// We need to remove the old python frame created in the LLVM tier otherwise we would have a duplicate frame because
// the interpreter will set the new state before executing the first statement.
RELEASE_ASSERT
(
cur_thread_state
.
frame_info
==
frame_state
.
frame_info
,
""
);
cur_thread_state
.
frame_info
=
frame_state
.
frame_info
->
back
;
Box
*
v
=
ASTInterpreter
::
execute
(
interpreter
,
start_block
,
starting_statement
);
Box
*
v
=
ASTInterpreter
::
execute
(
interpreter
,
start_block
,
starting_statement
);
return
v
?
v
:
None
;
return
v
?
v
:
None
;
}
}
...
@@ -2023,33 +2041,9 @@ static ASTInterpreter* getInterpreterFromFramePtr(void* frame_ptr) {
...
@@ -2023,33 +2041,9 @@ static ASTInterpreter* getInterpreterFromFramePtr(void* frame_ptr) {
return
*
ptr
;
return
*
ptr
;
}
}
FunctionMetadata
*
getMDForInterpretedFrame
(
void
*
frame_ptr
)
{
ASTInterpreter
*
interpreter
=
getInterpreterFromFramePtr
(
frame_ptr
);
assert
(
interpreter
);
return
interpreter
->
getMD
();
}
FrameInfo
*
getFrameInfoForInterpretedFrame
(
void
*
frame_ptr
)
{
FrameInfo
*
getFrameInfoForInterpretedFrame
(
void
*
frame_ptr
)
{
ASTInterpreter
*
interpreter
=
getInterpreterFromFramePtr
(
frame_ptr
);
ASTInterpreter
*
interpreter
=
getInterpreterFromFramePtr
(
frame_ptr
);
assert
(
interpreter
);
assert
(
interpreter
);
return
interpreter
->
getFrameInfo
();
return
interpreter
->
getFrameInfo
();
}
}
BoxedDict
*
localsForInterpretedFrame
(
Box
**
vregs
,
CFG
*
cfg
)
{
BoxedDict
*
rtn
=
new
BoxedDict
();
for
(
auto
&
l
:
cfg
->
sym_vreg_map_user_visible
)
{
Box
*
val
=
vregs
[
l
.
second
];
if
(
val
)
{
rtn
->
d
[
l
.
first
.
getBox
()]
=
val
;
}
}
return
rtn
;
}
BoxedDict
*
localsForInterpretedFrame
(
void
*
frame_ptr
)
{
ASTInterpreter
*
interpreter
=
getInterpreterFromFramePtr
(
frame_ptr
);
assert
(
interpreter
);
return
localsForInterpretedFrame
(
interpreter
->
getVRegs
(),
interpreter
->
getMD
()
->
source
->
cfg
);
}
}
}
src/codegen/ast_interpreter.h
View file @
6be5e446
...
@@ -76,13 +76,9 @@ Box* astInterpretFunctionEval(FunctionMetadata* cf, Box* globals, Box* boxedLoca
...
@@ -76,13 +76,9 @@ Box* astInterpretFunctionEval(FunctionMetadata* cf, Box* globals, Box* boxedLoca
Box
*
astInterpretDeopt
(
FunctionMetadata
*
cf
,
AST_expr
*
after_expr
,
AST_stmt
*
enclosing_stmt
,
Box
*
expr_val
,
Box
*
astInterpretDeopt
(
FunctionMetadata
*
cf
,
AST_expr
*
after_expr
,
AST_stmt
*
enclosing_stmt
,
Box
*
expr_val
,
FrameStackState
frame_state
);
FrameStackState
frame_state
);
FunctionMetadata
*
getMDForInterpretedFrame
(
void
*
frame_ptr
);
struct
FrameInfo
;
struct
FrameInfo
;
FrameInfo
*
getFrameInfoForInterpretedFrame
(
void
*
frame_ptr
);
FrameInfo
*
getFrameInfoForInterpretedFrame
(
void
*
frame_ptr
);
BoxedDict
*
localsForInterpretedFrame
(
Box
**
vregs
,
CFG
*
cfg
);
BoxedDict
*
localsForInterpretedFrame
(
void
*
frame_ptr
);
// Executes the equivalent of CPython's PRINT_EXPR opcode (call sys.displayhook)
// Executes the equivalent of CPython's PRINT_EXPR opcode (call sys.displayhook)
extern
"C"
void
printExprHelper
(
Box
*
b
);
extern
"C"
void
printExprHelper
(
Box
*
b
);
}
}
...
...
src/codegen/irgen/irgenerator.cpp
View file @
6be5e446
...
@@ -175,6 +175,11 @@ template <typename Builder> static llvm::Value* getGlobalsGep(Builder& builder,
...
@@ -175,6 +175,11 @@ template <typename Builder> static llvm::Value* getGlobalsGep(Builder& builder,
return
builder
.
CreateConstInBoundsGEP2_32
(
v
,
0
,
6
);
return
builder
.
CreateConstInBoundsGEP2_32
(
v
,
0
,
6
);
}
}
template
<
typename
Builder
>
static
llvm
::
Value
*
getMDGep
(
Builder
&
builder
,
llvm
::
Value
*
v
)
{
static_assert
(
offsetof
(
FrameInfo
,
md
)
==
64
+
16
,
""
);
return
builder
.
CreateConstInBoundsGEP2_32
(
v
,
0
,
8
);
}
void
IRGenState
::
setupFrameInfoVar
(
llvm
::
Value
*
passed_closure
,
llvm
::
Value
*
passed_globals
,
void
IRGenState
::
setupFrameInfoVar
(
llvm
::
Value
*
passed_closure
,
llvm
::
Value
*
passed_globals
,
llvm
::
Value
*
frame_info_arg
)
{
llvm
::
Value
*
frame_info_arg
)
{
/*
/*
...
@@ -279,9 +284,12 @@ void IRGenState::setupFrameInfoVar(llvm::Value* passed_closure, llvm::Value* pas
...
@@ -279,9 +284,12 @@ void IRGenState::setupFrameInfoVar(llvm::Value* passed_closure, llvm::Value* pas
builder
.
CreateStore
(
passed_globals
,
getGlobalsGep
(
builder
,
al
));
builder
.
CreateStore
(
passed_globals
,
getGlobalsGep
(
builder
,
al
));
// set frame_info.vregs
// set frame_info.vregs
builder
.
CreateStore
(
vregs
,
getVRegsGep
(
builder
,
al
));
builder
.
CreateStore
(
vregs
,
getVRegsGep
(
builder
,
al
));
builder
.
CreateStore
(
embedRelocatablePtr
(
getMD
(),
g
.
llvm_functionmetadata_type_ptr
),
getMDGep
(
builder
,
al
));
this
->
frame_info
=
al
;
this
->
frame_info
=
al
;
this
->
globals
=
passed_globals
;
this
->
globals
=
passed_globals
;
builder
.
CreateCall
(
g
.
funcs
.
initFrame
,
this
->
frame_info
);
}
}
stmt
=
getStmtGep
(
builder
,
frame_info
);
stmt
=
getStmtGep
(
builder
,
frame_info
);
...
@@ -350,6 +358,10 @@ private:
...
@@ -350,6 +358,10 @@ private:
llvm
::
CallSite
emitCall
(
const
UnwindInfo
&
unw_info
,
llvm
::
Value
*
callee
,
const
std
::
vector
<
llvm
::
Value
*>&
args
,
llvm
::
CallSite
emitCall
(
const
UnwindInfo
&
unw_info
,
llvm
::
Value
*
callee
,
const
std
::
vector
<
llvm
::
Value
*>&
args
,
ExceptionStyle
target_exception_style
)
{
ExceptionStyle
target_exception_style
)
{
llvm
::
Value
*
stmt
=
unw_info
.
current_stmt
?
embedRelocatablePtr
(
unw_info
.
current_stmt
,
g
.
llvm_aststmt_type_ptr
)
:
getNullPtr
(
g
.
llvm_aststmt_type_ptr
);
getBuilder
()
->
CreateStore
(
stmt
,
irstate
->
getStmtVar
());
bool
needs_cxx_interception
;
bool
needs_cxx_interception
;
if
(
unw_info
.
exc_dest
==
NO_CXX_INTERCEPTION
)
{
if
(
unw_info
.
exc_dest
==
NO_CXX_INTERCEPTION
)
{
needs_cxx_interception
=
false
;
needs_cxx_interception
=
false
;
...
@@ -430,7 +442,7 @@ private:
...
@@ -430,7 +442,7 @@ private:
pp_args
.
insert
(
pp_args
.
end
(),
ic_stackmap_args
.
begin
(),
ic_stackmap_args
.
end
());
pp_args
.
insert
(
pp_args
.
end
(),
ic_stackmap_args
.
begin
(),
ic_stackmap_args
.
end
());
irgenerator
->
addFrameStackmapArgs
(
info
,
unw_info
.
current_stmt
,
pp_args
);
irgenerator
->
addFrameStackmapArgs
(
info
,
pp_args
);
llvm
::
Intrinsic
::
ID
intrinsic_id
;
llvm
::
Intrinsic
::
ID
intrinsic_id
;
if
(
return_type
->
isIntegerTy
()
||
return_type
->
isPointerTy
())
{
if
(
return_type
->
isIntegerTy
()
||
return_type
->
isPointerTy
())
{
...
@@ -444,7 +456,6 @@ private:
...
@@ -444,7 +456,6 @@ private:
abort
();
abort
();
}
}
llvm
::
Function
*
patchpoint
=
this
->
getIntrinsic
(
intrinsic_id
);
llvm
::
Function
*
patchpoint
=
this
->
getIntrinsic
(
intrinsic_id
);
llvm
::
CallSite
rtn
=
this
->
emitCall
(
unw_info
,
patchpoint
,
pp_args
,
target_exception_style
);
llvm
::
CallSite
rtn
=
this
->
emitCall
(
unw_info
,
patchpoint
,
pp_args
,
target_exception_style
);
return
rtn
;
return
rtn
;
}
}
...
@@ -503,10 +514,6 @@ public:
...
@@ -503,10 +514,6 @@ public:
}
}
}
}
#endif
#endif
llvm
::
Value
*
stmt
=
unw_info
.
current_stmt
?
embedRelocatablePtr
(
unw_info
.
current_stmt
,
g
.
llvm_aststmt_type_ptr
)
:
getNullPtr
(
g
.
llvm_aststmt_type_ptr
);
getBuilder
()
->
CreateStore
(
stmt
,
irstate
->
getStmtVar
());
return
emitCall
(
unw_info
,
callee
,
args
,
target_exception_style
).
getInstruction
();
return
emitCall
(
unw_info
,
callee
,
args
,
target_exception_style
).
getInstruction
();
}
}
...
@@ -2098,6 +2105,9 @@ private:
...
@@ -2098,6 +2105,9 @@ private:
ConcreteCompilerVariable
*
rtn
=
val
->
makeConverted
(
emitter
,
opt_rtn_type
);
ConcreteCompilerVariable
*
rtn
=
val
->
makeConverted
(
emitter
,
opt_rtn_type
);
if
(
!
irstate
->
getCurFunction
()
->
entry_descriptor
)
emitter
.
createCall
(
unw_info
,
g
.
funcs
.
deinitFrame
,
irstate
->
getFrameInfoVar
());
assert
(
rtn
->
getValue
());
assert
(
rtn
->
getValue
());
auto
ret_inst
=
emitter
.
getBuilder
()
->
CreateRet
(
rtn
->
getValue
());
auto
ret_inst
=
emitter
.
getBuilder
()
->
CreateRet
(
rtn
->
getValue
());
...
@@ -2546,24 +2556,9 @@ private:
...
@@ -2546,24 +2556,9 @@ private:
}
}
public:
public:
void
addFrameStackmapArgs
(
PatchpointInfo
*
pp
,
AST_stmt
*
current_stmt
,
void
addFrameStackmapArgs
(
PatchpointInfo
*
pp
,
std
::
vector
<
llvm
::
Value
*>&
stackmap_args
)
override
{
std
::
vector
<
llvm
::
Value
*>&
stackmap_args
)
override
{
int
initial_args
=
stackmap_args
.
size
();
int
initial_args
=
stackmap_args
.
size
();
assert
(
UNBOXED_INT
->
llvmType
()
==
g
.
i64
);
if
(
ENABLE_JIT_OBJECT_CACHE
)
{
llvm
::
Value
*
v
;
if
(
current_stmt
)
v
=
emitter
.
getBuilder
()
->
CreatePtrToInt
(
embedRelocatablePtr
(
current_stmt
,
g
.
i8_ptr
),
g
.
i64
);
else
v
=
getConstantInt
(
0
,
g
.
i64
);
stackmap_args
.
push_back
(
v
);
}
else
{
stackmap_args
.
push_back
(
getConstantInt
((
uint64_t
)
current_stmt
,
g
.
i64
));
}
pp
->
addFrameVar
(
"!current_stmt"
,
UNBOXED_INT
);
// For deopts we need to add the compiler created names to the stackmap
// For deopts we need to add the compiler created names to the stackmap
if
(
ENABLE_FRAME_INTROSPECTION
&&
pp
->
isDeopt
())
{
if
(
ENABLE_FRAME_INTROSPECTION
&&
pp
->
isDeopt
())
{
// TODO: don't need to use a sorted symbol table if we're explicitly recording the names!
// TODO: don't need to use a sorted symbol table if we're explicitly recording the names!
...
@@ -2867,8 +2862,9 @@ public:
...
@@ -2867,8 +2862,9 @@ public:
emitter
.
setCurrentBasicBlock
(
capi_exc_dest
);
emitter
.
setCurrentBasicBlock
(
capi_exc_dest
);
assert
(
!
phi_node
);
assert
(
!
phi_node
);
phi_node
=
emitter
.
getBuilder
()
->
CreatePHI
(
g
.
llvm_aststmt_type_ptr
,
0
);
phi_node
=
emitter
.
getBuilder
()
->
CreatePHI
(
g
.
llvm_aststmt_type_ptr
,
0
);
emitter
.
getBuilder
()
->
CreateCall2
(
g
.
funcs
.
caughtCapiException
,
phi_node
,
embedRelocatablePtr
(
irstate
->
getSourceInfo
(),
g
.
i8_ptr
));
emitter
.
createCall
(
UnwindInfo
(
current_stmt
,
NULL
),
g
.
funcs
.
caughtCapiException
,
{
phi_node
,
embedRelocatablePtr
(
irstate
->
getSourceInfo
(),
g
.
i8_ptr
)
});
if
(
!
final_dest
)
{
if
(
!
final_dest
)
{
// Propagate the exception out of the function:
// Propagate the exception out of the function:
...
@@ -2876,6 +2872,7 @@ public:
...
@@ -2876,6 +2872,7 @@ public:
emitter
.
getBuilder
()
->
CreateCall
(
g
.
funcs
.
reraiseCapiExcAsCxx
);
emitter
.
getBuilder
()
->
CreateCall
(
g
.
funcs
.
reraiseCapiExcAsCxx
);
emitter
.
getBuilder
()
->
CreateUnreachable
();
emitter
.
getBuilder
()
->
CreateUnreachable
();
}
else
{
}
else
{
emitter
.
createCall
(
UnwindInfo
(
current_stmt
,
NULL
),
g
.
funcs
.
deinitFrame
,
irstate
->
getFrameInfoVar
());
emitter
.
getBuilder
()
->
CreateRet
(
getNullPtr
(
g
.
llvm_value_type_ptr
));
emitter
.
getBuilder
()
->
CreateRet
(
getNullPtr
(
g
.
llvm_value_type_ptr
));
}
}
}
else
{
}
else
{
...
...
src/codegen/irgen/irgenerator.h
View file @
6be5e446
...
@@ -163,8 +163,7 @@ public:
...
@@ -163,8 +163,7 @@ public:
virtual
void
run
(
const
CFGBlock
*
block
)
=
0
;
// primary entry point
virtual
void
run
(
const
CFGBlock
*
block
)
=
0
;
// primary entry point
virtual
EndingState
getEndingSymbolTable
()
=
0
;
virtual
EndingState
getEndingSymbolTable
()
=
0
;
virtual
void
doSafePoint
(
AST_stmt
*
next_statement
)
=
0
;
virtual
void
doSafePoint
(
AST_stmt
*
next_statement
)
=
0
;
virtual
void
addFrameStackmapArgs
(
PatchpointInfo
*
pp
,
AST_stmt
*
current_stmt
,
virtual
void
addFrameStackmapArgs
(
PatchpointInfo
*
pp
,
std
::
vector
<
llvm
::
Value
*>&
stackmap_args
)
=
0
;
std
::
vector
<
llvm
::
Value
*>&
stackmap_args
)
=
0
;
virtual
void
addOutgoingExceptionState
(
ExceptionState
exception_state
)
=
0
;
virtual
void
addOutgoingExceptionState
(
ExceptionState
exception_state
)
=
0
;
virtual
void
setIncomingExceptionState
(
llvm
::
SmallVector
<
ExceptionState
,
2
>
exc_state
)
=
0
;
virtual
void
setIncomingExceptionState
(
llvm
::
SmallVector
<
ExceptionState
,
2
>
exc_state
)
=
0
;
virtual
llvm
::
BasicBlock
*
getCXXExcDest
(
const
UnwindInfo
&
)
=
0
;
virtual
llvm
::
BasicBlock
*
getCXXExcDest
(
const
UnwindInfo
&
)
=
0
;
...
...
src/codegen/runtime_hooks.cpp
View file @
6be5e446
...
@@ -198,6 +198,8 @@ void initGlobalFuncs(GlobalState& g) {
...
@@ -198,6 +198,8 @@ void initGlobalFuncs(GlobalState& g) {
GET
(
createClosure
);
GET
(
createClosure
);
GET
(
createGenerator
);
GET
(
createGenerator
);
GET
(
createSet
);
GET
(
createSet
);
GET
(
initFrame
);
GET
(
deinitFrame
);
GET
(
getattr
);
GET
(
getattr
);
GET
(
getattr_capi
);
GET
(
getattr_capi
);
...
...
src/codegen/runtime_hooks.h
View file @
6be5e446
...
@@ -34,7 +34,7 @@ struct GlobalFuncs {
...
@@ -34,7 +34,7 @@ struct GlobalFuncs {
llvm
::
Value
*
boxInt
,
*
unboxInt
,
*
boxFloat
,
*
unboxFloat
,
*
createFunctionFromMetadata
,
*
getFunctionMetadata
,
llvm
::
Value
*
boxInt
,
*
unboxInt
,
*
boxFloat
,
*
unboxFloat
,
*
createFunctionFromMetadata
,
*
getFunctionMetadata
,
*
boxInstanceMethod
,
*
boxBool
,
*
unboxBool
,
*
createTuple
,
*
createDict
,
*
createList
,
*
createSlice
,
*
boxInstanceMethod
,
*
boxBool
,
*
unboxBool
,
*
createTuple
,
*
createDict
,
*
createList
,
*
createSlice
,
*
createUserClass
,
*
createClosure
,
*
createGenerator
,
*
createSet
;
*
createUserClass
,
*
createClosure
,
*
createGenerator
,
*
createSet
,
*
initFrame
,
*
deinitFrame
;
llvm
::
Value
*
getattr
,
*
getattr_capi
,
*
setattr
,
*
delattr
,
*
delitem
,
*
delGlobal
,
*
nonzero
,
*
binop
,
*
compare
,
llvm
::
Value
*
getattr
,
*
getattr_capi
,
*
setattr
,
*
delattr
,
*
delitem
,
*
delGlobal
,
*
nonzero
,
*
binop
,
*
compare
,
*
augbinop
,
*
unboxedLen
,
*
getitem
,
*
getitem_capi
,
*
getclsattr
,
*
getGlobal
,
*
setitem
,
*
unaryop
,
*
import
,
*
augbinop
,
*
unboxedLen
,
*
getitem
,
*
getitem_capi
,
*
getclsattr
,
*
getGlobal
,
*
setitem
,
*
unaryop
,
*
import
,
*
importFrom
,
*
importStar
,
*
repr
,
*
exceptionMatches
,
*
yield
,
*
getiterHelper
,
*
hasnext
,
*
setGlobal
,
*
apply_slice
;
*
importFrom
,
*
importStar
,
*
repr
,
*
exceptionMatches
,
*
yield
,
*
getiterHelper
,
*
hasnext
,
*
setGlobal
,
*
apply_slice
;
...
...
src/codegen/unwinding.cpp
View file @
6be5e446
This diff is collapsed.
Click to expand it.
src/codegen/unwinding.h
View file @
6be5e446
...
@@ -80,28 +80,15 @@ public:
...
@@ -80,28 +80,15 @@ public:
FrameInfo
*
getFrameInfo
();
FrameInfo
*
getFrameInfo
();
bool
exists
()
{
return
impl
.
get
()
!=
NULL
;
}
bool
exists
()
{
return
impl
.
get
()
!=
NULL
;
}
AST_stmt
*
getCurrentStatement
();
AST_stmt
*
getCurrentStatement
();
Box
*
fastLocalsToBoxedLocals
();
Box
*
getGlobalsDict
();
Box
*
getGlobalsDict
();
// Gets the "current version" of this frame: if the frame has executed since
// the iterator was obtained, the methods may return old values. This returns
// an updated copy that returns the updated values.
// The "current version" will live at the same stack location, but any other
// similarities need to be verified by the caller, ie it is up to the caller
// to determine that we didn't leave and reenter the stack frame.
// This function can only be called from the thread that created this object.
PythonFrameIterator
getCurrentVersion
();
// Assuming this is a valid frame iterator, return the next frame back (ie older).
PythonFrameIterator
back
();
PythonFrameIterator
(
PythonFrameIterator
&&
rhs
);
PythonFrameIterator
(
PythonFrameIterator
&&
rhs
);
void
operator
=
(
PythonFrameIterator
&&
rhs
);
void
operator
=
(
PythonFrameIterator
&&
rhs
);
PythonFrameIterator
(
std
::
unique_ptr
<
PythonFrameIteratorImpl
>
impl
);
PythonFrameIterator
(
std
::
unique_ptr
<
PythonFrameIteratorImpl
>
impl
);
~
PythonFrameIterator
();
~
PythonFrameIterator
();
};
};
PythonFrameIterator
getPythonFrame
(
int
depth
);
FrameInfo
*
getPythonFrameInfo
(
int
depth
);
// Fetches a writeable pointer to the frame-local excinfo object,
// Fetches a writeable pointer to the frame-local excinfo object,
// calculating it if necessary (from previous frames).
// calculating it if necessary (from previous frames).
...
...
src/core/threading.cpp
View file @
6be5e446
...
@@ -39,7 +39,7 @@ std::unordered_set<PerThreadSetBase*> PerThreadSetBase::all_instances;
...
@@ -39,7 +39,7 @@ std::unordered_set<PerThreadSetBase*> PerThreadSetBase::all_instances;
extern
"C"
{
extern
"C"
{
__thread
PyThreadState
cur_thread_state
__thread
PyThreadState
cur_thread_state
=
{
0
,
1
,
NULL
,
NULL
,
NULL
,
NULL
,
0
,
NULL
};
// not sure if we need to explicitly request zero-initialization
=
{
NULL
,
0
,
1
,
NULL
,
NULL
,
NULL
,
NULL
,
0
,
NULL
};
// not sure if we need to explicitly request zero-initialization
}
}
PthreadFastMutex
threading_lock
;
PthreadFastMutex
threading_lock
;
...
...
src/core/types.h
View file @
6be5e446
...
@@ -947,14 +947,16 @@ struct FrameInfo {
...
@@ -947,14 +947,16 @@ struct FrameInfo {
BoxedClosure
*
passed_closure
;
BoxedClosure
*
passed_closure
;
Box
**
vregs
;
Box
**
vregs
;
// Current statement
AST_stmt
*
stmt
;
// current statement
// Caution the llvm tier only updates this information on direct external calls but not for patchpoints.
// This means if a patchpoint "current_stmt" info is available it must be used instead of this field.
AST_stmt
*
stmt
;
// This is either a module or a dict
// This is either a module or a dict
Box
*
globals
;
Box
*
globals
;
FrameInfo
(
ExcInfo
exc
)
:
exc
(
exc
),
boxedLocals
(
NULL
),
frame_obj
(
0
),
passed_closure
(
0
),
vregs
(
0
),
stmt
(
0
),
globals
(
0
)
{}
FrameInfo
*
back
;
FunctionMetadata
*
md
;
Box
*
updateBoxedLocals
();
FrameInfo
(
ExcInfo
exc
)
:
exc
(
exc
),
boxedLocals
(
NULL
),
frame_obj
(
0
),
passed_closure
(
0
),
vregs
(
0
),
stmt
(
0
),
globals
(
0
),
back
(
0
),
md
(
0
)
{}
};
};
// callattr() takes a number of flags and arguments, and for performance we pack them into a single register:
// callattr() takes a number of flags and arguments, and for performance we pack them into a single register:
...
...
src/runtime/exceptions.cpp
View file @
6be5e446
...
@@ -51,7 +51,7 @@ void raiseSyntaxError(const char* msg, int lineno, int col_offset, llvm::StringR
...
@@ -51,7 +51,7 @@ void raiseSyntaxError(const char* msg, int lineno, int col_offset, llvm::StringR
}
else
{
}
else
{
// This is more like how the parser handles it:
// This is more like how the parser handles it:
exc
=
runtimeCall
(
SyntaxError
,
ArgPassSpec
(
1
),
boxString
(
msg
),
NULL
,
NULL
,
NULL
,
NULL
);
exc
=
runtimeCall
(
SyntaxError
,
ArgPassSpec
(
1
),
boxString
(
msg
),
NULL
,
NULL
,
NULL
,
NULL
);
tb
=
new
BoxedTraceback
(
LineInfo
(
lineno
,
col_offset
,
boxString
(
file
),
boxString
(
func
)),
None
);
tb
=
new
BoxedTraceback
(
LineInfo
(
lineno
,
col_offset
,
boxString
(
file
),
boxString
(
func
)),
None
,
getFrame
(
0
)
);
}
}
assert
(
!
PyErr_Occurred
());
assert
(
!
PyErr_Occurred
());
...
@@ -304,7 +304,7 @@ bool exceptionAtLineCheck() {
...
@@ -304,7 +304,7 @@ bool exceptionAtLineCheck() {
void
exceptionAtLine
(
LineInfo
line_info
,
Box
**
traceback
)
{
void
exceptionAtLine
(
LineInfo
line_info
,
Box
**
traceback
)
{
if
(
exceptionAtLineCheck
())
if
(
exceptionAtLineCheck
())
BoxedTraceback
::
here
(
line_info
,
traceback
);
BoxedTraceback
::
here
(
line_info
,
traceback
,
getFrame
((
FrameInfo
*
)
cur_thread_state
.
frame_info
)
);
}
}
void
startReraise
()
{
void
startReraise
()
{
...
...
src/runtime/frame.cpp
View file @
6be5e446
...
@@ -30,25 +30,24 @@ BoxedClass* frame_cls;
...
@@ -30,25 +30,24 @@ BoxedClass* frame_cls;
class
BoxedFrame
:
public
Box
{
class
BoxedFrame
:
public
Box
{
private:
private:
// Call boxFrame to get a BoxedFrame object.
// Call boxFrame to get a BoxedFrame object.
BoxedFrame
(
PythonFrameIterator
it
)
__attribute__
((
visibility
(
"default"
)))
BoxedFrame
(
FrameInfo
*
frame_info
)
__attribute__
((
visibility
(
"default"
)))
:
it
(
std
::
move
(
it
)),
thread_id
(
PyThread_get_thread_ident
())
{}
:
frame_info
(
frame_info
),
_back
(
NULL
),
_code
(
NULL
),
_globals
(
NULL
),
_locals
(
NULL
),
_stmt
(
NULL
)
{
assert
(
frame_info
);
}
public:
public:
PythonFrameIterator
it
;
FrameInfo
*
frame_info
;
long
thread_id
;
Box
*
_
globals
;
Box
*
_
back
;
Box
*
_code
;
Box
*
_code
;
Box
*
_globals
;
Box
*
_locals
;
AST_stmt
*
_stmt
;
bool
hasExited
()
const
{
return
frame_info
==
NULL
;
}
void
update
()
{
// This makes sense as an exception, but who knows how the user program would react
// (it might swallow it and do something different)
RELEASE_ASSERT
(
thread_id
==
PyThread_get_thread_ident
(),
"frame objects can only be accessed from the same thread"
);
PythonFrameIterator
new_it
=
it
.
getCurrentVersion
();
RELEASE_ASSERT
(
new_it
.
exists
()
&&
new_it
.
getFrameInfo
()
->
frame_obj
==
this
,
"frame has exited"
);
it
=
std
::
move
(
new_it
);
}
// cpython frame objects have the following attributes
// cpython frame objects have the following attributes
...
@@ -77,62 +76,85 @@ public:
...
@@ -77,62 +76,85 @@ public:
// * = unsupported in Pyston
// * = unsupported in Pyston
// ** = getter supported, but setter unsupported
// ** = getter supported, but setter unsupported
static
void
simpleDestructor
(
Box
*
b
)
{
auto
f
=
static_cast
<
BoxedFrame
*>
(
b
);
f
->
it
.
~
PythonFrameIterator
();
}
static
Box
*
code
(
Box
*
obj
,
void
*
)
{
static
Box
*
code
(
Box
*
obj
,
void
*
)
{
auto
f
=
static_cast
<
BoxedFrame
*>
(
obj
);
auto
f
=
static_cast
<
BoxedFrame
*>
(
obj
);
if
(
!
f
->
_code
)
f
->
_code
=
(
Box
*
)
f
->
frame_info
->
md
->
getCode
();
return
f
->
_code
;
return
f
->
_code
;
}
}
static
Box
*
locals
(
Box
*
obj
,
void
*
)
{
static
Box
*
locals
(
Box
*
obj
,
void
*
)
{
auto
f
=
static_cast
<
BoxedFrame
*>
(
obj
);
auto
f
=
static_cast
<
BoxedFrame
*>
(
obj
);
f
->
update
();
return
f
->
it
.
fastLocalsToBoxedLocals
();
if
(
f
->
hasExited
())
return
f
->
_locals
;
return
f
->
frame_info
->
updateBoxedLocals
();
}
}
static
Box
*
globals
(
Box
*
obj
,
void
*
)
{
static
Box
*
globals
(
Box
*
obj
,
void
*
)
{
auto
f
=
static_cast
<
BoxedFrame
*>
(
obj
);
auto
f
=
static_cast
<
BoxedFrame
*>
(
obj
);
if
(
!
f
->
_globals
)
{
f
->
_globals
=
f
->
frame_info
->
globals
;
if
(
f
->
_globals
&&
PyModule_Check
(
f
->
_globals
))
f
->
_globals
=
f
->
_globals
->
getAttrWrapper
();
}
return
f
->
_globals
;
return
f
->
_globals
;
}
}
static
Box
*
back
(
Box
*
obj
,
void
*
)
{
static
Box
*
back
(
Box
*
obj
,
void
*
)
{
auto
f
=
static_cast
<
BoxedFrame
*>
(
obj
);
auto
f
=
static_cast
<
BoxedFrame
*>
(
obj
);
f
->
update
();
PythonFrameIterator
it
=
f
->
it
.
back
();
if
(
!
f
->
_back
)
{
if
(
!
it
.
exists
())
if
(
!
f
->
frame_info
->
back
)
return
None
;
f
->
_back
=
None
;
return
BoxedFrame
::
boxFrame
(
std
::
move
(
it
));
else
f
->
_back
=
BoxedFrame
::
boxFrame
(
f
->
frame_info
->
back
);
}
return
f
->
_back
;
}
}
static
Box
*
lineno
(
Box
*
obj
,
void
*
)
{
static
Box
*
lineno
(
Box
*
obj
,
void
*
)
{
auto
f
=
static_cast
<
BoxedFrame
*>
(
obj
);
auto
f
=
static_cast
<
BoxedFrame
*>
(
obj
);
f
->
update
();
AST_stmt
*
stmt
=
f
->
it
.
getCurrentStatement
();
if
(
f
->
hasExited
())
return
boxInt
(
f
->
_stmt
->
lineno
);
AST_stmt
*
stmt
=
f
->
frame_info
->
stmt
;
return
boxInt
(
stmt
->
lineno
);
return
boxInt
(
stmt
->
lineno
);
}
}
DEFAULT_CLASS
(
frame_cls
);
void
handleFrameExit
()
{
if
(
hasExited
())
return
;
static
Box
*
boxFrame
(
PythonFrameIterator
it
)
{
_back
=
back
(
this
,
NULL
);
FrameInfo
*
fi
=
it
.
getFrameInfo
();
_code
=
code
(
this
,
NULL
);
if
(
fi
->
frame_obj
==
NULL
)
{
_globals
=
globals
(
this
,
NULL
);
auto
md
=
it
.
getMD
();
_locals
=
locals
(
this
,
NULL
);
Box
*
globals
=
it
.
getGlobalsDict
();
_stmt
=
frame_info
->
stmt
;
BoxedFrame
*
f
=
fi
->
frame_obj
=
new
BoxedFrame
(
std
::
move
(
it
));
f
->
_globals
=
globals
;
frame_info
=
NULL
;
// this means exited == true
f
->
_code
=
(
Box
*
)
md
->
getCode
();
assert
(
hasExited
());
}
}
DEFAULT_CLASS
(
frame_cls
);
static
Box
*
boxFrame
(
FrameInfo
*
fi
)
{
if
(
fi
->
frame_obj
==
NULL
)
fi
->
frame_obj
=
new
BoxedFrame
(
fi
);
assert
(
fi
->
frame_obj
->
cls
==
frame_cls
);
return
fi
->
frame_obj
;
return
fi
->
frame_obj
;
}
}
static
void
dealloc
(
Box
*
b
)
noexcept
{
static
void
dealloc
(
Box
*
b
)
noexcept
{
Py_FatalError
(
"unimplemented"
);
Py_FatalError
(
"unimplemented"
);
//Py_DECREF(f->_back);
//Py_DECREF(f->_code);
//Py_DECREF(f->_globals);
//Py_DECREF(f->_locals);
}
}
static
int
traverse
(
Box
*
self
,
visitproc
visit
,
void
*
arg
)
noexcept
{
static
int
traverse
(
Box
*
self
,
visitproc
visit
,
void
*
arg
)
noexcept
{
Py_FatalError
(
"unimplemented"
);
Py_FatalError
(
"unimplemented"
);
...
@@ -146,25 +168,37 @@ extern "C" int PyFrame_ClearFreeList(void) noexcept {
...
@@ -146,25 +168,37 @@ extern "C" int PyFrame_ClearFreeList(void) noexcept {
return
0
;
// number of entries cleared
return
0
;
// number of entries cleared
}
}
Box
*
getFrame
(
FrameInfo
*
frame_info
)
{
return
BoxedFrame
::
boxFrame
(
frame_info
);
}
Box
*
getFrame
(
int
depth
)
{
Box
*
getFrame
(
int
depth
)
{
auto
it
=
getPythonFrame
(
depth
);
FrameInfo
*
frame_info
=
getPythonFrameInfo
(
depth
);
if
(
!
it
.
exists
()
)
if
(
!
frame_info
)
return
NULL
;
return
NULL
;
return
BoxedFrame
::
boxFrame
(
frame_info
);
}
void
frameInvalidateBack
(
BoxedFrame
*
frame
)
{
RELEASE_ASSERT
(
!
frame
->
hasExited
(),
"should not happen"
);
frame
->
_back
=
NULL
;
}
extern
"C"
void
initFrame
(
FrameInfo
*
frame_info
)
{
frame_info
->
back
=
(
FrameInfo
*
)(
cur_thread_state
.
frame_info
);
cur_thread_state
.
frame_info
=
frame_info
;
}
return
BoxedFrame
::
boxFrame
(
std
::
move
(
it
));
extern
"C"
void
deinitFrame
(
FrameInfo
*
frame_info
)
{
cur_thread_state
.
frame_info
=
frame_info
->
back
;
BoxedFrame
*
frame
=
frame_info
->
frame_obj
;
if
(
frame
)
frame
->
handleFrameExit
();
}
}
extern
"C"
int
PyFrame_GetLineNumber
(
PyFrameObject
*
_f
)
noexcept
{
extern
"C"
int
PyFrame_GetLineNumber
(
PyFrameObject
*
_f
)
noexcept
{
// TODO remove this when we are able to introspect exited frames:
BoxedInt
*
lineno
=
(
BoxedInt
*
)
BoxedFrame
::
lineno
((
Box
*
)
_f
,
NULL
);
// We check if the frame exited and only return the correct line number when it is still available.
return
lineno
->
n
;
// Because of a limitation in out current frame introspection we can also not inspect OSRed frames.
BoxedFrame
*
f
=
(
BoxedFrame
*
)
_f
;
PythonFrameIterator
new_it
=
f
->
it
.
getCurrentVersion
();
if
(
new_it
.
exists
()
&&
new_it
.
getFrameInfo
()
->
frame_obj
==
f
)
{
BoxedInt
*
lineno
=
(
BoxedInt
*
)
BoxedFrame
::
lineno
((
Box
*
)
f
,
NULL
);
return
lineno
->
n
;
}
return
-
1
;
}
}
extern
"C"
PyObject
*
PyFrame_GetGlobals
(
PyFrameObject
*
f
)
noexcept
{
extern
"C"
PyObject
*
PyFrame_GetGlobals
(
PyFrameObject
*
f
)
noexcept
{
...
@@ -179,8 +213,6 @@ void setupFrame() {
...
@@ -179,8 +213,6 @@ void setupFrame() {
frame_cls
=
BoxedClass
::
create
(
type_cls
,
object_cls
,
0
,
0
,
sizeof
(
BoxedFrame
),
false
,
"frame"
,
false
,
frame_cls
=
BoxedClass
::
create
(
type_cls
,
object_cls
,
0
,
0
,
sizeof
(
BoxedFrame
),
false
,
"frame"
,
false
,
(
destructor
)
BoxedFrame
::
dealloc
,
NULL
,
true
,
(
traverseproc
)
BoxedFrame
::
traverse
,
(
destructor
)
BoxedFrame
::
dealloc
,
NULL
,
true
,
(
traverseproc
)
BoxedFrame
::
traverse
,
(
inquiry
)
BoxedFrame
::
clear
);
(
inquiry
)
BoxedFrame
::
clear
);
frame_cls
->
tp_dealloc
=
BoxedFrame
::
simpleDestructor
;
frame_cls
->
has_safe_tp_dealloc
=
true
;
frame_cls
->
giveAttrDescriptor
(
"f_code"
,
BoxedFrame
::
code
,
NULL
);
frame_cls
->
giveAttrDescriptor
(
"f_code"
,
BoxedFrame
::
code
,
NULL
);
frame_cls
->
giveAttrDescriptor
(
"f_locals"
,
BoxedFrame
::
locals
,
NULL
);
frame_cls
->
giveAttrDescriptor
(
"f_locals"
,
BoxedFrame
::
locals
,
NULL
);
...
...
src/runtime/generator.cpp
View file @
6be5e446
...
@@ -93,6 +93,8 @@ void generatorEntry(BoxedGenerator* g) {
...
@@ -93,6 +93,8 @@ void generatorEntry(BoxedGenerator* g) {
try
{
try
{
RegisterHelper
context_registerer
(
g
,
__builtin_frame_address
(
0
));
RegisterHelper
context_registerer
(
g
,
__builtin_frame_address
(
0
));
g
->
top_caller_frame_info
=
(
FrameInfo
*
)
cur_thread_state
.
frame_info
;
// call body of the generator
// call body of the generator
BoxedFunctionBase
*
func
=
g
->
function
;
BoxedFunctionBase
*
func
=
g
->
function
;
...
@@ -109,6 +111,7 @@ void generatorEntry(BoxedGenerator* g) {
...
@@ -109,6 +111,7 @@ void generatorEntry(BoxedGenerator* g) {
g
->
entryExited
=
true
;
g
->
entryExited
=
true
;
threading
::
popGenerator
();
threading
::
popGenerator
();
}
}
assert
(
g
->
top_caller_frame_info
==
cur_thread_state
.
frame_info
);
swapContext
(
&
g
->
context
,
g
->
returnContext
,
0
);
swapContext
(
&
g
->
context
,
g
->
returnContext
,
0
);
}
}
...
@@ -155,8 +158,11 @@ template <ExceptionStyle S> static bool generatorSendInternal(BoxedGenerator* se
...
@@ -155,8 +158,11 @@ template <ExceptionStyle S> static bool generatorSendInternal(BoxedGenerator* se
else
else
self
->
prev_stack
=
StatTimer
::
swapStack
(
self
->
prev_stack
);
self
->
prev_stack
=
StatTimer
::
swapStack
(
self
->
prev_stack
);
#endif
#endif
auto
*
top_caller_frame_info
=
(
FrameInfo
*
)
cur_thread_state
.
frame_info
;
swapContext
(
&
self
->
returnContext
,
self
->
context
,
(
intptr_t
)
self
);
swapContext
(
&
self
->
returnContext
,
self
->
context
,
(
intptr_t
)
self
);
assert
(
cur_thread_state
.
frame_info
==
top_caller_frame_info
&&
"the generator should reset the frame info before the swapContext"
);
#if STAT_TIMERS
#if STAT_TIMERS
self
->
prev_stack
=
StatTimer
::
swapStack
(
self
->
prev_stack
);
self
->
prev_stack
=
StatTimer
::
swapStack
(
self
->
prev_stack
);
...
@@ -314,7 +320,28 @@ extern "C" Box* yield(BoxedGenerator* obj, Box* value) {
...
@@ -314,7 +320,28 @@ extern "C" Box* yield(BoxedGenerator* obj, Box* value) {
self
->
returnValue
=
value
;
self
->
returnValue
=
value
;
threading
::
popGenerator
();
threading
::
popGenerator
();
FrameInfo
*
generator_frame_info
=
(
FrameInfo
*
)
cur_thread_state
.
frame_info
;
// a generator will only switch back (yield/unhandled exception) to its caller when it is one frame away from the
// caller
assert
(
self
->
top_caller_frame_info
==
generator_frame_info
->
back
);
// reset current frame to the caller tops frame --> removes the frame the generator added
cur_thread_state
.
frame_info
=
self
->
top_caller_frame_info
;
swapContext
(
&
self
->
context
,
self
->
returnContext
,
0
);
swapContext
(
&
self
->
context
,
self
->
returnContext
,
0
);
FrameInfo
*
top_new_caller_frame_info
=
(
FrameInfo
*
)
cur_thread_state
.
frame_info
;
// the caller of the generator can change between yield statements that means we can't just restore the top of the
// frame to the point before the yield instead we have to update it.
if
(
top_new_caller_frame_info
!=
self
->
top_caller_frame_info
)
{
// caller changed
self
->
top_caller_frame_info
=
top_new_caller_frame_info
;
generator_frame_info
->
back
=
top_new_caller_frame_info
;
if
(
generator_frame_info
->
frame_obj
)
frameInvalidateBack
(
generator_frame_info
->
frame_obj
);
}
cur_thread_state
.
frame_info
=
generator_frame_info
;
threading
::
pushGenerator
(
obj
,
obj
->
stack_begin
,
obj
->
returnContext
);
threading
::
pushGenerator
(
obj
,
obj
->
stack_begin
,
obj
->
returnContext
);
// if the generator receives a exception from the caller we have to throw it
// if the generator receives a exception from the caller we have to throw it
...
@@ -347,7 +374,8 @@ extern "C" BoxedGenerator::BoxedGenerator(BoxedFunctionBase* function, Box* arg1
...
@@ -347,7 +374,8 @@ extern "C" BoxedGenerator::BoxedGenerator(BoxedFunctionBase* function, Box* arg1
returnValue
(
nullptr
),
returnValue
(
nullptr
),
exception
(
nullptr
,
nullptr
,
nullptr
),
exception
(
nullptr
,
nullptr
,
nullptr
),
context
(
nullptr
),
context
(
nullptr
),
returnContext
(
nullptr
)
returnContext
(
nullptr
),
top_caller_frame_info
(
nullptr
)
#if STAT_TIMERS
#if STAT_TIMERS
,
,
prev_stack
(
NULL
),
prev_stack
(
NULL
),
...
...
src/runtime/inline/link_forcer.cpp
View file @
6be5e446
...
@@ -72,6 +72,8 @@ void force() {
...
@@ -72,6 +72,8 @@ void force() {
FORCE
(
createPureImaginary
);
FORCE
(
createPureImaginary
);
FORCE
(
createSet
);
FORCE
(
createSet
);
FORCE
(
decodeUTF8StringPtr
);
FORCE
(
decodeUTF8StringPtr
);
FORCE
(
initFrame
);
FORCE
(
deinitFrame
);
FORCE
(
getattr
);
FORCE
(
getattr
);
FORCE
(
getattr_capi
);
FORCE
(
getattr_capi
);
...
...
src/runtime/traceback.cpp
View file @
6be5e446
...
@@ -82,38 +82,15 @@ void printTraceback(Box* b) {
...
@@ -82,38 +82,15 @@ void printTraceback(Box* b) {
}
}
}
}
Box
*
BoxedTraceback
::
getLines
(
Box
*
b
)
{
assert
(
b
->
cls
==
traceback_cls
);
BoxedTraceback
*
tb
=
static_cast
<
BoxedTraceback
*>
(
b
);
if
(
!
tb
->
py_lines
)
{
BoxedList
*
lines
=
new
BoxedList
();
for
(
BoxedTraceback
*
wtb
=
tb
;
wtb
&&
wtb
!=
None
;
wtb
=
static_cast
<
BoxedTraceback
*>
(
wtb
->
tb_next
))
{
auto
&
line
=
wtb
->
line
;
auto
l
=
BoxedTuple
::
create
({
line
.
file
,
line
.
func
,
boxInt
(
line
.
line
)
});
listAppendInternal
(
lines
,
l
);
}
tb
->
py_lines
=
lines
;
}
return
tb
->
py_lines
;
}
void
BoxedTraceback
::
here
(
LineInfo
lineInfo
,
Box
**
tb
)
{
Box
*
old_tb
=
*
tb
;
*
tb
=
new
BoxedTraceback
(
std
::
move
(
lineInfo
),
*
tb
);
Py_DECREF
(
old_tb
);
}
void
BoxedTraceback
::
dealloc
(
Box
*
b
)
noexcept
{
void
BoxedTraceback
::
dealloc
(
Box
*
b
)
noexcept
{
BoxedTraceback
*
self
=
static_cast
<
BoxedTraceback
*>
(
b
);
BoxedTraceback
*
self
=
static_cast
<
BoxedTraceback
*>
(
b
);
Py_DECREF
(
self
->
tb_next
);
Py_DECREF
(
self
->
tb_next
);
Py_XDECREF
(
self
->
py_lines
);
Py_DECREF
(
self
->
line
.
file
);
Py_DECREF
(
self
->
line
.
file
);
Py_DECREF
(
self
->
line
.
func
);
Py_DECREF
(
self
->
line
.
func
);
Py_DECREF
(
self
->
tb_frame
);
PyObject_GC_Del
(
b
);
PyObject_GC_Del
(
b
);
}
}
...
@@ -121,7 +98,7 @@ int BoxedTraceback::traverse(Box* self, visitproc visit, void *arg) noexcept {
...
@@ -121,7 +98,7 @@ int BoxedTraceback::traverse(Box* self, visitproc visit, void *arg) noexcept {
BoxedTraceback
*
tb
=
static_cast
<
BoxedTraceback
*>
(
self
);
BoxedTraceback
*
tb
=
static_cast
<
BoxedTraceback
*>
(
self
);
Py_VISIT
(
tb
->
tb_next
);
Py_VISIT
(
tb
->
tb_next
);
Py_VISIT
(
tb
->
py_lines
);
Py_VISIT
(
tb
->
tb_frame
);
Py_VISIT
(
tb
->
line
.
file
);
Py_VISIT
(
tb
->
line
.
file
);
Py_VISIT
(
tb
->
line
.
func
);
Py_VISIT
(
tb
->
line
.
func
);
...
@@ -132,11 +109,10 @@ int BoxedTraceback::clear(Box* self) noexcept {
...
@@ -132,11 +109,10 @@ int BoxedTraceback::clear(Box* self) noexcept {
abort
();
abort
();
}
}
static
Box
*
traceback_tb_next
(
Box
*
self
,
void
*
)
{
void
BoxedTraceback
::
here
(
LineInfo
lineInfo
,
Box
**
tb
,
Box
*
frame
)
{
assert
(
self
->
cls
==
traceback_cls
);
Box
*
old_tb
=
*
tb
;
*
tb
=
new
BoxedTraceback
(
std
::
move
(
lineInfo
),
*
tb
,
frame
);
BoxedTraceback
*
traceback
=
static_cast
<
BoxedTraceback
*>
(
self
);
Py_DECREF
(
old_tb
);
return
traceback
->
tb_next
;
}
}
extern
"C"
int
_Py_DisplaySourceLine
(
PyObject
*
f
,
const
char
*
filename
,
int
lineno
,
int
indent
)
noexcept
{
extern
"C"
int
_Py_DisplaySourceLine
(
PyObject
*
f
,
const
char
*
filename
,
int
lineno
,
int
indent
)
noexcept
{
...
@@ -148,17 +124,15 @@ void setupTraceback() {
...
@@ -148,17 +124,15 @@ void setupTraceback() {
(
destructor
)
BoxedTraceback
::
dealloc
,
NULL
,
true
,
(
destructor
)
BoxedTraceback
::
dealloc
,
NULL
,
true
,
(
traverseproc
)
BoxedTraceback
::
traverse
,
(
inquiry
)
BoxedTraceback
::
clear
);
(
traverseproc
)
BoxedTraceback
::
traverse
,
(
inquiry
)
BoxedTraceback
::
clear
);
traceback_cls
->
giveAttr
(
"getLines"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
BoxedTraceback
::
getLines
,
UNKNOWN
,
1
)));
/*
/*
* Currently not supported.
* Currently not supported.
traceback_cls->giveAttr("tb_frame", new (pyston_getset_cls) BoxedGetsetDescriptor(traceback_tb_frame, NULL, NULL));
traceback_cls->giveAttr("tb_lasti", new (pyston_getset_cls) BoxedGetsetDescriptor(traceback_tb_lasti, NULL, NULL));
traceback_cls->giveAttr("tb_lasti", new (pyston_getset_cls) BoxedGetsetDescriptor(traceback_tb_lasti, NULL, NULL));
traceback_cls->giveAttr("tb_lineno", new (pyston_getset_cls) BoxedGetsetDescriptor(traceback_tb_lineno, NULL,
NULL));
*/
*/
traceback_cls
->
giveAttrDescriptor
(
"tb_next"
,
traceback_tb_next
,
NULL
);
traceback_cls
->
giveAttr
(
"tb_frame"
,
new
BoxedMemberDescriptor
(
BoxedMemberDescriptor
::
OBJECT
,
offsetof
(
BoxedTraceback
,
tb_frame
)));
traceback_cls
->
giveAttr
(
"tb_next"
,
new
BoxedMemberDescriptor
(
BoxedMemberDescriptor
::
OBJECT
,
offsetof
(
BoxedTraceback
,
tb_next
)));
traceback_cls
->
giveAttr
(
"tb_lineno"
,
traceback_cls
->
giveAttr
(
"tb_lineno"
,
new
BoxedMemberDescriptor
(
BoxedMemberDescriptor
::
INT
,
new
BoxedMemberDescriptor
(
BoxedMemberDescriptor
::
INT
,
offsetof
(
BoxedTraceback
,
line
)
+
offsetof
(
LineInfo
,
line
)));
offsetof
(
BoxedTraceback
,
line
)
+
offsetof
(
LineInfo
,
line
)));
...
...
src/runtime/traceback.h
View file @
6be5e446
...
@@ -27,24 +27,30 @@ class GCVisitor;
...
@@ -27,24 +27,30 @@ class GCVisitor;
extern
"C"
BoxedClass
*
traceback_cls
;
extern
"C"
BoxedClass
*
traceback_cls
;
class
BoxedTraceback
:
public
Box
{
class
BoxedTraceback
:
public
Box
{
public:
public:
Box
*
tb_next
;
LineInfo
line
;
LineInfo
line
;
Box
*
py_lines
;
Box
*
tb_next
;
Box
*
tb_frame
;
BoxedTraceback
(
LineInfo
line
,
Box
*
tb_next
)
:
tb_next
(
tb_next
),
line
(
std
::
move
(
line
)),
py_lines
(
NULL
)
{
BoxedTraceback
(
LineInfo
line
,
Box
*
tb_next
,
Box
*
tb_frame
)
:
line
(
std
::
move
(
line
)),
tb_next
(
tb_next
),
tb_frame
(
tb_frame
)
{
Py_INCREF
(
tb_next
);
Py_INCREF
(
tb_next
);
Py_INCREF
(
line
.
file
);
Py_INCREF
(
line
.
file
);
Py_INCREF
(
line
.
func
);
Py_INCREF
(
line
.
func
);
if
(
!
tb_frame
)
this
->
tb_frame
=
None
;
else
assert
(
tb_frame
->
cls
==
frame_cls
);
Py_INCREF
(
this
->
tb_frame
);
}
}
DEFAULT_CLASS
(
traceback_cls
);
DEFAULT_CLASS
(
traceback_cls
);
static
Box
*
getLines
(
Box
*
b
);
static
Box
*
lineno
(
Box
*
obj
,
void
*
);
static
void
gcHandler
(
gc
::
GCVisitor
*
v
,
Box
*
b
);
static
void
gcHandler
(
gc
::
GCVisitor
*
v
,
Box
*
b
);
// somewhat equivalent to PyTraceBack_Here
// somewhat equivalent to PyTraceBack_Here
static
void
here
(
LineInfo
lineInfo
,
Box
**
tb
);
static
void
here
(
LineInfo
lineInfo
,
Box
**
tb
,
Box
*
frame
);
static
void
dealloc
(
Box
*
b
)
noexcept
;
static
void
dealloc
(
Box
*
b
)
noexcept
;
static
int
traverse
(
Box
*
self
,
visitproc
visit
,
void
*
arg
)
noexcept
;
static
int
traverse
(
Box
*
self
,
visitproc
visit
,
void
*
arg
)
noexcept
;
...
...
src/runtime/types.h
View file @
6be5e446
...
@@ -1169,6 +1169,7 @@ public:
...
@@ -1169,6 +1169,7 @@ public:
struct
Context
*
context
,
*
returnContext
;
struct
Context
*
context
,
*
returnContext
;
void
*
stack_begin
;
void
*
stack_begin
;
FrameInfo
*
top_caller_frame_info
;
#if STAT_TIMERS
#if STAT_TIMERS
StatTimer
*
prev_stack
;
StatTimer
*
prev_stack
;
...
@@ -1272,7 +1273,11 @@ Box* codeForFunction(BoxedFunction*);
...
@@ -1272,7 +1273,11 @@ Box* codeForFunction(BoxedFunction*);
Box
*
codeForFunctionMetadata
(
FunctionMetadata
*
);
Box
*
codeForFunctionMetadata
(
FunctionMetadata
*
);
FunctionMetadata
*
metadataFromCode
(
Box
*
code
);
FunctionMetadata
*
metadataFromCode
(
Box
*
code
);
Box
*
getFrame
(
FrameInfo
*
frame_info
);
Box
*
getFrame
(
int
depth
);
Box
*
getFrame
(
int
depth
);
void
frameInvalidateBack
(
BoxedFrame
*
frame
);
extern
"C"
void
deinitFrame
(
FrameInfo
*
frame_info
);
extern
"C"
void
initFrame
(
FrameInfo
*
frame_info
);
inline
BoxedString
*
boxString
(
llvm
::
StringRef
s
)
{
inline
BoxedString
*
boxString
(
llvm
::
StringRef
s
)
{
if
(
s
.
size
()
<=
1
)
{
if
(
s
.
size
()
<=
1
)
{
...
...
test/tests/generator_threads2.py
0 → 100644
View file @
6be5e446
import
threading
import
traceback
,
sys
def
exc
():
1
/
0
def
G
():
traceback
.
print_stack
(
limit
=
2
)
yield
1
traceback
.
print_stack
(
limit
=
2
)
yield
2
exc
()
def
f1
(
x
):
print
x
.
next
()
def
f2
(
x
):
print
x
.
next
()
def
f3
(
x
):
try
:
print
x
.
next
()
except
:
print
"exc"
traceback
.
print_tb
(
sys
.
exc_info
()[
2
])
def
run
(
nthreads
=
4
):
g
=
G
()
def
t
(
f
):
return
threading
.
Thread
(
target
=
f
,
args
=
(
g
,))
for
t
in
[
t
(
f1
),
t
(
f2
),
t
(
f3
)]:
t
.
start
()
t
.
join
()
run
()
test/tests/sys_getframe_exited.py
View file @
6be5e446
# expected: fail
# - we don't (yet?) support looking at frame objects after
# their frame has exited
import
sys
import
sys
def
f
():
def
f
():
var
=
42
return
sys
.
_getframe
(
0
)
return
sys
.
_getframe
(
0
)
fr
=
f
()
fr
=
f
()
print
fr
.
f_locals
print
fr
.
f_locals
def
f
():
var
=
0
fr
=
sys
.
_getframe
(
0
)
var
+=
1
return
fr
fr
=
f
()
print
fr
.
f_locals
[
"var"
]
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