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