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
caa84b81
Commit
caa84b81
authored
Jul 12, 2015
by
Kevin Modzelewski
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #684 from kmod/tiering2
tiering refactoring
parents
0915db4e
a87e2eaf
Changes
19
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
331 additions
and
396 deletions
+331
-396
src/codegen/ast_interpreter.cpp
src/codegen/ast_interpreter.cpp
+83
-57
src/codegen/ast_interpreter.h
src/codegen/ast_interpreter.h
+6
-6
src/codegen/codegen.cpp
src/codegen/codegen.cpp
+22
-0
src/codegen/compvars.cpp
src/codegen/compvars.cpp
+15
-31
src/codegen/irgen.cpp
src/codegen/irgen.cpp
+6
-12
src/codegen/irgen.h
src/codegen/irgen.h
+3
-3
src/codegen/irgen/hooks.cpp
src/codegen/irgen/hooks.cpp
+31
-91
src/codegen/irgen/irgenerator.cpp
src/codegen/irgen/irgenerator.cpp
+35
-56
src/codegen/irgen/irgenerator.h
src/codegen/irgen/irgenerator.h
+5
-1
src/codegen/osrentry.h
src/codegen/osrentry.h
+5
-6
src/codegen/patchpoints.cpp
src/codegen/patchpoints.cpp
+0
-9
src/codegen/patchpoints.h
src/codegen/patchpoints.h
+4
-0
src/codegen/unwinding.cpp
src/codegen/unwinding.cpp
+65
-42
src/codegen/unwinding.h
src/codegen/unwinding.h
+10
-7
src/core/cfg.cpp
src/core/cfg.cpp
+2
-0
src/core/types.h
src/core/types.h
+14
-25
src/runtime/builtin_modules/builtins.cpp
src/runtime/builtin_modules/builtins.cpp
+1
-1
src/runtime/frame.cpp
src/runtime/frame.cpp
+4
-4
src/runtime/objmodel.cpp
src/runtime/objmodel.cpp
+20
-45
No files found.
src/codegen/ast_interpreter.cpp
View file @
caa84b81
...
...
@@ -79,7 +79,7 @@ class ASTInterpreter : public Box {
public:
typedef
ContiguousMap
<
InternedString
,
Box
*>
SymMap
;
ASTInterpreter
(
C
ompiledFunction
*
compiled_function
);
ASTInterpreter
(
C
LFunction
*
clfunc
);
void
initArguments
(
int
nargs
,
BoxedClosure
*
closure
,
BoxedGenerator
*
generator
,
Box
*
arg1
,
Box
*
arg2
,
Box
*
arg3
,
Box
**
args
);
...
...
@@ -155,7 +155,7 @@ private:
CFGBlock
*
next_block
,
*
current_block
;
AST_stmt
*
current_inst
;
C
ompiledFunction
*
compiled_
func
;
C
LFunction
*
cl
func
;
SourceInfo
*
source_info
;
ScopeInfo
*
scope_info
;
PhiAnalysis
*
phis
;
...
...
@@ -185,7 +185,7 @@ public:
return
globals
;
}
C
ompiledFunction
*
getCF
()
{
return
compiled_
func
;
}
C
LFunction
*
getCL
()
{
return
cl
func
;
}
FrameInfo
*
getFrameInfo
()
{
return
&
frame_info
;
}
BoxedClosure
*
getPassedClosure
()
{
return
passed_closure
;
}
const
SymMap
&
getSymbolTable
()
{
return
sym_table
;
}
...
...
@@ -263,11 +263,11 @@ void ASTInterpreter::gcHandler(GCVisitor* visitor, Box* box) {
interp
->
frame_info
.
gcVisit
(
visitor
);
}
ASTInterpreter
::
ASTInterpreter
(
C
ompiledFunction
*
compiled_function
)
ASTInterpreter
::
ASTInterpreter
(
C
LFunction
*
clfunc
)
:
current_block
(
0
),
current_inst
(
0
),
c
ompiled_func
(
compiled_function
),
source_info
(
c
ompiled_function
->
c
lfunc
->
source
.
get
()),
c
lfunc
(
clfunc
),
source_info
(
clfunc
->
source
.
get
()),
scope_info
(
0
),
phis
(
NULL
),
last_exception
(
NULL
,
NULL
,
NULL
),
...
...
@@ -279,10 +279,6 @@ ASTInterpreter::ASTInterpreter(CompiledFunction* compiled_function)
globals
(
0
),
frame_addr
(
0
)
{
CLFunction
*
f
=
compiled_function
->
clfunc
;
if
(
!
source_info
->
cfg
)
source_info
->
cfg
=
computeCFG
(
f
->
source
.
get
(),
f
->
source
->
body
);
scope_info
=
source_info
->
getScopeInfo
();
assert
(
scope_info
);
...
...
@@ -300,7 +296,7 @@ void ASTInterpreter::initArguments(int nargs, BoxedClosure* _closure, BoxedGener
for
(
int
i
=
3
;
i
<
nargs
;
++
i
)
argsArray
.
push_back
(
args
[
i
-
3
]);
const
ParamNames
&
param_names
=
c
ompiled_func
->
c
lfunc
->
param_names
;
const
ParamNames
&
param_names
=
clfunc
->
param_names
;
int
i
=
0
;
for
(
auto
&
name
:
param_names
.
args
)
{
...
...
@@ -345,7 +341,7 @@ void ASTInterpreter::startJITing(CFGBlock* block, int exit_offset) {
assert
(
ENABLE_BASELINEJIT
);
assert
(
!
jit
);
auto
&
code_blocks
=
c
ompiled_
func
->
code_blocks
;
auto
&
code_blocks
=
c
l
func
->
code_blocks
;
JitCodeBlock
*
code_block
=
NULL
;
if
(
!
code_blocks
.
empty
())
code_block
=
code_blocks
[
code_blocks
.
size
()
-
1
].
get
();
...
...
@@ -387,7 +383,7 @@ Box* ASTInterpreter::execJITedBlock(CFGBlock* b) {
if
(
stmt
->
type
!=
AST_TYPE
::
Invoke
)
throw
e
;
auto
source
=
getC
F
()
->
clfunc
->
source
.
get
();
auto
source
=
getC
L
()
->
source
.
get
();
exceptionCaughtInInterpreter
(
LineInfo
(
stmt
->
lineno
,
stmt
->
col_offset
,
source
->
fn
,
source
->
getName
()),
&
e
);
next_block
=
((
AST_Invoke
*
)
stmt
)
->
exc_dest
;
...
...
@@ -412,7 +408,7 @@ Value ASTInterpreter::executeInner(ASTInterpreter& interpreter, CFGBlock* start_
start_block
=
interpreter
.
source_info
->
cfg
->
getStartingBlock
();
start_at
=
start_block
->
body
[
0
];
if
(
ENABLE_BASELINEJIT
&&
interpreter
.
c
ompiled_func
->
times_call
ed
>=
REOPT_THRESHOLD_INTERPRETER
if
(
ENABLE_BASELINEJIT
&&
interpreter
.
c
lfunc
->
times_interpret
ed
>=
REOPT_THRESHOLD_INTERPRETER
&&
!
start_block
->
code
)
should_jit
=
true
;
}
...
...
@@ -475,6 +471,16 @@ Value ASTInterpreter::executeInner(ASTInterpreter& interpreter, CFGBlock* start_
Value
ASTInterpreter
::
execute
(
ASTInterpreter
&
interpreter
,
CFGBlock
*
start_block
,
AST_stmt
*
start_at
)
{
UNAVOIDABLE_STAT_TIMER
(
t0
,
"us_timer_in_interpreter"
);
// Note: due to some (avoidable) restrictions, this check is pretty constrained in where
// it can go, due to the fact that it can throw an exception.
// It can't go in the ASTInterpreter constructor, since that will cause the C++ runtime to
// delete the partially-constructed memory which we don't currently handle. It can't go into
// executeInner since we want the SyntaxErrors to happen *before* the stack frame is entered.
// (For instance, throwing the exception will try to fetch the current statement, but we determine
// that by looking at the cfg.)
if
(
!
interpreter
.
source_info
->
cfg
)
interpreter
.
source_info
->
cfg
=
computeCFG
(
interpreter
.
source_info
,
interpreter
.
source_info
->
body
);
RegisterHelper
frame_registerer
;
return
executeInner
(
interpreter
,
start_block
,
start_at
,
&
frame_registerer
);
}
...
...
@@ -640,7 +646,7 @@ Value ASTInterpreter::visit_branch(AST_Branch* node) {
}
Value
ASTInterpreter
::
visit_jump
(
AST_Jump
*
node
)
{
bool
backedge
=
node
->
target
->
idx
<
current_block
->
idx
&&
compiled_func
;
bool
backedge
=
node
->
target
->
idx
<
current_block
->
idx
;
if
(
backedge
)
{
threading
::
allowGLReadPreemption
();
...
...
@@ -681,7 +687,7 @@ Box* ASTInterpreter::doOSR(AST_Jump* node) {
LivenessAnalysis
*
liveness
=
source_info
->
getLiveness
();
std
::
unique_ptr
<
PhiAnalysis
>
phis
=
computeRequiredPhis
(
c
ompiled_func
->
c
lfunc
->
param_names
,
source_info
->
cfg
,
liveness
,
scope_info
);
=
computeRequiredPhis
(
clfunc
->
param_names
,
source_info
->
cfg
,
liveness
,
scope_info
);
std
::
vector
<
InternedString
>
dead_symbols
;
for
(
auto
&
it
:
sym_table
)
{
...
...
@@ -696,9 +702,7 @@ Box* ASTInterpreter::doOSR(AST_Jump* node) {
sym_table
.
erase
(
dead
);
const
OSREntryDescriptor
*
found_entry
=
nullptr
;
for
(
auto
&
p
:
compiled_func
->
clfunc
->
osr_versions
)
{
if
(
p
.
first
->
cf
!=
compiled_func
)
continue
;
for
(
auto
&
p
:
clfunc
->
osr_versions
)
{
if
(
p
.
first
->
backedge
!=
node
)
continue
;
...
...
@@ -748,7 +752,7 @@ Box* ASTInterpreter::doOSR(AST_Jump* node) {
sorted_symbol_table
[
source_info
->
getInternedStrings
().
get
(
FRAME_INFO_PTR_NAME
)]
=
(
Box
*
)
&
frame_info
;
if
(
found_entry
==
nullptr
)
{
OSREntryDescriptor
*
entry
=
OSREntryDescriptor
::
create
(
c
ompiled_
func
,
node
);
OSREntryDescriptor
*
entry
=
OSREntryDescriptor
::
create
(
c
l
func
,
node
);
for
(
auto
&
it
:
sorted_symbol_table
)
{
if
(
isIsDefinedName
(
it
.
first
))
...
...
@@ -768,7 +772,7 @@ Box* ASTInterpreter::doOSR(AST_Jump* node) {
found_entry
=
entry
;
}
OSRExit
exit
(
compiled_func
,
found_entry
);
OSRExit
exit
(
found_entry
);
std
::
vector
<
Box
*
,
StlCompatAllocator
<
Box
*>>
arg_array
;
for
(
auto
&
it
:
sorted_symbol_table
)
{
...
...
@@ -781,13 +785,8 @@ Box* ASTInterpreter::doOSR(AST_Jump* node) {
Box
*
r
=
partial_func
->
call
(
std
::
get
<
0
>
(
arg_tuple
),
std
::
get
<
1
>
(
arg_tuple
),
std
::
get
<
2
>
(
arg_tuple
),
std
::
get
<
3
>
(
arg_tuple
));
// This is one of the few times that we are allowed to have an invalid value in a Box* Value.
// Check for it, and return as an int so that we don't trigger a potential assert when
// creating the Value.
if
(
compiled_func
->
getReturnType
()
!=
VOID
)
assert
(
r
);
return
r
?
r
:
None
;
assert
(
r
);
return
r
;
}
Value
ASTInterpreter
::
visit_invoke
(
AST_Invoke
*
node
)
{
...
...
@@ -803,7 +802,7 @@ Value ASTInterpreter::visit_invoke(AST_Invoke* node) {
}
catch
(
ExcInfo
e
)
{
abortJITing
();
auto
source
=
getC
F
()
->
clfunc
->
source
.
get
();
auto
source
=
getC
L
()
->
source
.
get
();
exceptionCaughtInInterpreter
(
LineInfo
(
node
->
lineno
,
node
->
col_offset
,
source
->
fn
,
source
->
getName
()),
&
e
);
next_block
=
node
->
exc_dest
;
...
...
@@ -1034,7 +1033,7 @@ Box* ASTInterpreter::createFunction(AST* node, AST_arguments* args, const std::v
}
Box
*
passed_globals
=
NULL
;
if
(
!
getC
F
()
->
clfunc
->
source
->
scoping
->
areGlobalsFromModule
())
if
(
!
getC
L
()
->
source
->
scoping
->
areGlobalsFromModule
())
passed_globals
=
globals
;
return
boxCLFunction
(
cl
,
closure
,
passed_globals
,
u
.
il
);
}
...
...
@@ -1083,7 +1082,7 @@ Value ASTInterpreter::visit_makeClass(AST_MakeClass* mkclass) {
CLFunction
*
cl
=
wrapFunction
(
node
,
nullptr
,
node
->
body
,
source_info
);
Box
*
passed_globals
=
NULL
;
if
(
!
getC
F
()
->
clfunc
->
source
->
scoping
->
areGlobalsFromModule
())
if
(
!
getC
L
()
->
source
->
scoping
->
areGlobalsFromModule
())
passed_globals
=
globals
;
Box
*
attrDict
=
runtimeCall
(
boxCLFunction
(
cl
,
closure
,
passed_globals
,
{}),
ArgPassSpec
(
0
),
0
,
0
,
0
,
0
,
0
);
...
...
@@ -1661,17 +1660,45 @@ void ASTInterpreterJitInterface::setLocalHelper(void* _interpreter, InternedStri
const
void
*
interpreter_instr_addr
=
(
void
*
)
&
ASTInterpreter
::
executeInner
;
Box
*
astInterpretFunction
(
C
ompiledFunction
*
cf
,
int
nargs
,
Box
*
closure
,
Box
*
generator
,
Box
*
globals
,
Box
*
arg1
,
Box
*
astInterpretFunction
(
C
LFunction
*
clfunc
,
int
nargs
,
Box
*
closure
,
Box
*
generator
,
Box
*
globals
,
Box
*
arg1
,
Box
*
arg2
,
Box
*
arg3
,
Box
**
args
)
{
UNAVOIDABLE_STAT_TIMER
(
t0
,
"us_timer_in_interpreter"
);
assert
((
!
globals
)
==
cf
->
clfunc
->
source
->
scoping
->
areGlobalsFromModule
());
SourceInfo
*
source_info
=
clfunc
->
source
.
get
();
assert
((
!
globals
)
==
source_info
->
scoping
->
areGlobalsFromModule
());
bool
can_reopt
=
ENABLE_REOPT
&&
!
FORCE_INTERPRETER
&&
(
globals
==
NULL
);
int
num_blocks
=
cf
->
clfunc
->
source
->
cfg
->
blocks
.
size
();
// If the cfg hasn't been computed yet, just conservatively say that it will be a big function.
// It shouldn't matter, since the cfg should only be NULL if this is the first execution of this
// function.
int
num_blocks
=
source_info
->
cfg
?
source_info
->
cfg
->
blocks
.
size
()
:
10000
;
int
threshold
=
num_blocks
<=
20
?
(
REOPT_THRESHOLD_BASELINE
/
3
)
:
REOPT_THRESHOLD_BASELINE
;
if
(
unlikely
(
can_reopt
&&
cf
->
times_called
>
threshold
))
{
if
(
unlikely
(
can_reopt
&&
(
FORCE_OPTIMIZE
||
!
ENABLE_INTERPRETER
||
clfunc
->
times_interpreted
>
threshold
)
))
{
assert
(
!
globals
);
CompiledFunction
*
optimized
=
reoptCompiledFuncInternal
(
cf
);
clfunc
->
times_interpreted
=
0
;
EffortLevel
new_effort
=
EffortLevel
::
MODERATE
;
if
(
FORCE_OPTIMIZE
)
new_effort
=
EffortLevel
::
MAXIMAL
;
std
::
vector
<
ConcreteCompilerType
*>
arg_types
;
for
(
int
i
=
0
;
i
<
nargs
;
i
++
)
{
Box
*
arg
=
getArg
(
i
,
arg1
,
arg2
,
arg3
,
args
);
assert
(
arg
);
// only builtin functions can pass NULL args
// TODO: reenable argument-type specialization
arg_types
.
push_back
(
UNKNOWN
);
// arg_types.push_back(typeFromClass(arg->cls));
}
FunctionSpecialization
*
spec
=
new
FunctionSpecialization
(
UNKNOWN
,
arg_types
);
// this also pushes the new CompiledVersion to the back of the version list:
CompiledFunction
*
optimized
=
compileFunction
(
clfunc
,
spec
,
new_effort
,
NULL
);
clfunc
->
dependent_interp_callsites
.
invalidateAll
();
if
(
closure
&&
generator
)
return
optimized
->
closure_generator_call
((
BoxedClosure
*
)
closure
,
(
BoxedGenerator
*
)
generator
,
arg1
,
arg2
,
arg3
,
args
);
...
...
@@ -1682,16 +1709,15 @@ Box* astInterpretFunction(CompiledFunction* cf, int nargs, Box* closure, Box* ge
return
optimized
->
call
(
arg1
,
arg2
,
arg3
,
args
);
}
++
c
f
->
times_call
ed
;
ASTInterpreter
*
interpreter
=
new
ASTInterpreter
(
c
f
);
++
c
lfunc
->
times_interpret
ed
;
ASTInterpreter
*
interpreter
=
new
ASTInterpreter
(
c
lfunc
);
ScopeInfo
*
scope_info
=
cf
->
clfunc
->
source
->
getScopeInfo
();
SourceInfo
*
source_info
=
cf
->
clfunc
->
source
.
get
();
ScopeInfo
*
scope_info
=
clfunc
->
source
->
getScopeInfo
();
if
(
unlikely
(
scope_info
->
usesNameLookup
()))
{
interpreter
->
setBoxedLocals
(
new
BoxedDict
());
}
assert
((
!
globals
)
==
c
f
->
c
lfunc
->
source
->
scoping
->
areGlobalsFromModule
());
assert
((
!
globals
)
==
clfunc
->
source
->
scoping
->
areGlobalsFromModule
());
if
(
globals
)
{
interpreter
->
setGlobals
(
globals
);
}
else
{
...
...
@@ -1704,17 +1730,17 @@ Box* astInterpretFunction(CompiledFunction* cf, int nargs, Box* closure, Box* ge
return
v
.
o
?
v
.
o
:
None
;
}
Box
*
astInterpretFunctionEval
(
C
ompiledFunction
*
cf
,
Box
*
globals
,
Box
*
boxedLocals
)
{
++
c
f
->
times_call
ed
;
Box
*
astInterpretFunctionEval
(
C
LFunction
*
clfunc
,
Box
*
globals
,
Box
*
boxedLocals
)
{
++
c
lfunc
->
times_interpret
ed
;
ASTInterpreter
*
interpreter
=
new
ASTInterpreter
(
c
f
);
ASTInterpreter
*
interpreter
=
new
ASTInterpreter
(
c
lfunc
);
interpreter
->
initArguments
(
0
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
);
interpreter
->
setBoxedLocals
(
boxedLocals
);
ScopeInfo
*
scope_info
=
c
f
->
c
lfunc
->
source
->
getScopeInfo
();
SourceInfo
*
source_info
=
c
f
->
c
lfunc
->
source
.
get
();
ScopeInfo
*
scope_info
=
clfunc
->
source
->
getScopeInfo
();
SourceInfo
*
source_info
=
clfunc
->
source
.
get
();
assert
(
!
c
f
->
c
lfunc
->
source
->
scoping
->
areGlobalsFromModule
());
assert
(
!
clfunc
->
source
->
scoping
->
areGlobalsFromModule
());
assert
(
globals
);
interpreter
->
setGlobals
(
globals
);
...
...
@@ -1723,19 +1749,19 @@ Box* astInterpretFunctionEval(CompiledFunction* cf, Box* globals, Box* boxedLoca
return
v
.
o
?
v
.
o
:
None
;
}
Box
*
astInterpretFrom
(
C
ompiledFunction
*
cf
,
AST_expr
*
after_expr
,
AST_stmt
*
enclosing_stmt
,
Box
*
expr_val
,
Box
*
astInterpretFrom
(
C
LFunction
*
clfunc
,
AST_expr
*
after_expr
,
AST_stmt
*
enclosing_stmt
,
Box
*
expr_val
,
FrameStackState
frame_state
)
{
assert
(
c
f
);
assert
(
c
lfunc
);
assert
(
enclosing_stmt
);
assert
(
frame_state
.
locals
);
assert
(
after_expr
);
assert
(
expr_val
);
ASTInterpreter
*
interpreter
=
new
ASTInterpreter
(
c
f
);
ASTInterpreter
*
interpreter
=
new
ASTInterpreter
(
c
lfunc
);
ScopeInfo
*
scope_info
=
c
f
->
c
lfunc
->
source
->
getScopeInfo
();
SourceInfo
*
source_info
=
c
f
->
c
lfunc
->
source
.
get
();
assert
(
c
f
->
c
lfunc
->
source
->
scoping
->
areGlobalsFromModule
());
ScopeInfo
*
scope_info
=
clfunc
->
source
->
getScopeInfo
();
SourceInfo
*
source_info
=
clfunc
->
source
.
get
();
assert
(
clfunc
->
source
->
scoping
->
areGlobalsFromModule
());
interpreter
->
setGlobals
(
source_info
->
parent_module
);
for
(
const
auto
&
p
:
frame_state
.
locals
->
d
)
{
...
...
@@ -1748,7 +1774,7 @@ Box* astInterpretFrom(CompiledFunction* cf, AST_expr* after_expr, AST_stmt* encl
}
else
if
(
name
==
CREATED_CLOSURE_NAME
)
{
interpreter
->
setCreatedClosure
(
p
.
second
);
}
else
{
InternedString
interned
=
c
f
->
c
lfunc
->
source
->
getInternedStrings
().
get
(
name
);
InternedString
interned
=
clfunc
->
source
->
getInternedStrings
().
get
(
name
);
interpreter
->
addSymbol
(
interned
,
p
.
second
,
false
);
}
}
...
...
@@ -1784,7 +1810,7 @@ Box* astInterpretFrom(CompiledFunction* cf, AST_expr* after_expr, AST_stmt* encl
if
(
start_block
==
NULL
)
{
// TODO innefficient
for
(
auto
block
:
c
f
->
c
lfunc
->
source
->
cfg
->
blocks
)
{
for
(
auto
block
:
clfunc
->
source
->
cfg
->
blocks
)
{
int
n
=
block
->
body
.
size
();
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
if
(
block
->
body
[
i
]
==
enclosing_stmt
)
{
...
...
@@ -1820,10 +1846,10 @@ Box* getGlobalsForInterpretedFrame(void* frame_ptr) {
return
interpreter
->
getGlobals
();
}
C
ompiledFunction
*
getCF
ForInterpretedFrame
(
void
*
frame_ptr
)
{
C
LFunction
*
getCL
ForInterpretedFrame
(
void
*
frame_ptr
)
{
ASTInterpreter
*
interpreter
=
s_interpreterMap
[
frame_ptr
];
assert
(
interpreter
);
return
interpreter
->
getC
F
();
return
interpreter
->
getC
L
();
}
FrameInfo
*
getFrameInfoForInterpretedFrame
(
void
*
frame_ptr
)
{
...
...
src/codegen/ast_interpreter.h
View file @
caa84b81
...
...
@@ -29,7 +29,7 @@ class AST_Jump;
class
Box
;
class
BoxedClosure
;
class
BoxedDict
;
struct
C
ompiled
Function
;
struct
C
L
Function
;
struct
LineInfo
;
extern
const
void
*
interpreter_instr_addr
;
...
...
@@ -72,15 +72,15 @@ struct Value {
};
void
setupInterpreter
();
Box
*
astInterpretFunction
(
C
ompiledFunction
*
f
,
int
nargs
,
Box
*
closure
,
Box
*
generator
,
Box
*
globals
,
Box
*
arg1
,
Box
*
arg
2
,
Box
*
arg
3
,
Box
**
args
);
Box
*
astInterpretFunctionEval
(
C
ompiled
Function
*
cf
,
Box
*
globals
,
Box
*
boxedLocals
);
Box
*
astInterpretFrom
(
C
ompiled
Function
*
cf
,
AST_expr
*
after_expr
,
AST_stmt
*
enclosing_stmt
,
Box
*
expr_val
,
Box
*
astInterpretFunction
(
C
LFunction
*
f
,
int
nargs
,
Box
*
closure
,
Box
*
generator
,
Box
*
globals
,
Box
*
arg1
,
Box
*
arg2
,
Box
*
arg3
,
Box
**
args
);
Box
*
astInterpretFunctionEval
(
C
L
Function
*
cf
,
Box
*
globals
,
Box
*
boxedLocals
);
Box
*
astInterpretFrom
(
C
L
Function
*
cf
,
AST_expr
*
after_expr
,
AST_stmt
*
enclosing_stmt
,
Box
*
expr_val
,
FrameStackState
frame_state
);
AST_stmt
*
getCurrentStatementForInterpretedFrame
(
void
*
frame_ptr
);
Box
*
getGlobalsForInterpretedFrame
(
void
*
frame_ptr
);
C
ompiledFunction
*
getCF
ForInterpretedFrame
(
void
*
frame_ptr
);
C
LFunction
*
getCL
ForInterpretedFrame
(
void
*
frame_ptr
);
struct
FrameInfo
;
FrameInfo
*
getFrameInfoForInterpretedFrame
(
void
*
frame_ptr
);
BoxedClosure
*
passedClosureForInterpretedFrame
(
void
*
frame_ptr
);
...
...
src/codegen/codegen.cpp
View file @
caa84b81
...
...
@@ -27,6 +27,7 @@
#include "analysis/function_analysis.h"
#include "analysis/scoping_analysis.h"
#include "codegen/baseline_jit.h"
#include "codegen/compvars.h"
#include "core/ast.h"
#include "core/util.h"
...
...
@@ -35,6 +36,27 @@ namespace pyston {
DS_DEFINE_RWLOCK
(
codegen_rwlock
);
CLFunction
::
CLFunction
(
int
num_args
,
int
num_defaults
,
bool
takes_varargs
,
bool
takes_kwargs
,
std
::
unique_ptr
<
SourceInfo
>
source
)
:
paramspec
(
num_args
,
num_defaults
,
takes_varargs
,
takes_kwargs
),
source
(
std
::
move
(
source
)),
param_names
(
this
->
source
->
ast
,
this
->
source
->
getInternedStrings
()),
always_use_version
(
NULL
),
code_obj
(
NULL
),
times_interpreted
(
0
)
{
assert
(
num_args
>=
num_defaults
);
}
CLFunction
::
CLFunction
(
int
num_args
,
int
num_defaults
,
bool
takes_varargs
,
bool
takes_kwargs
,
const
ParamNames
&
param_names
)
:
paramspec
(
num_args
,
num_defaults
,
takes_varargs
,
takes_kwargs
),
source
(
nullptr
),
param_names
(
param_names
),
always_use_version
(
NULL
),
code_obj
(
NULL
),
times_interpreted
(
0
)
{
assert
(
num_args
>=
num_defaults
);
}
SourceInfo
::
SourceInfo
(
BoxedModule
*
m
,
ScopingAnalysis
*
scoping
,
FutureFlags
future_flags
,
AST
*
ast
,
std
::
vector
<
AST_stmt
*>
body
,
std
::
string
fn
)
:
parent_module
(
m
),
...
...
src/codegen/compvars.cpp
View file @
caa84b81
...
...
@@ -249,7 +249,7 @@ public:
// var->getValue()->dump(); llvm::errs() << '\n';
// ptr->dump(); llvm::errs() << '\n';
// converted->getValue()->dump(); llvm::errs() << '\n';
bool
do_patchpoint
=
ENABLE_ICSETATTRS
&&
!
info
.
isInterpreted
()
;
bool
do_patchpoint
=
ENABLE_ICSETATTRS
;
if
(
do_patchpoint
)
{
ICSetupInfo
*
pp
=
createSetattrIC
(
info
.
getTypeRecorder
());
...
...
@@ -269,7 +269,7 @@ public:
llvm
::
Constant
*
ptr
=
embedRelocatablePtr
(
attr
,
g
.
llvm_boxedstring_type_ptr
);
// TODO
// bool do_patchpoint = ENABLE_ICDELATTRS
&& !info.isInterpreted()
;
// bool do_patchpoint = ENABLE_ICDELATTRS;
bool
do_patchpoint
=
false
;
if
(
do_patchpoint
)
{
...
...
@@ -317,7 +317,7 @@ public:
}
ConcreteCompilerVariable
*
len
(
IREmitter
&
emitter
,
const
OpInfo
&
info
,
ConcreteCompilerVariable
*
var
)
override
{
bool
do_patchpoint
=
ENABLE_ICGENERICS
&&
!
info
.
isInterpreted
()
;
bool
do_patchpoint
=
ENABLE_ICGENERICS
;
llvm
::
Value
*
rtn
;
if
(
do_patchpoint
)
{
ICSetupInfo
*
pp
=
createGenericIC
(
info
.
getTypeRecorder
(),
true
,
256
);
...
...
@@ -337,7 +337,7 @@ public:
CompilerVariable
*
slice
)
override
{
ConcreteCompilerVariable
*
converted_slice
=
slice
->
makeConverted
(
emitter
,
slice
->
getBoxType
());
bool
do_patchpoint
=
ENABLE_ICGETITEMS
&&
!
info
.
isInterpreted
()
;
bool
do_patchpoint
=
ENABLE_ICGETITEMS
;
llvm
::
Value
*
rtn
;
if
(
do_patchpoint
)
{
ICSetupInfo
*
pp
=
createGetitemIC
(
info
.
getTypeRecorder
());
...
...
@@ -414,7 +414,7 @@ public:
ConcreteCompilerVariable
*
converted_rhs
=
rhs
->
makeConverted
(
emitter
,
rhs
->
getBoxType
());
llvm
::
Value
*
rtn
;
bool
do_patchpoint
=
ENABLE_ICBINEXPS
&&
!
info
.
isInterpreted
()
;
bool
do_patchpoint
=
ENABLE_ICBINEXPS
;
llvm
::
Value
*
rt_func
;
void
*
rt_func_addr
;
...
...
@@ -495,7 +495,7 @@ CompilerVariable* UnknownType::getattr(IREmitter& emitter, const OpInfo& info, C
raw_func
=
(
void
*
)
pyston
::
getattr
;
}
bool
do_patchpoint
=
ENABLE_ICGETATTRS
&&
!
info
.
isInterpreted
()
;
bool
do_patchpoint
=
ENABLE_ICGETATTRS
;
if
(
do_patchpoint
)
{
ICSetupInfo
*
pp
=
createGetattrIC
(
info
.
getTypeRecorder
());
...
...
@@ -551,19 +551,13 @@ static ConcreteCompilerVariable* _call(IREmitter& emitter, const OpInfo& info, l
if
(
args
.
size
()
>=
4
)
{
llvm
::
Value
*
arg_array
;
if
(
info
.
isInterpreted
())
{
llvm
::
Value
*
n_bytes
=
getConstantInt
((
args
.
size
()
-
3
)
*
sizeof
(
Box
*
),
g
.
i64
);
mallocsave
=
emitter
.
getBuilder
()
->
CreateCall
(
g
.
funcs
.
malloc
,
n_bytes
);
arg_array
=
emitter
.
getBuilder
()
->
CreateBitCast
(
mallocsave
,
g
.
llvm_value_type_ptr
->
getPointerTo
());
}
else
{
llvm
::
Value
*
n_varargs
=
getConstantInt
(
args
.
size
()
-
3
,
g
.
i64
);
llvm
::
Value
*
n_varargs
=
getConstantInt
(
args
.
size
()
-
3
,
g
.
i64
);
// Don't use the IRBuilder since we want to specifically put this in the entry block so it only gets called
// once.
// TODO we could take this further and use the same alloca for all function calls?
llvm
::
Instruction
*
insertion_point
=
emitter
.
currentFunction
()
->
func
->
getEntryBlock
().
getFirstInsertionPt
();
arg_array
=
new
llvm
::
AllocaInst
(
g
.
llvm_value_type_ptr
,
n_varargs
,
"arg_scratch"
,
insertion_point
);
}
// Don't use the IRBuilder since we want to specifically put this in the entry block so it only gets called
// once.
// TODO we could take this further and use the same alloca for all function calls?
llvm
::
Instruction
*
insertion_point
=
emitter
.
currentFunction
()
->
func
->
getEntryBlock
().
getFirstInsertionPt
();
arg_array
=
new
llvm
::
AllocaInst
(
g
.
llvm_value_type_ptr
,
n_varargs
,
"arg_scratch"
,
insertion_point
);
for
(
int
i
=
3
;
i
<
args
.
size
();
i
++
)
{
llvm
::
Value
*
ptr
=
emitter
.
getBuilder
()
->
CreateConstGEP1_32
(
arg_array
,
i
-
3
);
...
...
@@ -590,8 +584,7 @@ static ConcreteCompilerVariable* _call(IREmitter& emitter, const OpInfo& info, l
// for (auto a : llvm_args)
// a->dump();
bool
do_patchpoint
=
ENABLE_ICCALLSITES
&&
!
info
.
isInterpreted
()
&&
(
func_addr
==
runtimeCall
||
func_addr
==
pyston
::
callattr
);
bool
do_patchpoint
=
ENABLE_ICCALLSITES
&&
(
func_addr
==
runtimeCall
||
func_addr
==
pyston
::
callattr
);
if
(
do_patchpoint
)
{
assert
(
func_addr
);
...
...
@@ -685,7 +678,7 @@ CompilerVariable* UnknownType::callattr(IREmitter& emitter, const OpInfo& info,
}
ConcreteCompilerVariable
*
UnknownType
::
nonzero
(
IREmitter
&
emitter
,
const
OpInfo
&
info
,
ConcreteCompilerVariable
*
var
)
{
bool
do_patchpoint
=
ENABLE_ICNONZEROS
&&
!
info
.
isInterpreted
()
;
bool
do_patchpoint
=
ENABLE_ICNONZEROS
;
llvm
::
Value
*
rtn_val
;
if
(
do_patchpoint
)
{
ICSetupInfo
*
pp
=
createNonzeroIC
(
info
.
getTypeRecorder
());
...
...
@@ -702,7 +695,7 @@ ConcreteCompilerVariable* UnknownType::nonzero(IREmitter& emitter, const OpInfo&
}
ConcreteCompilerVariable
*
UnknownType
::
hasnext
(
IREmitter
&
emitter
,
const
OpInfo
&
info
,
ConcreteCompilerVariable
*
var
)
{
bool
do_patchpoint
=
ENABLE_ICS
&&
!
info
.
isInterpreted
()
;
bool
do_patchpoint
=
ENABLE_ICS
;
do_patchpoint
=
false
;
// we are currently using runtime ics for this
llvm
::
Value
*
rtn_val
;
if
(
do_patchpoint
)
{
...
...
@@ -1573,7 +1566,6 @@ public:
}
assert
(
found
);
assert
(
!
cf
->
is_interpreted
);
assert
(
cf
->
code
);
std
::
vector
<
llvm
::
Type
*>
arg_types
;
...
...
@@ -1965,14 +1957,6 @@ CompilerVariable* makeStr(BoxedString* s) {
return
new
ValuedCompilerVariable
<
BoxedString
*>
(
STR_CONSTANT
,
s
,
true
);
}
class
VoidType
:
public
ConcreteCompilerType
{
public:
llvm
::
Type
*
llvmType
()
override
{
return
g
.
void_
;
}
Box
*
deserializeFromFrame
(
const
FrameVals
&
vals
)
override
{
abort
();
}
};
ConcreteCompilerType
*
VOID
=
new
VoidType
();
ConcreteCompilerType
*
typeFromClass
(
BoxedClass
*
c
)
{
assert
(
c
);
return
NormalObjectType
::
fromClass
(
c
);
...
...
src/codegen/irgen.cpp
View file @
caa84b81
...
...
@@ -579,11 +579,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
// printf("%ld\n", args.size());
llvm
::
CallInst
*
postcall
=
emitter
->
getBuilder
()
->
CreateCall
(
bitcast_r
,
args
);
postcall
->
setTailCall
(
true
);
if
(
rtn_type
==
VOID
)
{
emitter
->
getBuilder
()
->
CreateRetVoid
();
}
else
{
emitter
->
getBuilder
()
->
CreateRet
(
postcall
);
}
emitter
->
getBuilder
()
->
CreateRet
(
postcall
);
emitter
->
getBuilder
()
->
SetInsertPoint
(
llvm_entry_blocks
[
source
->
cfg
->
getStartingBlock
()]);
}
...
...
@@ -941,16 +937,15 @@ static std::string getUniqueFunctionName(std::string nameprefix, EffortLevel eff
os
<<
"_e"
<<
(
int
)
effort
;
if
(
entry
)
{
os
<<
"_osr"
<<
entry
->
backedge
->
target
->
idx
;
if
(
entry
->
cf
->
func
)
os
<<
"_from_"
<<
entry
->
cf
->
func
->
getName
().
data
();
}
os
<<
'_'
<<
num_functions
;
num_functions
++
;
return
os
.
str
();
}
CompiledFunction
*
doCompile
(
SourceInfo
*
source
,
ParamNames
*
param_names
,
const
OSREntryDescriptor
*
entry_descriptor
,
EffortLevel
effort
,
FunctionSpecialization
*
spec
,
std
::
string
nameprefix
)
{
CompiledFunction
*
doCompile
(
CLFunction
*
clfunc
,
SourceInfo
*
source
,
ParamNames
*
param_names
,
const
OSREntryDescriptor
*
entry_descriptor
,
EffortLevel
effort
,
FunctionSpecialization
*
spec
,
std
::
string
nameprefix
)
{
Timer
_t
(
"in doCompile"
);
Timer
_t2
;
long
irgen_us
=
0
;
...
...
@@ -1014,8 +1009,7 @@ CompiledFunction* doCompile(SourceInfo* source, ParamNames* param_names, const O
}
CompiledFunction
*
cf
=
new
CompiledFunction
(
NULL
,
spec
,
(
effort
==
EffortLevel
::
INTERPRETED
),
NULL
,
effort
,
entry_descriptor
);
CompiledFunction
*
cf
=
new
CompiledFunction
(
NULL
,
spec
,
NULL
,
effort
,
entry_descriptor
);
// Make sure that the instruction memory keeps the module object alive.
// TODO: implement this for real
...
...
@@ -1065,7 +1059,7 @@ CompiledFunction* doCompile(SourceInfo* source, ParamNames* param_names, const O
else
phis
=
computeRequiredPhis
(
*
param_names
,
source
->
cfg
,
liveness
,
source
->
getScopeInfo
());
IRGenState
irstate
(
cf
,
source
,
std
::
move
(
phis
),
param_names
,
getGCBuilder
(),
dbg_funcinfo
);
IRGenState
irstate
(
c
lfunc
,
c
f
,
source
,
std
::
move
(
phis
),
param_names
,
getGCBuilder
(),
dbg_funcinfo
);
emitBBs
(
&
irstate
,
types
,
entry_descriptor
,
blocks
);
...
...
src/codegen/irgen.h
View file @
caa84b81
...
...
@@ -100,8 +100,9 @@ extern const std::string PASSED_GENERATOR_NAME;
InternedString
getIsDefinedName
(
InternedString
name
,
InternedStringPool
&
interned_strings
);
bool
isIsDefinedName
(
llvm
::
StringRef
name
);
CompiledFunction
*
doCompile
(
SourceInfo
*
source
,
ParamNames
*
param_names
,
const
OSREntryDescriptor
*
entry_descriptor
,
EffortLevel
effort
,
FunctionSpecialization
*
spec
,
std
::
string
nameprefix
);
CompiledFunction
*
doCompile
(
CLFunction
*
clfunc
,
SourceInfo
*
source
,
ParamNames
*
param_names
,
const
OSREntryDescriptor
*
entry_descriptor
,
EffortLevel
effort
,
FunctionSpecialization
*
spec
,
std
::
string
nameprefix
);
// A common pattern is to branch based off whether a variable is defined but only if it is
// potentially-undefined. If it is potentially-undefined, we have to generate control-flow
...
...
@@ -134,7 +135,6 @@ public:
OpInfo
(
EffortLevel
effort
,
TypeRecorder
*
type_recorder
,
UnwindInfo
unw_info
)
:
effort
(
effort
),
type_recorder
(
type_recorder
),
unw_info
(
unw_info
)
{}
bool
isInterpreted
()
const
{
return
effort
==
EffortLevel
::
INTERPRETED
;
}
TypeRecorder
*
getTypeRecorder
()
const
{
return
type_recorder
;
}
};
}
...
...
src/codegen/irgen/hooks.cpp
View file @
caa84b81
...
...
@@ -127,23 +127,14 @@ LivenessAnalysis* SourceInfo::getLiveness() {
return
liveness_info
.
get
();
}
EffortLevel
initialEffort
()
{
if
(
FORCE_INTERPRETER
)
return
EffortLevel
::
INTERPRETED
;
if
(
FORCE_OPTIMIZE
)
return
EffortLevel
::
MAXIMAL
;
if
(
ENABLE_INTERPRETER
)
return
EffortLevel
::
INTERPRETED
;
return
EffortLevel
::
MODERATE
;
}
static
void
compileIR
(
CompiledFunction
*
cf
,
EffortLevel
effort
)
{
assert
(
cf
);
assert
(
cf
->
func
);
void
*
compiled
=
NULL
;
cf
->
code
=
NULL
;
if
(
effort
>
EffortLevel
::
INTERPRETED
)
{
{
Timer
_t
(
"to jit the IR"
);
#if LLVMREV < 215967
g
.
engine
->
addModule
(
cf
->
func
->
getParent
());
...
...
@@ -195,7 +186,7 @@ CompiledFunction* compileFunction(CLFunction* f, FunctionSpecialization* spec, E
ASSERT
(
f
->
versions
.
size
()
<
20
,
"%s %ld"
,
name
.
c_str
(),
f
->
versions
.
size
());
if
(
VERBOSITY
(
"irgen"
)
>=
2
||
(
VERBOSITY
(
"irgen"
)
==
1
&&
effort
>
EffortLevel
::
INTERPRETED
)
)
{
if
(
VERBOSITY
(
"irgen"
)
>=
1
)
{
std
::
string
s
;
llvm
::
raw_string_ostream
ss
(
s
);
...
...
@@ -233,13 +224,6 @@ CompiledFunction* compileFunction(CLFunction* f, FunctionSpecialization* spec, E
printf
(
"%s"
,
ss
.
str
().
c_str
());
}
#ifndef NDEBUG
if
(
effort
==
EffortLevel
::
INTERPRETED
)
{
for
(
auto
arg_type
:
spec
->
arg_types
)
assert
(
arg_type
==
UNKNOWN
);
}
#endif
// Do the analysis now if we had deferred it earlier:
if
(
source
->
cfg
==
NULL
)
{
source
->
cfg
=
computeCFG
(
source
,
source
->
body
);
...
...
@@ -247,17 +231,10 @@ CompiledFunction* compileFunction(CLFunction* f, FunctionSpecialization* spec, E
CompiledFunction
*
cf
=
0
;
if
(
effort
==
EffortLevel
::
INTERPRETED
)
{
assert
(
!
entry_descriptor
);
cf
=
new
CompiledFunction
(
0
,
spec
,
true
,
NULL
,
effort
,
0
);
}
else
{
cf
=
doCompile
(
source
,
&
f
->
param_names
,
entry_descriptor
,
effort
,
spec
,
name
);
compileIR
(
cf
,
effort
);
}
CompiledFunction
*
cf
=
doCompile
(
f
,
source
,
&
f
->
param_names
,
entry_descriptor
,
effort
,
spec
,
name
);
compileIR
(
cf
,
effort
);
f
->
addVersion
(
cf
);
assert
(
f
->
versions
.
size
());
long
us
=
_t
.
end
();
static
StatCounter
us_compiling
(
"us_compiling"
);
...
...
@@ -270,13 +247,6 @@ CompiledFunction* compileFunction(CLFunction* f, FunctionSpecialization* spec, E
num_compiles
.
log
();
switch
(
effort
)
{
case
EffortLevel
:
:
INTERPRETED
:
{
static
StatCounter
us_compiling
(
"us_compiling_0_interpreted"
);
us_compiling
.
log
(
us
);
static
StatCounter
num_compiles
(
"num_compiles_0_interpreted"
);
num_compiles
.
log
();
break
;
}
case
EffortLevel
:
:
MODERATE
:
{
static
StatCounter
us_compiling
(
"us_compiling_2_moderate"
);
us_compiling
.
log
(
us
);
...
...
@@ -299,7 +269,7 @@ CompiledFunction* compileFunction(CLFunction* f, FunctionSpecialization* spec, E
}
void
compileAndRunModule
(
AST_Module
*
m
,
BoxedModule
*
bm
)
{
C
ompiledFunction
*
cf
;
C
LFunction
*
clfunc
;
{
// scope for limiting the locked region:
LOCK_REGION
(
codegen_rwlock
.
asWrite
());
...
...
@@ -317,23 +287,12 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm) {
if
(
!
bm
->
hasattr
(
"__builtins__"
))
bm
->
giveAttr
(
"__builtins__"
,
PyModule_GetDict
(
builtins_module
));
CLFunction
*
cl_f
=
new
CLFunction
(
0
,
0
,
false
,
false
,
std
::
move
(
si
));
EffortLevel
effort
=
initialEffort
();
assert
(
scoping
->
areGlobalsFromModule
());
cf
=
compileFunction
(
cl_f
,
new
FunctionSpecialization
(
VOID
),
effort
,
NULL
);
assert
(
cf
->
clfunc
->
versions
.
size
());
clfunc
=
new
CLFunction
(
0
,
0
,
false
,
false
,
std
::
move
(
si
));
}
if
(
cf
->
is_interpreted
)
{
UNAVOIDABLE_STAT_TIMER
(
t0
,
"us_timer_interpreted_module_toplevel"
);
astInterpretFunction
(
cf
,
0
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
);
}
else
{
UNAVOIDABLE_STAT_TIMER
(
t1
,
"us_timer_jitted_module_toplevel"
);
((
void
(
*
)())
cf
->
code
)();
}
UNAVOIDABLE_STAT_TIMER
(
t0
,
"us_timer_interpreted_module_toplevel"
);
Box
*
r
=
astInterpretFunction
(
clfunc
,
0
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
);
assert
(
r
==
None
);
}
Box
*
evalOrExec
(
CLFunction
*
cl
,
Box
*
globals
,
Box
*
boxedLocals
)
{
...
...
@@ -341,24 +300,13 @@ Box* evalOrExec(CLFunction* cl, Box* globals, Box* boxedLocals) {
assert
(
globals
&&
(
globals
->
cls
==
module_cls
||
globals
->
cls
==
dict_cls
));
// TODO Right now we only support going into an exec or eval through the
// intepretter, since the interpretter has a special function which lets
// us set the locals object. We should probably support it for optimized
// code as well, so we could use initialEffort() here instead of hard-coding
// INTERPRETED. This could actually be useful if we actually cache the parse
// results (since sometimes eval or exec might be called on constant strings).
EffortLevel
effort
=
EffortLevel
::
INTERPRETED
;
Box
*
doc_string
=
cl
->
source
->
getDocString
();
if
(
doc_string
!=
None
)
{
static
BoxedString
*
doc_box
=
static_cast
<
BoxedString
*>
(
PyString_InternFromString
(
"__doc__"
));
setGlobal
(
boxedLocals
,
doc_box
,
doc_string
);
}
CompiledFunction
*
cf
=
compileFunction
(
cl
,
new
FunctionSpecialization
(
VOID
),
effort
,
NULL
);
assert
(
cf
->
clfunc
->
versions
.
size
());
return
astInterpretFunctionEval
(
cf
,
globals
,
boxedLocals
);
return
astInterpretFunctionEval
(
cl
,
globals
,
boxedLocals
);
}
CLFunction
*
compileForEvalOrExec
(
AST
*
source
,
std
::
vector
<
AST_stmt
*>
body
,
std
::
string
fn
,
PyCompilerFlags
*
flags
)
{
...
...
@@ -502,10 +450,10 @@ Box* compile(Box* source, Box* fn, Box* type, Box** _args) {
if
(
dont_inherit
)
{
future_flags
=
arg_future_flags
;
}
else
{
C
ompiledFunction
*
caller_cf
=
getTopCompiled
Function
();
assert
(
caller_c
f
!=
NULL
);
assert
(
caller_c
f
->
clfunc
->
source
!=
NULL
);
FutureFlags
caller_future_flags
=
caller_c
f
->
clfunc
->
source
->
future_flags
;
C
LFunction
*
caller_cl
=
getTopPython
Function
();
assert
(
caller_c
l
!=
NULL
);
assert
(
caller_c
l
->
source
!=
NULL
);
FutureFlags
caller_future_flags
=
caller_c
l
->
source
->
future_flags
;
future_flags
=
arg_future_flags
|
caller_future_flags
;
}
...
...
@@ -602,10 +550,10 @@ static Box* evalMain(Box* boxedCode, Box* globals, Box* locals, PyCompilerFlags*
}
Box
*
eval
(
Box
*
boxedCode
,
Box
*
globals
,
Box
*
locals
)
{
C
ompiledFunction
*
caller_cf
=
getTopCompiled
Function
();
assert
(
caller_c
f
!=
NULL
);
assert
(
caller_c
f
->
clfunc
->
source
!=
NULL
);
FutureFlags
caller_future_flags
=
caller_c
f
->
clfunc
->
source
->
future_flags
;
C
LFunction
*
caller_cl
=
getTopPython
Function
();
assert
(
caller_c
l
!=
NULL
);
assert
(
caller_c
l
->
source
!=
NULL
);
FutureFlags
caller_future_flags
=
caller_c
l
->
source
->
future_flags
;
PyCompilerFlags
pcf
;
pcf
.
cf_flags
=
caller_future_flags
;
...
...
@@ -742,13 +690,12 @@ void CompiledFunction::speculationFailed() {
}
}
CompiledFunction
::
CompiledFunction
(
llvm
::
Function
*
func
,
FunctionSpecialization
*
spec
,
bool
is_interpreted
,
void
*
code
,
EffortLevel
effort
,
const
OSREntryDescriptor
*
entry_descriptor
)
CompiledFunction
::
CompiledFunction
(
llvm
::
Function
*
func
,
FunctionSpecialization
*
spec
,
void
*
code
,
EffortLevel
effort
,
const
OSREntryDescriptor
*
entry_descriptor
)
:
clfunc
(
NULL
),
func
(
func
),
spec
(
spec
),
entry_descriptor
(
entry_descriptor
),
is_interpreted
(
is_interpreted
),
code
(
code
),
effort
(
effort
),
times_called
(
0
),
...
...
@@ -758,9 +705,11 @@ CompiledFunction::CompiledFunction(llvm::Function* func, FunctionSpecialization*
}
ConcreteCompilerType
*
CompiledFunction
::
getReturnType
()
{
assert
(((
bool
)
spec
)
^
((
bool
)
entry_descriptor
));
if
(
spec
)
return
spec
->
rtn_type
;
return
entry_descriptor
->
cf
->
getReturnType
();
else
return
UNKNOWN
;
}
/// Reoptimizes the given function version at the new effort level.
...
...
@@ -809,18 +758,16 @@ CompiledFunction* compilePartialFuncInternal(OSRExit* exit) {
LOCK_REGION
(
codegen_rwlock
.
asWrite
());
assert
(
exit
);
assert
(
exit
->
parent_cf
);
assert
(
exit
->
parent_cf
->
effort
<
EffortLevel
::
MAXIMAL
);
stat_osrexits
.
log
();
// if (VERBOSITY("irgen") >= 1) printf("In compilePartialFunc, handling %p\n", exit);
assert
(
exit
->
parent_cf
->
clfunc
);
CompiledFunction
*&
new_cf
=
exit
->
parent_cf
->
clfunc
->
osr_versions
[
exit
->
entry
];
CLFunction
*
clfunc
=
exit
->
entry
->
clfunc
;
assert
(
clfunc
);
CompiledFunction
*&
new_cf
=
clfunc
->
osr_versions
[
exit
->
entry
];
if
(
new_cf
==
NULL
)
{
EffortLevel
new_effort
=
exit
->
parent_cf
->
effort
==
EffortLevel
::
INTERPRETED
?
EffortLevel
::
MODERATE
:
EffortLevel
::
MAXIMAL
;
CompiledFunction
*
compiled
=
compileFunction
(
exit
->
parent_cf
->
clfunc
,
NULL
,
new_effort
,
exit
->
entry
);
EffortLevel
new_effort
=
EffortLevel
::
MAXIMAL
;
CompiledFunction
*
compiled
=
compileFunction
(
clfunc
,
NULL
,
new_effort
,
exit
->
entry
);
assert
(
compiled
==
new_cf
);
stat_osr_compiles
.
log
();
...
...
@@ -843,16 +790,9 @@ extern "C" CompiledFunction* reoptCompiledFuncInternal(CompiledFunction* cf) {
assert
(
cf
->
effort
<
EffortLevel
::
MAXIMAL
);
assert
(
cf
->
clfunc
->
versions
.
size
());
EffortLevel
new_effort
;
if
(
cf
->
effort
==
EffortLevel
::
INTERPRETED
)
new_effort
=
EffortLevel
::
MODERATE
;
else
if
(
cf
->
effort
==
EffortLevel
::
MODERATE
)
new_effort
=
EffortLevel
::
MAXIMAL
;
else
RELEASE_ASSERT
(
0
,
"unknown effort: %d"
,
cf
->
effort
);
EffortLevel
new_effort
=
EffortLevel
::
MAXIMAL
;
CompiledFunction
*
new_cf
=
_doReopt
(
cf
,
new_effort
);
assert
(
!
new_cf
->
is_interpreted
);
return
new_cf
;
}
...
...
@@ -905,6 +845,6 @@ void addRTFunction(CLFunction* cl_f, void* f, ConcreteCompilerType* rtn_type,
#endif
FunctionSpecialization
*
spec
=
new
FunctionSpecialization
(
processType
(
rtn_type
),
arg_types
);
cl_f
->
addVersion
(
new
CompiledFunction
(
NULL
,
spec
,
f
alse
,
f
,
EffortLevel
::
MAXIMAL
,
NULL
));
cl_f
->
addVersion
(
new
CompiledFunction
(
NULL
,
spec
,
f
,
EffortLevel
::
MAXIMAL
,
NULL
));
}
}
src/codegen/irgen/irgenerator.cpp
View file @
caa84b81
...
...
@@ -42,9 +42,11 @@ extern "C" void dumpLLVM(llvm::Value* v) {
v
->
dump
();
}
IRGenState
::
IRGenState
(
CompiledFunction
*
cf
,
SourceInfo
*
source_info
,
std
::
unique_ptr
<
PhiAnalysis
>
phis
,
ParamNames
*
param_names
,
GCBuilder
*
gc
,
llvm
::
MDNode
*
func_dbg_info
)
:
cf
(
cf
),
IRGenState
::
IRGenState
(
CLFunction
*
clfunc
,
CompiledFunction
*
cf
,
SourceInfo
*
source_info
,
std
::
unique_ptr
<
PhiAnalysis
>
phis
,
ParamNames
*
param_names
,
GCBuilder
*
gc
,
llvm
::
MDNode
*
func_dbg_info
)
:
clfunc
(
clfunc
),
cf
(
cf
),
source_info
(
source_info
),
phis
(
std
::
move
(
phis
)),
param_names
(
param_names
),
...
...
@@ -402,8 +404,6 @@ public:
llvm
::
Value
*
createIC
(
const
ICSetupInfo
*
pp
,
void
*
func_addr
,
const
std
::
vector
<
llvm
::
Value
*>&
args
,
UnwindInfo
unw_info
)
override
{
assert
(
irstate
->
getEffortLevel
()
!=
EffortLevel
::
INTERPRETED
);
std
::
vector
<
llvm
::
Value
*>
stackmap_args
;
llvm
::
CallSite
rtn
...
...
@@ -493,7 +493,7 @@ private:
assert
(
ast
);
EffortLevel
effort
=
irstate
->
getEffortLevel
();
bool
record_types
=
(
effort
!=
EffortLevel
::
INTERPRETED
&&
effort
!=
EffortLevel
::
MAXIMAL
)
;
bool
record_types
=
effort
!=
EffortLevel
::
MAXIMAL
;
TypeRecorder
*
type_recorder
;
if
(
record_types
)
{
...
...
@@ -531,10 +531,7 @@ private:
emitter
.
getBuilder
()
->
SetInsertPoint
(
curblock
);
llvm
::
Value
*
v
=
emitter
.
createCall2
(
UnwindInfo
(
current_statement
,
NULL
),
g
.
funcs
.
deopt
,
embedRelocatablePtr
(
node
,
g
.
llvm_aststmt_type_ptr
),
node_value
);
if
(
irstate
->
getReturnType
()
==
VOID
)
emitter
.
getBuilder
()
->
CreateRetVoid
();
else
emitter
.
getBuilder
()
->
CreateRet
(
v
);
emitter
.
getBuilder
()
->
CreateRet
(
v
);
curblock
=
success_bb
;
emitter
.
getBuilder
()
->
SetInsertPoint
(
curblock
);
...
...
@@ -594,38 +591,29 @@ private:
llvm
::
Value
*
cxaexc_pointer
=
emitter
.
getBuilder
()
->
CreateExtractValue
(
landing_pad
,
{
0
});
if
(
irstate
->
getEffortLevel
()
!=
EffortLevel
::
INTERPRETED
)
{
llvm
::
Function
*
std_module_catch
=
g
.
stdlib_module
->
getFunction
(
"__cxa_begin_catch"
);
auto
begin_catch_func
=
g
.
cur_module
->
getOrInsertFunction
(
std_module_catch
->
getName
(),
std_module_catch
->
getFunctionType
());
assert
(
begin_catch_func
);
llvm
::
Value
*
excinfo_pointer
=
emitter
.
getBuilder
()
->
CreateCall
(
begin_catch_func
,
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
();
llvm
::
Function
*
std_module_catch
=
g
.
stdlib_module
->
getFunction
(
"__cxa_begin_catch"
);
auto
begin_catch_func
=
g
.
cur_module
->
getOrInsertFunction
(
std_module_catch
->
getName
(),
std_module_catch
->
getFunctionType
());
assert
(
begin_catch_func
);
// 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:
llvm
::
Value
*
exc_obj
=
emitter
.
getBuilder
()
->
CreateBitCast
(
cxaexc_pointer
,
g
.
llvm_value_type_ptr
);
}
llvm
::
Value
*
excinfo_pointer
=
emitter
.
getBuilder
()
->
CreateCall
(
begin_catch_func
,
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
)
});
}
case
AST_LangPrimitive
:
:
LOCALS
:
{
return
new
ConcreteCompilerVariable
(
UNKNOWN
,
irstate
->
getBoxedLocalsVar
(),
true
);
...
...
@@ -986,7 +974,7 @@ private:
if
(
node
->
id
.
s
()
==
"None"
)
return
getNone
();
bool
do_patchpoint
=
ENABLE_ICGETGLOBALS
&&
(
irstate
->
getEffortLevel
()
!=
EffortLevel
::
INTERPRETED
)
;
bool
do_patchpoint
=
ENABLE_ICGETGLOBALS
;
if
(
do_patchpoint
)
{
ICSetupInfo
*
pp
=
createGetGlobalIC
(
getOpInfoForNode
(
node
,
unw_info
).
getTypeRecorder
());
...
...
@@ -1657,7 +1645,7 @@ private:
// TODO add a CompilerVariable::setattr, which can (similar to getitem)
// statically-resolve the function if possible, and only fall back to
// patchpoints if it couldn't.
bool
do_patchpoint
=
ENABLE_ICSETITEMS
&&
(
irstate
->
getEffortLevel
()
!=
EffortLevel
::
INTERPRETED
)
;
bool
do_patchpoint
=
ENABLE_ICSETITEMS
;
if
(
do_patchpoint
)
{
ICSetupInfo
*
pp
=
createSetitemIC
(
getEmptyOpInfo
(
unw_info
).
getTypeRecorder
());
...
...
@@ -1783,7 +1771,7 @@ private:
tget
->
decvref
(
emitter
);
slice
->
decvref
(
emitter
);
bool
do_patchpoint
=
ENABLE_ICDELITEMS
&&
(
irstate
->
getEffortLevel
()
!=
EffortLevel
::
INTERPRETED
)
;
bool
do_patchpoint
=
ENABLE_ICDELITEMS
;
if
(
do_patchpoint
)
{
ICSetupInfo
*
pp
=
createDelitemIC
(
getEmptyOpInfo
(
unw_info
).
getTypeRecorder
());
...
...
@@ -1955,12 +1943,6 @@ private:
CompilerVariable
*
val
;
if
(
node
->
value
==
NULL
)
{
if
(
irstate
->
getReturnType
()
==
VOID
)
{
endBlock
(
DEAD
);
emitter
.
getBuilder
()
->
CreateRetVoid
();
return
;
}
val
=
getNone
();
}
else
{
val
=
evalExpr
(
node
->
value
,
unw_info
);
...
...
@@ -2051,8 +2033,8 @@ private:
// Emitting the actual OSR:
emitter
.
getBuilder
()
->
SetInsertPoint
(
onramp
);
OSREntryDescriptor
*
entry
=
OSREntryDescriptor
::
create
(
irstate
->
getC
urFunction
(),
osr_key
);
OSRExit
*
exit
=
new
OSRExit
(
irstate
->
getCurFunction
(),
entry
);
OSREntryDescriptor
*
entry
=
OSREntryDescriptor
::
create
(
irstate
->
getC
L
(),
osr_key
);
OSRExit
*
exit
=
new
OSRExit
(
entry
);
llvm
::
Value
*
partial_func
=
emitter
.
getBuilder
()
->
CreateCall
(
g
.
funcs
.
compilePartialFunc
,
embedRelocatablePtr
(
exit
,
g
.
i8
->
getPointerTo
()));
...
...
@@ -2185,10 +2167,7 @@ private:
converted_args
[
i
]
->
decvref
(
emitter
);
}
if
(
irstate
->
getReturnType
()
==
VOID
)
emitter
.
getBuilder
()
->
CreateRetVoid
();
else
emitter
.
getBuilder
()
->
CreateRet
(
rtn
);
emitter
.
getBuilder
()
->
CreateRet
(
rtn
);
emitter
.
getBuilder
()
->
SetInsertPoint
(
starting_block
);
}
...
...
src/codegen/irgen/irgenerator.h
View file @
caa84b81
...
...
@@ -54,6 +54,9 @@ extern const std::string FRAME_INFO_PTR_NAME;
// TODO this probably shouldn't be here
class
IRGenState
{
private:
// Note: due to some not-yet-fixed behavior, cf->clfunc is NULL will only get set to point
// to clfunc at the end of irgen.
CLFunction
*
clfunc
;
CompiledFunction
*
cf
;
SourceInfo
*
source_info
;
std
::
unique_ptr
<
PhiAnalysis
>
phis
;
...
...
@@ -69,11 +72,12 @@ private:
public:
IRGenState
(
CompiledFunction
*
cf
,
SourceInfo
*
source_info
,
std
::
unique_ptr
<
PhiAnalysis
>
phis
,
IRGenState
(
C
LFunction
*
clfunc
,
C
ompiledFunction
*
cf
,
SourceInfo
*
source_info
,
std
::
unique_ptr
<
PhiAnalysis
>
phis
,
ParamNames
*
param_names
,
GCBuilder
*
gc
,
llvm
::
MDNode
*
func_dbg_info
);
~
IRGenState
();
CompiledFunction
*
getCurFunction
()
{
return
cf
;
}
CLFunction
*
getCL
()
{
return
clfunc
;
}
llvm
::
Function
*
getLLVMFunction
()
{
return
cf
->
func
;
}
...
...
src/codegen/osrentry.h
View file @
caa84b81
...
...
@@ -31,26 +31,25 @@ struct StackMap;
class
OSREntryDescriptor
{
private:
OSREntryDescriptor
(
C
ompiledFunction
*
from_cf
,
AST_Jump
*
backedge
)
:
cf
(
from_cf
),
backedge
(
backedge
)
{
}
OSREntryDescriptor
(
C
LFunction
*
clfunc
,
AST_Jump
*
backedge
)
:
clfunc
(
clfunc
),
backedge
(
backedge
)
{
assert
(
clfunc
);
}
public:
C
ompiledFunction
*
const
cf
;
C
LFunction
*
clfunc
;
AST_Jump
*
const
backedge
;
typedef
std
::
map
<
InternedString
,
ConcreteCompilerType
*>
ArgMap
;
ArgMap
args
;
static
OSREntryDescriptor
*
create
(
C
ompiledFunction
*
from_cf
,
AST_Jump
*
backedge
)
{
return
new
OSREntryDescriptor
(
from_cf
,
backedge
);
static
OSREntryDescriptor
*
create
(
C
LFunction
*
clfunc
,
AST_Jump
*
backedge
)
{
return
new
OSREntryDescriptor
(
clfunc
,
backedge
);
}
};
class
OSRExit
{
private:
public:
CompiledFunction
*
const
parent_cf
;
const
OSREntryDescriptor
*
entry
;
OSRExit
(
CompiledFunction
*
parent_cf
,
const
OSREntryDescriptor
*
entry
)
:
parent_cf
(
parent_cf
),
entry
(
entry
)
{}
OSRExit
(
const
OSREntryDescriptor
*
entry
)
:
entry
(
entry
)
{}
};
}
...
...
src/codegen/patchpoints.cpp
View file @
caa84b81
...
...
@@ -143,15 +143,6 @@ static std::unordered_set<int> extractLiveOuts(StackMap::Record* r, llvm::Callin
}
void
processStackmap
(
CompiledFunction
*
cf
,
StackMap
*
stackmap
)
{
// FIXME: this is pretty hacky, that we don't delete the patchpoints here.
// We need them currently for the llvm interpreter.
// Eventually we'll get rid of that and use an AST interpreter, and then we won't need this hack.
if
(
cf
->
effort
==
EffortLevel
::
INTERPRETED
)
{
assert
(
!
stackmap
);
new_patchpoints
.
clear
();
return
;
}
int
nrecords
=
stackmap
?
stackmap
->
records
.
size
()
:
0
;
assert
(
cf
->
location_map
==
NULL
);
...
...
src/codegen/patchpoints.h
View file @
caa84b81
...
...
@@ -135,10 +135,14 @@ public:
bool
hasReturnValue
()
const
{
return
has_return_value
;
}
llvm
::
CallingConv
::
ID
getCallingConvention
()
const
{
// FIXME: we currently have some issues with using PreserveAll (the rewriter currently
// does not completely preserve live outs), so disable it temporarily.
#if 0
// The plan is to switch probably everything over to PreseveAll (and potentially AnyReg),
// but for only switch Getattr so the testing can be localized:
if (type == Getattr || type == Setattr)
return llvm::CallingConv::PreserveAll;
#endif
return
llvm
::
CallingConv
::
C
;
}
...
...
src/codegen/unwinding.cpp
View file @
caa84b81
...
...
@@ -276,6 +276,9 @@ struct PythonFrameId {
class
PythonFrameIteratorImpl
{
public:
PythonFrameId
id
;
CLFunction
*
cl
;
// always exists
// These only exist if id.type==COMPILED:
CompiledFunction
*
cf
;
// We have to save a copy of the regs since it's very difficult to keep the unw_context_t
// structure valid.
...
...
@@ -284,15 +287,26 @@ public:
PythonFrameIteratorImpl
()
:
regs_valid
(
0
)
{}
PythonFrameIteratorImpl
(
PythonFrameId
::
FrameType
type
,
uint64_t
ip
,
uint64_t
bp
,
CompiledFunction
*
cf
)
:
id
(
PythonFrameId
(
type
,
ip
,
bp
)),
cf
(
cf
),
regs_valid
(
0
)
{}
PythonFrameIteratorImpl
(
PythonFrameId
::
FrameType
type
,
uint64_t
ip
,
uint64_t
bp
,
CLFunction
*
cl
,
CompiledFunction
*
cf
)
:
id
(
PythonFrameId
(
type
,
ip
,
bp
)),
cl
(
cl
),
cf
(
cf
),
regs_valid
(
0
)
{
assert
(
cl
);
assert
((
type
==
PythonFrameId
::
COMPILED
)
==
(
cf
!=
NULL
));
}
CompiledFunction
*
getCF
()
const
{
assert
(
cf
);
return
cf
;
}
CLFunction
*
getCL
()
const
{
assert
(
cl
);
return
cl
;
}
uint64_t
readLocation
(
const
StackMap
::
Record
::
Location
&
loc
)
{
assert
(
id
.
type
==
PythonFrameId
::
COMPILED
);
if
(
loc
.
type
==
StackMap
::
Record
::
Location
::
LocationType
::
Register
)
{
// TODO: need to make sure we deal with patchpoints appropriately
return
getReg
(
loc
.
regnum
);
...
...
@@ -412,6 +426,11 @@ static bool inGeneratorEntry(unw_word_t ip) {
return
((
unw_word_t
)
generatorEntry
<
ip
&&
ip
<=
generator_entry_end
);
}
static
bool
inDeopt
(
unw_word_t
ip
)
{
static
unw_word_t
deopt_end
=
getFunctionEnd
((
unw_word_t
)
deopt
);
return
((
unw_word_t
)
deopt
<
ip
&&
ip
<=
deopt_end
);
}
static
inline
unw_word_t
get_cursor_reg
(
unw_cursor_t
*
cursor
,
int
reg
)
{
unw_word_t
v
;
...
...
@@ -430,18 +449,16 @@ static inline unw_word_t get_cursor_bp(unw_cursor_t* cursor) {
// frame information through the PythonFrameIteratorImpl* info arg.
bool
frameIsPythonFrame
(
unw_word_t
ip
,
unw_word_t
bp
,
unw_cursor_t
*
cursor
,
PythonFrameIteratorImpl
*
info
)
{
CompiledFunction
*
cf
=
getCFForAddress
(
ip
);
CLFunction
*
cl
=
cf
?
cf
->
clfunc
:
NULL
;
bool
jitted
=
cf
!=
NULL
;
if
(
!
cf
)
{
if
(
inASTInterpreterExecuteInner
(
ip
))
{
cf
=
getCFForInterpretedFrame
((
void
*
)
bp
);
assert
(
cf
);
}
}
bool
interpreted
=
!
jitted
&&
inASTInterpreterExecuteInner
(
ip
);
if
(
interpreted
)
cl
=
getCLForInterpretedFrame
((
void
*
)
bp
);
if
(
!
cf
)
if
(
!
jitted
&&
!
interpreted
)
return
false
;
*
info
=
PythonFrameIteratorImpl
(
jitted
?
PythonFrameId
::
COMPILED
:
PythonFrameId
::
INTERPRETED
,
ip
,
bp
,
cf
);
*
info
=
PythonFrameIteratorImpl
(
jitted
?
PythonFrameId
::
COMPILED
:
PythonFrameId
::
INTERPRETED
,
ip
,
bp
,
c
l
,
c
f
);
if
(
jitted
)
{
// Try getting all the callee-save registers, and save the ones we were able to get.
// Some of them may be inaccessible, I think because they weren't defined by that
...
...
@@ -576,10 +593,10 @@ void throwingException(PythonUnwindSession* unwind) {
static
const
LineInfo
lineInfoForFrame
(
PythonFrameIteratorImpl
*
frame_it
)
{
AST_stmt
*
current_stmt
=
frame_it
->
getCurrentStatement
();
auto
*
c
f
=
frame_it
->
getCF
();
assert
(
c
f
);
auto
*
c
l
=
frame_it
->
getCL
();
assert
(
c
l
);
auto
source
=
c
f
->
clfunc
->
source
.
get
();
auto
source
=
c
l
->
source
.
get
();
return
LineInfo
(
current_stmt
->
lineno
,
current_stmt
->
col_offset
,
source
->
fn
,
source
->
getName
());
}
...
...
@@ -609,12 +626,16 @@ void unwindingThroughFrame(PythonUnwindSession* unwind_session, unw_cursor_t* cu
unw_word_t
bp
=
get_cursor_bp
(
cursor
);
PythonFrameIteratorImpl
frame_iter
;
if
(
frameIsPythonFrame
(
ip
,
bp
,
cursor
,
&
frame_iter
))
{
if
(
inDeopt
(
ip
))
{
assert
(
!
unwind_session
->
shouldSkipFrame
());
unwind_session
->
setShouldSkipNextFrame
(
true
);
}
else
if
(
frameIsPythonFrame
(
ip
,
bp
,
cursor
,
&
frame_iter
))
{
if
(
!
unwind_session
->
shouldSkipFrame
())
unwind_session
->
addTraceback
(
lineInfoForFrame
(
&
frame_iter
));
// frame_iter->cf->entry_descriptor will be non-null for OSR frames.
unwind_session
->
setShouldSkipNextFrame
((
bool
)
frame_iter
.
cf
->
entry_descriptor
);
bool
was_osr
=
(
frame_iter
.
getId
().
type
==
PythonFrameId
::
COMPILED
)
&&
(
frame_iter
.
cf
->
entry_descriptor
);
unwind_session
->
setShouldSkipNextFrame
(
was_osr
);
}
}
...
...
@@ -641,16 +662,21 @@ template <typename Func> void unwindPythonStack(Func func) {
unw_word_t
ip
=
get_cursor_ip
(
&
cursor
);
unw_word_t
bp
=
get_cursor_bp
(
&
cursor
);
// TODO: this should probably just call unwindingThroughFrame?
bool
stop_unwinding
=
false
;
PythonFrameIteratorImpl
frame_iter
;
if
(
frameIsPythonFrame
(
ip
,
bp
,
&
cursor
,
&
frame_iter
))
{
if
(
inDeopt
(
ip
))
{
assert
(
!
unwind_session
->
shouldSkipFrame
());
unwind_session
->
setShouldSkipNextFrame
(
true
);
}
else
if
(
frameIsPythonFrame
(
ip
,
bp
,
&
cursor
,
&
frame_iter
))
{
if
(
!
unwind_session
->
shouldSkipFrame
())
stop_unwinding
=
func
(
&
frame_iter
);
// frame_iter->cf->entry_descriptor will be non-null for OSR frames.
unwind_session
->
setShouldSkipNextFrame
((
bool
)
frame_iter
.
cf
->
entry_descriptor
);
bool
was_osr
=
(
frame_iter
.
getId
().
type
==
PythonFrameId
::
COMPILED
)
&&
(
frame_iter
.
cf
->
entry_descriptor
);
unwind_session
->
setShouldSkipNextFrame
(
was_osr
);
}
if
(
stop_unwinding
)
...
...
@@ -791,11 +817,11 @@ ExcInfo* getFrameExcInfo() {
return
cur_exc
;
}
C
ompiledFunction
*
getTopCompiled
Function
()
{
C
LFunction
*
getTopPython
Function
()
{
auto
rtn
=
getTopPythonFrame
();
if
(
!
rtn
)
return
NULL
;
return
getTopPythonFrame
()
->
getC
F
();
return
getTopPythonFrame
()
->
getC
L
();
}
Box
*
getGlobals
()
{
...
...
@@ -810,10 +836,10 @@ Box* getGlobalsDict() {
}
BoxedModule
*
getCurrentModule
()
{
C
ompiledFunction
*
compiledFunction
=
getTopCompiled
Function
();
if
(
!
c
ompiledFunction
)
C
LFunction
*
clfunc
=
getTopPython
Function
();
if
(
!
c
lfunc
)
return
NULL
;
return
c
ompiledFunction
->
c
lfunc
->
source
->
parent_module
;
return
clfunc
->
source
->
parent_module
;
}
PythonFrameIterator
getPythonFrame
(
int
depth
)
{
...
...
@@ -844,11 +870,11 @@ PythonFrameIterator::PythonFrameIterator(std::unique_ptr<PythonFrameIteratorImpl
std
::
swap
(
this
->
impl
,
impl
);
}
// TODO factor get
StackLocalsIncludingUserHidden
and fastLocalsToBoxedLocals
// TODO factor get
DeoptState
and fastLocalsToBoxedLocals
// because they are pretty ugly but have a pretty repetitive pattern.
FrameStackState
getFrameStack
State
()
{
FrameStackState
rtn
(
NULL
,
NULL
)
;
DeoptState
getDeopt
State
()
{
DeoptState
rtn
;
bool
found
=
false
;
unwindPythonStack
([
&
](
PythonFrameIteratorImpl
*
frame_iter
)
{
BoxedDict
*
d
;
...
...
@@ -917,7 +943,9 @@ FrameStackState getFrameStackState() {
abort
();
}
rtn
=
FrameStackState
(
d
,
frame_iter
->
getFrameInfo
());
rtn
.
frame_state
=
FrameStackState
(
d
,
frame_iter
->
getFrameInfo
());
rtn
.
cf
=
cf
;
rtn
.
current_stmt
=
frame_iter
->
getCurrentStatement
();
found
=
true
;
return
true
;
});
...
...
@@ -937,17 +965,18 @@ Box* PythonFrameIterator::fastLocalsToBoxedLocals() {
BoxedClosure
*
closure
;
FrameInfo
*
frame_info
;
C
ompiledFunction
*
cf
=
impl
->
getCF
();
ScopeInfo
*
scope_info
=
c
f
->
c
lfunc
->
source
->
getScopeInfo
();
C
LFunction
*
clfunc
=
impl
->
getCL
();
ScopeInfo
*
scope_info
=
clfunc
->
source
->
getScopeInfo
();
if
(
scope_info
->
areLocalsFromModule
())
{
// TODO we should cache this in frame_info->locals or something so that locals()
// (and globals() too) will always return the same dict
RELEASE_ASSERT
(
c
f
->
c
lfunc
->
source
->
scoping
->
areGlobalsFromModule
(),
""
);
return
c
f
->
c
lfunc
->
source
->
parent_module
->
getAttrWrapper
();
RELEASE_ASSERT
(
clfunc
->
source
->
scoping
->
areGlobalsFromModule
(),
""
);
return
clfunc
->
source
->
parent_module
->
getAttrWrapper
();
}
if
(
impl
->
getId
().
type
==
PythonFrameId
::
COMPILED
)
{
CompiledFunction
*
cf
=
impl
->
getCF
();
d
=
new
BoxedDict
();
uint64_t
ip
=
impl
->
getId
().
ip
;
...
...
@@ -1081,24 +1110,18 @@ Box* PythonFrameIterator::fastLocalsToBoxedLocals() {
return
frame_info
->
boxedLocals
;
}
ExecutionPoint
getExecutionPoint
()
{
auto
frame
=
getTopPythonFrame
();
auto
cf
=
frame
->
getCF
();
auto
current_stmt
=
frame
->
getCurrentStatement
();
return
ExecutionPoint
({.
cf
=
cf
,
.
current_stmt
=
current_stmt
});
}
std
::
unique_ptr
<
ExecutionPoint
>
PythonFrameIterator
::
getExecutionPoint
()
{
assert
(
impl
.
get
());
auto
cf
=
impl
->
getCF
();
auto
stmt
=
impl
->
getCurrentStatement
();
return
std
::
unique_ptr
<
ExecutionPoint
>
(
new
ExecutionPoint
({.
cf
=
cf
,
.
current_stmt
=
stmt
}));
AST_stmt
*
PythonFrameIterator
::
getCurrentStatement
()
{
return
impl
->
getCurrentStatement
();
}
CompiledFunction
*
PythonFrameIterator
::
getCF
()
{
return
impl
->
getCF
();
}
CLFunction
*
PythonFrameIterator
::
getCL
()
{
return
impl
->
getCL
();
}
Box
*
PythonFrameIterator
::
getGlobalsDict
()
{
return
impl
->
getGlobalsDict
();
}
...
...
src/codegen/unwinding.h
View file @
caa84b81
...
...
@@ -51,11 +51,7 @@ void unwindingThroughFrame(PythonUnwindSession* unwind_session, unw_cursor_t* cu
void
exceptionCaughtInInterpreter
(
LineInfo
line_info
,
ExcInfo
*
exc_info
);
struct
ExecutionPoint
{
CompiledFunction
*
cf
;
AST_stmt
*
current_stmt
;
};
ExecutionPoint
getExecutionPoint
();
CLFunction
*
getTopPythonFunction
();
// debugging/stat helper, returns python filename:linenumber, or "unknown:-1" if it fails
std
::
string
getCurrentPythonLine
();
...
...
@@ -73,9 +69,10 @@ private:
public:
CompiledFunction
*
getCF
();
CLFunction
*
getCL
();
FrameInfo
*
getFrameInfo
();
bool
exists
()
{
return
impl
.
get
()
!=
NULL
;
}
std
::
unique_ptr
<
ExecutionPoint
>
getExecutionPoi
nt
();
AST_stmt
*
getCurrentStateme
nt
();
Box
*
fastLocalsToBoxedLocals
();
Box
*
getGlobalsDict
();
...
...
@@ -114,13 +111,19 @@ struct FrameStackState {
// after the frame ends.
FrameInfo
*
frame_info
;
FrameStackState
()
{}
FrameStackState
(
BoxedDict
*
locals
,
FrameInfo
*
frame_info
)
:
locals
(
locals
),
frame_info
(
frame_info
)
{}
};
// Returns all the stack locals, including hidden ones.
FrameStackState
getFrameStackState
();
CompiledFunction
*
getTopCompiledFunction
();
struct
DeoptState
{
FrameStackState
frame_state
;
CompiledFunction
*
cf
;
AST_stmt
*
current_stmt
;
};
DeoptState
getDeoptState
();
}
#endif
src/core/cfg.cpp
View file @
caa84b81
...
...
@@ -2472,6 +2472,8 @@ void CFG::print() {
}
CFG
*
computeCFG
(
SourceInfo
*
source
,
std
::
vector
<
AST_stmt
*>
body
)
{
STAT_TIMER
(
t0
,
"us_timer_computecfg"
,
0
);
CFG
*
rtn
=
new
CFG
();
ScopingAnalysis
*
scoping_analysis
=
source
->
scoping
;
...
...
src/core/types.h
View file @
caa84b81
...
...
@@ -64,7 +64,6 @@ public:
using
gc
::
GCVisitor
;
enum
class
EffortLevel
{
INTERPRETED
=
0
,
MODERATE
=
2
,
MAXIMAL
=
3
,
};
...
...
@@ -74,8 +73,8 @@ template <class V> class ValuedCompilerType;
typedef
ValuedCompilerType
<
llvm
::
Value
*>
ConcreteCompilerType
;
ConcreteCompilerType
*
typeFromClass
(
BoxedClass
*
);
extern
ConcreteCompilerType
*
INT
,
*
BOXED_INT
,
*
LONG
,
*
FLOAT
,
*
BOXED_FLOAT
,
*
VOID
,
*
UNKNOWN
,
*
BOOL
,
*
STR
,
*
NONE
,
*
LIST
,
*
SLICE
,
*
MODULE
,
*
DICT
,
*
BOOL
,
*
BOXED_BOOL
,
*
BOXED_TUPLE
,
*
SET
,
*
FROZENSET
,
*
CLOSURE
,
*
GENERATOR
,
*
BOXED_COMPLEX
,
extern
ConcreteCompilerType
*
INT
,
*
BOXED_INT
,
*
LONG
,
*
FLOAT
,
*
BOXED_FLOAT
,
*
UNKNOWN
,
*
BOOL
,
*
STR
,
*
NONE
,
*
LIST
,
*
SLICE
,
*
MODULE
,
*
DICT
,
*
BOOL
,
*
BOXED_BOOL
,
*
BOXED_TUPLE
,
*
SET
,
*
FROZENSET
,
*
CLOSURE
,
*
GENERATOR
,
*
BOXED_COMPLEX
,
*
FRAME_INFO
;
extern
CompilerType
*
UNDEF
;
...
...
@@ -229,7 +228,6 @@ public:
llvm
::
Function
*
func
;
// the llvm IR object
FunctionSpecialization
*
spec
;
const
OSREntryDescriptor
*
entry_descriptor
;
bool
is_interpreted
;
union
{
Box
*
(
*
call
)(
Box
*
,
Box
*
,
Box
*
,
Box
**
);
...
...
@@ -246,13 +244,12 @@ public:
int64_t
times_called
,
times_speculation_failed
;
ICInvalidator
dependent_callsites
;
LocationMap
*
location_map
;
// only meaningful if this is a compiled frame
LocationMap
*
location_map
;
std
::
vector
<
ICInfo
*>
ics
;
std
::
vector
<
std
::
unique_ptr
<
JitCodeBlock
>>
code_blocks
;
CompiledFunction
(
llvm
::
Function
*
func
,
FunctionSpecialization
*
spec
,
bool
is_interpreted
,
void
*
code
,
EffortLevel
effort
,
const
OSREntryDescriptor
*
entry_descriptor
);
CompiledFunction
(
llvm
::
Function
*
func
,
FunctionSpecialization
*
spec
,
void
*
code
,
EffortLevel
effort
,
const
OSREntryDescriptor
*
entry_descriptor
);
ConcreteCompilerType
*
getReturnType
();
...
...
@@ -322,6 +319,11 @@ public:
// Please use codeForFunction() to access this:
BoxedCode
*
code_obj
;
// For use by the interpreter/baseline jit:
int
times_interpreted
;
std
::
vector
<
std
::
unique_ptr
<
JitCodeBlock
>>
code_blocks
;
ICInvalidator
dependent_interp_callsites
;
// Functions can provide an "internal" version, which will get called instead
// of the normal dispatch through the functionlist.
// This can be used to implement functions which know how to rewrite themselves,
...
...
@@ -331,22 +333,9 @@ public:
InternalCallable
internal_callable
=
NULL
;
CLFunction
(
int
num_args
,
int
num_defaults
,
bool
takes_varargs
,
bool
takes_kwargs
,
std
::
unique_ptr
<
SourceInfo
>
source
)
:
paramspec
(
num_args
,
num_defaults
,
takes_varargs
,
takes_kwargs
),
source
(
std
::
move
(
source
)),
param_names
(
this
->
source
->
ast
,
this
->
source
->
getInternedStrings
()),
always_use_version
(
NULL
),
code_obj
(
NULL
)
{
assert
(
num_args
>=
num_defaults
);
}
CLFunction
(
int
num_args
,
int
num_defaults
,
bool
takes_varargs
,
bool
takes_kwargs
,
const
ParamNames
&
param_names
)
:
paramspec
(
num_args
,
num_defaults
,
takes_varargs
,
takes_kwargs
),
source
(
nullptr
),
param_names
(
param_names
),
always_use_version
(
NULL
),
code_obj
(
NULL
)
{
assert
(
num_args
>=
num_defaults
);
}
std
::
unique_ptr
<
SourceInfo
>
source
);
CLFunction
(
int
num_args
,
int
num_defaults
,
bool
takes_varargs
,
bool
takes_kwargs
,
const
ParamNames
&
param_names
);
~
CLFunction
();
int
numReceivedArgs
()
{
return
paramspec
.
totalReceived
();
}
...
...
@@ -354,7 +343,7 @@ public:
assert
(
compiled
);
assert
((
compiled
->
spec
!=
NULL
)
+
(
compiled
->
entry_descriptor
!=
NULL
)
==
1
);
assert
(
compiled
->
clfunc
==
NULL
);
assert
(
compiled
->
is_interpreted
==
(
compiled
->
code
==
NULL
)
);
assert
(
compiled
->
code
);
compiled
->
clfunc
=
this
;
if
(
compiled
->
entry_descriptor
==
NULL
)
{
...
...
src/runtime/builtin_modules/builtins.cpp
View file @
caa84b81
...
...
@@ -849,7 +849,7 @@ Box* execfile(Box* _fn) {
// Run directly inside the current module:
AST_Module
*
ast
=
caching_parse_file
(
fn
->
data
());
ASSERT
(
get
ExecutionPoint
().
cf
->
clfunc
->
source
->
scoping
->
areGlobalsFromModule
(),
"need to pass custom globals in"
);
ASSERT
(
get
TopPythonFunction
()
->
source
->
scoping
->
areGlobalsFromModule
(),
"need to pass custom globals in"
);
compileAndRunModule
(
ast
,
getCurrentModule
());
return
None
;
...
...
src/runtime/frame.cpp
View file @
caa84b81
...
...
@@ -121,8 +121,8 @@ public:
static
Box
*
lineno
(
Box
*
obj
,
void
*
)
{
auto
f
=
static_cast
<
BoxedFrame
*>
(
obj
);
f
->
update
();
std
::
unique_ptr
<
ExecutionPoint
>
fr
=
f
->
it
.
getExecutionPoi
nt
();
return
boxInt
(
fr
->
current_
stmt
->
lineno
);
AST_stmt
*
stmt
=
f
->
it
.
getCurrentStateme
nt
();
return
boxInt
(
stmt
->
lineno
);
}
DEFAULT_CLASS
(
frame_cls
);
...
...
@@ -130,11 +130,11 @@ public:
static
Box
*
boxFrame
(
PythonFrameIterator
it
)
{
FrameInfo
*
fi
=
it
.
getFrameInfo
();
if
(
fi
->
frame_obj
==
NULL
)
{
auto
c
f
=
it
.
getCF
();
auto
c
l
=
it
.
getCL
();
Box
*
globals
=
it
.
getGlobalsDict
();
BoxedFrame
*
f
=
fi
->
frame_obj
=
new
BoxedFrame
(
std
::
move
(
it
));
f
->
_globals
=
globals
;
f
->
_code
=
codeForCLFunction
(
c
f
->
clfunc
);
f
->
_code
=
codeForCLFunction
(
c
l
);
}
return
fi
->
frame_obj
;
...
...
src/runtime/objmodel.cpp
View file @
caa84b81
...
...
@@ -162,20 +162,19 @@ extern "C" Box* deopt(AST_expr* expr, Box* value) {
RELEASE_ASSERT
(
0
,
"deopt is currently broken..."
);
FrameStackState
frame_state
=
getFrameStackState
();
auto
execution_point
=
getExecutionPoint
();
auto
deopt_state
=
getDeoptState
();
// Should we only do this selectively?
execution_point
.
cf
->
speculationFailed
();
deopt_state
.
cf
->
speculationFailed
();
// Except of exc.type we skip initializing the exc fields inside the JITed code path (small perf improvement) that's
// why we have todo it now if we didn't set an exception (which sets all fields)
if
(
frame_state
.
frame_info
->
exc
.
type
==
NULL
)
{
frame_state
.
frame_info
->
exc
.
traceback
=
NULL
;
frame_state
.
frame_info
->
exc
.
value
=
NULL
;
if
(
deopt_state
.
frame_state
.
frame_info
->
exc
.
type
==
NULL
)
{
deopt_state
.
frame_state
.
frame_info
->
exc
.
traceback
=
NULL
;
deopt_state
.
frame_state
.
frame_info
->
exc
.
value
=
NULL
;
}
return
astInterpretFrom
(
execution_point
.
cf
,
expr
,
execution_point
.
current_stmt
,
value
,
frame_state
);
return
astInterpretFrom
(
deopt_state
.
cf
->
clfunc
,
expr
,
deopt_state
.
current_stmt
,
value
,
deopt_state
.
frame_state
);
}
extern
"C"
bool
softspace
(
Box
*
b
,
bool
newval
)
{
...
...
@@ -2662,16 +2661,12 @@ extern "C" void dumpEx(void* p, int levels) {
printf
(
"Has %ld function versions
\n
"
,
cl
->
versions
.
size
());
for
(
CompiledFunction
*
cf
:
cl
->
versions
)
{
if
(
cf
->
is_interpreted
)
{
printf
(
"[interpreted]
\n
"
);
}
else
{
bool
got_name
;
std
::
string
name
=
g
.
func_addr_registry
.
getFuncNameAtAddress
(
cf
->
code
,
true
,
&
got_name
);
if
(
got_name
)
printf
(
"%s
\n
"
,
name
.
c_str
());
else
printf
(
"%p
\n
"
,
cf
->
code
);
}
bool
got_name
;
std
::
string
name
=
g
.
func_addr_registry
.
getFuncNameAtAddress
(
cf
->
code
,
true
,
&
got_name
);
if
(
got_name
)
printf
(
"%s
\n
"
,
name
.
c_str
());
else
printf
(
"%p
\n
"
,
cf
->
code
);
}
}
...
...
@@ -2930,26 +2925,7 @@ static CompiledFunction* pickVersion(CLFunction* f, int num_output_args, Box* oa
abort
();
}
EffortLevel
new_effort
=
initialEffort
();
// Only the interpreter currently supports non-module-globals:
if
(
!
f
->
source
->
scoping
->
areGlobalsFromModule
())
new_effort
=
EffortLevel
::
INTERPRETED
;
std
::
vector
<
ConcreteCompilerType
*>
arg_types
;
for
(
int
i
=
0
;
i
<
num_output_args
;
i
++
)
{
if
(
new_effort
==
EffortLevel
::
INTERPRETED
)
{
arg_types
.
push_back
(
UNKNOWN
);
}
else
{
Box
*
arg
=
getArg
(
i
,
oarg1
,
oarg2
,
oarg3
,
oargs
);
assert
(
arg
);
// only builtin functions can pass NULL args
arg_types
.
push_back
(
typeFromClass
(
arg
->
cls
));
}
}
FunctionSpecialization
*
spec
=
new
FunctionSpecialization
(
UNKNOWN
,
arg_types
);
// this also pushes the new CompiledVersion to the back of the version list:
return
compileFunction
(
f
,
spec
,
new_effort
,
NULL
);
return
NULL
;
}
static
llvm
::
StringRef
getFunctionName
(
CLFunction
*
f
)
{
...
...
@@ -3500,7 +3476,7 @@ static Box* callChosenCF(CompiledFunction* chosen_cf, BoxedClosure* closure, Box
// This function exists for the rewriter: astInterpretFunction takes 9 args, but the rewriter
// only supports calling functions with at most 6 since it can currently only pass arguments
// in registers.
static
Box
*
astInterpretHelper
(
C
ompiled
Function
*
f
,
int
num_args
,
BoxedClosure
*
closure
,
BoxedGenerator
*
generator
,
static
Box
*
astInterpretHelper
(
C
L
Function
*
f
,
int
num_args
,
BoxedClosure
*
closure
,
BoxedGenerator
*
generator
,
Box
*
globals
,
Box
**
_args
)
{
Box
*
arg1
=
_args
[
0
];
Box
*
arg2
=
_args
[
1
];
...
...
@@ -3514,16 +3490,15 @@ Box* callCLFunc(CLFunction* f, CallRewriteArgs* rewrite_args, int num_output_arg
BoxedGenerator
*
generator
,
Box
*
globals
,
Box
*
oarg1
,
Box
*
oarg2
,
Box
*
oarg3
,
Box
**
oargs
)
{
CompiledFunction
*
chosen_cf
=
pickVersion
(
f
,
num_output_args
,
oarg1
,
oarg2
,
oarg3
,
oargs
);
assert
(
chosen_cf
->
is_interpreted
==
(
chosen_cf
->
code
==
NULL
));
if
(
chosen_cf
->
is_interpreted
)
{
if
(
!
chosen_cf
)
{
if
(
rewrite_args
)
{
rewrite_args
->
rewriter
->
addDependenceOn
(
chosen_cf
->
dependent_callsites
);
RewriterVar
::
SmallVector
arg_vec
;
rewrite_args
->
rewriter
->
addDependenceOn
(
f
->
dependent_interp_callsites
);
// TODO this kind of embedded reference needs to be tracked by the GC somehow?
// Or maybe it's ok, since we've guarded on the function object?
arg_vec
.
push_back
(
rewrite_args
->
rewriter
->
loadConst
((
intptr_t
)
chosen_c
f
,
Location
::
forArg
(
0
)));
arg_vec
.
push_back
(
rewrite_args
->
rewriter
->
loadConst
((
intptr_t
)
f
,
Location
::
forArg
(
0
)));
arg_vec
.
push_back
(
rewrite_args
->
rewriter
->
loadConst
((
intptr_t
)
num_output_args
,
Location
::
forArg
(
1
)));
arg_vec
.
push_back
(
rewrite_args
->
rewriter
->
loadConst
((
intptr_t
)
closure
,
Location
::
forArg
(
2
)));
arg_vec
.
push_back
(
rewrite_args
->
rewriter
->
loadConst
((
intptr_t
)
generator
,
Location
::
forArg
(
3
)));
...
...
@@ -3531,6 +3506,7 @@ Box* callCLFunc(CLFunction* f, CallRewriteArgs* rewrite_args, int num_output_arg
// Hacky workaround: the rewriter can only pass arguments in registers, so use this helper function
// to unpack some of the additional arguments:
// TODO if there's only one arg we could just pass it normally
RewriterVar
*
arg_array
=
rewrite_args
->
rewriter
->
allocate
(
4
);
arg_vec
.
push_back
(
arg_array
);
if
(
num_output_args
>=
1
)
...
...
@@ -3546,8 +3522,7 @@ Box* callCLFunc(CLFunction* f, CallRewriteArgs* rewrite_args, int num_output_arg
rewrite_args
->
out_success
=
true
;
}
return
astInterpretFunction
(
chosen_cf
,
num_output_args
,
closure
,
generator
,
globals
,
oarg1
,
oarg2
,
oarg3
,
oargs
);
return
astInterpretFunction
(
f
,
num_output_args
,
closure
,
generator
,
globals
,
oarg1
,
oarg2
,
oarg3
,
oargs
);
}
ASSERT
(
!
globals
,
"need to update the calling conventions if we want to pass globals"
);
...
...
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